diff --git a/locales/index.d.ts b/locales/index.d.ts index 27c8a36842..f125a9fa53 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -9064,6 +9064,14 @@ export interface Locale extends ILocale { * フォローを承認制にしている場合、フォローリクエストを許可した時に表示されます。 */ "followedMessageDescriptionForLockedAccount": string; + /** + * Update avatar + */ + "updateAvatar": string; + /** + * Remove avatar + */ + "removeAvatar": string; /** * Update banner */ diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index 337cbfc532..6bc171cceb 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -249,30 +249,71 @@ function save() { } function changeAvatar(ev) { - selectFile(ev.currentTarget ?? ev.target, i18n.ts.avatar).then(async (file) => { - let originalOrCropped = file; + if ($i.avatarId) { + os.popupMenu([{ + text: i18n.ts._profile.updateAvatar, + action: async () => { + selectFile(ev.currentTarget ?? ev.target, i18n.ts.avatar).then(async (file) => { + let originalOrCropped = file; - const { canceled } = await os.confirm({ - type: 'question', - text: i18n.ts.cropImageAsk, - okText: i18n.ts.cropYes, - cancelText: i18n.ts.cropNo, - }); + const { canceled } = await os.confirm({ + type: 'question', + text: i18n.ts.cropImageAsk, + okText: i18n.ts.cropYes, + cancelText: i18n.ts.cropNo, + }); - if (!canceled) { - originalOrCropped = await os.cropImage(file, { - aspectRatio: 1, + if (!canceled) { + originalOrCropped = await os.cropImage(file, { + aspectRatio: 1, + }); + } + + const i = await os.apiWithDialog('i/update', { + avatarId: originalOrCropped.id, + }); + $i.avatarId = i.avatarId; + $i.avatarUrl = i.avatarUrl; + globalEvents.emit('requestClearPageCache'); + }); + }, + }, { + text: i18n.ts._profile.removeAvatar, + action: async () => { + const i = await os.apiWithDialog('i/update', { + avatarId: null, + }); + $i.avatarId = i.avatarId; + $i.avatarUrl = i.avatarUrl; + globalEvents.emit('requestClearPageCache'); + }, + }], ev.currentTarget ?? ev.target); + } else { + selectFile(ev.currentTarget ?? ev.target, i18n.ts.avatar).then(async (file) => { + let originalOrCropped = file; + + const { canceled } = await os.confirm({ + type: 'question', + text: i18n.ts.cropImageAsk, + okText: i18n.ts.cropYes, + cancelText: i18n.ts.cropNo, }); - } - const i = await os.apiWithDialog('i/update', { - avatarId: originalOrCropped.id, + if (!canceled) { + originalOrCropped = await os.cropImage(file, { + aspectRatio: 1, + }); + } + + const i = await os.apiWithDialog('i/update', { + avatarId: originalOrCropped.id, + }); + $i.avatarId = i.avatarId; + $i.avatarUrl = i.avatarUrl; + globalEvents.emit('requestClearPageCache'); + claimAchievement('profileFilled'); }); - $i.avatarId = i.avatarId; - $i.avatarUrl = i.avatarUrl; - globalEvents.emit('requestClearPageCache'); - claimAchievement('profileFilled'); - }); + } } function changeBanner(ev) { diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml index 9a41a9d762..7be3022f24 100644 --- a/sharkey-locales/en-US.yml +++ b/sharkey-locales/en-US.yml @@ -278,6 +278,8 @@ _widgets: _poll: multiple: "Multiple choices" _profile: + updateAvatar: "Update avatar" + removeAvatar: "Remove avatar" updateBanner: "Update banner" removeBanner: "Remove banner" changeBackground: "Change background"