enhance: アイコンデコレーションの位置を微調整できるように
This commit is contained in:
		
							parent
							
								
									239507d7d6
								
							
						
					
					
						commit
						417852779f
					
				
					 8 changed files with 45 additions and 3 deletions
				
			
		| 
						 | 
				
			
			@ -31,6 +31,7 @@
 | 
			
		|||
- Feat: モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能を追加 (cherry-pick from https://github.com/TeamNijimiss/misskey/commit/e0eb5a752f6e5616d6312bb7c9790302f9dbff83)
 | 
			
		||||
- Feat: TL上からノートが見えなくなるワードミュートであるハードミュートを追加
 | 
			
		||||
- Enhance: アイコンデコレーションを複数設定できるように
 | 
			
		||||
- Enhance: アイコンデコレーションの位置を微調整できるように
 | 
			
		||||
- Fix: MFM `$[unixtime ]` に不正な値を入力した際に発生する各種エラーを修正
 | 
			
		||||
 | 
			
		||||
### Client
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -143,8 +143,10 @@ export class MiUser {
 | 
			
		|||
	})
 | 
			
		||||
	public avatarDecorations: {
 | 
			
		||||
		id: string;
 | 
			
		||||
		angle: number;
 | 
			
		||||
		flipH: boolean;
 | 
			
		||||
		angle?: number;
 | 
			
		||||
		flipH?: boolean;
 | 
			
		||||
		offsetX?: number;
 | 
			
		||||
		offsetY?: number;
 | 
			
		||||
	}[];
 | 
			
		||||
 | 
			
		||||
	@Index()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
				}));
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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, () => {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue