1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
/*
* 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);
}
|