diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index 0b5794d1e3..6f6dbfc8cc 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -116,7 +116,7 @@ import { formatTimeString } from '@/scripts/format-time-string.js';
import { Autocomplete } from '@/scripts/autocomplete.js';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
-import { selectFiles } from '@/scripts/select-file.js';
+import { selectFile } from '@/scripts/select-file.js';
import { defaultStore, notePostInterruptors, postFormActions } from '@/store.js';
import MkInfo from '@/components/MkInfo.vue';
import { i18n } from '@/i18n.js';
@@ -413,7 +413,10 @@ function focus() {
function chooseFileFrom(ev) {
if (props.mock) return;
- selectFiles(ev.currentTarget ?? ev.target, i18n.ts.attachFile).then(files_ => {
+ selectFile(ev.currentTarget ?? ev.target, {
+ label: i18n.ts.attachFile,
+ multiple: true,
+ }).then(files_ => {
for (const file of files_) {
files.value.push(file);
}
diff --git a/packages/frontend/src/components/MkUserSetupDialog.Profile.vue b/packages/frontend/src/components/MkUserSetupDialog.Profile.vue
index 7cb48f6afb..ac7d0a6a83 100644
--- a/packages/frontend/src/components/MkUserSetupDialog.Profile.vue
+++ b/packages/frontend/src/components/MkUserSetupDialog.Profile.vue
@@ -68,7 +68,9 @@ watch(description, () => {
});
function setAvatar(ev) {
- chooseFileFromPc(false).then(async (files) => {
+ chooseFileFromPc({
+ multiple: false,
+ }).then(async (files) => {
const file = files[0];
let originalOrCropped = file;
diff --git a/packages/frontend/src/pages/channel-editor.vue b/packages/frontend/src/pages/channel-editor.vue
index 6d8274a55c..67fa904015 100644
--- a/packages/frontend/src/pages/channel-editor.vue
+++ b/packages/frontend/src/pages/channel-editor.vue
@@ -189,7 +189,7 @@ async function archive() {
}
function setBannerImage(evt) {
- selectFile(evt.currentTarget ?? evt.target, null).then(file => {
+ selectFile(evt.currentTarget ?? evt.target).then(file => {
bannerId.value = file.id;
});
}
diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue
index 3765319b25..eea726dbe6 100644
--- a/packages/frontend/src/pages/emoji-edit-dialog.vue
+++ b/packages/frontend/src/pages/emoji-edit-dialog.vue
@@ -121,7 +121,7 @@ watch(roleIdsThatCanBeUsedThisEmojiAsReaction, async () => {
const imgUrl = computed(() => file.value ? file.value.url : props.emoji ? `/emoji/${props.emoji.name}.webp` : null);
async function changeImage(ev: Event) {
- file.value = await selectFile(ev.currentTarget ?? ev.target, null);
+ file.value = await selectFile(ev.currentTarget ?? ev.target);
const candidate = file.value.name.replace(/\.(.+)$/, '');
if (candidate.match(/^[a-z0-9_]+$/)) {
name.value = candidate;
diff --git a/packages/frontend/src/pages/gallery/edit.vue b/packages/frontend/src/pages/gallery/edit.vue
index 70f8b2c31d..8c5be813e4 100644
--- a/packages/frontend/src/pages/gallery/edit.vue
+++ b/packages/frontend/src/pages/gallery/edit.vue
@@ -21,7 +21,7 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ file.name }}
- {{ i18n.ts.attachFile }}
+ {{ i18n.ts.attachFile }}
{{ i18n.ts.markAsSensitive }}
@@ -45,7 +45,7 @@ import MkInput from '@/components/MkInput.vue';
import MkTextarea from '@/components/MkTextarea.vue';
import MkSwitch from '@/components/MkSwitch.vue';
import FormSuspense from '@/components/form/suspense.vue';
-import { selectFiles } from '@/scripts/select-file.js';
+import { selectFile } from '@/scripts/select-file.js';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { definePageMetadata } from '@/scripts/page-metadata.js';
@@ -64,8 +64,8 @@ const description = ref(null);
const title = ref(null);
const isSensitive = ref(false);
-function selectFile(evt) {
- selectFiles(evt.currentTarget ?? evt.target, null).then(selected => {
+function chooseFile(evt) {
+ selectFile(evt.currentTarget ?? evt.target, { multiple: true }).then(selected => {
files.value = files.value.concat(selected);
});
}
diff --git a/packages/frontend/src/pages/page-editor/page-editor.vue b/packages/frontend/src/pages/page-editor/page-editor.vue
index ddb808390c..134849925d 100644
--- a/packages/frontend/src/pages/page-editor/page-editor.vue
+++ b/packages/frontend/src/pages/page-editor/page-editor.vue
@@ -217,7 +217,7 @@ async function add() {
}
function setEyeCatchingImage(img) {
- selectFile(img.currentTarget ?? img.target, null).then(file => {
+ selectFile(img.currentTarget ?? img.target).then(file => {
eyeCatchingImageId.value = file.id;
});
}
diff --git a/packages/frontend/src/pages/settings/profile.vue b/packages/frontend/src/pages/settings/profile.vue
index 561894d2b7..aaecea1aa3 100644
--- a/packages/frontend/src/pages/settings/profile.vue
+++ b/packages/frontend/src/pages/settings/profile.vue
@@ -223,7 +223,7 @@ function save() {
}
function changeAvatar(ev) {
- selectFile(ev.currentTarget ?? ev.target, i18n.ts.avatar).then(async (file) => {
+ selectFile(ev.currentTarget ?? ev.target, { label: i18n.ts.avatar }).then(async (file) => {
let originalOrCropped = file;
const { canceled } = await os.confirm({
@@ -250,7 +250,7 @@ function changeAvatar(ev) {
}
function changeBanner(ev) {
- selectFile(ev.currentTarget ?? ev.target, i18n.ts.banner).then(async (file) => {
+ selectFile(ev.currentTarget ?? ev.target, { label: i18n.ts.banner }).then(async (file) => {
let originalOrCropped = file;
const { canceled } = await os.confirm({
diff --git a/packages/frontend/src/pages/settings/sounds.sound.vue b/packages/frontend/src/pages/settings/sounds.sound.vue
index 56f65e2309..be68afed98 100644
--- a/packages/frontend/src/pages/settings/sounds.sound.vue
+++ b/packages/frontend/src/pages/settings/sounds.sound.vue
@@ -94,7 +94,9 @@ const friendlyFileName = computed(() => {
});
function selectSound(ev) {
- selectFile(ev.currentTarget ?? ev.target, i18n.ts._soundSettings.driveFile).then(async (file) => {
+ selectFile(ev.currentTarget ?? ev.target, {
+ label: i18n.ts._soundSettings.driveFile,
+ }).then(async (file) => {
if (!file.type.startsWith('audio')) {
os.alert({
type: 'warning',
diff --git a/packages/frontend/src/pages/settings/theme.vue b/packages/frontend/src/pages/settings/theme.vue
index f1ec231588..cbd128d69f 100644
--- a/packages/frontend/src/pages/settings/theme.vue
+++ b/packages/frontend/src/pages/settings/theme.vue
@@ -158,7 +158,7 @@ fetchThemes().then(() => {
});
function setWallpaper(event) {
- selectFile(event.currentTarget ?? event.target, null).then(file => {
+ selectFile(event.currentTarget ?? event.target).then(file => {
wallpaper.value = file.url;
});
}
diff --git a/packages/frontend/src/scripts/select-file.ts b/packages/frontend/src/scripts/select-file.ts
index 667226ed68..747ce3600e 100644
--- a/packages/frontend/src/scripts/select-file.ts
+++ b/packages/frontend/src/scripts/select-file.ts
@@ -9,19 +9,22 @@ import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { useStream } from '@/stream.js';
import { i18n } from '@/i18n.js';
-import { $i } from '@/account.js';
import { defaultStore } from '@/store.js';
import { uploadFile } from '@/scripts/upload.js';
import type { MenuItem } from '@/types/menu.js';
-export function chooseFileFromPc(multiple: boolean, keepOriginal = false, useWatermark = false): Promise {
+export function chooseFileFromPc(opts?: {
+ multiple?: boolean;
+ keepOriginal?: boolean;
+ useWatermark?: boolean;
+}): Promise {
return new Promise((res, rej) => {
const input = document.createElement('input');
input.type = 'file';
- input.multiple = multiple;
+ input.multiple = opts?.multiple ?? false;
input.onchange = () => {
if (!input.files) return res([]);
- const promises = Array.from(input.files, file => uploadFile(file, defaultStore.state.uploadFolder, undefined, keepOriginal, useWatermark));
+ const promises = Array.from(input.files, file => uploadFile(file, defaultStore.state.uploadFolder, undefined, opts?.keepOriginal, opts?.useWatermark));
Promise.all(promises).then(driveFiles => {
res(driveFiles);
@@ -41,9 +44,11 @@ export function chooseFileFromPc(multiple: boolean, keepOriginal = false, useWat
});
}
-export function chooseFileFromDrive(multiple: boolean): Promise {
+export function chooseFileFromDrive(opts?: {
+ multiple?: boolean;
+}): Promise {
return new Promise((res, rej) => {
- os.selectDriveFile(multiple).then(files => {
+ os.selectDriveFile(opts?.multiple ?? false).then(files => {
res(files);
});
});
@@ -82,42 +87,76 @@ export function chooseFileFromUrl(): Promise {
});
}
-function select(src: HTMLElement | EventTarget | null, label: string | null, multiple: boolean): Promise {
+function select(src: HTMLElement | EventTarget | null, opts?: {
+ label?: string;
+ multiple?: boolean;
+ dontUseWatermark?: boolean;
+}): Promise {
return new Promise((res, rej) => {
const keepOriginal = ref(defaultStore.state.keepOriginalUploading);
- const useWatermark = ref(defaultStore.state.useWatermark);
+ const useWatermark = ref(opts?.dontUseWatermark ? false : defaultStore.state.useWatermark);
- os.popupMenu([label ? {
- text: label,
- type: 'label',
- } : undefined, {
+ const menu: MenuItem[] = [];
+
+ if (opts?.label) {
+ menu.push({
+ text: opts.label,
+ type: 'label',
+ });
+ }
+
+ menu.push({
type: 'switch',
text: i18n.ts.keepOriginalUploading,
ref: keepOriginal,
- }, {
- type: 'switch',
- text: i18n.ts.useWatermark,
- ref: useWatermark,
- }, {
+ });
+
+ if (!opts?.dontUseWatermark) {
+ menu.push({
+ type: 'switch',
+ text: i18n.ts.useWatermark,
+ ref: useWatermark,
+ });
+ }
+
+ menu.push({
text: i18n.ts.upload,
icon: 'ti ti-upload',
- action: () => chooseFileFromPc(multiple, keepOriginal.value, useWatermark.value).then(files => res(files)),
+ action: () => chooseFileFromPc({
+ multiple: opts?.multiple,
+ keepOriginal: keepOriginal.value,
+ useWatermark: useWatermark.value,
+ }).then(files => res(files)),
}, {
text: i18n.ts.fromDrive,
icon: 'ti ti-cloud',
- action: () => chooseFileFromDrive(multiple).then(files => res(files)),
+ action: () => chooseFileFromDrive({ multiple: opts?.multiple }).then(files => res(files)),
}, {
text: i18n.ts.fromUrl,
icon: 'ti ti-link',
action: () => chooseFileFromUrl().then(file => res([file])),
- }], src);
+ });
+
+ os.popupMenu(menu, src);
});
}
-export function selectFile(src: HTMLElement | EventTarget | null, label: string | null = null): Promise {
- return select(src, label, false).then(files => files[0]);
-}
-
-export function selectFiles(src: HTMLElement | EventTarget | null, label: string | null = null): Promise {
- return select(src, label, true);
+export function selectFile(src: HTMLElement | EventTarget | null, opts: {
+ label?: string;
+ multiple: true;
+ dontUseWatermark?: boolean;
+}): Promise;
+export function selectFile(src: HTMLElement | EventTarget | null, opts?: {
+ label?: string;
+ multiple?: false;
+ dontUseWatermark?: boolean;
+}): Promise;
+export function selectFile(src: HTMLElement | EventTarget | null, opts?: {
+ label?: string;
+ multiple?: boolean;
+ dontUseWatermark?: boolean;
+}): Promise {
+ return select(src, opts).then(files => {
+ return opts?.multiple ? files : files[0];
+ });
}