f9ad127aaf
* 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>
160 lines
4.9 KiB
TypeScript
160 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 })));
|
|
}
|
|
}
|
|
|