|
@ -68,6 +68,30 @@ |
|
|
<router-link :to="{ name: 'new-edit-account' }"> |
|
|
<router-link :to="{ name: 'new-edit-account' }"> |
|
|
<fa icon="pen" class="text-xs text-blue-500 mb-1"></fa> |
|
|
<fa icon="pen" class="text-xs text-blue-500 mb-1"></fa> |
|
|
</router-link> |
|
|
</router-link> |
|
|
|
|
|
<div class="flex justify-center mt-4"> |
|
|
|
|
|
<span v-if="profileImageUrl" class="flex justify-between"> |
|
|
|
|
|
<a |
|
|
|
|
|
:href="profileImageUrl" |
|
|
|
|
|
target="_blank" |
|
|
|
|
|
class="text-blue-500 ml-4" |
|
|
|
|
|
> |
|
|
|
|
|
<img :src="profileImageUrl" class="h-24 rounded-xl" /> |
|
|
|
|
|
</a> |
|
|
|
|
|
<fa |
|
|
|
|
|
icon="trash-can" |
|
|
|
|
|
@click="confirmDeleteImage" |
|
|
|
|
|
class="text-red-500 fa-fw ml-8 mt-10" |
|
|
|
|
|
/> |
|
|
|
|
|
</span> |
|
|
|
|
|
<span v-else> |
|
|
|
|
|
<fa |
|
|
|
|
|
icon="camera" |
|
|
|
|
|
class="bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-2 rounded-md" |
|
|
|
|
|
@click="openPhotoDialog" |
|
|
|
|
|
/> |
|
|
|
|
|
</span> |
|
|
|
|
|
<GiftedPhotoDialog ref="photoDialog" /> |
|
|
|
|
|
</div> |
|
|
</h2> |
|
|
</h2> |
|
|
<span v-else> |
|
|
<span v-else> |
|
|
<router-link |
|
|
<router-link |
|
@ -537,6 +561,7 @@ import { ref } from "vue"; |
|
|
import { Component, Vue } from "vue-facing-decorator"; |
|
|
import { Component, Vue } from "vue-facing-decorator"; |
|
|
import { useClipboard } from "@vueuse/core"; |
|
|
import { useClipboard } from "@vueuse/core"; |
|
|
|
|
|
|
|
|
|
|
|
import GiftedPhotoDialog from "@/components/GiftedPhotoDialog.vue"; |
|
|
import QuickNav from "@/components/QuickNav.vue"; |
|
|
import QuickNav from "@/components/QuickNav.vue"; |
|
|
import TopMessage from "@/components/TopMessage.vue"; |
|
|
import TopMessage from "@/components/TopMessage.vue"; |
|
|
import { |
|
|
import { |
|
@ -566,7 +591,7 @@ interface IAccount { |
|
|
const inputFileNameRef = ref<Blob>(); |
|
|
const inputFileNameRef = ref<Blob>(); |
|
|
|
|
|
|
|
|
@Component({ |
|
|
@Component({ |
|
|
components: { QuickNav, TopMessage }, |
|
|
components: { GiftedPhotoDialog, QuickNav, TopMessage }, |
|
|
}) |
|
|
}) |
|
|
export default class AccountViewView extends Vue { |
|
|
export default class AccountViewView extends Vue { |
|
|
$notify!: (notification: NotificationIface, timeout?: number) => void; |
|
|
$notify!: (notification: NotificationIface, timeout?: number) => void; |
|
@ -586,10 +611,12 @@ export default class AccountViewView extends Vue { |
|
|
isRegistered = false; |
|
|
isRegistered = false; |
|
|
isSubscribed = false; |
|
|
isSubscribed = false; |
|
|
notificationMaybeChanged = false; |
|
|
notificationMaybeChanged = false; |
|
|
|
|
|
profileImageUrl: string | null = null; |
|
|
publicHex = ""; |
|
|
publicHex = ""; |
|
|
publicBase64 = ""; |
|
|
publicBase64 = ""; |
|
|
webPushServer = ""; |
|
|
webPushServer = ""; |
|
|
webPushServerInput = ""; |
|
|
webPushServerInput = ""; |
|
|
|
|
|
|
|
|
limitsMessage = ""; |
|
|
limitsMessage = ""; |
|
|
loadingLimits = false; |
|
|
loadingLimits = false; |
|
|
showContactGives = false; |
|
|
showContactGives = false; |
|
@ -1260,5 +1287,87 @@ export default class AccountViewView extends Vue { |
|
|
-1, |
|
|
-1, |
|
|
); |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
openPhotoDialog() { |
|
|
|
|
|
(this.$refs.photoDialog as GiftedPhotoDialog).open((imgUrl) => { |
|
|
|
|
|
this.profileImageUrl = imgUrl; |
|
|
|
|
|
console.log("Got image URL:", imgUrl); |
|
|
|
|
|
}); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
confirmDeleteImage() { |
|
|
|
|
|
this.$notify( |
|
|
|
|
|
{ |
|
|
|
|
|
group: "modal", |
|
|
|
|
|
type: "confirm", |
|
|
|
|
|
title: "Are you sure you want to delete your profile picture?", |
|
|
|
|
|
text: "", |
|
|
|
|
|
onYes: this.deleteImage, |
|
|
|
|
|
}, |
|
|
|
|
|
-1, |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
async deleteImage() { |
|
|
|
|
|
if (!this.profileImageUrl) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
try { |
|
|
|
|
|
const identity = await this.getIdentity(this.activeDid); |
|
|
|
|
|
if (!identity) { |
|
|
|
|
|
throw Error("No identity found."); |
|
|
|
|
|
} |
|
|
|
|
|
const token = await accessToken(identity); |
|
|
|
|
|
const response = await this.axios.delete( |
|
|
|
|
|
DEFAULT_IMAGE_API_SERVER + |
|
|
|
|
|
"/image/" + |
|
|
|
|
|
encodeURIComponent(this.profileImageUrl), |
|
|
|
|
|
{ |
|
|
|
|
|
headers: { |
|
|
|
|
|
Authorization: `Bearer ${token}`, |
|
|
|
|
|
}, |
|
|
|
|
|
}, |
|
|
|
|
|
); |
|
|
|
|
|
if (response.status === 204) { |
|
|
|
|
|
// don't bother with a notification |
|
|
|
|
|
// (either they'll simply continue or they're canceling and going back) |
|
|
|
|
|
} else { |
|
|
|
|
|
console.error("Non-success deleting image:", response); |
|
|
|
|
|
this.$notify( |
|
|
|
|
|
{ |
|
|
|
|
|
group: "alert", |
|
|
|
|
|
type: "danger", |
|
|
|
|
|
title: "Error", |
|
|
|
|
|
text: "There was a problem deleting the image.", |
|
|
|
|
|
}, |
|
|
|
|
|
5000, |
|
|
|
|
|
); |
|
|
|
|
|
// keep the imageUrl in localStorage so the user can try again if they want |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
this.profileImageUrl = ""; |
|
|
|
|
|
} catch (error) { |
|
|
|
|
|
console.error("Error deleting image:", error); |
|
|
|
|
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any |
|
|
|
|
|
if ((error as any).response.status === 404) { |
|
|
|
|
|
console.log("The image was already deleted:", error); |
|
|
|
|
|
|
|
|
|
|
|
this.profileImageUrl = ""; |
|
|
|
|
|
|
|
|
|
|
|
// it already doesn't exist so we won't say anything to the user |
|
|
|
|
|
} else { |
|
|
|
|
|
this.$notify( |
|
|
|
|
|
{ |
|
|
|
|
|
group: "alert", |
|
|
|
|
|
type: "danger", |
|
|
|
|
|
title: "Error", |
|
|
|
|
|
text: "There was an error deleting the image.", |
|
|
|
|
|
}, |
|
|
|
|
|
5000, |
|
|
|
|
|
); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
</script> |
|
|
</script> |
|
|