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 957134c1ad..ea91be8dca 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -96,10 +96,14 @@ export default class extends Endpoint { // eslint- emojiId = emoji.id; } + let categoryNfc: string|null|undefined = ps.category?.normalize('NFC'); + // stop ?. from turning a null into an undefined + if (ps.category === null) categoryNfc = null; + await this.customEmojiService.update(emojiId, { driveFile, name: nameNfc, - category: ps.category?.normalize('NFC'), + category: categoryNfc, aliases: ps.aliases?.map(a => a.normalize('NFC')), license: ps.license, isSensitive: ps.isSensitive, diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index b42c2f1503..7de29f11e3 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -216,6 +216,7 @@ SPDX-License-Identifier: AGPL-3.0-only + diff --git a/packages/frontend/src/pages/settings/import-export.vue b/packages/frontend/src/pages/settings/import-export.vue index e000c608fe..1f23b6c9d6 100644 --- a/packages/frontend/src/pages/settings/import-export.vue +++ b/packages/frontend/src/pages/settings/import-export.vue @@ -11,7 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.export }} + {{ i18n.ts.export }} @@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.import }} + {{ i18n.ts.import }} @@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.export }} + {{ i18n.ts.export }} @@ -41,7 +41,7 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.export }} + {{ i18n.ts.export }} @@ -57,7 +57,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._exportOrImport.excludeInactiveUsers }} - {{ i18n.ts.export }} + {{ i18n.ts.export }} @@ -66,7 +66,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._exportOrImport.withReplies }} - {{ i18n.ts.import }} + {{ i18n.ts.import }} @@ -76,12 +76,12 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.export }} + {{ i18n.ts.export }} - {{ i18n.ts.import }} + {{ i18n.ts.import }} @@ -91,12 +91,12 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.export }} + {{ i18n.ts.export }} - {{ i18n.ts.import }} + {{ i18n.ts.import }} @@ -106,12 +106,12 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.export }} + {{ i18n.ts.export }} - {{ i18n.ts.import }} + {{ i18n.ts.import }} @@ -121,12 +121,12 @@ SPDX-License-Identifier: AGPL-3.0-only - {{ i18n.ts.export }} + {{ i18n.ts.export }} - {{ i18n.ts.import }} + {{ i18n.ts.import }} @@ -152,6 +152,7 @@ const excludeMutingUsers = ref(false); const excludeInactiveUsers = ref(false); const noteType = ref(null); const withReplies = ref(defaultStore.state.defaultWithReplies); +const disableButtons = ref(false); const onExportSuccess = () => { os.alert({ @@ -174,76 +175,110 @@ const onError = (ev) => { }); }; +// HACK: purely theatrical lockout delay when the file picker is opened, because we actually can't tell +// if it was canceled, and file upload can take a while. this is stupid and gets in the user's way if +// they accidentally cancel out, but it's better than them spamming the import button 50 times +const tempDisable = () => { + disableButtons.value = true; + return setTimeout(() => { disableButtons.value = false; }, 10000); +}; + const exportNotes = () => { - misskeyApi('i/export-notes', {}).then(onExportSuccess).catch(onError); + disableButtons.value = true; + misskeyApi('i/export-notes', {}).then(onExportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const exportFavorites = () => { - misskeyApi('i/export-favorites', {}).then(onExportSuccess).catch(onError); + disableButtons.value = true; + misskeyApi('i/export-favorites', {}).then(onExportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const exportClips = () => { - misskeyApi('i/export-clips', {}).then(onExportSuccess).catch(onError); + disableButtons.value = true; + misskeyApi('i/export-clips', {}).then(onExportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const exportFollowing = () => { + disableButtons.value = true; misskeyApi('i/export-following', { excludeMuting: excludeMutingUsers.value, excludeInactive: excludeInactiveUsers.value, }) - .then(onExportSuccess).catch(onError); + .then(onExportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const exportBlocking = () => { - misskeyApi('i/export-blocking', {}).then(onExportSuccess).catch(onError); + disableButtons.value = true; + misskeyApi('i/export-blocking', {}).then(onExportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const exportUserLists = () => { - misskeyApi('i/export-user-lists', {}).then(onExportSuccess).catch(onError); + disableButtons.value = true; + misskeyApi('i/export-user-lists', {}).then(onExportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const exportMuting = () => { - misskeyApi('i/export-mute', {}).then(onExportSuccess).catch(onError); + disableButtons.value = true; + misskeyApi('i/export-mute', {}).then(onExportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const exportAntennas = () => { - misskeyApi('i/export-antennas', {}).then(onExportSuccess).catch(onError); + disableButtons.value = true; + misskeyApi('i/export-antennas', {}).then(onExportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const importFollowing = async (ev) => { + const timer = tempDisable(); const file = await selectFile(ev.currentTarget ?? ev.target); + clearTimeout(timer); + disableButtons.value = true; misskeyApi('i/import-following', { fileId: file.id, withReplies: withReplies.value, - }).then(onImportSuccess).catch(onError); + }).then(onImportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const importNotes = async (ev) => { + const timer = tempDisable(); const file = await selectFile(ev.currentTarget ?? ev.target); + clearTimeout(timer); + disableButtons.value = true; misskeyApi('i/import-notes', { fileId: file.id, type: noteType.value, - }).then(onImportSuccess).catch(onError); + }).then(onImportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const importUserLists = async (ev) => { + const timer = tempDisable(); const file = await selectFile(ev.currentTarget ?? ev.target); - misskeyApi('i/import-user-lists', { fileId: file.id }).then(onImportSuccess).catch(onError); + clearTimeout(timer); + disableButtons.value = true; + misskeyApi('i/import-user-lists', { fileId: file.id }).then(onImportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const importMuting = async (ev) => { + const timer = tempDisable(); const file = await selectFile(ev.currentTarget ?? ev.target); - misskeyApi('i/import-muting', { fileId: file.id }).then(onImportSuccess).catch(onError); + clearTimeout(timer); + disableButtons.value = true; + misskeyApi('i/import-muting', { fileId: file.id }).then(onImportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const importBlocking = async (ev) => { + const timer = tempDisable(); const file = await selectFile(ev.currentTarget ?? ev.target); - misskeyApi('i/import-blocking', { fileId: file.id }).then(onImportSuccess).catch(onError); + clearTimeout(timer); + disableButtons.value = true; + misskeyApi('i/import-blocking', { fileId: file.id }).then(onImportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const importAntennas = async (ev) => { + const timer = tempDisable(); const file = await selectFile(ev.currentTarget ?? ev.target); - misskeyApi('i/import-antennas', { fileId: file.id }).then(onImportSuccess).catch(onError); + clearTimeout(timer); + disableButtons.value = true; + misskeyApi('i/import-antennas', { fileId: file.id }).then(onImportSuccess).catch(onError).finally(() => { disableButtons.value = false; }); }; const headerActions = computed(() => []); diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index 67a6e493a4..aa7e081db1 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -317,7 +317,7 @@ export const defaultStore = markRaw(new Storage('base', { }, emojiStyle: { where: 'device', - default: 'twemoji', // twemoji / fluentEmoji / native + default: 'fluentEmoji', // twemoji / fluentEmoji / native }, menuStyle: { where: 'device', diff --git a/packages/frontend/src/style.scss b/packages/frontend/src/style.scss index 2eebfdd1a3..8eb287d238 100644 --- a/packages/frontend/src/style.scss +++ b/packages/frontend/src/style.scss @@ -110,6 +110,9 @@ html { } } + &.f--1 { + font-size: 12.5px; + } &.f-1 { font-size: 15px; }