diff --git a/CHANGELOG.md b/CHANGELOG.md index a51204781944..4f7389c31c16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -177,6 +177,7 @@ ### Client - Enhance: TLの返信表示オプションを記憶するように - Enhance: 投稿されてから時間が経過しているノートであることを視覚的に分かりやすく +- Feat: 絵文字ピッカーのカテゴリに「/」を入れることでフォルダ分け表示できるように ### Server - Enhance: タイムライン取得時のパフォーマンスを向上 diff --git a/locales/index.d.ts b/locales/index.d.ts index 402c2413f882..a8f54e2e18e7 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -314,6 +314,7 @@ export interface Locale { "createFolder": string; "renameFolder": string; "deleteFolder": string; + "folder": string; "addFile": string; "emptyDrive": string; "emptyFolder": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 2b2f05aa8829..04fb1f947d55 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -311,6 +311,7 @@ folderName: "フォルダー名" createFolder: "フォルダーを作成" renameFolder: "フォルダー名を変更" deleteFolder: "フォルダーを削除" +folder: "フォルダー" addFile: "ファイルを追加" emptyDrive: "ドライブは空です" emptyFolder: "フォルダーは空です" diff --git a/packages/frontend/src/components/MkEmojiPicker.section.vue b/packages/frontend/src/components/MkEmojiPicker.section.vue index 08297ea5baef..35de9bbb5e77 100644 --- a/packages/frontend/src/components/MkEmojiPicker.section.vue +++ b/packages/frontend/src/components/MkEmojiPicker.section.vue @@ -5,9 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 5b420c499e13..603f676d5d96 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -73,18 +73,20 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.customEmojis }}
- {{ category || i18n.ts.other }} + {{ child.value || i18n.ts.other }}
{{ i18n.ts.emoji }}
- {{ category }} + {{ category }}
@@ -100,7 +102,14 @@ SPDX-License-Identifier: AGPL-3.0-only import { ref, shallowRef, computed, watch, onMounted } from 'vue'; import * as Misskey from 'misskey-js'; import XSection from '@/components/MkEmojiPicker.section.vue'; -import { emojilist, emojiCharByCategory, UnicodeEmojiDef, unicodeEmojiCategories as categories, getEmojiName } from '@/scripts/emojilist.js'; +import { + emojilist, + emojiCharByCategory, + UnicodeEmojiDef, + unicodeEmojiCategories as categories, + getEmojiName, + CustomEmojiFolderTree +} from '@/scripts/emojilist.js'; import MkRippleEffect from '@/components/MkRippleEffect.vue'; import * as os from '@/os.js'; import { isTouchUsing } from '@/scripts/touch.js'; @@ -144,6 +153,35 @@ const searchResultCustom = ref([]); const searchResultUnicode = ref([]); const tab = ref<'index' | 'custom' | 'unicode' | 'tags'>('index'); +const customEmojiFolderRoot: CustomEmojiFolderTree = { value: "", category: "", children: [] }; + +function parseAndMergeCategories(input: string, root: CustomEmojiFolderTree): CustomEmojiFolderTree { + const parts = input.split('/').map(p => p.trim()); + let currentNode: CustomEmojiFolderTree = root; + + for (const part of parts) { + let existingNode = currentNode.children.find((node) => node.value === part); + + if (!existingNode) { + const newNode: CustomEmojiFolderTree = { value: part, category: input, children: [] }; + currentNode.children.push(newNode); + existingNode = newNode; + } + + currentNode = existingNode; + } + + return currentNode; +} + +customEmojiCategories.value.forEach(ec => { + if (ec !== null) { + parseAndMergeCategories(ec, customEmojiFolderRoot); + } +}); + +parseAndMergeCategories('', customEmojiFolderRoot); + watch(q, () => { if (emojisEl.value) emojisEl.value.scrollTop = 0; @@ -572,8 +610,7 @@ defineExpose({ position: sticky; top: 0; left: 0; - height: 32px; - line-height: 32px; + line-height: 28px; z-index: 1; padding: 0 8px; font-size: 12px; diff --git a/packages/frontend/src/scripts/emojilist.ts b/packages/frontend/src/scripts/emojilist.ts index 4159da84c883..8885bf4b7f5f 100644 --- a/packages/frontend/src/scripts/emojilist.ts +++ b/packages/frontend/src/scripts/emojilist.ts @@ -43,3 +43,9 @@ export function getEmojiName(char: string): string | null { return emojilist[idx].name; } } + +export interface CustomEmojiFolderTree { + value: string; + category: string; + children: CustomEmojiFolderTree[]; +}