barkey/packages/frontend/src/scripts/select-file.ts
おさむのひと f9ad127aaf
feat: 新カスタム絵文字管理画面(β)の追加 (#13473)
* 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>
2025-01-20 11:35:37 +00:00

130 lines
3.9 KiB
TypeScript

/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { ref } from 'vue';
import * as Misskey from 'misskey-js';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { useStream } from '@/stream.js';
import { i18n } from '@/i18n.js';
import { defaultStore } from '@/store.js';
import { uploadFile } from '@/scripts/upload.js';
export function chooseFileFromPc(
multiple: boolean,
options?: {
uploadFolder?: string | null;
keepOriginal?: boolean;
nameConverter?: (file: File) => string | undefined;
},
): Promise<Misskey.entities.DriveFile[]> {
const uploadFolder = options?.uploadFolder ?? defaultStore.state.uploadFolder;
const keepOriginal = options?.keepOriginal ?? defaultStore.state.keepOriginalUploading;
const nameConverter = options?.nameConverter ?? (() => undefined);
return new Promise((res, rej) => {
const input = document.createElement('input');
input.type = 'file';
input.multiple = multiple;
input.onchange = () => {
if (!input.files) return res([]);
const promises = Array.from(
input.files,
file => uploadFile(file, uploadFolder, nameConverter(file), keepOriginal),
);
Promise.all(promises).then(driveFiles => {
res(driveFiles);
}).catch(err => {
// アップロードのエラーは uploadFile 内でハンドリングされているためアラートダイアログを出したりはしてはいけない
});
// 一応廃棄
(window as any).__misskey_input_ref__ = null;
};
// https://qiita.com/fukasawah/items/b9dc732d95d99551013d
// iOS Safari で正常に動かす為のおまじない
(window as any).__misskey_input_ref__ = input;
input.click();
});
}
export function chooseFileFromDrive(multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
return new Promise((res, rej) => {
os.selectDriveFile(multiple).then(files => {
res(files);
});
});
}
export function chooseFileFromUrl(): Promise<Misskey.entities.DriveFile> {
return new Promise((res, rej) => {
os.inputText({
title: i18n.ts.uploadFromUrl,
type: 'url',
placeholder: i18n.ts.uploadFromUrlDescription,
}).then(({ canceled, result: url }) => {
if (canceled) return;
const marker = Math.random().toString(); // TODO: UUIDとか使う
const connection = useStream().useChannel('main');
connection.on('urlUploadFinished', urlResponse => {
if (urlResponse.marker === marker) {
res(urlResponse.file);
connection.dispose();
}
});
misskeyApi('drive/files/upload-from-url', {
url: url,
folderId: defaultStore.state.uploadFolder,
marker,
});
os.alert({
title: i18n.ts.uploadFromUrlRequested,
text: i18n.ts.uploadFromUrlMayTakeTime,
});
});
});
}
function select(src: HTMLElement | EventTarget | null, label: string | null, multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
return new Promise((res, rej) => {
const keepOriginal = ref(defaultStore.state.keepOriginalUploading);
os.popupMenu([label ? {
text: label,
type: 'label',
} : undefined, {
type: 'switch',
text: i18n.ts.keepOriginalUploading,
ref: keepOriginal,
}, {
text: i18n.ts.upload,
icon: 'ti ti-upload',
action: () => chooseFileFromPc(multiple, { keepOriginal: keepOriginal.value }).then(files => res(files)),
}, {
text: i18n.ts.fromDrive,
icon: 'ti ti-cloud',
action: () => chooseFileFromDrive(multiple).then(files => res(files)),
}, {
text: i18n.ts.fromUrl,
icon: 'ti ti-link',
action: () => chooseFileFromUrl().then(file => res([file])),
}], src);
});
}
export function selectFile(src: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile> {
return select(src, label, false).then(files => files[0]);
}
export function selectFiles(src: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile[]> {
return select(src, label, true);
}