Skip to content

Commit

Permalink
Abstract media conversion into adapter pattern
Browse files Browse the repository at this point in the history
  • Loading branch information
Thavarshan committed Sep 20, 2024
1 parent e339539 commit b7bf466
Show file tree
Hide file tree
Showing 31 changed files with 740 additions and 429 deletions.
105 changes: 105 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/* eslint-env node */

const { defineConfig } = require('eslint-define-config');
const prettierConfig = require('./.prettierrc.js');

module.exports = defineConfig({
root: true,
env: {
browser: true,
es6: true,
node: true,
jest: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:import/recommended',
'plugin:import/electron',
'plugin:import/typescript',
'prettier',
'@vue/eslint-config-typescript',
'plugin:vue/vue3-essential',
'plugin:vuejs-accessibility/recommended',
],
plugins: ['prettier', 'vuejs-accessibility', '@typescript-eslint'],
parser: 'vue-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser',
ecmaVersion: 2020,
sourceType: 'module',
},
rules: {
indent: [
'error',
2,
{
SwitchCase: 1,
},
],
'max-len': [
'error',
{
code: 120,
},
],
'no-console': [
'error',
{
allow: ['warn', 'error'],
},
],
'comma-dangle': ['error', 'always-multiline'],
'space-before-function-paren': [
'warn',
{
anonymous: 'ignore',
named: 'never',
asyncArrow: 'always',
},
],
'prettier/prettier': [
'error',
{
...prettierConfig,
},
],
'vue/html-indent': ['error', 2],
'vue/multiline-html-element-content-newline': 'off',
'vue/multi-word-component-names': 'off',
'vue/max-attributes-per-line': 0,
'vue/require-default-prop': 0,
'vue/no-multiple-template-root': 0,
'@typescript-eslint/no-unused-vars': [
'warn',
{
varsIgnorePattern: '^_$',
argsIgnorePattern: '^_$',
},
],
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
project: './tsconfig.json',
},
},
},
ignorePatterns: ['*.test.ts'],
overrides: [
{
files: ['tests/**/*'],
env: {
jest: true,
},
},
{
files: ['*.vue'],
rules: {
'max-len': 'off',
},
},
],
});
119 changes: 0 additions & 119 deletions .eslintrc.json

This file was deleted.

10 changes: 0 additions & 10 deletions .prettierrc

This file was deleted.

10 changes: 10 additions & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module.exports = {
semi: true,
trailingComma: 'all',
singleQuote: true,
printWidth: 120,
tabWidth: 2,
useTabs: false,
endOfLine: 'auto',
spaceBeforeFunctionParen: false
}
12 changes: 11 additions & 1 deletion forge.env.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { Media } from '@/types/media';
import { ColorMode } from '@/types/theme';
import { VideoFormat } from '@/enum/video-format';
import { AudioFormat } from '@/enum/audio-format';
import { ImageFormat } from '@/enum/image-format';

export {}; // Make this a module

Expand Down Expand Up @@ -33,7 +37,13 @@ declare global {
getFilePath: (file: File) => string;
cancelConversion: () => Promise<unknown>;
cancelItemConversion: (id: number | string) => Promise<unknown>;
convertVideo: (id: string, filePath: string, outputFormat: string, saveDirectory: string) => Promise<string>;
convertMedia: (
id: string,
filePath: string,
outputFormat: VideoFormat | AudioFormat | ImageFormat,
saveDirectory: string,
mediaType: Media,
) => Promise<string>;
send: (channel: string, ...args: unknown[]) => void;
on: (channel: string, callback: (event: Electron.IpcRendererEvent, ...args: unknown[]) => void) => void;
removeAllListeners: (channel: string) => void;
Expand Down
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<!DOCTYPE html>
<html class="mac theme-blue light" data-theme="light">
<html class="theme-blue light" data-theme="light">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
Expand Down
2 changes: 0 additions & 2 deletions src/consts/formats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,5 @@ export const IMAGE_CONVERSION_FORMATS = [
ImageFormat.BMP,
ImageFormat.GIF,
ImageFormat.TIFF,
ImageFormat.WEBP,
ImageFormat.ICO,
ImageFormat.JPEG,
];
2 changes: 0 additions & 2 deletions src/enum/image-format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,5 @@ export enum ImageFormat {
BMP = 'bmp',
GIF = 'gif',
TIFF = 'tiff',
WEBP = 'webp',
ICO = 'ico',
JPEG = 'jpeg',
}
5 changes: 5 additions & 0 deletions src/enum/media.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum Media {
VIDEO = 'video',
IMAGE = 'image',
AUDIO = 'audio',
}
72 changes: 72 additions & 0 deletions src/lib/conversion/conversion-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Media } from '@/types/media';
import { Media as MediaType } from '@/enum/media';
import { VideoFormat } from '@/enum/video-format';
import { AudioFormat } from '@/enum/audio-format';
import { ImageFormat } from '@/enum/image-format';
import { FfmpegAdapter } from './ffmpeg';
import { JimpAdapter } from './jimp';

export class ConversionHandler {
protected conversions: Map<string, FfmpegAdapter | JimpAdapter> = new Map();

/**
* Adds a new conversion to the handler.
*/
handle(
id: string,
filePath: string,
outputFormat: VideoFormat | AudioFormat | ImageFormat,
saveDirectory: string,
type: Media,
event: Electron.IpcMainInvokeEvent,
): Promise<string> {
const adapter = this.getAdapter(type);

return new Promise((resolve, reject) => {
this.conversions.set(id, adapter);

adapter
.convert(id, filePath, outputFormat, saveDirectory, event)
.then(() => {
this.conversions.delete(id);
resolve(filePath);
})
.catch((error) => {
this.conversions.delete(id);
reject(error);
});
});
}

/**
* Cancels the conversion with the given ID.
*/
cancel(id: string): boolean {
const adapter = this.conversions.get(id);
return adapter ? adapter.cancel(id) : false;
}

/**
* Cancels all conversions.
*/
cancelAll(): void {
this.conversions.forEach((adapter, id) => adapter.cancel(id));
this.conversions.clear();
}

/**
* Returns the appropriate adapter for the given type.
*/
protected getAdapter(type: Media) {
switch (type) {
case MediaType.IMAGE:
return new JimpAdapter();
case MediaType.VIDEO:
return new FfmpegAdapter();
case MediaType.AUDIO:
return new FfmpegAdapter();
default:
throw new Error(`Unsupported type: ${type}`);
}
}
}
Loading

0 comments on commit b7bf466

Please sign in to comment.