summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2024-01-13 15:45:25 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2024-01-13 15:45:25 +0900
commit79370aaee24d5613c3042a80d4c9bb0881a34db2 (patch)
treee0cbb1b450b3d9ccdf17b62243891aae30ce0959
parenttweak (diff)
parentFeat(frontend): リアクション・ノート内絵文字・/about#emojisで... (diff)
downloadmisskey-79370aaee24d5613c3042a80d4c9bb0881a34db2.tar.gz
misskey-79370aaee24d5613c3042a80d4c9bb0881a34db2.tar.bz2
misskey-79370aaee24d5613c3042a80d4c9bb0881a34db2.zip
Merge branch 'develop' of https://github.com/misskey-dev/misskey into develop
-rw-r--r--CHANGELOG.md1
-rw-r--r--packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue102
-rw-r--r--packages/frontend/src/components/MkReactionsViewer.reaction.vue18
-rw-r--r--packages/frontend/src/components/global/MkCustomEmoji.vue16
-rw-r--r--packages/frontend/src/pages/emojis.emoji.vue23
5 files changed, 146 insertions, 14 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 13ad3a3508..a5e1f27b7d 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@
### Client
- Feat: 新しいゲームを追加
+- Feat: 絵文字の詳細ダイアログを追加
- Enhance: ハッシュタグ入力時に、本文の末尾の行に何も書かれていない場合は新たにスペースを追加しないように
- Enhance: チャンネルノートのピン留めをノートのメニューからできるように
- Enhance: 管理者の場合はAPI tokenの発行画面で管理機能に関する権限を付与できるように
diff --git a/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue b/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue
new file mode 100644
index 0000000000..c53bbca37c
--- /dev/null
+++ b/packages/frontend/src/components/MkCustomEmojiDetailedDialog.vue
@@ -0,0 +1,102 @@
+<!--
+SPDX-FileCopyrightText: syuilo and other misskey contributors
+SPDX-License-Identifier: AGPL-3.0-only
+-->
+
+<template>
+ <MkModalWindow ref="dialogEl" @close="cancel()" @closed="$emit('closed')">
+ <template #header>:{{ emoji.name }}:</template>
+ <template #default>
+ <MkSpacer>
+ <div style="display: flex; flex-direction: column; gap: 1em;">
+ <div :class="$style.emojiImgWrapper">
+ <MkCustomEmoji :name="emoji.name" :normal="true" style="height: 100%;"></MkCustomEmoji>
+ </div>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.name }}</template>
+ <template #value>{{ emoji.name }}</template>
+ </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.tags }}</template>
+ <template #value>
+ <div v-if="emoji.aliases.length === 0">{{ i18n.ts.none }}</div>
+ <div v-else :class="$style.aliases">
+ <span v-for="alias in emoji.aliases" :key="alias" :class="$style.alias">
+ {{ alias }}
+ </span>
+ </div>
+ </template>
+ </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.category }}</template>
+ <template #value>{{ emoji.category ?? i18n.ts.none }}</template>
+ </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.sensitive }}</template>
+ <template #value>{{ emoji.isSensitive ? i18n.ts.yes : i18n.ts.no }}</template>
+ </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.localOnly }}</template>
+ <template #value>{{ emoji.localOnly ? i18n.ts.yes : i18n.ts.no }}</template>
+ </MkKeyValue>
+ <MkKeyValue>
+ <template #key>{{ i18n.ts.license }}</template>
+ <template #value>{{ emoji.license ?? i18n.ts.none }}</template>
+ </MkKeyValue>
+ <MkKeyValue :copy="emoji.url">
+ <template #key>{{ i18n.ts.emojiUrl }}</template>
+ <template #value>
+ <a :href="emoji.url" target="_blank">{{ emoji.url }}</a>
+ </template>
+ </MkKeyValue>
+ </div>
+ </MkSpacer>
+ </template>
+ </MkModalWindow>
+</template>
+
+<script lang="ts" setup>
+import * as Misskey from 'misskey-js';
+import { defineProps, shallowRef } from 'vue';
+import { i18n } from '@/i18n.js';
+import MkModalWindow from '@/components/MkModalWindow.vue';
+import MkKeyValue from '@/components/MkKeyValue.vue';
+const props = defineProps<{
+ emoji: Misskey.entities.EmojiDetailed,
+}>();
+const emit = defineEmits<{
+ (ev: 'ok', cropped: Misskey.entities.DriveFile): void;
+ (ev: 'cancel'): void;
+ (ev: 'closed'): void;
+}>();
+const dialogEl = shallowRef<InstanceType<typeof MkModalWindow>>();
+const cancel = () => {
+ emit('cancel');
+ dialogEl.value!.close();
+};
+</script>
+
+<style lang="scss" module>
+.emojiImgWrapper {
+ max-width: 100%;
+ height: 40cqh;
+ background-image: repeating-linear-gradient(45deg, transparent, transparent 8px, var(--X5) 8px, var(--X5) 14px);
+ border-radius: var(--radius);
+ margin: auto;
+ overflow-y: hidden;
+}
+
+.aliases {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 3px;
+}
+
+.alias {
+ display: inline-block;
+ padding: 3px 10px;
+ background-color: var(--X5);
+ border: solid 1px var(--divider);
+ border-radius: var(--radius);
+}
+</style>
diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
index 5ca09fa822..330e54f08a 100644
--- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
@@ -10,6 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
class="_button"
:class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: canToggle, [$style.small]: defaultStore.state.reactionsDisplaySize === 'small', [$style.large]: defaultStore.state.reactionsDisplaySize === 'large' }]"
@click="toggleReaction()"
+ @contextmenu.prevent.stop="menu"
>
<MkReactionIcon :class="defaultStore.state.limitWidthOfReaction ? $style.limitWidth : ''" :reaction="reaction" :emojiUrl="note.reactionEmojis[reaction.substring(1, reaction.length - 1)]"/>
<span :class="$style.count">{{ count }}</span>
@@ -21,6 +22,7 @@ import { computed, inject, onMounted, shallowRef, watch } from 'vue';
import * as Misskey from 'misskey-js';
import XDetails from '@/components/MkReactionsViewer.details.vue';
import MkReactionIcon from '@/components/MkReactionIcon.vue';
+import MkCustomEmojiDetailedDialog from './MkCustomEmojiDetailedDialog.vue';
import * as os from '@/os.js';
import { misskeyApi, misskeyApiGet } from '@/scripts/misskey-api.js';
import { useTooltip } from '@/scripts/use-tooltip.js';
@@ -98,6 +100,22 @@ async function toggleReaction() {
}
}
+async function menu(ev) {
+ if (!canToggle.value) return;
+ if (!props.reaction.includes(":")) return;
+ os.popupMenu([{
+ text: i18n.ts.info,
+ icon: 'ti ti-info-circle',
+ action: async () => {
+ os.popup(MkCustomEmojiDetailedDialog, {
+ emoji: await misskeyApiGet('emoji', {
+ name: props.reaction.replace(/:/g, '').replace(/@\./, ''),
+ }),
+ });
+ },
+ }], ev.currentTarget ?? ev.target);
+}
+
function anime() {
if (document.hidden) return;
if (!defaultStore.state.animation) return;
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
index dd3fe77251..b384e8afcb 100644
--- a/packages/frontend/src/components/global/MkCustomEmoji.vue
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -24,9 +24,11 @@ import { getProxiedImageUrl, getStaticImageUrl } from '@/scripts/media-proxy.js'
import { defaultStore } from '@/store.js';
import { customEmojisMap } from '@/custom-emojis.js';
import * as os from '@/os.js';
+import { misskeyApiGet } from '@/scripts/misskey-api.js';
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
import * as sound from '@/scripts/sound.js';
import { i18n } from '@/i18n.js';
+import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
const props = defineProps<{
name: string;
@@ -93,7 +95,19 @@ function onClick(ev: MouseEvent) {
react(`:${props.name}:`);
sound.playMisskeySfx('reaction');
},
- }] : [])], ev.currentTarget ?? ev.target);
+ }] : []), {
+ text: i18n.ts.info,
+ icon: 'ti ti-info-circle',
+ action: async () => {
+ os.popup(MkCustomEmojiDetailedDialog, {
+ emoji: await misskeyApiGet('emoji', {
+ name: customEmojiName.value,
+ }),
+ }, {
+ anchor: ev.target,
+ });
+ },
+ }], ev.currentTarget ?? ev.target);
}
}
</script>
diff --git a/packages/frontend/src/pages/emojis.emoji.vue b/packages/frontend/src/pages/emojis.emoji.vue
index ea6947bbba..faa7acdcb8 100644
--- a/packages/frontend/src/pages/emojis.emoji.vue
+++ b/packages/frontend/src/pages/emojis.emoji.vue
@@ -14,19 +14,15 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
<script lang="ts" setup>
-import { } from 'vue';
import * as os from '@/os.js';
+import * as Misskey from 'misskey-js';
import { misskeyApiGet } from '@/scripts/misskey-api.js';
import copyToClipboard from '@/scripts/copy-to-clipboard.js';
import { i18n } from '@/i18n.js';
+import MkCustomEmojiDetailedDialog from '@/components/MkCustomEmojiDetailedDialog.vue';
const props = defineProps<{
- emoji: {
- name: string;
- aliases: string[];
- category: string;
- url: string;
- };
+ emoji: Misskey.entities.EmojiSimple;
}>();
function menu(ev) {
@@ -43,12 +39,13 @@ function menu(ev) {
}, {
text: i18n.ts.info,
icon: 'ti ti-info-circle',
- action: () => {
- misskeyApiGet('emoji', { name: props.emoji.name }).then(res => {
- os.alert({
- type: 'info',
- text: `Name: ${res.name}\nAliases: ${res.aliases.join(' ')}\nCategory: ${res.category}\nisSensitive: ${res.isSensitive}\nlocalOnly: ${res.localOnly}\nLicense: ${res.license}\nURL: ${res.url}`,
- });
+ action: async () => {
+ os.popup(MkCustomEmojiDetailedDialog, {
+ emoji: await misskeyApiGet('emoji', {
+ name: props.emoji.name,
+ })
+ }, {
+ anchor: ev.target,
});
},
}], ev.currentTarget ?? ev.target);