mirror of
https://github.com/luanslimadev/Wand-Enhancer.git
synced 2026-08-28 22:01:17 +00:00
Added basic app skeleton
This commit is contained in:
+27
-2
@@ -2,9 +2,34 @@
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<title>WeMod Patcher</title>
|
||||
<link rel="stylesheet" href="styles.css">
|
||||
</head>
|
||||
<body>
|
||||
Setup with electron
|
||||
<div class="container">
|
||||
<div class="main-section">
|
||||
<div class="header">
|
||||
<h1>WeMod Patcher</h1>
|
||||
<p>Select the folder with the WeMod version like: “app-X.XX.X” and click patch</p>
|
||||
</div>
|
||||
|
||||
<div class="path-section">
|
||||
<label for="file-path">Folder path:</label>
|
||||
<div class="path-input-container">
|
||||
<input type="text" id="file-path" class="path-input" placeholder="Select file..." readonly>
|
||||
<button class="browse-btn" id="browse-btn">Browse</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button id="patch-btn" class="patch-btn" disabled>
|
||||
Patch
|
||||
</button>
|
||||
|
||||
<div class="log-section">
|
||||
<div class="log-entry info">Waiting for action...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,26 +1,92 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const path = require('path')
|
||||
const { app, BrowserWindow, ipcMain, dialog } = require('electron');
|
||||
const path = require('path');
|
||||
const fs = require("fs");
|
||||
|
||||
app.disableHardwareAcceleration()
|
||||
app.commandLine.appendSwitch('disable-http-cache')
|
||||
|
||||
function createWindow () {
|
||||
function createWindow() {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
resizable: false,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: {
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
spellcheck: false
|
||||
},
|
||||
autoHideMenuBar: true
|
||||
})
|
||||
contextIsolation: false
|
||||
}
|
||||
});
|
||||
|
||||
win.loadFile('index.html')
|
||||
win.loadFile('index.html');
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow)
|
||||
const checkWeModPath = (root) => fs.existsSync(path.join(root, 'WeMod.exe')) &&
|
||||
fs.existsSync(path.join(root, 'resources/app.asar'))
|
||||
|
||||
app.whenReady().then(createWindow);
|
||||
|
||||
app.on('window-all-closed', () => {
|
||||
app.quit()
|
||||
})
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.handle('select-file', async () => {
|
||||
const result = await dialog.showOpenDialog({
|
||||
properties: ["openDirectory"],
|
||||
defaultPath: process.env.LOCALAPPDATA || path.join(process.env.HOME || process.env.USERPROFILE, 'AppData', 'Local')
|
||||
});
|
||||
|
||||
if (!result.canceled && result.filePaths.length > 0) {
|
||||
return {
|
||||
filePath: result.filePaths[0],
|
||||
fileName: path.basename(result.filePaths[0]),
|
||||
valid: checkWeModPath(result.filePaths[0])
|
||||
};
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
ipcMain.handle('resolve-default-path', async () => {
|
||||
const defaultDir = path.join(process.env.LOCALAPPDATA || path.join(process.env.HOME || process.env.USERPROFILE, 'AppData', 'Local'), 'WeMod');
|
||||
|
||||
if (!fs.existsSync(defaultDir)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const items = fs.readdirSync(defaultDir, {withFileTypes: true});
|
||||
const appFolders = items
|
||||
.filter(item => item.isDirectory() && /^app-\w+/.test(item.name))
|
||||
.map(item => {
|
||||
const folderPath = path.join(defaultDir, item.name);
|
||||
const stats = fs.statSync(folderPath);
|
||||
return {
|
||||
name: item.name,
|
||||
path: folderPath,
|
||||
mtime: stats.mtime,
|
||||
};
|
||||
});
|
||||
|
||||
let appDir = null;
|
||||
appFolders.sort((a, b) => b.mtime - a.mtime);
|
||||
for (const folder of appFolders) {
|
||||
if (checkWeModPath(folder.path)) {
|
||||
appDir = folder.path;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return appDir;
|
||||
})
|
||||
|
||||
ipcMain.handle('start-patch', async (event, filePath) => {
|
||||
try {
|
||||
// stub
|
||||
return {
|
||||
success: true,
|
||||
message: 'Patch completed successfully!'
|
||||
};
|
||||
} catch (error) {
|
||||
return {
|
||||
success: false,
|
||||
message: error.message
|
||||
};
|
||||
}
|
||||
});
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
const { ipcRenderer } = require('electron');
|
||||
|
||||
class PatcherUI {
|
||||
constructor() {
|
||||
this.selectedPath = '';
|
||||
this.initializeElements();
|
||||
this.bindEvents();
|
||||
}
|
||||
|
||||
initializeElements() {
|
||||
this.filePathInput = document.getElementById('file-path');
|
||||
this.browseBtn = document.getElementById('browse-btn');
|
||||
this.patchBtn = document.getElementById('patch-btn');
|
||||
this.logSection = document.querySelector('.log-section');
|
||||
}
|
||||
|
||||
bindEvents() {
|
||||
this.browseBtn.addEventListener('click', () => this.selectFile());
|
||||
this.patchBtn.addEventListener('click', () => this.startPatch());
|
||||
}
|
||||
|
||||
setPath(path) {
|
||||
this.filePathInput.value = this.selectedPath = path
|
||||
this.patchBtn.disabled = !path;
|
||||
}
|
||||
|
||||
async selectFile() {
|
||||
try {
|
||||
const result = await ipcRenderer.invoke('select-file');
|
||||
if (!result?.filePath) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!result.valid) {
|
||||
this.addLog(`The folder “${result.filePath}” is not recognized as a Wemod directory`, 'error')
|
||||
return;
|
||||
}
|
||||
|
||||
this.setPath(result.filePath)
|
||||
this.addLog('Folder selected: ' + result.fileName, 'info');
|
||||
} catch (error) {
|
||||
this.addLog('Error selecting file: ' + error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
addLog(message, type = 'info') {
|
||||
const entry = document.createElement('div');
|
||||
entry.className = `log-entry ${type}`;
|
||||
entry.textContent = `[${new Date().toLocaleTimeString()}] ${message}`;
|
||||
this.logSection.appendChild(entry);
|
||||
this.logSection.scrollTop = this.logSection.scrollHeight;
|
||||
}
|
||||
|
||||
async startPatch() {
|
||||
if (!this.selectedPath) return;
|
||||
|
||||
this.patchBtn.disabled = true;
|
||||
this.addLog('Starting patch process...', 'info');
|
||||
|
||||
try {
|
||||
const result = await ipcRenderer.invoke('start-patch', this.selectedPath);
|
||||
this.addLog(result.message, result.success ? 'success' : 'error');
|
||||
} catch (error) {
|
||||
this.addLog('Patch failed: ' + error.message, 'error');
|
||||
} finally {
|
||||
this.patchBtn.disabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
resolveDefault() {
|
||||
ipcRenderer.invoke("resolve-default-path").then(path => {
|
||||
this.addLog(path ? 'The WeMod folder has been found!' :
|
||||
"WeMod folder was not found. You need to specify the path manually", path ? "success" : "warning"
|
||||
);
|
||||
this.setPath(path)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', async() => {
|
||||
const ui = new PatcherUI();
|
||||
await ui.resolveDefault()
|
||||
});
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: #191a33;
|
||||
color: #beb2b2;
|
||||
padding: 0 50px 0 50px;
|
||||
height: 100vh;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.container {
|
||||
background: #21223d;
|
||||
padding: 24px;
|
||||
border: 1px solid #1e2039;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
margin: auto;
|
||||
gap: 24px;
|
||||
}
|
||||
|
||||
.main-section {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.header h1 {
|
||||
font-size: 26px;
|
||||
margin-bottom: 8px;
|
||||
color: #6d67fd;
|
||||
background: #3a3881;
|
||||
border-radius: 10px;
|
||||
padding: 5px 10px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.header p {
|
||||
color: #beb2b2;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.path-section {
|
||||
background: #26254b;
|
||||
padding: 16px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #1e2039;
|
||||
}
|
||||
|
||||
.path-section label {
|
||||
display: block;
|
||||
margin-bottom: 8px;
|
||||
font-size: 13px;
|
||||
color: #f8f6f6;
|
||||
}
|
||||
|
||||
.path-input-container {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.path-input {
|
||||
flex: 1;
|
||||
background: #21223d;
|
||||
color: #beb2b2;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #6d67fd;
|
||||
border-radius: 4px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.browse-btn {
|
||||
background: #6d67fd;
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
color: #f8f6f6;
|
||||
transition: background 0.2s;
|
||||
}
|
||||
|
||||
.browse-btn:hover {
|
||||
background: #6d67fd;
|
||||
}
|
||||
|
||||
.patch-btn {
|
||||
background: #6d67fd;
|
||||
color: #f8f6f6;
|
||||
border: none;
|
||||
padding: 12px 24px;
|
||||
border-radius: 4px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
|
||||
.patch-btn:hover:enabled {
|
||||
scale: 105%;
|
||||
}
|
||||
|
||||
.patch-btn:disabled {
|
||||
background: #3a3881;
|
||||
cursor: not-allowed;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.log-section {
|
||||
background: #26254b;
|
||||
color: #beb2b2;
|
||||
padding: 16px;
|
||||
border-radius: 6px;
|
||||
height: 100%;
|
||||
font-family: monospace;
|
||||
font-size: 14px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #1e2039;
|
||||
}
|
||||
|
||||
.log-entry {
|
||||
margin-bottom: 8px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: #08fc81;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #f04343;
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: #facc15;
|
||||
}
|
||||
|
||||
.info {
|
||||
color: #6d67fd;
|
||||
}
|
||||
Reference in New Issue
Block a user