summaryrefslogtreecommitdiff
path: root/packages/frontend/src/utility
diff options
context:
space:
mode:
Diffstat (limited to 'packages/frontend/src/utility')
-rw-r--r--packages/frontend/src/utility/drive.ts26
-rw-r--r--packages/frontend/src/utility/image-effector/ImageEffector.ts14
-rw-r--r--packages/frontend/src/utility/watermark.ts23
3 files changed, 41 insertions, 22 deletions
diff --git a/packages/frontend/src/utility/drive.ts b/packages/frontend/src/utility/drive.ts
index 0e10f80145..bc1813f48c 100644
--- a/packages/frontend/src/utility/drive.ts
+++ b/packages/frontend/src/utility/drive.ts
@@ -16,6 +16,7 @@ import { instance } from '@/instance.js';
import { globalEvents } from '@/events.js';
import { getProxiedImageUrl } from '@/utility/media-proxy.js';
import { genId } from '@/utility/id.js';
+import type { UploaderDialogFeatures } from '@/components/MkUploaderDialog.vue';
type UploadReturnType = {
filePromise: Promise<Misskey.entities.DriveFile>;
@@ -155,6 +156,7 @@ export function uploadFile(file: File | Blob, options: {
export function chooseFileFromPcAndUpload(
options: {
multiple?: boolean;
+ features?: UploaderDialogFeatures;
folderId?: string | null;
} = {},
): Promise<Misskey.entities.DriveFile[]> {
@@ -163,6 +165,7 @@ export function chooseFileFromPcAndUpload(
if (files.length === 0) return;
os.launchUploader(files, {
folderId: options.folderId,
+ features: options.features,
}).then(driveFiles => {
res(driveFiles);
});
@@ -194,7 +197,7 @@ export function chooseFileFromUrl(): Promise<Misskey.entities.DriveFile> {
type: 'url',
placeholder: i18n.ts.uploadFromUrlDescription,
}).then(({ canceled, result: url }) => {
- if (canceled) return;
+ if (canceled || url == null) return;
const marker = genId();
@@ -221,7 +224,7 @@ export function chooseFileFromUrl(): Promise<Misskey.entities.DriveFile> {
});
}
-function select(anchorElement: HTMLElement | EventTarget | null, label: string | null, multiple: boolean): Promise<Misskey.entities.DriveFile[]> {
+function select(anchorElement: HTMLElement | EventTarget | null, label: string | null, multiple: boolean, features?: UploaderDialogFeatures): Promise<Misskey.entities.DriveFile[]> {
return new Promise((res, rej) => {
os.popupMenu([label ? {
text: label,
@@ -229,7 +232,7 @@ function select(anchorElement: HTMLElement | EventTarget | null, label: string |
} : undefined, {
text: i18n.ts.upload,
icon: 'ti ti-upload',
- action: () => chooseFileFromPcAndUpload({ multiple }).then(files => res(files)),
+ action: () => chooseFileFromPcAndUpload({ multiple, features }).then(files => res(files)),
}, {
text: i18n.ts.fromDrive,
icon: 'ti ti-cloud',
@@ -242,12 +245,19 @@ function select(anchorElement: HTMLElement | EventTarget | null, label: string |
});
}
-export function selectFile(anchorElement: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile> {
- return select(anchorElement, label, false).then(files => files[0]);
-}
+type SelectFileOptions<M extends boolean> = {
+ anchorElement: HTMLElement | EventTarget | null;
+ multiple: M;
+ label?: string | null;
+ features?: UploaderDialogFeatures;
+};
-export function selectFiles(anchorElement: HTMLElement | EventTarget | null, label: string | null = null): Promise<Misskey.entities.DriveFile[]> {
- return select(anchorElement, label, true);
+export async function selectFile<
+ M extends boolean,
+ MR extends M extends true ? Misskey.entities.DriveFile[] : Misskey.entities.DriveFile
+>(opts: SelectFileOptions<M>): Promise<MR> {
+ const files = await select(opts.anchorElement, opts.label ?? null, opts.multiple ?? false, opts.features);
+ return opts.multiple ? (files as MR) : (files[0]! as MR);
}
export async function createCroppedImageDriveFileFromImageDriveFile(imageDriveFile: Misskey.entities.DriveFile, options: {
diff --git a/packages/frontend/src/utility/image-effector/ImageEffector.ts b/packages/frontend/src/utility/image-effector/ImageEffector.ts
index fe253017e5..80e3ff65de 100644
--- a/packages/frontend/src/utility/image-effector/ImageEffector.ts
+++ b/packages/frontend/src/utility/image-effector/ImageEffector.ts
@@ -57,7 +57,7 @@ function getValue<T extends keyof ParamTypeToPrimitive>(params: Record<string, a
return params[k];
}
-export class ImageEffector {
+export class ImageEffector<IEX extends ReadonlyArray<ImageEffectorFx<any, any, any>>> {
private gl: WebGL2RenderingContext;
private canvas: HTMLCanvasElement | null = null;
private renderTextureProgram: WebGLProgram;
@@ -70,7 +70,7 @@ export class ImageEffector {
private shaderCache: Map<string, WebGLProgram> = new Map();
private perLayerResultTextures: Map<string, WebGLTexture> = new Map();
private perLayerResultFrameBuffers: Map<string, WebGLFramebuffer> = new Map();
- private fxs: ImageEffectorFx[];
+ private fxs: [...IEX];
private paramTextures: Map<string, { texture: WebGLTexture; width: number; height: number; }> = new Map();
constructor(options: {
@@ -78,7 +78,7 @@ export class ImageEffector {
renderWidth: number;
renderHeight: number;
image: ImageData | ImageBitmap | HTMLImageElement | HTMLCanvasElement;
- fxs: ImageEffectorFx[];
+ fxs: [...IEX];
}) {
this.canvas = options.canvas;
this.renderWidth = options.renderWidth;
@@ -230,7 +230,7 @@ export class ImageEffector {
gl: gl,
program: shaderProgram,
params: Object.fromEntries(
- Object.entries(fx.params).map(([key, param]) => {
+ Object.entries(fx.params as ImageEffectorFxParamDefs).map(([key, param]) => {
return [key, layer.params[key] ?? param.default];
}),
),
@@ -238,7 +238,7 @@ export class ImageEffector {
width: this.renderWidth,
height: this.renderHeight,
textures: Object.fromEntries(
- Object.entries(fx.params).map(([k, v]) => {
+ Object.entries(fx.params as ImageEffectorFxParamDefs).map(([k, v]) => {
if (v.type !== 'texture') return [k, null];
const param = getValue<typeof v.type>(layer.params, k);
if (param == null) return [k, null];
@@ -329,7 +329,7 @@ export class ImageEffector {
unused.delete(textureKey);
if (this.paramTextures.has(textureKey)) continue;
- console.log(`Baking texture of <${textureKey}>...`);
+ if (_DEV_) console.log(`Baking texture of <${textureKey}>...`);
const texture = v.type === 'text' ? await createTextureFromText(this.gl, v.text) : v.type === 'url' ? await createTextureFromUrl(this.gl, v.url) : null;
if (texture == null) continue;
@@ -339,7 +339,7 @@ export class ImageEffector {
}
for (const k of unused) {
- console.log(`Dispose unused texture <${k}>...`);
+ if (_DEV_) console.log(`Dispose unused texture <${k}>...`);
this.gl.deleteTexture(this.paramTextures.get(k)!.texture);
this.paramTextures.delete(k);
}
diff --git a/packages/frontend/src/utility/watermark.ts b/packages/frontend/src/utility/watermark.ts
index 8ee93181a6..f0b38684f0 100644
--- a/packages/frontend/src/utility/watermark.ts
+++ b/packages/frontend/src/utility/watermark.ts
@@ -3,13 +3,20 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/
-import { FX_watermarkPlacement } from './image-effector/fxs/watermarkPlacement.js';
-import { FX_stripe } from './image-effector/fxs/stripe.js';
-import { FX_polkadot } from './image-effector/fxs/polkadot.js';
-import { FX_checker } from './image-effector/fxs/checker.js';
-import type { ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js';
+import { FX_watermarkPlacement } from '@/utility/image-effector/fxs/watermarkPlacement.js';
+import { FX_stripe } from '@/utility/image-effector/fxs/stripe.js';
+import { FX_polkadot } from '@/utility/image-effector/fxs/polkadot.js';
+import { FX_checker } from '@/utility/image-effector/fxs/checker.js';
+import type { ImageEffectorFx, ImageEffectorLayer } from '@/utility/image-effector/ImageEffector.js';
import { ImageEffector } from '@/utility/image-effector/ImageEffector.js';
+const WATERMARK_FXS = [
+ FX_watermarkPlacement,
+ FX_stripe,
+ FX_polkadot,
+ FX_checker,
+] as const satisfies ImageEffectorFx<string, any>[];
+
export type WatermarkPreset = {
id: string;
name: string;
@@ -64,7 +71,7 @@ export type WatermarkPreset = {
};
export class WatermarkRenderer {
- private effector: ImageEffector;
+ private effector: ImageEffector<typeof WATERMARK_FXS>;
private layers: WatermarkPreset['layers'] = [];
constructor(options: {
@@ -78,7 +85,7 @@ export class WatermarkRenderer {
renderWidth: options.renderWidth,
renderHeight: options.renderHeight,
image: options.image,
- fxs: [FX_watermarkPlacement, FX_stripe, FX_polkadot, FX_checker],
+ fxs: WATERMARK_FXS,
});
}
@@ -157,6 +164,8 @@ export class WatermarkRenderer {
opacity: layer.opacity,
},
};
+ } else {
+ throw new Error(`Unknown layer type`);
}
});
}