summaryrefslogtreecommitdiff
path: root/packages/frontend/src
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 /packages/frontend/src
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.
Diffstat (limited to 'packages/frontend/src')
-rw-r--r--packages/frontend/src/composables/use-uploader.ts112
1 files changed, 51 insertions, 61 deletions
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(),
+ });
+ },
+ }],
});
}