enhance(server): clean emoji response
This commit is contained in:
		
							parent
							
								
									fcfcb8da1d
								
							
						
					
					
						commit
						b2d6561bc6
					
				
					 11 changed files with 9 additions and 186 deletions
				
			
		|  | @ -21,6 +21,11 @@ You should also include the user name that made the change. | ||||||
| - 新たに動的なPagesを作ることはできなくなりました | - 新たに動的なPagesを作ることはできなくなりました | ||||||
| 	- 代わりに今後AiScriptを用いてより柔軟に動的なコンテンツを作成できるMisskey Play機能の実装を予定しています。 | 	- 代わりに今後AiScriptを用いてより柔軟に動的なコンテンツを作成できるMisskey Play機能の実装を予定しています。 | ||||||
| - iOS15以下のデバイスはサポートされなくなりました | - iOS15以下のデバイスはサポートされなくなりました | ||||||
|  | - API: カスタム絵文字エンティティに`url`プロパティが含まれなくなりました | ||||||
|  | 	- 絵文字画像を表示するには、`<instance host>/emoji/<emoji name>.webp`にリクエストすると画像が返ります。 | ||||||
|  | 	- e.g. `https://p1.a9z.dev/emoji/misskey.webp` | ||||||
|  | 	- remote: `https://p1.a9z.dev/emoji/syuilo_birth_present@mk.f72u.net.webp` | ||||||
|  | - API: `user`および`note`エンティティに`emojis`プロパティが含まれなくなりました | ||||||
| 
 | 
 | ||||||
| ### Improvements | ### Improvements | ||||||
| - Push notification of Antenna note @tamaina | - Push notification of Antenna note @tamaina | ||||||
|  |  | ||||||
|  | @ -1,29 +1,14 @@ | ||||||
| import { Inject, Injectable } from '@nestjs/common'; | import { Inject, Injectable } from '@nestjs/common'; | ||||||
| import { DataSource, In, IsNull } from 'typeorm'; | import { DataSource, In, IsNull } from 'typeorm'; | ||||||
| import { GlobalEventService } from '@/core/GlobalEventService.js'; |  | ||||||
| import { DI } from '@/di-symbols.js'; | import { DI } from '@/di-symbols.js'; | ||||||
| import { IdService } from '@/core/IdService.js'; | import { IdService } from '@/core/IdService.js'; | ||||||
| import type { DriveFile } from '@/models/entities/DriveFile.js'; | import type { DriveFile } from '@/models/entities/DriveFile.js'; | ||||||
| import type { Emoji } from '@/models/entities/Emoji.js'; | import type { Emoji } from '@/models/entities/Emoji.js'; | ||||||
| import { Cache } from '@/misc/cache.js'; |  | ||||||
| import type { Note } from '@/models/entities/Note.js'; |  | ||||||
| import type { EmojisRepository } from '@/models/index.js'; | import type { EmojisRepository } from '@/models/index.js'; | ||||||
| import { UtilityService } from '@/core/UtilityService.js'; |  | ||||||
| import { ReactionService } from '@/core/ReactionService.js'; |  | ||||||
| import { bindThis } from '@/decorators.js'; | import { bindThis } from '@/decorators.js'; | ||||||
| 
 | 
 | ||||||
| /** |  | ||||||
|  * 添付用絵文字情報 |  | ||||||
|  */ |  | ||||||
| type PopulatedEmoji = { |  | ||||||
| 	name: string; |  | ||||||
| 	url: string; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| @Injectable() | @Injectable() | ||||||
| export class CustomEmojiService { | export class CustomEmojiService { | ||||||
| 	private cache: Cache<Emoji | null>; |  | ||||||
| 
 |  | ||||||
| 	constructor( | 	constructor( | ||||||
| 		@Inject(DI.db) | 		@Inject(DI.db) | ||||||
| 		private db: DataSource, | 		private db: DataSource, | ||||||
|  | @ -32,11 +17,7 @@ export class CustomEmojiService { | ||||||
| 		private emojisRepository: EmojisRepository, | 		private emojisRepository: EmojisRepository, | ||||||
| 
 | 
 | ||||||
| 		private idService: IdService, | 		private idService: IdService, | ||||||
| 		private globalEventServie: GlobalEventService, |  | ||||||
| 		private utilityService: UtilityService, |  | ||||||
| 		private reactionService: ReactionService, |  | ||||||
| 	) { | 	) { | ||||||
| 		this.cache = new Cache<Emoji | null>(1000 * 60 * 60 * 12); |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@bindThis | 	@bindThis | ||||||
|  | @ -63,117 +44,4 @@ export class CustomEmojiService { | ||||||
| 
 | 
 | ||||||
| 		return emoji; | 		return emoji; | ||||||
| 	} | 	} | ||||||
| 	 |  | ||||||
| 	@bindThis |  | ||||||
| 	private normalizeHost(src: string | undefined, noteUserHost: string | null): string | null { |  | ||||||
| 	// クエリに使うホスト
 |  | ||||||
| 		let host = src === '.' ? null	// .はローカルホスト (ここがマッチするのはリアクションのみ)
 |  | ||||||
| 			: src === undefined ? noteUserHost	// ノートなどでホスト省略表記の場合はローカルホスト (ここがリアクションにマッチすることはない)
 |  | ||||||
| 			: this.utilityService.isSelfHost(src) ? null	// 自ホスト指定
 |  | ||||||
| 			: (src || noteUserHost);	// 指定されたホスト || ノートなどの所有者のホスト (こっちがリアクションにマッチすることはない)
 |  | ||||||
| 
 |  | ||||||
| 		host = this.utilityService.toPunyNullable(host); |  | ||||||
| 
 |  | ||||||
| 		return host; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@bindThis |  | ||||||
| 	private parseEmojiStr(emojiName: string, noteUserHost: string | null) { |  | ||||||
| 		const match = emojiName.match(/^(\w+)(?:@([\w.-]+))?$/); |  | ||||||
| 		if (!match) return { name: null, host: null }; |  | ||||||
| 
 |  | ||||||
| 		const name = match[1]; |  | ||||||
| 
 |  | ||||||
| 		// ホスト正規化
 |  | ||||||
| 		const host = this.utilityService.toPunyNullable(this.normalizeHost(match[2], noteUserHost)); |  | ||||||
| 
 |  | ||||||
| 		return { name, host }; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
|  * 添付用絵文字情報を解決する |  | ||||||
|  * @param emojiName ノートやユーザープロフィールに添付された、またはリアクションのカスタム絵文字名 (:は含めない, リアクションでローカルホストの場合は@.を付ける (これはdecodeReactionで可能)) |  | ||||||
|  * @param noteUserHost ノートやユーザープロフィールの所有者のホスト |  | ||||||
|  * @returns 絵文字情報, nullは未マッチを意味する |  | ||||||
|  */ |  | ||||||
| 	@bindThis |  | ||||||
| 	public async populateEmoji(emojiName: string, noteUserHost: string | null): Promise<PopulatedEmoji | null> { |  | ||||||
| 		const { name, host } = this.parseEmojiStr(emojiName, noteUserHost); |  | ||||||
| 		if (name == null) return null; |  | ||||||
| 
 |  | ||||||
| 		const queryOrNull = async () => (await this.emojisRepository.findOneBy({ |  | ||||||
| 			name, |  | ||||||
| 			host: host ?? IsNull(), |  | ||||||
| 		})) ?? null; |  | ||||||
| 
 |  | ||||||
| 		const emoji = await this.cache.fetch(`${name} ${host}`, queryOrNull); |  | ||||||
| 
 |  | ||||||
| 		if (emoji == null) return null; |  | ||||||
| 
 |  | ||||||
| 		const isLocal = emoji.host == null; |  | ||||||
| 		// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
 |  | ||||||
| 		const emojiUrl = emoji.publicUrl || emoji.originalUrl; |  | ||||||
| 		const url = emojiUrl; |  | ||||||
| 
 |  | ||||||
| 		return { |  | ||||||
| 			name: emojiName, |  | ||||||
| 			url, |  | ||||||
| 		}; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
|  * 複数の添付用絵文字情報を解決する (キャシュ付き, 存在しないものは結果から除外される) |  | ||||||
|  */ |  | ||||||
| 	@bindThis |  | ||||||
| 	public async populateEmojis(emojiNames: string[], noteUserHost: string | null): Promise<PopulatedEmoji[]> { |  | ||||||
| 		const emojis = await Promise.all(emojiNames.map(x => this.populateEmoji(x, noteUserHost))); |  | ||||||
| 		return emojis.filter((x): x is PopulatedEmoji => x != null); |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	@bindThis |  | ||||||
| 	public aggregateNoteEmojis(notes: Note[]) { |  | ||||||
| 		let emojis: { name: string | null; host: string | null; }[] = []; |  | ||||||
| 		for (const note of notes) { |  | ||||||
| 			emojis = emojis.concat(note.emojis |  | ||||||
| 				.map(e => this.parseEmojiStr(e, note.userHost))); |  | ||||||
| 			if (note.renote) { |  | ||||||
| 				emojis = emojis.concat(note.renote.emojis |  | ||||||
| 					.map(e => this.parseEmojiStr(e, note.renote!.userHost))); |  | ||||||
| 				if (note.renote.user) { |  | ||||||
| 					emojis = emojis.concat(note.renote.user.emojis |  | ||||||
| 						.map(e => this.parseEmojiStr(e, note.renote!.userHost))); |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 			const customReactions = Object.keys(note.reactions).map(x => this.reactionService.decodeReaction(x)).filter(x => x.name != null) as typeof emojis; |  | ||||||
| 			emojis = emojis.concat(customReactions); |  | ||||||
| 			if (note.user) { |  | ||||||
| 				emojis = emojis.concat(note.user.emojis |  | ||||||
| 					.map(e => this.parseEmojiStr(e, note.userHost))); |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		return emojis.filter(x => x.name != null) as { name: string; host: string | null; }[]; |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	/** |  | ||||||
|  * 与えられた絵文字のリストをデータベースから取得し、キャッシュに追加します |  | ||||||
|  */ |  | ||||||
| 	@bindThis |  | ||||||
| 	public async prefetchEmojis(emojis: { name: string; host: string | null; }[]): Promise<void> { |  | ||||||
| 		const notCachedEmojis = emojis.filter(emoji => this.cache.get(`${emoji.name} ${emoji.host}`) == null); |  | ||||||
| 		const emojisQuery: any[] = []; |  | ||||||
| 		const hosts = new Set(notCachedEmojis.map(e => e.host)); |  | ||||||
| 		for (const host of hosts) { |  | ||||||
| 			emojisQuery.push({ |  | ||||||
| 				name: In(notCachedEmojis.filter(e => e.host === host).map(e => e.name)), |  | ||||||
| 				host: host ?? IsNull(), |  | ||||||
| 			}); |  | ||||||
| 		} |  | ||||||
| 		const _emojis = emojisQuery.length > 0 ? await this.emojisRepository.find({ |  | ||||||
| 			where: emojisQuery, |  | ||||||
| 			select: ['name', 'host', 'originalUrl', 'publicUrl'], |  | ||||||
| 		}) : []; |  | ||||||
| 		for (const emoji of _emojis) { |  | ||||||
| 			this.cache.set(`${emoji.name} ${emoji.host}`, emoji); |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -22,7 +22,6 @@ export class EmojiEntityService { | ||||||
| 	@bindThis | 	@bindThis | ||||||
| 	public async pack( | 	public async pack( | ||||||
| 		src: Emoji['id'] | Emoji, | 		src: Emoji['id'] | Emoji, | ||||||
| 		opts: { omitUrl?: boolean } = {}, |  | ||||||
| 	): Promise<Packed<'Emoji'>> { | 	): Promise<Packed<'Emoji'>> { | ||||||
| 		const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src }); | 		const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src }); | ||||||
| 
 | 
 | ||||||
|  | @ -32,17 +31,14 @@ export class EmojiEntityService { | ||||||
| 			name: emoji.name, | 			name: emoji.name, | ||||||
| 			category: emoji.category, | 			category: emoji.category, | ||||||
| 			host: emoji.host, | 			host: emoji.host, | ||||||
| 			// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
 |  | ||||||
| 			url: opts.omitUrl ? undefined : (emoji.publicUrl || emoji.originalUrl), |  | ||||||
| 		}; | 		}; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	@bindThis | 	@bindThis | ||||||
| 	public packMany( | 	public packMany( | ||||||
| 		emojis: any[], | 		emojis: any[], | ||||||
| 		opts: { omitUrl?: boolean } = {}, |  | ||||||
| 	) { | 	) { | ||||||
| 		return Promise.all(emojis.map(x => this.pack(x, opts))); | 		return Promise.all(emojis.map(x => this.pack(x))); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -11,12 +11,12 @@ import type { User } from '@/models/entities/User.js'; | ||||||
| import type { Note } from '@/models/entities/Note.js'; | import type { Note } from '@/models/entities/Note.js'; | ||||||
| import type { NoteReaction } from '@/models/entities/NoteReaction.js'; | import type { NoteReaction } from '@/models/entities/NoteReaction.js'; | ||||||
| import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository, DriveFilesRepository } from '@/models/index.js'; | import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository, DriveFilesRepository } from '@/models/index.js'; | ||||||
|  | import { bindThis } from '@/decorators.js'; | ||||||
| import type { OnModuleInit } from '@nestjs/common'; | import type { OnModuleInit } from '@nestjs/common'; | ||||||
| import type { CustomEmojiService } from '../CustomEmojiService.js'; | import type { CustomEmojiService } from '../CustomEmojiService.js'; | ||||||
| import type { ReactionService } from '../ReactionService.js'; | import type { ReactionService } from '../ReactionService.js'; | ||||||
| import type { UserEntityService } from './UserEntityService.js'; | import type { UserEntityService } from './UserEntityService.js'; | ||||||
| import type { DriveFileEntityService } from './DriveFileEntityService.js'; | import type { DriveFileEntityService } from './DriveFileEntityService.js'; | ||||||
| import { bindThis } from '@/decorators.js'; |  | ||||||
| 
 | 
 | ||||||
| @Injectable() | @Injectable() | ||||||
| export class NoteEntityService implements OnModuleInit { | export class NoteEntityService implements OnModuleInit { | ||||||
|  | @ -300,7 +300,6 @@ export class NoteEntityService implements OnModuleInit { | ||||||
| 			repliesCount: note.repliesCount, | 			repliesCount: note.repliesCount, | ||||||
| 			reactions: this.reactionService.convertLegacyReactions(note.reactions), | 			reactions: this.reactionService.convertLegacyReactions(note.reactions), | ||||||
| 			tags: note.tags.length > 0 ? note.tags : undefined, | 			tags: note.tags.length > 0 ? note.tags : undefined, | ||||||
| 			emojis: this.customEmojiService.populateEmojis(note.emojis.concat(reactionEmojiNames), host), |  | ||||||
| 			fileIds: note.fileIds, | 			fileIds: note.fileIds, | ||||||
| 			files: this.driveFileEntityService.packMany(note.fileIds), | 			files: this.driveFileEntityService.packMany(note.fileIds), | ||||||
| 			replyId: note.replyId, | 			replyId: note.replyId, | ||||||
|  | @ -385,8 +384,6 @@ export class NoteEntityService implements OnModuleInit { | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		await this.customEmojiService.prefetchEmojis(this.customEmojiService.aggregateNoteEmojis(notes)); |  | ||||||
| 
 |  | ||||||
| 		return await Promise.all(notes.map(n => this.pack(n, me, { | 		return await Promise.all(notes.map(n => this.pack(n, me, { | ||||||
| 			...options, | 			...options, | ||||||
| 			_hint_: { | 			_hint_: { | ||||||
|  |  | ||||||
|  | @ -8,12 +8,12 @@ import type { Notification } from '@/models/entities/Notification.js'; | ||||||
| import type { NoteReaction } from '@/models/entities/NoteReaction.js'; | import type { NoteReaction } from '@/models/entities/NoteReaction.js'; | ||||||
| import type { Note } from '@/models/entities/Note.js'; | import type { Note } from '@/models/entities/Note.js'; | ||||||
| import type { Packed } from '@/misc/schema.js'; | import type { Packed } from '@/misc/schema.js'; | ||||||
|  | import { bindThis } from '@/decorators.js'; | ||||||
| import type { OnModuleInit } from '@nestjs/common'; | import type { OnModuleInit } from '@nestjs/common'; | ||||||
| import type { CustomEmojiService } from '../CustomEmojiService.js'; | import type { CustomEmojiService } from '../CustomEmojiService.js'; | ||||||
| import type { UserEntityService } from './UserEntityService.js'; | import type { UserEntityService } from './UserEntityService.js'; | ||||||
| import type { NoteEntityService } from './NoteEntityService.js'; | import type { NoteEntityService } from './NoteEntityService.js'; | ||||||
| import type { UserGroupInvitationEntityService } from './UserGroupInvitationEntityService.js'; | import type { UserGroupInvitationEntityService } from './UserGroupInvitationEntityService.js'; | ||||||
| import { bindThis } from '@/decorators.js'; |  | ||||||
| 
 | 
 | ||||||
| @Injectable() | @Injectable() | ||||||
| export class NotificationEntityService implements OnModuleInit { | export class NotificationEntityService implements OnModuleInit { | ||||||
|  | @ -143,8 +143,6 @@ export class NotificationEntityService implements OnModuleInit { | ||||||
| 			myReactionsMap.set(target, myReactions.find(reaction => reaction.noteId === target) ?? null); | 			myReactionsMap.set(target, myReactions.find(reaction => reaction.noteId === target) ?? null); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		await this.customEmojiService.prefetchEmojis(this.customEmojiService.aggregateNoteEmojis(notes)); |  | ||||||
| 
 |  | ||||||
| 		return await Promise.all(notifications.map(x => this.pack(x, { | 		return await Promise.all(notifications.map(x => this.pack(x, { | ||||||
| 			_hintForEachNotes_: { | 			_hintForEachNotes_: { | ||||||
| 				myReactions: myReactionsMap, | 				myReactions: myReactionsMap, | ||||||
|  |  | ||||||
|  | @ -408,7 +408,6 @@ export class UserEntityService implements OnModuleInit { | ||||||
| 				faviconUrl: instance.faviconUrl, | 				faviconUrl: instance.faviconUrl, | ||||||
| 				themeColor: instance.themeColor, | 				themeColor: instance.themeColor, | ||||||
| 			} : undefined) : undefined, | 			} : undefined) : undefined, | ||||||
| 			emojis: this.customEmojiService.populateEmojis(user.emojis, user.host), |  | ||||||
| 			onlineStatus: this.getOnlineStatus(user), | 			onlineStatus: this.getOnlineStatus(user), | ||||||
| 			driveCapacityOverrideMb: user.driveCapacityOverrideMb, | 			driveCapacityOverrideMb: user.driveCapacityOverrideMb, | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -141,24 +141,6 @@ export const packedNoteSchema = { | ||||||
| 			type: 'boolean', | 			type: 'boolean', | ||||||
| 			optional: true, nullable: false, | 			optional: true, nullable: false, | ||||||
| 		}, | 		}, | ||||||
| 		emojis: { |  | ||||||
| 			type: 'array', |  | ||||||
| 			optional: false, nullable: false, |  | ||||||
| 			items: { |  | ||||||
| 				type: 'object', |  | ||||||
| 				optional: false, nullable: false, |  | ||||||
| 				properties: { |  | ||||||
| 					name: { |  | ||||||
| 						type: 'string', |  | ||||||
| 						optional: false, nullable: false, |  | ||||||
| 					}, |  | ||||||
| 					url: { |  | ||||||
| 						type: 'string', |  | ||||||
| 						optional: false, nullable: true, |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		reactions: { | 		reactions: { | ||||||
| 			type: 'object', | 			type: 'object', | ||||||
| 			optional: false, nullable: false, | 			optional: false, nullable: false, | ||||||
|  |  | ||||||
|  | @ -55,25 +55,6 @@ export const packedUserLiteSchema = { | ||||||
| 			type: 'boolean', | 			type: 'boolean', | ||||||
| 			nullable: false, optional: true, | 			nullable: false, optional: true, | ||||||
| 		}, | 		}, | ||||||
| 		emojis: { |  | ||||||
| 			type: 'array', |  | ||||||
| 			nullable: false, optional: false, |  | ||||||
| 			items: { |  | ||||||
| 				type: 'object', |  | ||||||
| 				nullable: false, optional: false, |  | ||||||
| 				properties: { |  | ||||||
| 					name: { |  | ||||||
| 						type: 'string', |  | ||||||
| 						nullable: false, optional: false, |  | ||||||
| 					}, |  | ||||||
| 					url: { |  | ||||||
| 						type: 'string', |  | ||||||
| 						nullable: false, optional: false, |  | ||||||
| 						format: 'url', |  | ||||||
| 					}, |  | ||||||
| 				}, |  | ||||||
| 			}, |  | ||||||
| 		}, |  | ||||||
| 		onlineStatus: { | 		onlineStatus: { | ||||||
| 			type: 'string', | 			type: 'string', | ||||||
| 			format: 'url', | 			format: 'url', | ||||||
|  |  | ||||||
|  | @ -309,7 +309,6 @@ export const paramDef = { | ||||||
| 	type: 'object', | 	type: 'object', | ||||||
| 	properties: { | 	properties: { | ||||||
| 		detail: { type: 'boolean', default: true }, | 		detail: { type: 'boolean', default: true }, | ||||||
| 		omitEmojiUrl: { type: 'boolean', default: false }, |  | ||||||
| 	}, | 	}, | ||||||
| 	required: [], | 	required: [], | ||||||
| } as const; | } as const; | ||||||
|  | @ -391,7 +390,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { | ||||||
| 				backgroundImageUrl: instance.backgroundImageUrl, | 				backgroundImageUrl: instance.backgroundImageUrl, | ||||||
| 				logoImageUrl: instance.logoImageUrl, | 				logoImageUrl: instance.logoImageUrl, | ||||||
| 				maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため
 | 				maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため
 | ||||||
| 				emojis: await this.emojiEntityService.packMany(emojis, { omitUrl: ps.omitEmojiUrl }), | 				emojis: await this.emojiEntityService.packMany(emojis), | ||||||
| 				defaultLightTheme: instance.defaultLightTheme, | 				defaultLightTheme: instance.defaultLightTheme, | ||||||
| 				defaultDarkTheme: instance.defaultDarkTheme, | 				defaultDarkTheme: instance.defaultDarkTheme, | ||||||
| 				ads: ads.map(ad => ({ | 				ads: ads.map(ad => ({ | ||||||
|  |  | ||||||
|  | @ -81,7 +81,6 @@ useTooltip(buttonRef, async (showing) => { | ||||||
| 	os.popup(XDetails, { | 	os.popup(XDetails, { | ||||||
| 		showing, | 		showing, | ||||||
| 		reaction: props.reaction, | 		reaction: props.reaction, | ||||||
| 		emojis: props.note.emojis, |  | ||||||
| 		users, | 		users, | ||||||
| 		count: props.count, | 		count: props.count, | ||||||
| 		targetElement: buttonRef.value, | 		targetElement: buttonRef.value, | ||||||
|  |  | ||||||
|  | @ -15,7 +15,6 @@ export const instance: Misskey.entities.InstanceMetadata = reactive(instanceData | ||||||
| export async function fetchInstance() { | export async function fetchInstance() { | ||||||
| 	const meta = await api('meta', { | 	const meta = await api('meta', { | ||||||
| 		detail: false, | 		detail: false, | ||||||
| 		omitEmojiUrl: true, |  | ||||||
| 	}); | 	}); | ||||||
| 
 | 
 | ||||||
| 	for (const [k, v] of Object.entries(meta)) { | 	for (const [k, v] of Object.entries(meta)) { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue