mirror of
https://github.com/sim1222/misskey.git
synced 2025-04-29 02:37:22 +09:00
feat: admin/mod emoji import contextMenu
This commit is contained in:
parent
45688dfafd
commit
9f409e3ae0
@ -6,6 +6,7 @@
|
||||
class="hkzvhatu _button"
|
||||
:class="{ reacted: note.myReaction == reaction, canToggle }"
|
||||
@click="toggleReaction()"
|
||||
@contextmenu.stop="onContextmenu"
|
||||
>
|
||||
<XReactionIcon class="icon" :reaction="reaction" :custom-emojis="note.emojis"/>
|
||||
<span class="count">{{ count }}</span>
|
||||
@ -20,6 +21,7 @@ import XReactionIcon from '@/components/reaction-icon.vue';
|
||||
import * as os from '@/os';
|
||||
import { useTooltip } from '@/scripts/use-tooltip';
|
||||
import { $i } from '@/account';
|
||||
import { openReactionImportMenu } from '@/scripts/reactionImportMenu';
|
||||
|
||||
const props = defineProps<{
|
||||
reaction: string;
|
||||
@ -88,6 +90,11 @@ useTooltip(buttonRef, async (showing) => {
|
||||
targetElement: buttonRef.value,
|
||||
}, {}, 'closed');
|
||||
}, 100);
|
||||
|
||||
const onContextmenu = (e: MouseEvent) => {
|
||||
e.preventDefault();
|
||||
openReactionImportMenu(e, props.reaction);
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
113
packages/client/src/scripts/reactionImportMenu.ts
Normal file
113
packages/client/src/scripts/reactionImportMenu.ts
Normal file
@ -0,0 +1,113 @@
|
||||
import { defineAsyncComponent } from 'vue';
|
||||
import { $i } from '@/account';
|
||||
import { i18n } from '@/i18n';
|
||||
import * as os from '@/os';
|
||||
import copyToClipboard from '@/scripts/copy-to-clipboard';
|
||||
import { MenuItem } from '@/types/menu';
|
||||
|
||||
export async function openReactionImportMenu(ev: MouseEvent, reaction: string): Promise<void> {
|
||||
if (!reaction) return;
|
||||
|
||||
const host = reaction.match(/(?<=@).*\.*(?=:)/g)?.[0];
|
||||
const name = reaction.match(/(?<=:).*(?=@.*\.*(?=:))/g)?.[0];
|
||||
const isLocal = (host === null || host === '.');
|
||||
const isCustom = reaction.startsWith(':');
|
||||
|
||||
const getEmojiObject = (emojiId): Promise<Record<string, any> | null> => new Promise<Record<string, any> | null>(async resolve => {
|
||||
const sinceId = await os.api('admin/emoji/list', {
|
||||
limit: 1,
|
||||
untilId: emojiId.id,
|
||||
});
|
||||
|
||||
if (!sinceId || !sinceId[0] || !sinceId[0].id) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
const id = await os.api('admin/emoji/list', {
|
||||
limit: 1,
|
||||
sinceId: sinceId[0].id,
|
||||
});
|
||||
|
||||
if (!id || !id[0]) {
|
||||
resolve(null);
|
||||
return;
|
||||
}
|
||||
|
||||
resolve(id[0]);
|
||||
});
|
||||
|
||||
const getEmojiId = async (): Promise<string | null> => {
|
||||
if (isLocal) return null;
|
||||
if (!host || !name) return null;
|
||||
|
||||
const resList: Record<string, any>[] = await os.api('admin/emoji/list-remote', {
|
||||
host,
|
||||
query: name,
|
||||
limit: 100,
|
||||
});
|
||||
|
||||
const emojiId = await resList.find(emoji => emoji.name === name && emoji.host === host)?.id;
|
||||
|
||||
return emojiId;
|
||||
};
|
||||
|
||||
const importEmoji = async (): Promise<void> => {
|
||||
const emojiId = await getEmojiId();
|
||||
if (!await emojiId) return;
|
||||
os.api('admin/emoji/copy', {
|
||||
emojiId: emojiId,
|
||||
}).then(async emoji => os.popup(defineAsyncComponent(() => import('@/pages/admin/emoji-edit-dialog.vue')), {
|
||||
emoji: await getEmojiObject(emoji),
|
||||
}));
|
||||
};
|
||||
|
||||
const menuItems: MenuItem[] = [{
|
||||
type: 'label',
|
||||
text: reaction,
|
||||
}, {
|
||||
type: 'button',
|
||||
icon: 'fas fa-copy',
|
||||
text: i18n.ts.copy,
|
||||
action: (): void => {
|
||||
copyToClipboard(isCustom ? `:${name}:` : reaction);
|
||||
},
|
||||
}];
|
||||
|
||||
const emojiId = await getEmojiId() ? await getEmojiId() : reaction;
|
||||
|
||||
if (
|
||||
isCustom &&
|
||||
emojiId &&
|
||||
($i?.isAdmin || $i?.isModerator) &&
|
||||
!isLocal
|
||||
) {
|
||||
menuItems.push({
|
||||
type: 'button',
|
||||
icon: 'fas fa-download',
|
||||
text: i18n.ts.import,
|
||||
action: async () => {
|
||||
const duplication: boolean = await os.api('meta').then(meta => {
|
||||
const emojis = meta.emojis;
|
||||
return emojis.some((emoji) => {
|
||||
return (emoji.name === name);
|
||||
});
|
||||
});
|
||||
|
||||
if (await duplication) {
|
||||
os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.ts.duplicateEmoji,
|
||||
}).then(res => {
|
||||
if (res.canceled) return;
|
||||
importEmoji();
|
||||
});
|
||||
} else {
|
||||
importEmoji();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
os.contextMenu(menuItems, ev);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user