refactor: 絵文字URLを引き回すのをやめる (#9423)
This commit is contained in:
parent
510e6ec7e9
commit
912791b3ab
28 changed files with 79 additions and 58 deletions
|
@ -6,8 +6,8 @@ import type { Packed } from '@/misc/schema.js';
|
|||
import type { } from '@/models/entities/Blocking.js';
|
||||
import type { User } from '@/models/entities/User.js';
|
||||
import type { Emoji } from '@/models/entities/Emoji.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import { UserEntityService } from './UserEntityService.js';
|
||||
|
||||
@Injectable()
|
||||
export class EmojiEntityService {
|
||||
|
@ -22,6 +22,7 @@ export class EmojiEntityService {
|
|||
@bindThis
|
||||
public async pack(
|
||||
src: Emoji['id'] | Emoji,
|
||||
opts: { omitUrl?: boolean } = {},
|
||||
): Promise<Packed<'Emoji'>> {
|
||||
const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src });
|
||||
|
||||
|
@ -32,15 +33,16 @@ export class EmojiEntityService {
|
|||
category: emoji.category,
|
||||
host: emoji.host,
|
||||
// ?? emoji.originalUrl してるのは後方互換性のため
|
||||
url: emoji.publicUrl ?? emoji.originalUrl,
|
||||
url: opts.omitUrl ? undefined : (emoji.publicUrl ?? emoji.originalUrl),
|
||||
};
|
||||
}
|
||||
|
||||
@bindThis
|
||||
public packMany(
|
||||
emojis: any[],
|
||||
opts: { omitUrl?: boolean } = {},
|
||||
) {
|
||||
return Promise.all(emojis.map(x => this.pack(x)));
|
||||
return Promise.all(emojis.map(x => this.pack(x, opts)));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ export const packedEmojiSchema = {
|
|||
},
|
||||
url: {
|
||||
type: 'string',
|
||||
optional: false, nullable: false,
|
||||
optional: true, nullable: false,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
|
|
@ -309,6 +309,7 @@ export const paramDef = {
|
|||
type: 'object',
|
||||
properties: {
|
||||
detail: { type: 'boolean', default: true },
|
||||
omitEmojiUrl: { type: 'boolean', default: false },
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
|
@ -390,7 +391,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
|
|||
backgroundImageUrl: instance.backgroundImageUrl,
|
||||
logoImageUrl: instance.logoImageUrl,
|
||||
maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため
|
||||
emojis: await this.emojiEntityService.packMany(emojis),
|
||||
emojis: await this.emojiEntityService.packMany(emojis, { omitUrl: ps.omitEmojiUrl }),
|
||||
defaultLightTheme: instance.defaultLightTheme,
|
||||
defaultDarkTheme: instance.defaultDarkTheme,
|
||||
ads: ads.map(ad => ({
|
||||
|
|
|
@ -26,7 +26,7 @@ import { PageEntityService } from '@/core/entities/PageEntityService.js';
|
|||
import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js';
|
||||
import { ClipEntityService } from '@/core/entities/ClipEntityService.js';
|
||||
import { ChannelEntityService } from '@/core/entities/ChannelEntityService.js';
|
||||
import type { ChannelsRepository, ClipsRepository, GalleryPostsRepository, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js';
|
||||
import type { ChannelsRepository, ClipsRepository, EmojisRepository, GalleryPostsRepository, NotesRepository, PagesRepository, UserProfilesRepository, UsersRepository } from '@/models/index.js';
|
||||
import { deepClone } from '@/misc/clone.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import manifest from './manifest.json' assert { type: 'json' };
|
||||
|
@ -70,6 +70,9 @@ export class ClientServerService {
|
|||
@Inject(DI.pagesRepository)
|
||||
private pagesRepository: PagesRepository,
|
||||
|
||||
@Inject(DI.emojisRepository)
|
||||
private emojisRepository: EmojisRepository,
|
||||
|
||||
private userEntityService: UserEntityService,
|
||||
private noteEntityService: NoteEntityService,
|
||||
private pageEntityService: PageEntityService,
|
||||
|
@ -217,6 +220,33 @@ export class ClientServerService {
|
|||
return reply.sendFile('/apple-touch-icon.png', staticAssets);
|
||||
});
|
||||
|
||||
fastify.get<{ Params: { path: string } }>('/emoji/:path(.*)', async (request, reply) => {
|
||||
const path = request.params.path;
|
||||
|
||||
if (!path.match(/^[a-zA-Z0-9\-_@\.]+?\.webp$/)) {
|
||||
reply.code(404);
|
||||
return;
|
||||
}
|
||||
|
||||
const name = path.split('@')[0].replace('.webp', '');
|
||||
const host = path.split('@')[1]?.replace('.webp', '');
|
||||
|
||||
const emoji = await this.emojisRepository.findOneBy({
|
||||
host: host == null ? IsNull() : host,
|
||||
name: name,
|
||||
});
|
||||
|
||||
if (emoji == null) {
|
||||
reply.code(404);
|
||||
return;
|
||||
}
|
||||
|
||||
reply.header('Content-Security-Policy', 'default-src \'none\'; style-src \'unsafe-inline\'');
|
||||
|
||||
// ?? emoji.originalUrl してるのは後方互換性のため
|
||||
return await reply.redirect(301, emoji.publicUrl ?? emoji.originalUrl);
|
||||
});
|
||||
|
||||
fastify.get<{ Params: { path: string } }>('/fluent-emoji/:path(.*)', async (request, reply) => {
|
||||
const path = request.params.path;
|
||||
|
||||
|
|
|
@ -37,20 +37,20 @@
|
|||
<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/>
|
||||
<div class="body">
|
||||
<p v-if="appearNote.cw != null" class="cw">
|
||||
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
|
||||
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i"/>
|
||||
<XCwButton v-model="showContent" :note="appearNote"/>
|
||||
</p>
|
||||
<div v-show="appearNote.cw == null || showContent" class="content" :class="{ collapsed, isLong }">
|
||||
<div class="text">
|
||||
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
||||
<MkA v-if="appearNote.replyId" class="reply" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
|
||||
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
|
||||
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i"/>
|
||||
<a v-if="appearNote.renote != null" class="rp">RN:</a>
|
||||
<div v-if="translating || translation" class="translation">
|
||||
<MkLoading v-if="translating" mini/>
|
||||
<div v-else class="translated">
|
||||
<b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}: </b>
|
||||
<Mfm :text="translation.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
|
||||
<Mfm :text="translation.text" :author="appearNote.user" :i="$i"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -48,20 +48,20 @@
|
|||
<div class="main">
|
||||
<div class="body">
|
||||
<p v-if="appearNote.cw != null" class="cw">
|
||||
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
|
||||
<Mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$i"/>
|
||||
<XCwButton v-model="showContent" :note="appearNote"/>
|
||||
</p>
|
||||
<div v-show="appearNote.cw == null || showContent" class="content">
|
||||
<div class="text">
|
||||
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
||||
<MkA v-if="appearNote.replyId" class="reply" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
|
||||
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
|
||||
<Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i"/>
|
||||
<a v-if="appearNote.renote != null" class="rp">RN:</a>
|
||||
<div v-if="translating || translation" class="translation">
|
||||
<MkLoading v-if="translating" mini/>
|
||||
<div v-else class="translated">
|
||||
<b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}: </b>
|
||||
<Mfm :text="translation.text" :author="appearNote.user" :i="$i" :custom-emojis="appearNote.emojis"/>
|
||||
<Mfm :text="translation.text" :author="appearNote.user" :i="$i"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<XNoteHeader class="header" :note="note" :mini="true"/>
|
||||
<div class="body">
|
||||
<p v-if="note.cw != null" class="cw">
|
||||
<Mfm v-if="note.cw != ''" class="text" :text="note.cw" :author="note.user" :i="$i" :custom-emojis="note.emojis"/>
|
||||
<Mfm v-if="note.cw != ''" class="text" :text="note.cw" :author="note.user" :i="$i"/>
|
||||
<XCwButton v-model="showContent" :note="note"/>
|
||||
</p>
|
||||
<div v-show="note.cw == null || showContent" class="content">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<XNoteHeader class="header" :note="note" :mini="true"/>
|
||||
<div class="body">
|
||||
<p v-if="note.cw != null" class="cw">
|
||||
<Mfm v-if="note.cw != ''" class="text" :text="note.cw" :author="note.user" :i="$i" :custom-emojis="note.emojis"/>
|
||||
<Mfm v-if="note.cw != ''" class="text" :text="note.cw" :author="note.user" :i="$i"/>
|
||||
<XCwButton v-model="showContent" :note="note"/>
|
||||
</p>
|
||||
<div v-show="note.cw == null || showContent" class="content">
|
||||
|
|
|
@ -34,31 +34,31 @@
|
|||
</header>
|
||||
<MkA v-if="notification.type === 'reaction'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<i class="ti ti-quote"></i>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full"/>
|
||||
<i class="ti ti-quote"></i>
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'renote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)">
|
||||
<i class="ti ti-quote"></i>
|
||||
<Mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.renote.emojis"/>
|
||||
<Mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="!full"/>
|
||||
<i class="ti ti-quote"></i>
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'reply'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full"/>
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'mention'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full"/>
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'quote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full"/>
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'pollVote'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<i class="ti ti-quote"></i>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full"/>
|
||||
<i class="ti ti-quote"></i>
|
||||
</MkA>
|
||||
<MkA v-if="notification.type === 'pollEnded'" class="text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
|
||||
<i class="ti ti-quote"></i>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :custom-emojis="notification.note.emojis"/>
|
||||
<Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full"/>
|
||||
<i class="ti ti-quote"></i>
|
||||
</MkA>
|
||||
<span v-if="notification.type === 'follow'" class="text" style="opacity: 0.6;">{{ i18n.ts.youGotNewFollower }}<div v-if="full"><MkFollowButton :user="notification.user" :full="true"/></div></span>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="backdrop" :style="{ 'width': `${showResult ? (choice.votes / total * 100) : 0}%` }"></div>
|
||||
<span>
|
||||
<template v-if="choice.isVoted"><i class="ti ti-check"></i></template>
|
||||
<Mfm :text="choice.text" :plain="true" :custom-emojis="note.emojis"/>
|
||||
<Mfm :text="choice.text" :plain="true"/>
|
||||
<span v-if="showResult" class="votes">({{ $t('_poll.votesCount', { n: choice.votes }) }})</span>
|
||||
</span>
|
||||
</li>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<MkEmoji :emoji="reaction" :custom-emojis="customEmojis || []" :is-reaction="true" :normal="true" :no-style="noStyle"/>
|
||||
<MkEmoji :emoji="reaction" :is-reaction="true" :normal="true" :no-style="noStyle"/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -7,7 +7,6 @@ import { } from 'vue';
|
|||
|
||||
const props = defineProps<{
|
||||
reaction: string;
|
||||
customEmojis?: any[]; // TODO
|
||||
noStyle?: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<MkTooltip ref="tooltip" :showing="showing" :target-element="targetElement" :max-width="340" @closed="emit('closed')">
|
||||
<div class="beeadbfb">
|
||||
<XReactionIcon :reaction="reaction" :custom-emojis="emojis" class="icon" :no-style="true"/>
|
||||
<XReactionIcon :reaction="reaction" class="icon" :no-style="true"/>
|
||||
<div class="name">{{ reaction.replace('@.', '') }}</div>
|
||||
</div>
|
||||
</MkTooltip>
|
||||
|
@ -15,7 +15,6 @@ import XReactionIcon from '@/components/MkReactionIcon.vue';
|
|||
defineProps<{
|
||||
showing: boolean;
|
||||
reaction: string;
|
||||
emojis: any[]; // TODO
|
||||
targetElement: HTMLElement;
|
||||
}>();
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<MkTooltip ref="tooltip" :showing="showing" :target-element="targetElement" :max-width="340" @closed="emit('closed')">
|
||||
<div class="bqxuuuey">
|
||||
<div class="reaction">
|
||||
<XReactionIcon :reaction="reaction" :custom-emojis="emojis" class="icon" :no-style="true"/>
|
||||
<XReactionIcon :reaction="reaction" class="icon" :no-style="true"/>
|
||||
<div class="name">{{ getReactionName(reaction) }}</div>
|
||||
</div>
|
||||
<div class="users">
|
||||
|
@ -27,7 +27,6 @@ defineProps<{
|
|||
reaction: string;
|
||||
users: any[]; // TODO
|
||||
count: number;
|
||||
emojis: any[]; // TODO
|
||||
targetElement: HTMLElement;
|
||||
}>();
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
:class="{ reacted: note.myReaction == reaction, canToggle }"
|
||||
@click="toggleReaction()"
|
||||
>
|
||||
<XReactionIcon class="icon" :reaction="reaction" :custom-emojis="note.emojis"/>
|
||||
<XReactionIcon class="icon" :reaction="reaction"/>
|
||||
<span class="count">{{ count }}</span>
|
||||
</button>
|
||||
</template>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<span v-if="note.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
|
||||
<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deleted }})</span>
|
||||
<MkA v-if="note.replyId" class="reply" :to="`/notes/${note.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
|
||||
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :custom-emojis="note.emojis"/>
|
||||
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i"/>
|
||||
<MkA v-if="note.renoteId" class="rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
|
||||
</div>
|
||||
<details v-if="note.files.length > 0">
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<span v-if="$i && $i.id !== user.id && user.isFollowed" class="followed">{{ $ts.followsYou }}</span>
|
||||
<div class="description">
|
||||
<div v-if="user.description" class="mfm">
|
||||
<Mfm :text="user.description" :author="user" :i="$i" :custom-emojis="user.emojis"/>
|
||||
<Mfm :text="user.description" :author="user" :i="$i"/>
|
||||
</div>
|
||||
<span v-else style="opacity: 0.7;">{{ i18n.ts.noAccountDescription }}</span>
|
||||
</div>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<p class="username"><MkAcct :user="user"/></p>
|
||||
</div>
|
||||
<div class="description">
|
||||
<Mfm v-if="user.description" :text="user.description" :author="user" :i="$i" :custom-emojis="user.emojis"/>
|
||||
<Mfm v-if="user.description" :text="user.description" :author="user" :i="$i"/>
|
||||
</div>
|
||||
<div class="status">
|
||||
<div>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<img v-if="customEmoji" class="mk-emoji custom" :class="{ normal, noStyle }" :src="url" :alt="alt" :title="alt" decoding="async"/>
|
||||
<img v-if="isCustom" class="mk-emoji custom" :class="{ normal, noStyle }" :src="url" :alt="alt" :title="alt" decoding="async"/>
|
||||
<img v-else-if="char && !useOsNativeEmojis" class="mk-emoji" :src="url" :alt="alt" decoding="async" @pointerenter="computeTitle"/>
|
||||
<span v-else-if="char && useOsNativeEmojis" :alt="alt" @pointerenter="computeTitle">{{ char }}</span>
|
||||
<span v-else>{{ emoji }}</span>
|
||||
|
@ -7,44 +7,40 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { computed } from 'vue';
|
||||
import { CustomEmoji } from 'misskey-js/built/entities';
|
||||
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||
import { char2twemojiFilePath, char2fluentEmojiFilePath } from '@/scripts/emoji-base';
|
||||
import { defaultStore } from '@/store';
|
||||
import { instance } from '@/instance';
|
||||
import { getEmojiName } from '@/scripts/emojilist';
|
||||
|
||||
const props = defineProps<{
|
||||
emoji: string;
|
||||
normal?: boolean;
|
||||
noStyle?: boolean;
|
||||
customEmojis?: CustomEmoji[];
|
||||
isReaction?: boolean;
|
||||
}>();
|
||||
|
||||
const char2path = defaultStore.state.emojiStyle === 'twemoji' ? char2twemojiFilePath : char2fluentEmojiFilePath;
|
||||
|
||||
const isCustom = computed(() => props.emoji.startsWith(':'));
|
||||
const customEmojiName = props.emoji.substr(1, props.emoji.length - 2);
|
||||
const char = computed(() => isCustom.value ? undefined : props.emoji);
|
||||
const useOsNativeEmojis = computed(() => defaultStore.state.emojiStyle === 'native' && !props.isReaction);
|
||||
const ce = computed(() => props.customEmojis ?? instance.emojis ?? []);
|
||||
const customEmoji = computed(() => isCustom.value ? ce.value.find(x => x.name === props.emoji.substr(1, props.emoji.length - 2)) : undefined);
|
||||
const url = computed(() => {
|
||||
if (char.value) {
|
||||
return char2path(char.value);
|
||||
} else {
|
||||
const rawUrl = (customEmoji.value as CustomEmoji).url;
|
||||
const rawUrl = '/emoji/' + customEmojiName + '.webp';
|
||||
return defaultStore.state.disableShowingAnimatedImages
|
||||
? getStaticImageUrl(rawUrl)
|
||||
: rawUrl;
|
||||
}
|
||||
});
|
||||
const alt = computed(() => customEmoji.value ? `:${customEmoji.value.name}:` : char.value);
|
||||
const alt = computed(() => isCustom.value ? `:${customEmojiName}:` : char.value);
|
||||
|
||||
// Searching from an array with 2000 items for every emoji felt like too energy-consuming, so I decided to do it lazily on pointerenter
|
||||
function computeTitle(event: PointerEvent): void {
|
||||
const title = customEmoji.value
|
||||
? `:${customEmoji.value.name}:`
|
||||
const title = isCustom.value
|
||||
? `:${customEmojiName}:`
|
||||
: (getEmojiName(char.value as string) ?? char.value as string);
|
||||
(event.target as HTMLElement).title = title;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<MfmCore :text="text" :plain="plain" :nowrap="nowrap" :author="author" :customEmojis="customEmojis" :isNote="isNote" class="havbbuyv" :class="{ nowrap }"/>
|
||||
<MfmCore :text="text" :plain="plain" :nowrap="nowrap" :author="author" :is-note="isNote" class="havbbuyv" :class="{ nowrap }"/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
@ -11,7 +11,6 @@ const props = withDefaults(defineProps<{
|
|||
plain?: boolean;
|
||||
nowrap?: boolean;
|
||||
author?: any;
|
||||
customEmojis?: any;
|
||||
isNote?: boolean;
|
||||
}>(), {
|
||||
plain: false,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<Mfm :text="user.name || user.username" :plain="true" :nowrap="nowrap" :custom-emojis="user.emojis"/>
|
||||
<Mfm :text="user.name || user.username" :plain="true" :nowrap="nowrap"/>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
|
|
|
@ -35,9 +35,6 @@ export default defineComponent({
|
|||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
customEmojis: {
|
||||
required: false,
|
||||
},
|
||||
isNote: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
|
@ -275,7 +272,6 @@ export default defineComponent({
|
|||
return [h(MkEmoji, {
|
||||
key: Math.random(),
|
||||
emoji: `:${token.props.name}:`,
|
||||
customEmojis: this.customEmojis,
|
||||
normal: this.plain,
|
||||
})];
|
||||
}
|
||||
|
@ -284,7 +280,6 @@ export default defineComponent({
|
|||
return [h(MkEmoji, {
|
||||
key: Math.random(),
|
||||
emoji: token.props.emoji,
|
||||
customEmojis: this.customEmojis,
|
||||
normal: this.plain,
|
||||
})];
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ export const instance: Misskey.entities.InstanceMetadata = reactive(instanceData
|
|||
export async function fetchInstance() {
|
||||
const meta = await api('meta', {
|
||||
detail: false,
|
||||
omitEmojiUrl: true,
|
||||
});
|
||||
|
||||
for (const [k, v] of Object.entries(meta)) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<img src="/client-assets/about-icon.png" alt="" class="icon" draggable="false" @load="iconLoaded" @click="gravity"/>
|
||||
<div class="misskey">Misskey</div>
|
||||
<div class="version">v{{ version }}</div>
|
||||
<span v-for="emoji in easterEggEmojis" :key="emoji.id" class="emoji" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }"><MkEmoji class="emoji" :emoji="emoji.emoji" :custom-emojis="$instance.emojis" :is-reaction="false" :normal="true" :no-style="true"/></span>
|
||||
<span v-for="emoji in easterEggEmojis" :key="emoji.id" class="emoji" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }"><MkEmoji class="emoji" :emoji="emoji.emoji" :is-reaction="false" :normal="true" :no-style="true"/></span>
|
||||
</div>
|
||||
<div class="_formBlock" style="text-align: center;">
|
||||
{{ i18n.ts._aboutMisskey.about }}<br><a href="https://misskey-hub.net/docs/misskey.html" target="_blank" class="_link">{{ i18n.ts.learnMore }}</a>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<p class="acct">@{{ acct(req.follower) }}</p>
|
||||
</div>
|
||||
<div v-if="req.follower.description" class="description" :title="req.follower.description">
|
||||
<Mfm :text="req.follower.description" :is-note="false" :author="req.follower" :i="$i" :custom-emojis="req.follower.emojis" :plain="true" :nowrap="true"/>
|
||||
<Mfm :text="req.follower.description" :is-note="false" :author="req.follower" :i="$i" :plain="true" :nowrap="true"/>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<button class="_button" @click="accept(req.follower)"><i class="ti ti-check"></i></button>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="description">
|
||||
<Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i" :custom-emojis="user.emojis"/>
|
||||
<Mfm v-if="user.description" :text="user.description" :is-note="false" :author="user" :i="$i"/>
|
||||
<p v-else class="empty">{{ i18n.ts.noAccountDescription }}</p>
|
||||
</div>
|
||||
<div class="fields system">
|
||||
|
@ -61,10 +61,10 @@
|
|||
<div v-if="user.fields.length > 0" class="fields">
|
||||
<dl v-for="(field, i) in user.fields" :key="i" class="field">
|
||||
<dt class="name">
|
||||
<Mfm :text="field.name" :plain="true" :custom-emojis="user.emojis" :colored="false"/>
|
||||
<Mfm :text="field.name" :plain="true" :colored="false"/>
|
||||
</dt>
|
||||
<dd class="value">
|
||||
<Mfm :text="field.value" :author="user" :i="$i" :custom-emojis="user.emojis" :colored="false"/>
|
||||
<Mfm :text="field.value" :author="user" :i="$i" :colored="false"/>
|
||||
</dd>
|
||||
</dl>
|
||||
</div>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<div v-for="item in items" :key="item.id" :to="`/clips/${item.id}`" class="item _panel _gap afdcfbfb">
|
||||
<div class="header">
|
||||
<MkAvatar class="avatar" :user="user"/>
|
||||
<MkReactionIcon class="reaction" :reaction="item.type" :custom-emojis="item.note.emojis" :no-style="true"/>
|
||||
<MkReactionIcon class="reaction" :reaction="item.type" :no-style="true"/>
|
||||
<MkTime :time="item.createdAt" class="createdAt"/>
|
||||
</div>
|
||||
<MkNote :key="item.id" :note="item.note"/>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<div class="content _panel">
|
||||
<div class="body">
|
||||
<MkA v-if="note.replyId" class="reply" :to="`/notes/${note.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
|
||||
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i" :custom-emojis="note.emojis"/>
|
||||
<Mfm v-if="note.text" :text="note.text" :author="note.user" :i="$i"/>
|
||||
<MkA v-if="note.renoteId" class="rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
|
||||
</div>
|
||||
<div v-if="note.files.length > 0" class="richcontent">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<span v-for="note in notes" :key="note.id" class="item">
|
||||
<img class="avatar" :src="note.user.avatarUrl" decoding="async"/>
|
||||
<MkA class="text" :to="notePage(note)">
|
||||
<Mfm class="text" :text="getNoteSummary(note)" :plain="true" :nowrap="true" :custom-emojis="note.emojis"/>
|
||||
<Mfm class="text" :text="getNoteSummary(note)" :plain="true" :nowrap="true"/>
|
||||
</MkA>
|
||||
<span class="divider"></span>
|
||||
</span>
|
||||
|
|
Loading…
Reference in a new issue