1+ const fs = require ( 'fs' ) ;
2+ const path = require ( 'path' ) ;
3+ const { app, BrowserWindow, ipcMain, dialog, shell } = require ( 'electron' ) ;
4+
5+ // Converter (file)
6+ const ImageConverter = require ( './converters/ImageConverter' ) ;
7+ const Document = require ( './converters/Document' ) ;
8+ const Media = require ( './converters/Media' ) ;
9+ const { create } = require ( 'domain' ) ;
10+
11+ // Create main window
12+ function createWindow ( ) {
13+ const win = new BrowserWindow ( {
14+ width : 860 ,
15+ height : 620 ,
16+ minWidth : 720 ,
17+ minHeight : 500 ,
18+ frame : false , // for HTML
19+ transparent : false ,
20+ backgroundColor : '#0a0a0f' ,
21+ webPreferences : {
22+ preload : path . join ( __dirname , 'preload.js' ) ,
23+ contextIsolation : true , // Isolation Context
24+ nodeIntegration : false // Node.js blocked for renderer
25+ } ,
26+ icon : path . join ( __dirname , 'assets' , 'icon.ico' )
27+ } ) ;
28+
29+ // UI
30+ win . loadFile ( path . join ( __dirname , 'renderer' , 'index.html' ) ) ;
31+
32+ // Open DevTools (only develop)
33+ if ( process . env . NODE_ENV === 'development' ) {
34+ win . webContents . openDevTools ( ) ;
35+ }
36+
37+ return win ;
38+ }
39+
40+ // Start Application
41+ app . whenReady ( ) . then ( ( ) => {
42+ const win = createWindow ( ) ;
43+
44+ // MacOS
45+ app . on ( 'activate' , ( ) => {
46+ if ( BrowserWindow . getAllWindows ( ) . length === 0 ) createWindow ( ) ;
47+ } ) ;
48+ } ) ;
49+
50+ // Close Application
51+ app . on ( 'window-all-closed' , ( ) => {
52+ if ( process . platform !== 'darwin' ) app . quit ( ) ;
53+ } ) ;
54+
55+ // IPC - renderer
56+ ipcMain . handle ( 'dialog:openFile' , async ( ) => {
57+ const { canceled, filePaths } = await dialog . showOpenDialog ( {
58+ title : 'Pick file for convert' ,
59+ properties : [ 'openFile' ] ,
60+ filters : [
61+ { name : 'Photo' , extensions : [ 'jpg' , 'jpeg' , 'png' , 'webp' , 'avif' , 'tiff' , 'bmp' , 'gif' ] } ,
62+ { name : 'Documents' , extensions : [ 'pdf' , 'docx' , 'txt' , 'html' ] } ,
63+ { name : 'Audio' , extensions : [ 'mp3' , 'wav' , 'flac' , 'aac' , 'ogg' , 'm4a' ] } ,
64+ { name : 'Video' , extensions : [ 'mp4' , 'avi' , 'mkv' , 'mov' , 'webm' , 'wmv' ] } ,
65+ { name : 'All File' , extensions : [ '*' ] } ,
66+ ] ,
67+ } ) ;
68+
69+ if ( canceled || filePaths . length === 0 ) return null ;
70+
71+ const filePath = filePaths [ 0 ] ;
72+
73+ // Back basic info file
74+ return {
75+ path : filePath ,
76+ name : path . basename ( filePath ) ,
77+ ext : path . extname ( filePath ) . toLowerCase ( ) . replace ( '.' , '' ) ,
78+ size : fs . statSync ( filePath ) . size ,
79+ } ;
80+ } ) ;
81+
82+ // IPC - open
83+ ipcMain . handle ( 'dialog:saveFile' , async ( _ , { defaultName, ext } ) => {
84+ const { canceled, filePath } = await dialog . showSaveDialog ( {
85+ title : 'Uložit převedený soubor' ,
86+ defaultPath : defaultName ,
87+ filters : [ { name : ext . toUpperCase ( ) , extensions : [ ext ] } ] ,
88+ } ) ;
89+
90+ if ( canceled ) return null ;
91+ return filePath ;
92+ } ) ;
93+
94+ // IPC - converter
95+ ipcMain . handle ( 'file:convert' , async ( _ , { inputPath, outputPath, targetFormat } ) => {
96+ const inputExt = path . extname ( inputPath ) . toLowerCase ( ) . replace ( '.' , '' ) ;
97+
98+ try {
99+ // Determine file type and select converter
100+
101+ if ( isImage ( inputExt ) ) {
102+ // Convert image using sharp
103+ await ImageConverter . convert ( inputPath , outputPath , targetFormat ) ;
104+
105+ } else if ( isDocument ( inputExt ) ) {
106+ // Convert document
107+ await Document . convert ( inputPath , outputPath , targetFormat ) ;
108+
109+ } else if ( isMedia ( inputExt ) ) {
110+ // Convert audio or video using FFmpeg
111+ await Media . convert ( inputPath , outputPath , targetFormat ) ;
112+
113+ } else {
114+ throw new Error ( `Unsupported input file format: .${ inputExt } ` ) ;
115+ }
116+
117+ return { success : true , outputPath } ;
118+
119+ } catch ( err ) {
120+ // Return the error back to the renderer
121+ return { success : false , error : err . message } ;
122+ }
123+ } ) ;
124+
125+ // IPC - open folder
126+ ipcMain . handle ( 'shell:showInFolder' , async ( _ , filePath ) => {
127+ shell . showItemInFolder ( filePath ) ;
128+ } ) ;
129+
130+ // IPC - window
131+ ipcMain . on ( 'window:minimize' , ( ) => {
132+ BrowserWindow . getFocusedWindow ( ) ?. minimize ( ) ;
133+ } ) ;
134+
135+ ipcMain . on ( 'window:maximize' , ( ) => {
136+ const win = BrowserWindow . getFocusedWindow ( ) ;
137+ if ( ! win ) return ;
138+ win . isMaximized ( ) ? win . unmaximize ( ) : win . maximize ( ) ;
139+ } ) ;
140+
141+ ipcMain . on ( 'window:close' , ( ) => {
142+ BrowserWindow . getFocusedWindow ( ) ?. close ( ) ;
143+ } ) ;
144+
145+ // Helper function
146+ function isImage ( ext ) {
147+ return [ 'jpg' , 'jpeg' , 'png' , 'webp' , 'avif' , 'tiff' , 'tif' , 'bmp' , 'gif' ] . includes ( ext ) ;
148+ }
149+
150+ /** Returns true if the extension is a document format */
151+ function isDocument ( ext ) {
152+ return [ 'pdf' , 'docx' , 'txt' , 'html' , 'htm' ] . includes ( ext ) ;
153+ }
154+
155+ /** Returns true if the extension is an audio or video format */
156+ function isMedia ( ext ) {
157+ return [ 'mp3' , 'wav' , 'flac' , 'aac' , 'ogg' , 'm4a' , 'mp4' , 'avi' , 'mkv' , 'mov' , 'webm' , 'wmv' ] . includes ( ext ) ;
158+ }
0 commit comments