This commit is contained in:
syuilo 2025-05-13 18:45:27 +09:00
parent df2971e437
commit 7997ecb8cc
3 changed files with 29 additions and 9 deletions

View File

@ -39,7 +39,7 @@ import { i18n } from '@/i18n.js';
const props = defineProps<{
imageFile: File | Blob;
aspectRatio: number;
aspectRatio: number | null;
uploadFolder?: string | null;
}>();
@ -99,8 +99,8 @@ onMounted(() => {
const selection = cropper.getCropperSelection()!;
selection.themeColor = tinycolor(computedStyle.getPropertyValue('--MI_THEME-accent')).toHexString();
selection.aspectRatio = props.aspectRatio;
selection.initialAspectRatio = props.aspectRatio;
if (props.aspectRatio != null) selection.aspectRatio = props.aspectRatio;
selection.initialAspectRatio = props.aspectRatio ?? 1;
selection.outlined = true;
window.setTimeout(() => {

View File

@ -96,14 +96,18 @@ import { isWebpSupported } from '@/utility/isWebpSupported.js';
import { uploadFile } from '@/utility/upload.js';
import * as os from '@/os.js';
const $i = ensureSignin();
const compressionSupportedTypes = [
const COMPRESSION_SUPPORTED_TYPES = [
'image/jpeg',
'image/png',
'image/webp',
'image/svg+xml',
] as const;
];
const CROPPING_SUPPORTED_TYPES = [
'image/jpeg',
'image/png',
'image/webp',
];
const mimeTypeMap = {
'image/webp': 'webp',
@ -211,6 +215,21 @@ async function done() {
function showMenu(ev: MouseEvent, item: typeof items.value[0]) {
const menu: MenuItem[] = [];
if (CROPPING_SUPPORTED_TYPES.includes(item.file.type) && !item.waiting && !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 });
items.value.splice(items.value.indexOf(item), 1, {
...item,
file: markRaw(cropped),
thumbnail: window.URL.createObjectURL(cropped),
});
},
});
}
if (!item.waiting && !item.uploading && !item.uploaded) {
menu.push({
icon: 'ti ti-x',
@ -231,7 +250,7 @@ async function upload() { // エラーハンドリングなどを考慮してシ
item.waiting = true;
item.uploadFailed = false;
const shouldCompress = item.compressedImage == null && compressionLevel.value !== 0 && compressionSettings.value && compressionSupportedTypes.includes(item.file.type) && !(await isAnimated(item.file));
const shouldCompress = item.compressedImage == null && compressionLevel.value !== 0 && compressionSettings.value && COMPRESSION_SUPPORTED_TYPES.includes(item.file.type) && !(await isAnimated(item.file));
if (shouldCompress) {
const config = {
@ -275,6 +294,7 @@ async function upload() { // エラーハンドリングなどを考慮してシ
throw err;
}).finally(() => {
item.uploading = false;
item.waiting = false;
});
item.uploaded = driveFile;

View File

@ -656,7 +656,7 @@ export async function pickEmoji(src: HTMLElement, opts: ComponentProps<typeof Mk
}
export async function cropImageFile(imageFile: File | Blob, options: {
aspectRatio: number;
aspectRatio: number | null;
}): Promise<File> {
return new Promise(resolve => {
const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkCropperDialog.vue')), {