summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2025-06-26 12:10:15 +0900
committersyuilo <4439005+syuilo@users.noreply.github.com>2025-06-26 12:10:15 +0900
commitbf57557ba3566689bef97134f3c637aa43dd3605 (patch)
treea58e96c56bd6ea7d6772804dda84d33810bc536b
parentrefactor (diff)
downloadmisskey-bf57557ba3566689bef97134f3c637aa43dd3605.tar.gz
misskey-bf57557ba3566689bef97134f3c637aa43dd3605.tar.bz2
misskey-bf57557ba3566689bef97134f3c637aa43dd3605.zip
refactor(frontend): refactor uploader image editing features and menu
Replaces separate 'effect' and 'crop' features with a unified 'imageEditing' feature in the uploader. Groups crop and effect actions under a new parent 'editImage' menu item, adds localization for 'editImage', and updates supported types accordingly.
-rw-r--r--locales/index.d.ts4
-rw-r--r--locales/ja-JP.yml1
-rw-r--r--packages/frontend/src/composables/use-uploader.ts112
3 files changed, 56 insertions, 61 deletions
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 2ba4d7b0e4..52b333b689 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -11992,6 +11992,10 @@ export interface Locale extends ILocale {
};
"_uploader": {
/**
+ * 画像の編集
+ */
+ "editImage": string;
+ /**
* {x}に圧縮
*/
"compressedToX": ParameterizedString<"x">;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index 98b00c8435..dea1c4e4fa 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -3208,6 +3208,7 @@ _serverSetupWizard:
text3: "支援者向け特典もあります!"
_uploader:
+ editImage: "画像の編集"
compressedToX: "{x}に圧縮"
savedXPercent: "{x}%節約"
abortConfirm: "アップロードされていないファイルがありますが、中止しますか?"
diff --git a/packages/frontend/src/composables/use-uploader.ts b/packages/frontend/src/composables/use-uploader.ts
index ec01ed1a3c..6f4ed81f82 100644
--- a/packages/frontend/src/composables/use-uploader.ts
+++ b/packages/frontend/src/composables/use-uploader.ts
@@ -19,9 +19,8 @@ import { ensureSignin } from '@/i.js';
import { WatermarkRenderer } from '@/utility/watermark.js';
export type UploaderFeatures = {
- effect?: boolean;
+ imageEditing?: boolean;
watermark?: boolean;
- crop?: boolean;
};
const THUMBNAIL_SUPPORTED_TYPES = [
@@ -38,12 +37,6 @@ const IMAGE_COMPRESSION_SUPPORTED_TYPES = [
'image/svg+xml',
];
-const CROPPING_SUPPORTED_TYPES = [
- 'image/jpeg',
- 'image/png',
- 'image/webp',
-];
-
const IMAGE_EDITING_SUPPORTED_TYPES = [
'image/jpeg',
'image/png',
@@ -55,7 +48,6 @@ const WATERMARK_SUPPORTED_TYPES = IMAGE_EDITING_SUPPORTED_TYPES;
const IMAGE_PREPROCESS_NEEDED_TYPES = [
...WATERMARK_SUPPORTED_TYPES,
...IMAGE_COMPRESSION_SUPPORTED_TYPES,
- ...CROPPING_SUPPORTED_TYPES,
...IMAGE_EDITING_SUPPORTED_TYPES,
];
@@ -112,17 +104,14 @@ export function useUploader(options: {
multiple?: boolean;
features?: UploaderFeatures;
} = {}) {
- const $i = ensureSignin();
-
const events = new EventEmitter<{
'itemUploaded': (ctx: { item: UploaderItem; }) => void;
}>();
const uploaderFeatures = computed<Required<UploaderFeatures>>(() => {
return {
- effect: options.features?.effect ?? true,
+ imageEditing: options.features?.imageEditing ?? true,
watermark: options.features?.watermark ?? true,
- crop: options.features?.crop ?? true,
};
});
@@ -215,60 +204,61 @@ export function useUploader(options: {
}
if (
- uploaderFeatures.value.crop &&
- CROPPING_SUPPORTED_TYPES.includes(item.file.type) &&
- !item.preprocessing &&
- !item.uploading &&
- !item.uploaded
- ) {
- menu.push({
- icon: 'ti ti-crop',
- text: i18n.ts.cropImage,
- action: async () => {
- const cropped = await os.cropImageFile(item.file, { aspectRatio: null });
- if (item.thumbnail != null) URL.revokeObjectURL(item.thumbnail);
- items.value.splice(items.value.indexOf(item), 1, {
- ...item,
- file: markRaw(cropped),
- thumbnail: window.URL.createObjectURL(cropped),
- });
- const reactiveItem = items.value.find(x => x.id === item.id)!;
- preprocess(reactiveItem).then(() => {
- triggerRef(items);
- });
- },
- });
- }
-
- if (
- uploaderFeatures.value.effect &&
+ uploaderFeatures.value.imageEditing &&
IMAGE_EDITING_SUPPORTED_TYPES.includes(item.file.type) &&
!item.preprocessing &&
!item.uploading &&
!item.uploaded
) {
menu.push({
- icon: 'ti ti-sparkles',
- text: i18n.ts._imageEffector.title + ' (BETA)',
- action: async () => {
- const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkImageEffectorDialog.vue').then(x => x.default), {
- image: item.file,
- }, {
- ok: (file) => {
- if (item.thumbnail != null) URL.revokeObjectURL(item.thumbnail);
- items.value.splice(items.value.indexOf(item), 1, {
- ...item,
- file: markRaw(file),
- thumbnail: window.URL.createObjectURL(file),
- });
- const reactiveItem = items.value.find(x => x.id === item.id)!;
- preprocess(reactiveItem).then(() => {
- triggerRef(items);
- });
- },
- closed: () => dispose(),
- });
- },
+ type: 'parent',
+ icon: 'ti ti-photo-edit',
+ text: i18n.ts._uploader.editImage,
+ children: [{
+ icon: 'ti ti-crop',
+ text: i18n.ts.cropImage,
+ action: async () => {
+ const cropped = await os.cropImageFile(item.file, { aspectRatio: null });
+ if (item.thumbnail != null) URL.revokeObjectURL(item.thumbnail);
+ items.value.splice(items.value.indexOf(item), 1, {
+ ...item,
+ file: markRaw(cropped),
+ thumbnail: window.URL.createObjectURL(cropped),
+ });
+ const reactiveItem = items.value.find(x => x.id === item.id)!;
+ preprocess(reactiveItem).then(() => {
+ triggerRef(items);
+ });
+ },
+ }, /*{
+ icon: 'ti ti-resize',
+ text: i18n.ts.resize,
+ action: async () => {
+ // TODO
+ },
+ },*/ {
+ icon: 'ti ti-sparkles',
+ text: i18n.ts._imageEffector.title + ' (BETA)',
+ action: async () => {
+ const { dispose } = await os.popupAsyncWithDialog(import('@/components/MkImageEffectorDialog.vue').then(x => x.default), {
+ image: item.file,
+ }, {
+ ok: (file) => {
+ if (item.thumbnail != null) URL.revokeObjectURL(item.thumbnail);
+ items.value.splice(items.value.indexOf(item), 1, {
+ ...item,
+ file: markRaw(file),
+ thumbnail: window.URL.createObjectURL(file),
+ });
+ const reactiveItem = items.value.find(x => x.id === item.id)!;
+ preprocess(reactiveItem).then(() => {
+ triggerRef(items);
+ });
+ },
+ closed: () => dispose(),
+ });
+ },
+ }],
});
}