Skip to content

Commit

Permalink
Add converter test and update UI elements
Browse files Browse the repository at this point in the history
  • Loading branch information
Thavarshan committed Sep 12, 2024
1 parent c522f2d commit 1dcad8f
Show file tree
Hide file tree
Showing 37 changed files with 631 additions and 146 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
![Comet UI 1](./assets/screenshot_1.png)
![Comet UI 2](./assets/screenshot_2.png)
![Comet UI 3](./assets/screenshot_3.png)
![Comet UI 4](./assets/screenshot_4.png)
![Comet UI 4](./assets/screenshot_4.png)
![Comet UI 5](./assets/screenshot_5.png)
![Comet UI 6](./assets/screenshot_6.png)

<p align="center"><a href="https://comet.thavarshan.com" target="_blank"><img src="./assets/demo.gif" width="600" alt="Comet Demo"></a></p>

Expand Down
Binary file modified assets/screenshot_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/screenshot_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/screenshot_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshot_4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshot_5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/screenshot_6.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 0 additions & 3 deletions forge.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ const config: ForgeConfig = {
win32metadata: {
CompanyName: author.name,
OriginalFilename: productName,
},
osxSign: {
identity: `Developer ID Application: ${author.name}`,
}
},
rebuildConfig: {},
Expand Down
3 changes: 2 additions & 1 deletion forge.env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ declare global {
selectDirectory: () => Promise<string | undefined>;
getDesktopPath: () => string;
getFilePath: (file: File) => string;
cancelConversion: (id: number | string) => Promise<unknown>;
cancelConversion: () => Promise<unknown>;
cancelItemConversion: (id: number | string) => Promise<unknown>;
convertVideo: (id: string, filePath: string, outputFormat: string, saveDirectory: string) => Promise<string>;
on: (channel: string, callback: (event: Electron.IpcRendererEvent, ...args: unknown[]) => void) => void;
removeAllListeners: (channel: string) => void;
Expand Down
8 changes: 6 additions & 2 deletions jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@
import type { Config } from 'jest';

const config: Config = {
bail: true,
verbose: true,
silent: false,
bail: false,
clearMocks: true,
collectCoverageFrom: ['src/**/*.{ts,tsx}', '!**/*.d.ts', '!**/*constants.ts'],
coveragePathIgnorePatterns: ['/node_modules/', '/tests/.*\\.(ts|js)$'],
Expand All @@ -28,8 +30,10 @@ const config: Config = {
"^@vue/test-utils": "<rootDir>/node_modules/@vue/test-utils/dist/vue-test-utils.cjs.js",
"radix-vue": "<rootDir>/node_modules/radix-vue/dist/radix-vue.cjs.js",
'\\.(css|less|scss|sass)$': 'identity-obj-proxy',
"^.+\\.(svg|png|jpg|jpeg|gif)$": "jest-transform-stub",

},
resetMocks: true,
resetMocks: false,
resetModules: true,
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
testEnvironment: "jsdom",
Expand Down
1 change: 1 addition & 0 deletions src/consts/ffprobe.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const INITIAL_PROGRESS = 0;
50 changes: 42 additions & 8 deletions src/consts/formats.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,47 @@
import { AudioFormat } from '@/enum/audio-format';
import { VideoFormat } from '@/enum/video-format';

export const VIDEO_CONVERSION_FORMATS = [
'mp4', 'webm', 'ogg', 'flv', 'avi',
'mov', 'wmv', '3gp', 'mkv', 'm4v',
'mpg', 'mpeg', 'vob', 'ts', 'asf',
'f4v', 'h264', 'hevc', 'm2ts', 'm2v',
'mts', 'ogv', 'rm', 'swf', 'xvid',
VideoFormat.MP4,
VideoFormat.WEBM,
VideoFormat.OGG,
VideoFormat.FLV,
VideoFormat.AVI,
VideoFormat.MOV,
VideoFormat.WMV,
VideoFormat.GP3,
VideoFormat.MKV,
VideoFormat.M4V,
VideoFormat.MPG,
VideoFormat.MPEG,
VideoFormat.VOB,
VideoFormat.TS,
VideoFormat.ASF,
VideoFormat.F4V,
VideoFormat.H264,
VideoFormat.HEVC,
VideoFormat.M2TS,
VideoFormat.M2V,
VideoFormat.MTS,
VideoFormat.OGV,
VideoFormat.RM,
VideoFormat.SWF
];

export const AUDIO_CONVERSION_FORMATS = [
'mp3', 'wav', 'ogg', 'm4a', 'flac',
'wma', 'aac', 'amr', 'aiff', 'au',
'mka', 'ac3', 'ape', 'mpc', 'opus',
AudioFormat.MP3,
AudioFormat.WAV,
AudioFormat.OGG,
AudioFormat.M4A,
AudioFormat.FLAC,
AudioFormat.WMA,
AudioFormat.AAC,
AudioFormat.AMR,
AudioFormat.AIFF,
AudioFormat.AU,
AudioFormat.MKA,
AudioFormat.AC3,
AudioFormat.APE,
AudioFormat.MPC,
AudioFormat.OPUS
];
7 changes: 7 additions & 0 deletions src/enum/arch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export enum Architecture {
IA32 = 'ia32',
X64 = 'x64',
ARM = 'arm',
ARM64 = 'arm64',
UNKNOWN = 'unknown'
}
17 changes: 17 additions & 0 deletions src/enum/audio-format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export enum AudioFormat {
MP3 = 'mp3',
WAV = 'wav',
OGG = 'ogg',
M4A = 'm4a',
FLAC = 'flac',
WMA = 'wma',
AAC = 'aac',
AMR = 'amr',
AIFF = 'aiff',
AU = 'au',
MKA = 'mka',
AC3 = 'ac3',
APE = 'ape',
MPC = 'mpc',
OPUS = 'opus',
}
3 changes: 0 additions & 3 deletions src/enum/ffprobe.ts

This file was deleted.

12 changes: 11 additions & 1 deletion src/enum/ipc-event.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export enum IpcEvent {
CANCEL_CONVERSION = 'cancel-conversion',
CANCEL_ITEM_CONVERSION = 'cancel-item-conversion',
CONVERT_VIDEO = 'convert-video',
DIALOG_SELECT_DIRECTORY = 'dialog:select-directory',
GET_DESKTOP_PATH = 'get-desktop-path',
Expand All @@ -15,8 +16,17 @@ export enum IpcEvent {

export const ipcMainEvents = [
IpcEvent.CANCEL_CONVERSION,
IpcEvent.CANCEL_ITEM_CONVERSION,
IpcEvent.CONVERT_VIDEO,
IpcEvent.DIALOG_SELECT_DIRECTORY,
IpcEvent.GET_DESKTOP_PATH
IpcEvent.GET_DESKTOP_PATH,
IpcEvent.SHOW_WINDOW,
IpcEvent.CLICK_TITLEBAR_MAC,
IpcEvent.SET_NATIVE_THEME,
IpcEvent.IS_DEV_MODE,
IpcEvent.OPEN_EXTERNAL_LINK,
IpcEvent.GET_PROJECT_NAME,
IpcEvent.LOAD_GIST_REQUEST,
IpcEvent.LOAD_ELECTRON_EXAMPLE_REQUEST,
];

5 changes: 5 additions & 0 deletions src/enum/platform.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum Platform {
DARWIN = 'darwin',
LINUX = 'linux',
WIN32 = 'win32'
}
26 changes: 26 additions & 0 deletions src/enum/video-format.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export enum VideoFormat {
MP4 = 'mp4',
WEBM = 'webm',
FLV = 'flv',
AVI = 'avi',
MOV = 'mov',
WMV = 'wmv',
GP3 = '3gp',
MKV = 'mkv',
M4V = 'm4v',
MPG = 'mpg',
MPEG = 'mpeg',
VOB = 'vob',
TS = 'ts',
ASF = 'asf',
F4V = 'f4v',
H264 = 'h264',
HEVC = 'hevc',
M2TS = 'm2ts',
M2V = 'm2v',
MTS = 'mts',
OGV = 'ogv',
RM = 'rm',
SWF = 'swf',
XVID = 'xvid',
}
78 changes: 33 additions & 45 deletions src/lib/ffmpeg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ const ffmpegProcesses = new Map<string, ffmpeg.FfmpegCommand>();
*
* @param {string} id
* @param {ffmpeg.FfmpegCommand} ffmpegCommand
*
* @returns {void}
*/
export function setFfmpegProcess(id: string, ffmpegCommand: ffmpeg.FfmpegCommand): void {
ffmpegProcesses.set(id, ffmpegCommand);
Expand All @@ -21,51 +19,30 @@ let ffmpegPath: string;
let ffprobePath: string;

try {
if (!ffmpegStatic) {
throw new Error('ffmpegStatic not found');
}
if (!ffmpegStatic) throw new Error('ffmpegStatic not found');
ffmpegPath = ffmpegStatic.replace('app.asar', 'app.asar.unpacked');
ffprobePath = ffprobe.path.replace('app.asar', 'app.asar.unpacked');

ffmpeg.setFfmpegPath(ffmpegPath);
ffmpeg.setFfprobePath(ffprobePath);
} catch (error) {
console.error('Failed to find ffmpegStatic:', error.message);
// Handle the failure gracefully, e.g., by setting default paths or exiting the application
ffmpegPath = ''; // or any other default value or action
ffprobePath = ''; // or any other default value or action
}

/**
* Parse a timemark string into seconds
*
* @param {string} timemark
*
* @returns {number}
* Parse a timemark string into seconds.
*/
export function parseTimemark(timemark: string): number {
const parts = timemark.split(':').reverse();
let seconds = 0;

if (parts.length > 0) seconds += parseFloat(parts[0]);
if (parts.length > 1) seconds += parseInt(parts[1]) * 60;
if (parts.length > 2) seconds += parseInt(parts[2]) * 3600;

return seconds;
}

/**
* Handle the video conversion process
*
* @param {Electron.IpcMainInvokeEvent} event
* @param {string} id
* @param {string} filePath
* @param {string} outputFormat
* @param {string} saveDirectory
* @param {(value: string) => void} resolve
* @param {(reason: unknown) => void} reject
*
* @returns {void}
* Handle the video conversion process.
*/
export function handleConversion(
event: Electron.IpcMainInvokeEvent,
Expand All @@ -76,9 +53,7 @@ export function handleConversion(
resolve: (value: string) => void,
reject: (reason: unknown) => void
): void {
const outputFileName = path.basename(filePath, path.extname(filePath))
+ '.'
+ outputFormat;
const outputFileName = `${path.basename(filePath, path.extname(filePath))}.${outputFormat}`;
const outputPath = path.join(saveDirectory, outputFileName);

ffmpeg.ffprobe(filePath, (err, metadata) => {
Expand All @@ -94,11 +69,7 @@ export function handleConversion(
.on('progress', (progress) => {
const processedSeconds = parseTimemark(progress.timemark);
const calculatedProgress = duration ? (processedSeconds / duration) * 100 : 0;

event.sender.send('conversion-progress', {
id,
progress: calculatedProgress
});
event.sender.send('conversion-progress', { id, progress: calculatedProgress });
})
.on('end', () => {
ffmpegProcesses.delete(id);
Expand All @@ -108,9 +79,9 @@ export function handleConversion(
ffmpegProcesses.delete(id);
if (error.message.includes('SIGKILL')) {
reject(new Error('Conversion canceled by user'));
return;
} else {
reject(error);
}
reject(error);
})
.save(outputPath);

Expand All @@ -119,25 +90,42 @@ export function handleConversion(
}

/**
* Handle the video conversion cancellation
*
* @param {Electron.IpcMainInvokeEvent} event
* @param {string} id
*
* @returns {boolean}
* Cancel a single FFmpeg process.
*/
export function handleConversionCancellation(
export function handleItemConversionCancellation(
_event: Electron.IpcMainInvokeEvent,
id: string
): boolean {
const ffmpegCommand = ffmpegProcesses.get(id);

if (!ffmpegCommand) {
console.warn(`No FFmpeg process found for ID: ${id}`);
return false;
}

ffmpegCommand.kill('SIGKILL');
ffmpegProcesses.delete(id);
try {
// Send SIGKILL to forcefully stop the process
ffmpegCommand.kill('SIGKILL');
ffmpegProcesses.delete(id);
return true;
} catch (error) {
console.error(`Failed to kill FFmpeg process for ID: ${id}`, error);
return false;
}
}

/**
* Cancel all FFmpeg processes.
*/
export function handleConversionCancellation(_event: Electron.IpcMainInvokeEvent): boolean {
for (const [id, ffmpegCommand] of ffmpegProcesses.entries()) {
try {
ffmpegCommand.kill('SIGKILL');
ffmpegProcesses.delete(id);
} catch (error) {
console.error(`Failed to kill FFmpeg process for ID: ${id}`, error);
return false;
}
}
return true;
}
11 changes: 9 additions & 2 deletions src/lib/ipc-handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { getDesktopPath } from './desktop-path';
import { IpcEvent } from '../enum/ipc-event';
import {
handleConversion,
handleConversionCancellation
handleConversionCancellation,
handleItemConversionCancellation
} from './ffmpeg';

/**
Expand Down Expand Up @@ -53,9 +54,15 @@ export function configureIpcHandlers(ipcMain: IpcMain): void {
});

ipcMain.handle(IpcEvent.CANCEL_CONVERSION, (
event: IpcMainInvokeEvent
) => {
return handleConversionCancellation(event);
});

ipcMain.handle(IpcEvent.CANCEL_ITEM_CONVERSION, (
event: IpcMainInvokeEvent,
id: string
) => {
return handleConversionCancellation(event, id);
return handleItemConversionCancellation(event, id);
});
}
5 changes: 3 additions & 2 deletions src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@ import type { BrowserWindowConstructorOptions } from 'electron';
import { Windows } from './enum/windows';
import path from 'node:path';
import { isDevMode } from './lib/devmode';
import { Platform } from './enum/platform';

export const browserWindowOptions = {
width: isDevMode() ? Windows.DEV_WIDTH : Windows.WIDTH,
height: Windows.HEIGHT,
minHeight: Windows.MIN_HEIGHT,
minWidth: Windows.MIN_WIDTH,
titleBarStyle: process.platform === 'darwin' ? 'hiddenInset' : undefined,
titleBarOverlay: process.platform === 'darwin',
titleBarStyle: process.platform === Platform.DARWIN ? 'hiddenInset' : undefined,
titleBarOverlay: process.platform === Platform.DARWIN,
resizable: false,
autoHideMenuBar: true,
acceptFirstMouse: true,
Expand Down
Loading

0 comments on commit 1dcad8f

Please sign in to comment.