Skip to content

Commit 5e50b18

Browse files
committed
v1.1.0
1 parent e2a7c55 commit 5e50b18

File tree

7 files changed

+1418
-107
lines changed

7 files changed

+1418
-107
lines changed

.hintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@
2020
"axe/text-alternatives": "off",
2121
"button-type": "off",
2222
"axe/name-role-value": "off",
23-
"disown-opener": "off"
23+
"disown-opener": "off",
24+
"no-inline-styles": "off"
2425
},
2526
"browserslist": [
2627
"defaults",

main.js

Lines changed: 95 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,61 @@
1-
const { app, BrowserWindow, Tray, Menu, ipcMain } = require('electron');
1+
const { app, BrowserWindow, Tray, Menu, dialog, ipcMain } = require('electron');
2+
require('dotenv').config();
23
const path = require('path');
34
const fs = require('fs');
45
const Registry = require('winreg');
6+
const DiscordRPC = require('discord-rpc');
57

68
let mainWindow;
79
let tray = null;
810

11+
const clientId = process.env.DISCORD_CLIENT_ID;
12+
if (!clientId) {
13+
console.error('DISCORD_CLIENT_ID not found in .env file. Discord RPC will not work.');
14+
}
15+
16+
const rpc = new DiscordRPC.Client({ transport: 'ipc' });
17+
let rpcReady = false;
18+
19+
if (clientId) {
20+
DiscordRPC.register(clientId);
21+
22+
rpc.on('ready', () => {
23+
console.log('Discord RPC is ready');
24+
rpcReady = true;
25+
updateDiscordActivity();
26+
});
27+
28+
rpc.on('error', (err) => {
29+
console.error('Discord RPC error:', err);
30+
});
31+
32+
rpc.login({ clientId }).catch(console.error);
33+
}
34+
35+
function updateDiscordActivity(clientId, theme) {
36+
if (!rpcReady) return;
37+
rpc.setActivity({
38+
details: `Using ${theme} theme`,
39+
state: `On ${clientId} Client Page`,
40+
startTimestamp: Math.floor(Date.now() / 1000),
41+
largeImageKey: 'twl_main',
42+
largeImageText: '@noxygalaxy',
43+
instance: false,
44+
});
45+
console.log(`Discord activity updated for ${clientId} with ${theme} theme`);
46+
}
47+
48+
const configPath = path.join(app.getPath('appData'), 'TWLauncher', 'twlconfig.json');
49+
let config = { installPath: path.join(app.getPath('appData'), 'TWLauncher', 'clients'), theme: 'default' };
50+
51+
if (fs.existsSync(configPath)) {
52+
config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
53+
}
54+
55+
function saveConfig() {
56+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
57+
}
58+
959
function createWindow() {
1060
mainWindow = new BrowserWindow({
1161
width: 1280,
@@ -26,6 +76,10 @@ function createWindow() {
2676
mainWindow.hide();
2777
});
2878

79+
mainWindow.webContents.on('did-finish-load', () => {
80+
mainWindow.webContents.send('apply-theme', config.theme);
81+
});
82+
2983
createTray();
3084
}
3185

@@ -204,6 +258,42 @@ function launchGame(id) {
204258
mainWindow.webContents.send('launch-game', id);
205259
}
206260

261+
ipcMain.handle('change-install-path', async () => {
262+
const result = await dialog.showOpenDialog(mainWindow, {
263+
properties: ['openDirectory'],
264+
title: 'Select Installation Directory'
265+
});
266+
if (!result.canceled && result.filePaths.length > 0) {
267+
config.installPath = result.filePaths[0];
268+
saveConfig();
269+
return config.installPath;
270+
}
271+
return null;
272+
});
273+
274+
ipcMain.handle('get-install-path', () => {
275+
return config.installPath;
276+
});
277+
278+
ipcMain.on('save-settings', (event, { installPath, theme }) => {
279+
config.installPath = installPath;
280+
config.theme = theme;
281+
saveConfig();
282+
mainWindow.webContents.send('apply-theme', theme);
283+
});
284+
285+
ipcMain.on('select-client', (event, clientId) => {
286+
mainWindow.webContents.send('client-selected', clientId);
287+
});
288+
289+
ipcMain.handle('get-initial-theme', () => {
290+
return config.theme;
291+
});
292+
293+
ipcMain.on('update-discord-rpc', (event, { clientId, theme }) => {
294+
updateDiscordActivity(clientId, theme);
295+
});
296+
207297
ipcMain.on('minimize-window', () => {
208298
mainWindow.minimize();
209299
});
@@ -215,6 +305,9 @@ ipcMain.on('hide-window', () => {
215305
content: 'Launcher will work in background, to close it right click on the tray icon',
216306
icon: path.join(__dirname, 'src', 'assets', 'logos', 'twl.png'),
217307
});
308+
if (rpcReady) {
309+
rpc.destroy();
310+
}
218311
});
219312

220313
ipcMain.on('launch-game', async () => {
@@ -223,8 +316,7 @@ ipcMain.on('launch-game', async () => {
223316
});
224317

225318
app.whenReady().then(() => {
226-
const appDataPath = app.getPath('appData');
227-
const clientsPath = path.join(appDataPath, 'TWLauncher', 'clients');
319+
const clientsPath = config.installPath;
228320

229321
if (!fs.existsSync(clientsPath)) {
230322
fs.mkdirSync(clientsPath, { recursive: true });

package-lock.json

Lines changed: 108 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
"dependencies": {
1313
"adm-zip": "^0.5.16",
1414
"axios": "^1.6.7",
15+
"discord-rpc": "^4.0.1",
16+
"dotenv": "^16.4.7",
1517
"fs-extra": "^11.1.1",
1618
"winreg": "^1.2.5"
1719
},
@@ -23,7 +25,7 @@
2325
"bugs": {
2426
"url": "https://github.com/noxygalaxy/twlauncher/issues"
2527
},
26-
"build": {
28+
"build": {
2729
"appId": "com.noxygalaxy.twlauncher",
2830
"productName": "TWLauncher",
2931
"copyright": "2025 noxygalaxy",
@@ -36,6 +38,12 @@
3638
"node_modules/**/*",
3739
"package.json"
3840
],
41+
"extraFiles": [
42+
{
43+
"from": ".env",
44+
"to": "."
45+
}
46+
],
3947
"win": {
4048
"target": ["portable"],
4149
"icon": "src/assets/logos/twl.ico"

0 commit comments

Comments
 (0)