This commit is contained in:
samunohito 2024-02-08 08:12:04 +09:00
parent e84790e619
commit b7192e5ac6
4 changed files with 97 additions and 82 deletions

View File

@ -1,11 +1,3 @@
import * as Misskey from 'misskey-js';
export type EmojiOperationResult = {
item: GridItem,
success: boolean,
err?: Error
};
export type RequestLogItem = { export type RequestLogItem = {
failed: boolean; failed: boolean;
url: string; url: string;
@ -13,52 +5,15 @@ export type RequestLogItem = {
error?: string; error?: string;
}; };
export type GridItem = { export function emptyStrToUndefined(value: string | null) {
checked: boolean; return value ? value : undefined;
id?: string;
fileId?: string;
url: string;
name: string;
host: string;
category: string;
aliases: string;
license: string;
isSensitive: boolean;
localOnly: boolean;
roleIdsThatCanBeUsedThisEmojiAsReaction: string;
} }
export function fromEmojiDetailedAdmin(it: Misskey.entities.EmojiDetailedAdmin): GridItem { export function emptyStrToNull(value: string) {
return { return value === '' ? null : value;
checked: false,
id: it.id,
fileId: undefined,
url: it.publicUrl,
name: it.name,
host: it.host ?? '',
category: it.category ?? '',
aliases: it.aliases.join(', '),
license: it.license ?? '',
isSensitive: it.isSensitive,
localOnly: it.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: it.roleIdsThatCanBeUsedThisEmojiAsReaction.join(', '),
};
} }
export function fromDriveFile(it: Misskey.entities.DriveFile): GridItem { export function emptyStrToEmptyArray(value: string) {
return { return value === '' ? [] : value.split(',').map(it => it.trim());
checked: false,
id: undefined,
fileId: it.id,
url: it.url,
name: it.name.replace(/(\.[a-zA-Z0-9]+)+$/, ''),
host: '',
category: '',
aliases: '',
license: '',
isSensitive: it.isSensitive,
localOnly: false,
roleIdsThatCanBeUsedThisEmojiAsReaction: '',
};
} }

View File

@ -103,7 +103,12 @@
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { fromEmojiDetailedAdmin, GridItem, RequestLogItem } from '@/pages/admin/custom-emojis-grid.impl.js'; import {
emptyStrToEmptyArray,
emptyStrToNull,
emptyStrToUndefined,
RequestLogItem,
} from '@/pages/admin/custom-emojis-grid.impl.js';
import MkGrid from '@/components/grid/MkGrid.vue'; import MkGrid from '@/components/grid/MkGrid.vue';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import MkInput from '@/components/MkInput.vue'; import MkInput from '@/components/MkInput.vue';
@ -128,9 +133,19 @@ import MkFolder from '@/components/MkFolder.vue';
import MkSelect from '@/components/MkSelect.vue'; import MkSelect from '@/components/MkSelect.vue';
import { deviceKind } from '@/scripts/device-kind.js'; import { deviceKind } from '@/scripts/device-kind.js';
const emptyStrToUndefined = (value: string | null) => value ? value : undefined; type GridItem = {
const emptyStrToNull = (value: string) => value === '' ? null : value; checked: boolean;
const emptyStrToEmptyArray = (value: string) => value === '' ? [] : value.split(',').map(it => it.trim()); id: string;
url: string;
name: string;
host: string;
category: string;
aliases: string;
license: string;
isSensitive: boolean;
localOnly: boolean;
roleIdsThatCanBeUsedThisEmojiAsReaction: string;
}
const gridSetting: GridSetting = { const gridSetting: GridSetting = {
rowNumberVisible: true, rowNumberVisible: true,
@ -312,7 +327,7 @@ function onGridEvent(event: GridEvent, currentState: GridCurrentState) {
onGridCellContextMenu(event, currentState); onGridCellContextMenu(event, currentState);
break; break;
case 'cell-value-change': case 'cell-value-change':
onGridCellValueChange(event, currentState); onGridCellValueChange(event);
break; break;
case 'keydown': case 'keydown':
onGridKeyDown(event, currentState); onGridKeyDown(event, currentState);
@ -372,7 +387,7 @@ function onGridCellContextMenu(event: GridCellContextMenuEvent, currentState: Gr
); );
} }
function onGridCellValueChange(event: GridCellValueChangeEvent, currentState: GridCurrentState) { function onGridCellValueChange(event: GridCellValueChangeEvent) {
const { row, column, newValue } = event; const { row, column, newValue } = event;
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) { if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
gridItems.value[row.index][column.setting.bindTo] = newValue; gridItems.value[row.index][column.setting.bindTo] = newValue;
@ -442,7 +457,20 @@ async function refreshCustomEmojis() {
} }
function refreshGridItems() { function refreshGridItems() {
gridItems.value = customEmojis.value.map(it => fromEmojiDetailedAdmin(it)); gridItems.value = customEmojis.value.map(it => ({
checked: false,
id: it.id,
fileId: undefined,
url: it.publicUrl,
name: it.name,
host: it.host ?? '',
category: it.category ?? '',
aliases: it.aliases.join(', '),
license: it.license ?? '',
isSensitive: it.isSensitive,
localOnly: it.localOnly,
roleIdsThatCanBeUsedThisEmojiAsReaction: it.roleIdsThatCanBeUsedThisEmojiAsReaction.join(', '),
}));
originGridItems.value = JSON.parse(JSON.stringify(gridItems.value)); originGridItems.value = JSON.parse(JSON.stringify(gridItems.value));
} }

View File

@ -76,9 +76,8 @@ import * as Misskey from 'misskey-js';
import { onMounted, ref } from 'vue'; import { onMounted, ref } from 'vue';
import { misskeyApi } from '@/scripts/misskey-api.js'; import { misskeyApi } from '@/scripts/misskey-api.js';
import { import {
EmojiOperationResult, emptyStrToEmptyArray,
fromDriveFile, emptyStrToNull,
GridItem,
RequestLogItem, RequestLogItem,
} from '@/pages/admin/custom-emojis-grid.impl.js'; } from '@/pages/admin/custom-emojis-grid.impl.js';
import MkGrid from '@/components/grid/MkGrid.vue'; import MkGrid from '@/components/grid/MkGrid.vue';
@ -113,6 +112,19 @@ type FolderItem = {
name: string; name: string;
}; };
type GridItem = {
fileId: string;
url: string;
name: string;
host: string;
category: string;
aliases: string;
license: string;
isSensitive: boolean;
localOnly: boolean;
roleIdsThatCanBeUsedThisEmojiAsReaction: string;
}
const required = validators.required(); const required = validators.required();
const regex = validators.regex(/^[a-zA-Z0-9_]+$/); const regex = validators.regex(/^[a-zA-Z0-9_]+$/);
const columnSettings: ColumnSetting[] = [ const columnSettings: ColumnSetting[] = [
@ -126,10 +138,6 @@ const columnSettings: ColumnSetting[] = [
{ bindTo: 'roleIdsThatCanBeUsedThisEmojiAsReaction', title: 'role', type: 'text', editable: true, width: 100 }, { bindTo: 'roleIdsThatCanBeUsedThisEmojiAsReaction', title: 'role', type: 'text', editable: true, width: 100 },
]; ];
const emit = defineEmits<{
(ev: 'operation:registered'): void;
}>();
const uploadFolders = ref<FolderItem[]>([]); const uploadFolders = ref<FolderItem[]>([]);
const gridItems = ref<GridItem[]>([]); const gridItems = ref<GridItem[]>([]);
const selectedFolderId = ref(defaultStore.state.uploadFolder); const selectedFolderId = ref(defaultStore.state.uploadFolder);
@ -150,12 +158,9 @@ async function onRegistryClicked() {
return; return;
} }
const items = new Map<string, GridItem>(gridItems.value.map(it => [`${it.fileId}|${it.name}`, it])); const items = gridItems.value;
const upload = (): Promise<EmojiOperationResult>[] => { const upload = () => {
const emptyStrToNull = (value: string) => value === '' ? null : value; return items.slice(0, MAXIMUM_EMOJI_COUNT)
const emptyStrToEmptyArray = (value: string) => value === '' ? [] : value.split(',').map(it => it.trim());
return [...items.values()].slice(0, MAXIMUM_EMOJI_COUNT)
.map(item => .map(item =>
misskeyApi( misskeyApi(
'admin/emoji/add', { 'admin/emoji/add', {
@ -194,8 +199,6 @@ async function onRegistryClicked() {
// //
const successItems = result.filter(it => it.success).map(it => it.item); const successItems = result.filter(it => it.success).map(it => it.item);
gridItems.value = gridItems.value.filter(it => !successItems.includes(it)); gridItems.value = gridItems.value.filter(it => !successItems.includes(it));
emit('operation:registered');
} }
async function onClearClicked() { async function onClearClicked() {
@ -255,7 +258,7 @@ async function onDrop(ev: DragEvent) {
gridItems.value.push(...items); gridItems.value.push(...items);
} }
async function onFileSelectClicked(ev: MouseEvent) { async function onFileSelectClicked() {
const driveFiles = await os.promiseDialog( const driveFiles = await os.promiseDialog(
chooseFileFromPc( chooseFileFromPc(
true, true,
@ -271,7 +274,7 @@ async function onFileSelectClicked(ev: MouseEvent) {
gridItems.value.push(...driveFiles.map(fromDriveFile)); gridItems.value.push(...driveFiles.map(fromDriveFile));
} }
async function onDriveSelectClicked(ev: MouseEvent) { async function onDriveSelectClicked() {
const driveFiles = await os.promiseDialog(chooseFileFromDrive(true)); const driveFiles = await os.promiseDialog(chooseFileFromDrive(true));
gridItems.value.push(...driveFiles.map(fromDriveFile)); gridItems.value.push(...driveFiles.map(fromDriveFile));
} }
@ -288,7 +291,7 @@ function onGridEvent(event: GridEvent, currentState: GridCurrentState) {
onGridCellContextMenu(event, currentState); onGridCellContextMenu(event, currentState);
break; break;
case 'cell-value-change': case 'cell-value-change':
onGridCellValueChange(event, currentState); onGridCellValueChange(event);
break; break;
case 'keydown': case 'keydown':
onGridKeyDown(event, currentState); onGridKeyDown(event, currentState);
@ -334,7 +337,7 @@ function onGridCellContextMenu(event: GridCellContextMenuEvent, currentState: Gr
); );
} }
function onGridCellValueChange(event: GridCellValueChangeEvent, currentState: GridCurrentState) { function onGridCellValueChange(event: GridCellValueChangeEvent) {
const { row, column, newValue } = event; const { row, column, newValue } = event;
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) { if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
gridItems.value[row.index][column.setting.bindTo] = newValue; gridItems.value[row.index][column.setting.bindTo] = newValue;
@ -345,6 +348,21 @@ function onGridKeyDown(event: GridKeyDownEvent, currentState: GridCurrentState)
optInGridUtils.defaultKeyDownHandler(gridItems, event, currentState); optInGridUtils.defaultKeyDownHandler(gridItems, event, currentState);
} }
function fromDriveFile(it: Misskey.entities.DriveFile): GridItem {
return {
fileId: it.id,
url: it.url,
name: it.name.replace(/(\.[a-zA-Z0-9]+)+$/, ''),
host: '',
category: '',
aliases: '',
license: '',
isSensitive: it.isSensitive,
localOnly: false,
roleIdsThatCanBeUsedThisEmojiAsReaction: '',
};
}
async function refreshUploadFolders() { async function refreshUploadFolders() {
const result = await misskeyApi('drive/folders', {}); const result = await misskeyApi('drive/folders', {});
uploadFolders.value = Array.of<FolderItem>({ name: '-' }, ...result); uploadFolders.value = Array.of<FolderItem>({ name: '-' }, ...result);

View File

@ -52,7 +52,7 @@ import MkButton from '@/components/MkButton.vue';
import MkInput from '@/components/MkInput.vue'; import MkInput from '@/components/MkInput.vue';
import MkGrid from '@/components/grid/MkGrid.vue'; import MkGrid from '@/components/grid/MkGrid.vue';
import { ColumnSetting } from '@/components/grid/column.js'; import { ColumnSetting } from '@/components/grid/column.js';
import { fromEmojiDetailedAdmin, GridItem, RequestLogItem } from '@/pages/admin/custom-emojis-grid.impl.js'; import { RequestLogItem } from '@/pages/admin/custom-emojis-grid.impl.js';
import { import {
GridCellContextMenuEvent, GridCellContextMenuEvent,
GridCellValueChangeEvent, GridCellValueChangeEvent,
@ -66,6 +66,14 @@ import MkFolder from '@/components/MkFolder.vue';
import XRegisterLogs from '@/pages/admin/custom-emojis-grid.local.logs.vue'; import XRegisterLogs from '@/pages/admin/custom-emojis-grid.local.logs.vue';
import * as os from '@/os.js'; import * as os from '@/os.js';
type GridItem = {
checked: boolean;
id: string;
url: string;
name: string;
host: string;
}
const columnSettings: ColumnSetting[] = [ const columnSettings: ColumnSetting[] = [
{ bindTo: 'checked', icon: 'ti-download', type: 'boolean', editable: true, width: 34 }, { bindTo: 'checked', icon: 'ti-download', type: 'boolean', editable: true, width: 34 },
{ bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto' }, { bindTo: 'url', icon: 'ti-icons', type: 'image', editable: false, width: 'auto' },
@ -109,7 +117,7 @@ function onGridEvent(event: GridEvent, currentState: GridCurrentState) {
onGridCellContextMenu(event, currentState); onGridCellContextMenu(event, currentState);
break; break;
case 'cell-value-change': case 'cell-value-change':
onGridCellValueChange(event, currentState); onGridCellValueChange(event);
break; break;
case 'keydown': case 'keydown':
onGridKeyDown(event, currentState); onGridKeyDown(event, currentState);
@ -146,7 +154,7 @@ function onGridCellContextMenu(event: GridCellContextMenuEvent, currentState: Gr
); );
} }
function onGridCellValueChange(event: GridCellValueChangeEvent, currentState: GridCurrentState) { function onGridCellValueChange(event: GridCellValueChangeEvent) {
const { row, column, newValue } = event; const { row, column, newValue } = event;
if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) { if (gridItems.value.length > row.index && column.setting.bindTo in gridItems.value[row.index]) {
gridItems.value[row.index][column.setting.bindTo] = newValue; gridItems.value[row.index][column.setting.bindTo] = newValue;
@ -173,7 +181,7 @@ async function importEmojis(targets: GridItem[]) {
const confirm = await os.confirm({ const confirm = await os.confirm({
type: 'info', type: 'info',
title: '絵文字のインポート', title: '絵文字のインポート',
text: `リモートから受信した${targets.length}個の絵文字のインポートを行います。絵文字のライセンスに十分な注意を払ってください。インポートを行いますか?`, text: `リモートから受信した${targets.length}個の絵文字のインポートを行います。絵文字のライセンスに十分な注意を払ってください。実行しますか?`,
}); });
if (confirm.canceled) { if (confirm.canceled) {
@ -214,7 +222,13 @@ async function refreshCustomEmojis(query?: string, host?: string, sinceId?: stri
}); });
customEmojis.value = emojis.emojis; customEmojis.value = emojis.emojis;
gridItems.value = customEmojis.value.map(it => fromEmojiDetailedAdmin(it)); gridItems.value = customEmojis.value.map(it => ({
checked: false,
id: it.id,
url: it.uri!,
name: it.name,
host: it.host!,
}));
} }
onMounted(async () => { onMounted(async () => {