Skip to content

Commit

Permalink
Refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
nekiro committed Jan 20, 2022
1 parent 8e7a378 commit 7be4bfa
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 211 deletions.
3 changes: 1 addition & 2 deletions App.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { app, BrowserWindow } from 'electron';
import Main from './src/Main';

Main.main(app, BrowserWindow);
Main.main();
3 changes: 1 addition & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ Languages: html, typescript, css
## Installation

Nekiro's Rcc Editor requires [Node.js](https://nodejs.org/) to run.
Install the dependencies and start the main script.
Install the dependencies and start.

```sh
cd nekiro-rcc-editor
npm i
npm run compile
npm run start
```

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
"description": "edit qt .rcc files",
"main": "build/App.js",
"scripts": {
"start": "electron-forge start",
"start": "npm run compile && electron-forge start",
"build": "npm run compile && electron-forge make",
"compile": "tsc && copyfiles src/html/*.html src/css/*.css src/assets/* src/rcc/rcc.exe build",
"package": "electron-forge package",
"build": "npm run compile && electron-forge make"
"package": "electron-forge package"
},
"author": "Nekiro",
"license": "MIT",
Expand Down
22 changes: 10 additions & 12 deletions src/Main.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
import { BrowserWindow, Menu, dialog, shell, app } from 'electron';
import { loadRcc, saveRcc, extractToPng } from './reader';
import path from 'path';
require('./ipc/main');
import RccLib from './RccLib';
import './ipc/Main';

export default class Main {
static mainWindow: Electron.BrowserWindow;
static application: Electron.App;
static BrowserWindow: any;

private static onWindowAllClosed() {
if (process.platform !== 'darwin') {
Expand All @@ -15,7 +14,7 @@ export default class Main {
}

private static createWindow() {
Main.mainWindow = new Main.BrowserWindow({
Main.mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
Expand All @@ -41,7 +40,7 @@ export default class Main {
});

if (!result.canceled) {
loadRcc(result.filePaths.pop() ?? null);
RccLib.loadRcc(result.filePaths.pop());
}
},
},
Expand All @@ -54,13 +53,13 @@ export default class Main {
});

if (!result.canceled) {
extractToPng(result.filePaths.pop() ?? null);
RccLib.extractToPng(result.filePaths.pop());
}
},
},
{
label: 'Save rcc',
click: () => saveRcc(),
click: () => RccLib.saveRcc(),
},
{
label: 'Save rcc as',
Expand All @@ -70,7 +69,7 @@ export default class Main {
});

if (!result.canceled) {
saveRcc(result.filePath);
RccLib.saveRcc(result.filePath);
}
},
},
Expand All @@ -95,13 +94,12 @@ export default class Main {
Main.mainWindow.show();
});

//Main.mainWindow.webContents.openDevTools();
Main.mainWindow.webContents.openDevTools();
}

static main(app: Electron.App, browserWindow: typeof BrowserWindow) {
if (require('electron-squirrel-startup')) return;
static main() {
if (require('electron-squirrel-startup')) return; // fixes launching app during installation/uninstallation

Main.BrowserWindow = browserWindow;
Main.application = app;
Main.application.on('window-all-closed', Main.onWindowAllClosed);
Main.application.on('ready', Main.onReady);
Expand Down
176 changes: 176 additions & 0 deletions src/RccLib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
import { app, dialog } from 'electron';
import path from 'path';
import util from 'util';
const execFile = util.promisify(require('child_process').execFile);
import fs from 'fs-extra';
import Main from './Main';
import { Image } from './Types';

const imageExt: Array<string> = ['.png', '.jpg'];

// TODO: refactor this method
const getFiles = async (path = './') => {
const entries = await fs.readdir(path, { withFileTypes: true });
const files = entries
.filter((file: any) => !file.isDirectory())
.map((file: any) => ({ ...file, path: path + file.name }));

const folders = entries.filter((folder: any) => folder.isDirectory());
for (const folder of folders) {
files.push(...(await getFiles(`${path}/${folder.name}/`)));
}
return files;
};

export default class RccLib {
static images: Image[] = [];
static loadedFilePath: string | undefined = undefined;
static localPath: string = path.resolve(
app.isPackaged ? process.resourcesPath : __dirname,
'rcc'
);

public static async loadRcc(filePath?: string): Promise<void> {
if (!filePath) {
return;
}

// clear previous images
this.images = [];

// delete res directory
if (fs.existsSync(path.join(this.localPath, 'qresource'))) {
await fs.rmdir(path.join(this.localPath, 'qresource'), {
recursive: true,
});
}

await fs.copyFile(filePath, path.join(this.localPath, 'res.rcc'));

await execFile(path.join(this.localPath, 'rcc.exe'), ['--reverse'], {
cwd: `${this.localPath}/`,
});

// get directory content
const files: any[] = await getFiles(
path.join(this.localPath, 'qresource', 'res', 'res.rcc')
);

for (const file of files) {
this.images.push({
name: path.parse(file.name).name,
path: path.relative(
path.join(this.localPath, 'qresource', 'res', 'res.rcc'),
file.path
),
isImage: imageExt.includes(path.extname(file.path)),
data: Buffer.from(await fs.readFile(file.path, 'binary'), 'binary'),
});
}

// sort by name
this.images.sort((a, b) => a.name.localeCompare(b.name));

// cleanup
await fs.rmdir(path.join(this.localPath, 'qresource'), { recursive: true });
await fs.rm(path.join(this.localPath, 'res.rcc'));

this.loadedFilePath = filePath;

Main.mainWindow.webContents.send('populate-list', this.images);
}

public static async extractToPng(directoryPath?: string): Promise<void> {
if (!directoryPath || !this.images.length) {
dialog.showErrorBox('Error', 'Nothing to extract.');
return;
}

for (const image of this.images) {
if (image.isImage) {
await fs.outputFile(
path.join(directoryPath as string, image.path),
image.data
);
}
}

dialog.showMessageBox(Main.mainWindow, {
message: `Png images extracted successfully. Extracted ${this.images.length} images.`,
type: 'info',
});
}

public static async saveRcc(
filePath: string | undefined = this.loadedFilePath
): Promise<void> {
if (!filePath || this.images.length === 0) {
return;
}

// create .qrc file
let data = '<!DOCTYPE RCC><RCC version="1.0">\n<qresource>\n';

for (const image of this.images) {
data += `<file>${image.path}</file>\n`;
}

data += '</qresource>\n</RCC>';

await fs.outputFile(path.join(this.localPath, 'res', 'res.qrc'), data);

// dump images
for (const image of this.images) {
await fs.outputFile(
path.join(this.localPath, 'res', image.path),
image.data
);
}

await execFile(
path.join(this.localPath, 'rcc.exe'),
[
'--format-version',
'1',
'--binary',
'./res/res.qrc',
'-o',
'./res/res_output.rcc',
],
{
cwd: `${this.localPath}/`,
}
);

await fs.move(path.join(this.localPath, '/res/res_output.rcc'), filePath, {
overwrite: true,
});

// cleanup
await fs.rmdir(path.join(this.localPath, 'res'), {
recursive: true,
});

dialog.showMessageBox(Main.mainWindow, {
message: 'Rcc saved successfully.',
type: 'info',
});
}

public static async replaceImage(
index: number,
filePath: string
): Promise<Buffer | null> {
const image = this.images[index];
if (!image) {
return null;
}

image.data = Buffer.from(await fs.readFile(filePath, 'binary'), 'binary');
return image.data;
}

public static getImageByIndex(index: number): Buffer {
return this.images[index]?.data;
}
}
6 changes: 3 additions & 3 deletions src/ipc/main.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const { ipcMain } = require('electron');
import { getImageByIndex, replaceImage } from '../reader';
import RccLib from '../RccLib';

ipcMain.on('get-image-data', (event: Electron.IpcMainEvent, index: number) => {
event.reply('update-preview', getImageByIndex(index));
event.reply('update-preview', RccLib.getImageByIndex(index));
});

ipcMain.on('replace-image', async (event: Electron.IpcMainEvent, obj) => {
const data = await replaceImage(obj.index, obj.path);
const data = await RccLib.replaceImage(obj.index, obj.path);
if (data) {
event.reply('update-preview', data);
event.reply('update-miniature', { index: obj.index, data });
Expand Down
38 changes: 18 additions & 20 deletions src/ipc/renderer.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,33 @@
//renderer process
import { ipcRenderer } from 'electron';
import { ImageBuffer } from '../types';
import { ImageBuffer } from '../Types';

const preview: any = document.querySelector('.preview');
const list: any = document.querySelector('.list');
let focused: any = null;

if (preview) {
preview.addEventListener('drop', (event: any) => {
event.preventDefault();
event.stopPropagation();
preview?.addEventListener('drop', (event: any) => {
event.preventDefault();
event.stopPropagation();

if (!focused) {
return;
}
if (!focused) {
return;
}

ipcRenderer.send('replace-image', {
index: parseInt(focused.id.split('-')[1], 10),
path: event.dataTransfer.files[0].path,
});
ipcRenderer.send('replace-image', {
index: parseInt(focused.id.split('-')[1], 10),
path: event.dataTransfer.files[0].path,
});
});

preview.addEventListener('dragover', (event: any) => {
event.preventDefault();
event.stopPropagation();
});
}
preview?.addEventListener('dragover', (event: any) => {
event.preventDefault();
event.stopPropagation();
});

ipcRenderer.on(
'update-preview',
(event: Electron.IpcRendererEvent, data: Buffer) => {
(_: Electron.IpcRendererEvent, data: Buffer) => {
if (preview) {
preview.src = `data:image/png;base64,${Buffer.from(data).toString(
'base64'
Expand All @@ -40,7 +38,7 @@ ipcRenderer.on(

ipcRenderer.on(
'update-miniature',
(event: Electron.IpcRendererEvent, { index, data }: ImageBuffer) => {
(_: Electron.IpcRendererEvent, { index, data }: ImageBuffer) => {
list.querySelector(
`#btn-${index} > img`
).src = `data:image/png;base64,${Buffer.from(data).toString('base64')}`;
Expand All @@ -49,7 +47,7 @@ ipcRenderer.on(

ipcRenderer.on(
'populate-list',
(event: Electron.IpcRendererEvent, images: any[]) => {
(_: Electron.IpcRendererEvent, images: any[]) => {
focused = null;

while (list.firstChild) {
Expand Down
Loading

0 comments on commit 7be4bfa

Please sign in to comment.