* wip * wip * wip * wip * wip * wip * wip * wip * fix * fix * fix * fix size * fix register logs * fix img autosize * fix row selection * support delete * fix border rendering * fix display:none * tweak comments * support choose pc file and drive file * support directory drag-drop * fix * fix comment * support context menu on data area * fix autogen * wip イベント整理 * イベントの整理 * refactor grid * fix cell re-render bugs * fix row remove * fix comment * fix validation * fix utils * list maximum * add mimetype check * fix * fix number cell focus * fix over 100 file drop * remove log * fix patchData * fix performance * fix * support update and delete * support remote import * fix layout * heightやめる * fix performance * add list v2 endpoint * support pagination * fix api call * fix no clickable input text * fix limit * fix paging * fix * fix * support search * tweak logs * tweak cell selection * fix range select * block delete * add comment * fix * support import log * fix dialog * refactor * add confirm dialog * fix name * fix autogen * wip * support image change and highlight row * add columns * wip * support sort * add role name * add index to emoji * refine context menu setting * support role select * remove unused buttons * fix url * fix MkRoleSelectDialog.vue * add route * refine remote page * enter key search * fix paste bugs * fix copy/paste * fix keyEvent * fix copy/paste and delete * fix comment * fix MkRoleSelectDialog.vue and storybook scenario * fix MkRoleSelectDialog.vue and storybook scenario * add MkGrid.stories.impl.ts * fix * [wip] add custom-emojis-manager2.stories.impl.ts * [wip] add custom-emojis-manager2.stories.impl.ts * wip * 課題はまだ残っているが、ひとまず完了 * fix validation and register roles * fix upload * optimize import * patch from dev * i18n * revert excess fixes * separate sort order component * add SPDX * revert excess fixes * fix pre test * fix bugs * add type column * fix types * fix CHANGELOG.md * fix lit * lint * tweak style * refactor * fix ci * autogen * Update types.ts * CSS Module化 * fix log * 縦スクロールを無効化 * MkStickyContainer化 * regenerate locales index.d.ts * fix * fix * テスト * ランダム値によるUI変更の抑制 * テスト * tableタグやめる * fix last-child css * fix overflow css * fix endpoint.ts * tweak css * 最新への追従とレイアウト微調整 * ソートキーの指定方法を他と合わせた * fix focus * fix layout * v2エンドポイントのルールに対応 * 表示条件などを微調整 * fix MkDataCell.vue * fix error code * fix error * add comment to MkModal.vue * Update index.d.ts * fix CHANGELOG.md * fix color theme * fix CHANGELOG.md * fix CHANGELOG.md * fix center * fix: テーブルにフォーカスがあり、通常状態であるときはキーイベントの伝搬を止める * fix: ロール選択用のダイアログにてコンディショナルロールを×ボタンで除外できなかったのを修正 * fix remote list folder * sticky footers * chore: fix ci error(just single line-break diff) * fix loading * fix like * comma to space * fix ci * fix ci * removed align-center --------- Co-authored-by: osamu <46447427+sam-osamu@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> Co-authored-by: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com>
159 lines
4.9 KiB
TypeScript
159 lines
4.9 KiB
TypeScript
/*
|
||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||
* SPDX-License-Identifier: AGPL-3.0-only
|
||
*/
|
||
|
||
import { Inject, Injectable } from '@nestjs/common';
|
||
import { In } from 'typeorm';
|
||
import { DI } from '@/di-symbols.js';
|
||
import type { EmojisRepository, MiRole, RolesRepository } from '@/models/_.js';
|
||
import type { Packed } from '@/misc/json-schema.js';
|
||
import type { MiEmoji } from '@/models/Emoji.js';
|
||
import { bindThis } from '@/decorators.js';
|
||
|
||
@Injectable()
|
||
export class EmojiEntityService {
|
||
constructor(
|
||
@Inject(DI.emojisRepository)
|
||
private emojisRepository: EmojisRepository,
|
||
@Inject(DI.rolesRepository)
|
||
private rolesRepository: RolesRepository,
|
||
) {
|
||
}
|
||
|
||
@bindThis
|
||
public async packSimple(
|
||
src: MiEmoji['id'] | MiEmoji,
|
||
): Promise<Packed<'EmojiSimple'>> {
|
||
const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src });
|
||
|
||
return {
|
||
aliases: emoji.aliases,
|
||
name: emoji.name,
|
||
category: emoji.category,
|
||
// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
|
||
url: emoji.publicUrl || emoji.originalUrl,
|
||
localOnly: emoji.localOnly ? true : undefined,
|
||
isSensitive: emoji.isSensitive ? true : undefined,
|
||
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length > 0 ? emoji.roleIdsThatCanBeUsedThisEmojiAsReaction : undefined,
|
||
};
|
||
}
|
||
|
||
@bindThis
|
||
public packSimpleMany(
|
||
emojis: any[],
|
||
) {
|
||
return Promise.all(emojis.map(x => this.packSimple(x)));
|
||
}
|
||
|
||
@bindThis
|
||
public async packDetailed(
|
||
src: MiEmoji['id'] | MiEmoji,
|
||
): Promise<Packed<'EmojiDetailed'>> {
|
||
const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src });
|
||
|
||
return {
|
||
id: emoji.id,
|
||
aliases: emoji.aliases,
|
||
name: emoji.name,
|
||
category: emoji.category,
|
||
host: emoji.host,
|
||
// || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
|
||
url: emoji.publicUrl || emoji.originalUrl,
|
||
license: emoji.license,
|
||
isSensitive: emoji.isSensitive,
|
||
localOnly: emoji.localOnly,
|
||
roleIdsThatCanBeUsedThisEmojiAsReaction: emoji.roleIdsThatCanBeUsedThisEmojiAsReaction,
|
||
};
|
||
}
|
||
|
||
@bindThis
|
||
public packDetailedMany(
|
||
emojis: any[],
|
||
): Promise<Packed<'EmojiDetailed'>[]> {
|
||
return Promise.all(emojis.map(x => this.packDetailed(x)));
|
||
}
|
||
|
||
@bindThis
|
||
public async packDetailedAdmin(
|
||
src: MiEmoji['id'] | MiEmoji,
|
||
hint?: {
|
||
roles?: Map<MiRole['id'], MiRole>
|
||
},
|
||
): Promise<Packed<'EmojiDetailedAdmin'>> {
|
||
const emoji = typeof src === 'object' ? src : await this.emojisRepository.findOneByOrFail({ id: src });
|
||
|
||
const roles = Array.of<MiRole>();
|
||
if (emoji.roleIdsThatCanBeUsedThisEmojiAsReaction.length > 0) {
|
||
if (hint?.roles) {
|
||
const hintRoles = hint.roles;
|
||
roles.push(
|
||
...emoji.roleIdsThatCanBeUsedThisEmojiAsReaction
|
||
.filter(x => hintRoles.has(x))
|
||
.map(x => hintRoles.get(x)!),
|
||
);
|
||
} else {
|
||
roles.push(
|
||
...await this.rolesRepository.findBy({ id: In(emoji.roleIdsThatCanBeUsedThisEmojiAsReaction) }),
|
||
);
|
||
}
|
||
|
||
roles.sort((a, b) => {
|
||
if (a.displayOrder !== b.displayOrder) {
|
||
return b.displayOrder - a.displayOrder;
|
||
}
|
||
|
||
return a.id.localeCompare(b.id);
|
||
});
|
||
}
|
||
|
||
return {
|
||
id: emoji.id,
|
||
updatedAt: emoji.updatedAt?.toISOString() ?? null,
|
||
name: emoji.name,
|
||
host: emoji.host,
|
||
uri: emoji.uri,
|
||
type: emoji.type,
|
||
aliases: emoji.aliases,
|
||
category: emoji.category,
|
||
publicUrl: emoji.publicUrl,
|
||
originalUrl: emoji.originalUrl,
|
||
license: emoji.license,
|
||
localOnly: emoji.localOnly,
|
||
isSensitive: emoji.isSensitive,
|
||
roleIdsThatCanBeUsedThisEmojiAsReaction: roles.map(it => ({ id: it.id, name: it.name })),
|
||
};
|
||
}
|
||
|
||
@bindThis
|
||
public async packDetailedAdminMany(
|
||
emojis: MiEmoji['id'][] | MiEmoji[],
|
||
hint?: {
|
||
roles?: Map<MiRole['id'], MiRole>
|
||
},
|
||
): Promise<Packed<'EmojiDetailedAdmin'>[]> {
|
||
// IDのみの要素をピックアップし、DBからレコードを取り出して他の値を補完する
|
||
const emojiEntities = emojis.filter(x => typeof x === 'object') as MiEmoji[];
|
||
const emojiIdOnlyList = emojis.filter(x => typeof x === 'string') as string[];
|
||
if (emojiIdOnlyList.length > 0) {
|
||
emojiEntities.push(...await this.emojisRepository.findBy({ id: In(emojiIdOnlyList) }));
|
||
}
|
||
|
||
// 特定ロール専用の絵文字である場合、そのロール情報をあらかじめまとめて取得しておく(pack側で都度取得も出来るが負荷が高いので)
|
||
let hintRoles: Map<MiRole['id'], MiRole>;
|
||
if (hint?.roles) {
|
||
hintRoles = hint.roles;
|
||
} else {
|
||
const roles = Array.of<MiRole>();
|
||
const roleIds = [...new Set(emojiEntities.flatMap(x => x.roleIdsThatCanBeUsedThisEmojiAsReaction))];
|
||
if (roleIds.length > 0) {
|
||
roles.push(...await this.rolesRepository.findBy({ id: In(roleIds) }));
|
||
}
|
||
|
||
hintRoles = new Map(roles.map(x => [x.id, x]));
|
||
}
|
||
|
||
return Promise.all(emojis.map(x => this.packDetailedAdmin(x, { roles: hintRoles })));
|
||
}
|
||
}
|
||
|