diff --git a/packages/frontend/src/components/global/MkAvatar.vue b/packages/frontend/src/components/global/MkAvatar.vue index 6aa9a4203..9d13c0329 100644 --- a/packages/frontend/src/components/global/MkAvatar.vue +++ b/packages/frontend/src/components/global/MkAvatar.vue @@ -59,7 +59,7 @@ const props = withDefaults(defineProps<{ link?: boolean; preview?: boolean; indicator?: boolean; - decorations?: Misskey.entities.UserDetailed['avatarDecorations'][number][]; + decorations?: Omit[]; forceShowDecoration?: boolean; }>(), { target: null, @@ -89,12 +89,12 @@ function onClick(ev: MouseEvent): void { emit('click', ev); } -function getDecorationAngle(decoration: Misskey.entities.UserDetailed['avatarDecorations'][number]) { +function getDecorationAngle(decoration: Omit) { const angle = decoration.angle ?? 0; return angle === 0 ? undefined : `${angle * 360}deg`; } -function getDecorationScale(decoration: Misskey.entities.UserDetailed['avatarDecorations'][number]) { +function getDecorationScale(decoration: Omit) { const scaleX = decoration.flipH ? -1 : 1; return scaleX === 1 ? undefined : `${scaleX} 1`; } diff --git a/packages/frontend/src/pages/settings/profile.avatar-decoration.decoration.vue b/packages/frontend/src/pages/settings/profile.avatar-decoration.decoration.vue new file mode 100644 index 000000000..c11386823 --- /dev/null +++ b/packages/frontend/src/pages/settings/profile.avatar-decoration.decoration.vue @@ -0,0 +1,67 @@ + + + + + + + diff --git a/packages/frontend/src/pages/settings/profile.avatar-decoration-dialog.vue b/packages/frontend/src/pages/settings/profile.avatar-decoration.dialog.vue similarity index 66% rename from packages/frontend/src/pages/settings/profile.avatar-decoration-dialog.vue rename to packages/frontend/src/pages/settings/profile.avatar-decoration.dialog.vue index b7ea4c152..a27b46aa3 100644 --- a/packages/frontend/src/pages/settings/profile.avatar-decoration-dialog.vue +++ b/packages/frontend/src/pages/settings/profile.avatar-decoration.dialog.vue @@ -17,7 +17,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ decoration.name }}
- +
@@ -30,8 +30,8 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts.update }} - {{ i18n.ts.detach }} + {{ i18n.ts.update }} + {{ i18n.ts.detach }} {{ i18n.ts.attach }}
@@ -51,48 +51,69 @@ import MkRange from '@/components/MkRange.vue'; import { $i } from '@/account.js'; const props = defineProps<{ + usingIndex: number | null; decoration: { id: string; url: string; name: string; - } + }; }>(); const emit = defineEmits<{ (ev: 'closed'): void; + (ev: 'attach', payload: { + angle: number; + flipH: boolean; + }): void; + (ev: 'update', payload: { + angle: number; + flipH: boolean; + }): void; + (ev: 'detach'): void; }>(); const dialog = shallowRef>(); -const using = computed(() => $i.avatarDecorations.some(x => x.id === props.decoration.id)); -const angle = ref(using.value ? $i.avatarDecorations.find(x => x.id === props.decoration.id).angle ?? 0 : 0); -const flipH = ref(using.value ? $i.avatarDecorations.find(x => x.id === props.decoration.id).flipH ?? false : false); +const angle = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].angle : null) ?? 0); +const flipH = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].flipH : null) ?? false); + +const decorationsForPreview = computed(() => { + const decoration = { + id: props.decoration.id, + url: props.decoration.url, + angle: angle.value, + flipH: flipH.value, + }; + const decorations = [...$i.avatarDecorations]; + if (props.usingIndex != null) { + decorations[props.usingIndex] = decoration; + } else { + decorations.push(decoration); + } + return decorations; +}); function cancel() { dialog.value.close(); } -async function attach() { - const decoration = { - id: props.decoration.id, +async function update() { + emit('update', { angle: angle.value, flipH: flipH.value, - }; - const update = [...$i.avatarDecorations, decoration]; - await os.apiWithDialog('i/update', { - avatarDecorations: update, }); - $i.avatarDecorations = update; + dialog.value.close(); +} +async function attach() { + emit('attach', { + angle: angle.value, + flipH: flipH.value, + }); dialog.value.close(); } async function detach() { - const update = $i.avatarDecorations.filter(x => x.id !== props.decoration.id); - await os.apiWithDialog('i/update', { - avatarDecorations: update, - }); - $i.avatarDecorations = update; - + emit('detach'); dialog.value.close(); } diff --git a/packages/frontend/src/pages/settings/profile.avatar-decoration.vue b/packages/frontend/src/pages/settings/profile.avatar-decoration.vue new file mode 100644 index 000000000..90c2b75a4 --- /dev/null +++ b/packages/frontend/src/pages/settings/profile.avatar-decoration.vue @@ -0,0 +1,125 @@ + + + + + + + diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index a5d3835b9..5f0d1aee5 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -87,24 +87,7 @@ SPDX-License-Identifier: AGPL-3.0-only -
- {{ i18n.t('_profile.avatarDecorationMax', { max: $i?.policies.avatarDecorationLimit }) }} ({{ i18n.t('remainingN', { n: $i?.policies.avatarDecorationLimit - $i.avatarDecorations.length }) }}) - - {{ i18n.ts.detachAll }} - -
-
-
{{ avatarDecoration.name }}
- - -
-
-
+ @@ -128,7 +111,8 @@ SPDX-License-Identifier: AGPL-3.0-only