diff options
| author | syuilo <Syuilotan@yahoo.co.jp> | 2023-12-14 20:58:08 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2023-12-14 20:58:08 +0900 |
| commit | 417852779f871197f6aec2fec0fd56a2380836e4 (patch) | |
| tree | 2d135b2f5c5b9e298eb3c9f594021635f5b0140b /packages | |
| parent | fix: devモードの特定条件下でページが表示されなくなる問... (diff) | |
| download | misskey-417852779f871197f6aec2fec0fd56a2380836e4.tar.gz misskey-417852779f871197f6aec2fec0fd56a2380836e4.tar.bz2 misskey-417852779f871197f6aec2fec0fd56a2380836e4.zip | |
enhance: アイコンデコレーションの位置を微調整できるように
Diffstat (limited to 'packages')
7 files changed, 44 insertions, 3 deletions
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts index 917f4e06d0..fb7aa0c244 100644 --- a/packages/backend/src/core/entities/UserEntityService.ts +++ b/packages/backend/src/core/entities/UserEntityService.ts @@ -362,6 +362,8 @@ export class UserEntityService implements OnModuleInit { id: ud.id, angle: ud.angle || undefined, flipH: ud.flipH || undefined, + offsetX: ud.offsetX || undefined, + offsetY: ud.offsetY || undefined, url: decorations.find(d => d.id === ud.id)!.url, }))) : [], isBot: user.isBot, diff --git a/packages/backend/src/models/User.ts b/packages/backend/src/models/User.ts index c3762fcd3e..219497a125 100644 --- a/packages/backend/src/models/User.ts +++ b/packages/backend/src/models/User.ts @@ -143,8 +143,10 @@ export class MiUser { }) public avatarDecorations: { id: string; - angle: number; - flipH: boolean; + angle?: number; + flipH?: boolean; + offsetX?: number; + offsetY?: number; }[]; @Index() diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index 399e6b88cb..a56f50115b 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -143,6 +143,8 @@ export const paramDef = { id: { type: 'string', format: 'misskey:id' }, angle: { type: 'number', nullable: true, maximum: 0.5, minimum: -0.5 }, flipH: { type: 'boolean', nullable: true }, + offsetX: { type: 'number', nullable: true, maximum: 0.25, minimum: -0.25 }, + offsetY: { type: 'number', nullable: true, maximum: 0.25, minimum: -0.25 }, }, required: ['id'], } }, @@ -341,6 +343,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- id: d.id, angle: d.angle ?? 0, flipH: d.flipH ?? false, + offsetX: d.offsetX ?? 0, + offsetY: d.offsetY ?? 0, })); } diff --git a/packages/frontend/src/components/global/MkAvatar.vue b/packages/frontend/src/components/global/MkAvatar.vue index 9d13c03290..af5b6e44f5 100644 --- a/packages/frontend/src/components/global/MkAvatar.vue +++ b/packages/frontend/src/components/global/MkAvatar.vue @@ -31,6 +31,7 @@ SPDX-License-Identifier: AGPL-3.0-only :style="{ rotate: getDecorationAngle(decoration), scale: getDecorationScale(decoration), + translate: getDecorationOffset(decoration), }" alt="" > @@ -99,6 +100,12 @@ function getDecorationScale(decoration: Omit<Misskey.entities.UserDetailed['avat return scaleX === 1 ? undefined : `${scaleX} 1`; } +function getDecorationOffset(decoration: Omit<Misskey.entities.UserDetailed['avatarDecorations'][number], 'id'>) { + const offsetX = decoration.offsetX ?? 0; + const offsetY = decoration.offsetY ?? 0; + return offsetX === 0 && offsetY === 0 ? undefined : `${offsetX * 100}% ${offsetY * 100}%`; +} + const color = ref<string | undefined>(); watch(() => props.user.avatarBlurhash, () => { diff --git a/packages/frontend/src/pages/settings/profile.avatar-decoration.decoration.vue b/packages/frontend/src/pages/settings/profile.avatar-decoration.decoration.vue index c113868238..9c95b5547e 100644 --- a/packages/frontend/src/pages/settings/profile.avatar-decoration.decoration.vue +++ b/packages/frontend/src/pages/settings/profile.avatar-decoration.decoration.vue @@ -9,7 +9,7 @@ SPDX-License-Identifier: AGPL-3.0-only @click="emit('click')" > <div :class="$style.name"><MkCondensedLine :minScale="0.5">{{ decoration.name }}</MkCondensedLine></div> - <MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="[{ url: decoration.url, angle, flipH }]" forceShowDecoration/> + <MkAvatar style="width: 60px; height: 60px;" :user="$i" :decorations="[{ url: decoration.url, angle, flipH, offsetX, offsetY }]" forceShowDecoration/> <i v-if="decoration.roleIdsThatCanBeUsedThisDecoration.length > 0 && !$i.roles.some(r => decoration.roleIdsThatCanBeUsedThisDecoration.includes(r.id))" :class="$style.lock" class="ti ti-lock"></i> </div> </template> @@ -28,6 +28,8 @@ const props = defineProps<{ }; angle?: number; flipH?: boolean; + offsetX?: number; + offsetY?: number; }>(); const emit = defineEmits<{ diff --git a/packages/frontend/src/pages/settings/profile.avatar-decoration.dialog.vue b/packages/frontend/src/pages/settings/profile.avatar-decoration.dialog.vue index 26cacf3c37..77e6b28fad 100644 --- a/packages/frontend/src/pages/settings/profile.avatar-decoration.dialog.vue +++ b/packages/frontend/src/pages/settings/profile.avatar-decoration.dialog.vue @@ -23,6 +23,12 @@ SPDX-License-Identifier: AGPL-3.0-only <MkRange v-model="angle" continuousUpdate :min="-0.5" :max="0.5" :step="0.025" :textConverter="(v) => `${Math.floor(v * 360)}°`"> <template #label>{{ i18n.ts.angle }}</template> </MkRange> + <MkRange v-model="offsetX" continuousUpdate :min="-0.25" :max="0.25" :step="0.025" :textConverter="(v) => `${Math.floor(v * 100)}%`"> + <template #label>X {{ i18n.ts.position }}</template> + </MkRange> + <MkRange v-model="offsetY" continuousUpdate :min="-0.25" :max="0.25" :step="0.025" :textConverter="(v) => `${Math.floor(v * 100)}%`"> + <template #label>Y {{ i18n.ts.position }}</template> + </MkRange> <MkSwitch v-model="flipH"> <template #label>{{ i18n.ts.flip }}</template> </MkSwitch> @@ -64,10 +70,14 @@ const emit = defineEmits<{ (ev: 'attach', payload: { angle: number; flipH: boolean; + offsetX: number; + offsetY: number; }): void; (ev: 'update', payload: { angle: number; flipH: boolean; + offsetX: number; + offsetY: number; }): void; (ev: 'detach'): void; }>(); @@ -76,6 +86,8 @@ const dialog = shallowRef<InstanceType<typeof MkModalWindow>>(); const exceeded = computed(() => ($i.policies.avatarDecorationLimit - $i.avatarDecorations.length) <= 0); 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 offsetX = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].offsetX : null) ?? 0); +const offsetY = ref((props.usingIndex != null ? $i.avatarDecorations[props.usingIndex].offsetY : null) ?? 0); const decorationsForPreview = computed(() => { const decoration = { @@ -83,6 +95,8 @@ const decorationsForPreview = computed(() => { url: props.decoration.url, angle: angle.value, flipH: flipH.value, + offsetX: offsetX.value, + offsetY: offsetY.value, }; const decorations = [...$i.avatarDecorations]; if (props.usingIndex != null) { @@ -101,6 +115,8 @@ async function update() { emit('update', { angle: angle.value, flipH: flipH.value, + offsetX: offsetX.value, + offsetY: offsetY.value, }); dialog.value.close(); } @@ -109,6 +125,8 @@ async function attach() { emit('attach', { angle: angle.value, flipH: flipH.value, + offsetX: offsetX.value, + offsetY: offsetY.value, }); 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 index bfef6e0325..8579acfed8 100644 --- a/packages/frontend/src/pages/settings/profile.avatar-decoration.vue +++ b/packages/frontend/src/pages/settings/profile.avatar-decoration.vue @@ -16,6 +16,8 @@ SPDX-License-Identifier: AGPL-3.0-only :decoration="avatarDecorations.find(d => d.id === avatarDecoration.id)" :angle="avatarDecoration.angle" :flipH="avatarDecoration.flipH" + :offsetX="avatarDecoration.offsetX" + :offsetY="avatarDecoration.offsetY" :active="true" @click="openDecoration(avatarDecoration, i)" /> @@ -66,6 +68,8 @@ function openDecoration(avatarDecoration, index?: number) { id: avatarDecoration.id, angle: payload.angle, flipH: payload.flipH, + offsetX: payload.offsetX, + offsetY: payload.offsetY, }; const update = [...$i.avatarDecorations, decoration]; await os.apiWithDialog('i/update', { @@ -78,6 +82,8 @@ function openDecoration(avatarDecoration, index?: number) { id: avatarDecoration.id, angle: payload.angle, flipH: payload.flipH, + offsetX: payload.offsetX, + offsetY: payload.offsetY, }; const update = [...$i.avatarDecorations]; update[index] = decoration; |