From 4eaa02d25f83eff38cecd6db1724c8626dc3af2e Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 22 Oct 2023 13:02:24 +0900 Subject: enhance: improve avatar decoration --- packages/frontend/src/components/MkRange.vue | 5 + .../frontend/src/components/global/MkAvatar.vue | 43 +++++++- .../settings/profile.avatar-decoration-dialog.vue | 114 +++++++++++++++++++++ packages/frontend/src/pages/settings/profile.vue | 20 ++-- 4 files changed, 166 insertions(+), 16 deletions(-) create mode 100644 packages/frontend/src/pages/settings/profile.avatar-decoration-dialog.vue (limited to 'packages/frontend/src') diff --git a/packages/frontend/src/components/MkRange.vue b/packages/frontend/src/components/MkRange.vue index 2cfc27ceee..04390c6f0c 100644 --- a/packages/frontend/src/components/MkRange.vue +++ b/packages/frontend/src/components/MkRange.vue @@ -34,6 +34,7 @@ const props = withDefaults(defineProps<{ textConverter?: (value: number) => string, showTicks?: boolean; easing?: boolean; + continuousUpdate?: boolean; }>(), { step: 1, textConverter: (v) => v.toString(), @@ -123,6 +124,10 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => { const pointerX = ev.touches && ev.touches.length > 0 ? ev.touches[0].clientX : ev.clientX; const pointerPositionOnContainer = pointerX - (containerRect.left + (thumbWidth / 2)); rawValue.value = Math.min(1, Math.max(0, pointerPositionOnContainer / (containerEl.value!.offsetWidth - thumbWidth))); + + if (props.continuousUpdate) { + emit('update:modelValue', finalValue.value); + } }; let beforeValue = finalValue.value; diff --git a/packages/frontend/src/components/global/MkAvatar.vue b/packages/frontend/src/components/global/MkAvatar.vue index de684425a2..e22ed29b7e 100644 --- a/packages/frontend/src/components/global/MkAvatar.vue +++ b/packages/frontend/src/components/global/MkAvatar.vue @@ -23,7 +23,16 @@ SPDX-License-Identifier: AGPL-3.0-only - + @@ -48,12 +57,18 @@ const props = withDefaults(defineProps<{ link?: boolean; preview?: boolean; indicator?: boolean; - decoration?: string; + decoration?: { + url: string; + angle?: number; + flipH?: boolean; + flipV?: boolean; + }; }>(), { target: null, link: false, preview: false, indicator: false, + decoration: undefined, }); const emit = defineEmits<{ @@ -73,6 +88,30 @@ function onClick(ev: MouseEvent): void { emit('click', ev); } +function getDecorationAngle() { + let angle; + if (props.decoration) { + angle = props.decoration.angle ?? 0; + } else if (props.user.avatarDecorations.length > 0) { + angle = props.user.avatarDecorations[0].angle ?? 0; + } else { + angle = 0; + } + return angle === 0 ? undefined : `${angle * 360}deg`; +} + +function getDecorationScale() { + let scaleX; + if (props.decoration) { + scaleX = props.decoration.flipH ? -1 : 1; + } else if (props.user.avatarDecorations.length > 0) { + scaleX = props.user.avatarDecorations[0].flipH ? -1 : 1; + } else { + scaleX = 1; + } + return scaleX === 1 ? undefined : `${scaleX} 1`; +} + let color = $ref(); watch(() => props.user.avatarBlurhash, () => { diff --git a/packages/frontend/src/pages/settings/profile.avatar-decoration-dialog.vue b/packages/frontend/src/pages/settings/profile.avatar-decoration-dialog.vue new file mode 100644 index 0000000000..c4bdf4a49b --- /dev/null +++ b/packages/frontend/src/pages/settings/profile.avatar-decoration-dialog.vue @@ -0,0 +1,114 @@ + + + + + + + diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue index f3d0c12dce..8d9c3cf730 100644 --- a/packages/frontend/src/pages/settings/profile.vue +++ b/packages/frontend/src/pages/settings/profile.vue @@ -92,10 +92,10 @@ SPDX-License-Identifier: AGPL-3.0-only v-for="avatarDecoration in avatarDecorations" :key="avatarDecoration.id" :class="[$style.avatarDecoration, { [$style.avatarDecorationActive]: $i.avatarDecorations.some(x => x.id === avatarDecoration.id) }]" - @click="toggleDecoration(avatarDecoration)" + @click="openDecoration(avatarDecoration)" >
{{ avatarDecoration.name }}
- + @@ -266,18 +266,10 @@ function changeBanner(ev) { }); } -function toggleDecoration(avatarDecoration) { - if ($i.avatarDecorations.some(x => x.id === avatarDecoration.id)) { - os.apiWithDialog('i/update', { - avatarDecorations: [], - }); - $i.avatarDecorations = []; - } else { - os.apiWithDialog('i/update', { - avatarDecorations: [avatarDecoration.id], - }); - $i.avatarDecorations.push(avatarDecoration); - } +function openDecoration(avatarDecoration) { + os.popup(defineAsyncComponent(() => import('./profile.avatar-decoration-dialog.vue')), { + decoration: avatarDecoration, + }, {}, 'closed'); } const headerActions = $computed(() => []); -- cgit v1.2.3-freya