From 8b53982349114f77e678c2b95346df6250a53872 Mon Sep 17 00:00:00 2001 From: kakkokari-gtyih <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 11 Aug 2024 18:26:14 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=BF=80=E3=81=97=E3=81=84=E5=8B=95?= =?UTF-8?q?=E3=81=8D=E3=82=92=E5=90=AB=E3=82=80=E3=82=AB=E3=82=B9=E3=82=BF?= =?UTF-8?q?=E3=83=A0=E7=B5=B5=E6=96=87=E5=AD=97=E3=82=92=E6=89=8B=E5=8B=95?= =?UTF-8?q?=E3=81=A7=E6=8C=87=E5=AE=9A=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/index.d.ts | 14 ++++++++++++++ locales/ja-JP.yml | 5 +++++ .../migration/1723367092501-EmojiHasMovement.js | 11 +++++++++++ packages/backend/src/core/CustomEmojiService.ts | 4 ++++ .../src/core/entities/EmojiEntityService.ts | 4 ++++ packages/backend/src/models/Emoji.ts | 5 +++++ packages/backend/src/models/json-schema/emoji.ts | 10 ++++++++++ .../ImportCustomEmojisProcessorService.ts | 1 + .../src/server/api/endpoints/admin/emoji/add.ts | 2 ++ .../src/server/api/endpoints/admin/emoji/copy.ts | 1 + .../src/server/api/endpoints/admin/emoji/update.ts | 2 ++ .../src/components/MkCustomEmojiDetailedDialog.vue | 4 ++++ .../src/components/global/MkCustomEmoji.vue | 10 +++++++++- packages/frontend/src/hana/store.ts | 12 ++++++++++++ packages/frontend/src/pages/emoji-edit-dialog.vue | 3 +++ packages/misskey-js/src/autogen/types.ts | 4 ++++ 16 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 packages/backend/migration/1723367092501-EmojiHasMovement.js create mode 100644 packages/frontend/src/hana/store.ts diff --git a/locales/index.d.ts b/locales/index.d.ts index 91d36a14a627..a6f634d3fd4c 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -10172,6 +10172,20 @@ export interface Locale extends ILocale { */ "native": string; }; + "_hana": { + /** + * 激しい動きあり + */ + "hasMovement": string; + /** + * 激しい動きを含むカスタム絵文字のアニメーションだけを止める + */ + "stopAnimatingCustomEmojisWithMovement": string; + /** + * 激しい動きを含むとモデレーターが判断したものだけ、アニメーションを停止します。その他の絵文字(動きがゆるいもの等)は通常通りアニメーションされます。絵文字のアニメーションを完全に停止させたい場合は、「アニメーション画像を再生しない」を利用してください。 + */ + "stopAnimatingCustomEmojisWithMovementDescription": string; + }; } declare const locales: { [lang: string]: Locale; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index b493183974cc..9bd110b885f9 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2712,3 +2712,8 @@ _contextMenu: app: "アプリケーション" appWithShift: "Shiftキーでアプリケーション" native: "ブラウザのUI" + +_hana: + hasMovement: "激しい動きあり" + stopAnimatingCustomEmojisWithMovement: "激しい動きを含むカスタム絵文字のアニメーションだけを止める" + stopAnimatingCustomEmojisWithMovementDescription: "激しい動きを含むとモデレーターが判断したものだけ、アニメーションを停止します。その他の絵文字(動きがゆるいもの等)は通常通りアニメーションされます。絵文字のアニメーションを完全に停止させたい場合は、「アニメーション画像を再生しない」を利用してください。" diff --git a/packages/backend/migration/1723367092501-EmojiHasMovement.js b/packages/backend/migration/1723367092501-EmojiHasMovement.js new file mode 100644 index 000000000000..67175ac12b8c --- /dev/null +++ b/packages/backend/migration/1723367092501-EmojiHasMovement.js @@ -0,0 +1,11 @@ +export class EmojiHasMovement1723367092501 { + name = 'EmojiHasMovement1723367092501' + + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "emoji" ADD "hasMovement" boolean NOT NULL DEFAULT false`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "emoji" DROP COLUMN "hasMovement"`); + } +} diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index 7e11b9cdca15..ac0c4fee27d5 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -67,6 +67,7 @@ export class CustomEmojiService implements OnApplicationShutdown { isSensitive: boolean; localOnly: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction: MiRole['id'][]; + hasMovement: boolean; }, moderator?: MiUser): Promise { const emoji = await this.emojisRepository.insertOne({ id: this.idService.gen(), @@ -82,6 +83,7 @@ export class CustomEmojiService implements OnApplicationShutdown { isSensitive: data.isSensitive, localOnly: data.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction, + hasMovement: data.hasMovement, }); if (data.host == null) { @@ -112,6 +114,7 @@ export class CustomEmojiService implements OnApplicationShutdown { isSensitive?: boolean; localOnly?: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction?: MiRole['id'][]; + hasMovement?: boolean; }, moderator?: MiUser): Promise { const emoji = await this.emojisRepository.findOneByOrFail({ id: id }); const sameNameEmoji = await this.emojisRepository.findOneBy({ name: data.name, host: IsNull() }); @@ -129,6 +132,7 @@ export class CustomEmojiService implements OnApplicationShutdown { publicUrl: data.driveFile != null ? (data.driveFile.webpublicUrl ?? data.driveFile.url) : undefined, type: data.driveFile != null ? (data.driveFile.webpublicType ?? data.driveFile.type) : undefined, roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction ?? undefined, + hasMovement: data.hasMovement, }); this.localEmojisCache.refresh(); diff --git a/packages/backend/src/core/entities/EmojiEntityService.ts b/packages/backend/src/core/entities/EmojiEntityService.ts index 841bd731c0cb..6a02c91f539f 100644 --- a/packages/backend/src/core/entities/EmojiEntityService.ts +++ b/packages/backend/src/core/entities/EmojiEntityService.ts @@ -34,6 +34,8 @@ export class EmojiEntityService { localOnly: emoji.localOnly ? true : undefined, isSensitive: emoji.isSensitive ? true : undefined, roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length > 0 ? emoji.roleIdsThatCanBeUsedThisEmojiAsReaction : undefined, + + hasMovement: emoji.hasMovement, }; } @@ -62,6 +64,8 @@ export class EmojiEntityService { isSensitive: emoji.isSensitive, localOnly: emoji.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction, + + hasMovement: emoji.hasMovement, }; } diff --git a/packages/backend/src/models/Emoji.ts b/packages/backend/src/models/Emoji.ts index d62b6e9f6f19..903b46d60801 100644 --- a/packages/backend/src/models/Emoji.ts +++ b/packages/backend/src/models/Emoji.ts @@ -81,4 +81,9 @@ export class MiEmoji { array: true, length: 128, default: '{}', }) public roleIdsThatCanBeUsedThisEmojiAsReaction: string[]; + + @Column('boolean', { + default: false, + }) + public hasMovement: boolean; } diff --git a/packages/backend/src/models/json-schema/emoji.ts b/packages/backend/src/models/json-schema/emoji.ts index 62686ad5ae62..d3737ffde0ee 100644 --- a/packages/backend/src/models/json-schema/emoji.ts +++ b/packages/backend/src/models/json-schema/emoji.ts @@ -44,6 +44,11 @@ export const packedEmojiSimpleSchema = { format: 'id', }, }, + + hasMovement: { + type: 'boolean', + optional: true, nullable: false, + }, }, } as const; @@ -102,5 +107,10 @@ export const packedEmojiDetailedSchema = { format: 'id', }, }, + + hasMovement: { + type: 'boolean', + optional: true, nullable: false, + }, }, } as const; diff --git a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts index 171809d25c3a..60169a610376 100644 --- a/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportCustomEmojisProcessorService.ts @@ -103,6 +103,7 @@ export class ImportCustomEmojisProcessorService { isSensitive: emojiInfo.isSensitive, localOnly: emojiInfo.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: [], + hasMovement: emojiInfo.hasMovement, }); } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts index 796f273330fb..65415cdff5e4 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts @@ -56,6 +56,7 @@ export const paramDef = { roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: { type: 'string', } }, + hasMovement: { type: 'boolean' }, }, required: ['name', 'fileId'], } as const; @@ -88,6 +89,7 @@ export default class extends Endpoint { // eslint- isSensitive: ps.isSensitive ?? false, localOnly: ps.localOnly ?? false, roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [], + hasMovement: ps.hasMovement ?? false, }, me); return this.emojiEntityService.packDetailed(emoji); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts index 975f892df9b6..5249c2289531 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts @@ -95,6 +95,7 @@ export default class extends Endpoint { // eslint- isSensitive: emoji.isSensitive, localOnly: emoji.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction, + hasMovement: emoji.hasMovement, }, me); return this.emojiEntityService.packDetailed(addedEmoji); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index 22609a16a39a..4bf9ec3d37e7 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -56,6 +56,7 @@ export const paramDef = { roleIdsThatCanBeUsedThisEmojiAsReaction: { type: 'array', items: { type: 'string', } }, + hasMovement: { type: 'boolean' }, }, anyOf: [ { required: ['id'] }, @@ -103,6 +104,7 @@ export default class extends Endpoint { // eslint- isSensitive: ps.isSensitive, localOnly: ps.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction, + hasMovement: ps.hasMovement, }, me); }); } diff --git a/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue b/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue index c7f128872929..62a1301f3370 100644 --- a/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue +++ b/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue @@ -39,6 +39,10 @@ SPDX-License-Identifier: AGPL-3.0-only + + + + diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue index dff56cd7f0d7..09c00baf7f05 100644 --- a/packages/frontend/src/components/global/MkCustomEmoji.vue +++ b/packages/frontend/src/components/global/MkCustomEmoji.vue @@ -28,6 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only import { computed, inject, ref } from 'vue'; import { getProxiedImageUrl, getStaticImageUrl } from '@/scripts/media-proxy.js'; import { defaultStore } from '@/store.js'; +import { hanaStore } from '@/hana/store.js'; import { customEmojisMap } from '@/custom-emojis.js'; import * as os from '@/os.js'; import { misskeyApiGet } from '@/scripts/misskey-api.js'; @@ -63,6 +64,13 @@ const rawUrl = computed(() => { return props.host ? `/emoji/${customEmojiName.value}@${props.host}.webp` : `/emoji/${customEmojiName.value}.webp`; }); +const shouldStopAnimatingByHanaHasMovement = computed(() => { + return ( + hanaStore.reactiveState.stopAnimatingEmojisWithMovement.value && + customEmojisMap.get(customEmojiName.value)?.hasMovement + ); +}); + const url = computed(() => { if (rawUrl.value == null) return undefined; @@ -75,7 +83,7 @@ const url = computed(() => { false, true, ); - return defaultStore.reactiveState.disableShowingAnimatedImages.value + return (defaultStore.reactiveState.disableShowingAnimatedImages.value || shouldStopAnimatingByHanaHasMovement.value) ? getStaticImageUrl(proxied) : proxied; }); diff --git a/packages/frontend/src/hana/store.ts b/packages/frontend/src/hana/store.ts new file mode 100644 index 000000000000..c78e5db8c6d8 --- /dev/null +++ b/packages/frontend/src/hana/store.ts @@ -0,0 +1,12 @@ +import { markRaw } from 'vue'; +import { Storage } from '@/pizzax.js'; + +/** + * はなみすきー独自のデータ用 + */ +export const hanaStore = markRaw(new Storage('hanaMain', { + stopAnimatingEmojisWithMovement: { + where: 'device', + default: true, + }, +})); diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue index 853c1d6b0b5d..044a70d62099 100644 --- a/packages/frontend/src/pages/emoji-edit-dialog.vue +++ b/packages/frontend/src/pages/emoji-edit-dialog.vue @@ -68,6 +68,7 @@ SPDX-License-Identifier: AGPL-3.0-only isSensitive {{ i18n.ts.localOnly }} + {{ i18n.ts._hana.hasMovement }} {{ i18n.ts.delete }} @@ -108,6 +109,7 @@ const localOnly = ref(props.emoji ? props.emoji.localOnly : false); const roleIdsThatCanBeUsedThisEmojiAsReaction = ref(props.emoji ? props.emoji.roleIdsThatCanBeUsedThisEmojiAsReaction : []); const rolesThatCanBeUsedThisEmojiAsReaction = ref([]); const file = ref(); +const hasMovement = ref(props.emoji ? props.emoji.hasMovement : false); watch(roleIdsThatCanBeUsedThisEmojiAsReaction, async () => { rolesThatCanBeUsedThisEmojiAsReaction.value = (await Promise.all(roleIdsThatCanBeUsedThisEmojiAsReaction.value.map((id) => misskeyApi('admin/roles/show', { roleId: id }).catch(() => null)))).filter(x => x != null); @@ -153,6 +155,7 @@ async function done() { isSensitive: isSensitive.value, localOnly: localOnly.value, roleIdsThatCanBeUsedThisEmojiAsReaction: rolesThatCanBeUsedThisEmojiAsReaction.value.map(x => x.id), + hasMovement: hasMovement.value, }; if (file.value) { diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 6d2f78776729..a3fa9985efb7 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4641,6 +4641,7 @@ export type components = { localOnly?: boolean; isSensitive?: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction?: string[]; + hasMovement?: boolean; }; EmojiDetailed: { /** Format: id */ @@ -4655,6 +4656,7 @@ export type components = { isSensitive: boolean; localOnly: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction: string[]; + hasMovement?: boolean; }; Flash: { /** @@ -6956,6 +6958,7 @@ export type operations = { isSensitive?: boolean; localOnly?: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction?: string[]; + hasMovement?: boolean; }; }; }; @@ -7586,6 +7589,7 @@ export type operations = { isSensitive?: boolean; localOnly?: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction?: string[]; + hasMovement?: boolean; }; }; };