mirror of
https://gitea.shironeko-all.duckdns.org/shironeko/Hytale-F2P-2.git
synced 2026-02-26 10:41:46 -03:00
feat: add 'Close launcher on game start' option and improve app termination behavior (#93)
* update main branch to release/v2.0.2b (#86) * add more linux pkgs, create auto-release and pre-release feature for Github Actions * removed package-lock from gitignore * update .gitignore for local build * add package-lock.json to maintain stability development * update version to 2.0.2b also add deps for rpm and arch * update 2.0.2b: add arm64 support, product and executable name, maintainers; remove snap; * update 2.0.2b: add latest.yml for win & linux, arm64 support; remove snap * fix release build naming * Prepare release v2.0.2b * feat: add 'Close launcher on game start' option and improve app termination behavior - Added 'Close launcher on game start' setting in GUI and backend. - Implemented automatic app quit after game launch if setting is enabled. - Added Cmd+Q (Mac) and Ctrl+Q/Alt+F4 (Win/Linux) shortcuts to quit the app. - Updated 'window-close' handler to fully quit the app instead of just closing the window. - Added i18n support for the new setting in English, Spanish, and Portuguese. --------- Co-authored-by: Fazri Gading <fazrigading@gmail.com> Co-authored-by: Arnav Singh <hi.arnavsingh3@gmail.com>
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -8,6 +8,7 @@ pkg/
|
|||||||
|
|
||||||
# Package files
|
# Package files
|
||||||
*.tar.zst
|
*.tar.zst
|
||||||
|
*.zst.DS_Store
|
||||||
*.zst
|
*.zst
|
||||||
bun.lockb
|
bun.lockb
|
||||||
.env
|
.env
|
||||||
|
|||||||
@@ -431,6 +431,27 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="settings-section">
|
||||||
|
<h3 class="settings-section-title">
|
||||||
|
<i class="fas fa-window-close"></i>
|
||||||
|
<span data-i18n="settings.closeLauncher">Launcher Behavior</span>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<div class="settings-option">
|
||||||
|
<label class="settings-checkbox">
|
||||||
|
<input type="checkbox" id="closeLauncherCheck" />
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
<div class="checkbox-content">
|
||||||
|
<div class="checkbox-title" data-i18n="settings.closeOnStart">Close Launcher on game start</div>
|
||||||
|
<div class="checkbox-description" data-i18n="settings.closeOnStartDescription">
|
||||||
|
Automatically close the launcher after Hytale has launched
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="settings-section">
|
<div class="settings-section">
|
||||||
<h3 class="settings-section-title">
|
<h3 class="settings-section-title">
|
||||||
<i class="fas fa-coffee"></i>
|
<i class="fas fa-coffee"></i>
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ let customJavaCheck;
|
|||||||
let customJavaOptions;
|
let customJavaOptions;
|
||||||
let customJavaPath;
|
let customJavaPath;
|
||||||
let browseJavaBtn;
|
let browseJavaBtn;
|
||||||
let settingsPlayerName;
|
let settingsPlayerName;
|
||||||
let discordRPCCheck;
|
let discordRPCCheck;
|
||||||
let gpuPreferenceRadios;
|
let closeLauncherCheck;
|
||||||
|
let gpuPreferenceRadios;
|
||||||
|
|
||||||
|
|
||||||
// UUID Management elements
|
// UUID Management elements
|
||||||
let currentUuidDisplay;
|
let currentUuidDisplay;
|
||||||
@@ -159,9 +161,11 @@ function setupSettingsElements() {
|
|||||||
customJavaOptions = document.getElementById('customJavaOptions');
|
customJavaOptions = document.getElementById('customJavaOptions');
|
||||||
customJavaPath = document.getElementById('customJavaPath');
|
customJavaPath = document.getElementById('customJavaPath');
|
||||||
browseJavaBtn = document.getElementById('browseJavaBtn');
|
browseJavaBtn = document.getElementById('browseJavaBtn');
|
||||||
settingsPlayerName = document.getElementById('settingsPlayerName');
|
settingsPlayerName = document.getElementById('settingsPlayerName');
|
||||||
discordRPCCheck = document.getElementById('discordRPCCheck');
|
discordRPCCheck = document.getElementById('discordRPCCheck');
|
||||||
gpuPreferenceRadios = document.querySelectorAll('input[name="gpuPreference"]');
|
closeLauncherCheck = document.getElementById('closeLauncherCheck');
|
||||||
|
gpuPreferenceRadios = document.querySelectorAll('input[name="gpuPreference"]');
|
||||||
|
|
||||||
|
|
||||||
// UUID Management elements
|
// UUID Management elements
|
||||||
currentUuidDisplay = document.getElementById('currentUuid');
|
currentUuidDisplay = document.getElementById('currentUuid');
|
||||||
@@ -190,9 +194,14 @@ function setupSettingsElements() {
|
|||||||
settingsPlayerName.addEventListener('change', savePlayerName);
|
settingsPlayerName.addEventListener('change', savePlayerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (discordRPCCheck) {
|
if (discordRPCCheck) {
|
||||||
discordRPCCheck.addEventListener('change', saveDiscordRPC);
|
discordRPCCheck.addEventListener('change', saveDiscordRPC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (closeLauncherCheck) {
|
||||||
|
closeLauncherCheck.addEventListener('change', saveCloseLauncher);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// UUID event listeners
|
// UUID event listeners
|
||||||
if (copyUuidBtn) {
|
if (copyUuidBtn) {
|
||||||
@@ -335,18 +344,43 @@ async function saveDiscordRPC() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadDiscordRPC() {
|
async function loadDiscordRPC() {
|
||||||
try {
|
try {
|
||||||
if (window.electronAPI && window.electronAPI.loadDiscordRPC) {
|
if (window.electronAPI && window.electronAPI.loadDiscordRPC) {
|
||||||
const enabled = await window.electronAPI.loadDiscordRPC();
|
const enabled = await window.electronAPI.loadDiscordRPC();
|
||||||
if (discordRPCCheck) {
|
if (discordRPCCheck) {
|
||||||
discordRPCCheck.checked = enabled;
|
discordRPCCheck.checked = enabled;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error loading Discord RPC setting:', error);
|
console.error('Error loading Discord RPC setting:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function saveCloseLauncher() {
|
||||||
|
try {
|
||||||
|
if (window.electronAPI && window.electronAPI.saveCloseLauncher && closeLauncherCheck) {
|
||||||
|
const enabled = closeLauncherCheck.checked;
|
||||||
|
await window.electronAPI.saveCloseLauncher(enabled);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error saving close launcher setting:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function loadCloseLauncher() {
|
||||||
|
try {
|
||||||
|
if (window.electronAPI && window.electronAPI.loadCloseLauncher) {
|
||||||
|
const enabled = await window.electronAPI.loadCloseLauncher();
|
||||||
|
if (closeLauncherCheck) {
|
||||||
|
closeLauncherCheck.checked = enabled;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error loading close launcher setting:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function savePlayerName() {
|
async function savePlayerName() {
|
||||||
try {
|
try {
|
||||||
@@ -457,13 +491,15 @@ async function loadGpuPreference() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadAllSettings() {
|
async function loadAllSettings() {
|
||||||
await loadCustomJavaPath();
|
await loadCustomJavaPath();
|
||||||
await loadPlayerName();
|
await loadPlayerName();
|
||||||
await loadCurrentUuid();
|
await loadCurrentUuid();
|
||||||
await loadDiscordRPC();
|
await loadDiscordRPC();
|
||||||
await loadGpuPreference();
|
await loadCloseLauncher();
|
||||||
}
|
await loadGpuPreference();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function openGameLocation() {
|
async function openGameLocation() {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -122,7 +122,10 @@
|
|||||||
"logsCopy": "Copy",
|
"logsCopy": "Copy",
|
||||||
"logsRefresh": "Refresh",
|
"logsRefresh": "Refresh",
|
||||||
"logsFolder": "Open Folder",
|
"logsFolder": "Open Folder",
|
||||||
"logsLoading": "Loading logs..."
|
"logsLoading": "Loading logs...",
|
||||||
|
"closeLauncher": "Launcher Behavior",
|
||||||
|
"closeOnStart": "Close Launcher on game start",
|
||||||
|
"closeOnStartDescription": "Automatically close the launcher after Hytale has launched"
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"modalTitle": "UUID Management",
|
"modalTitle": "UUID Management",
|
||||||
|
|||||||
@@ -122,7 +122,10 @@
|
|||||||
"logsCopy": "Copiar",
|
"logsCopy": "Copiar",
|
||||||
"logsRefresh": "Actualizar",
|
"logsRefresh": "Actualizar",
|
||||||
"logsFolder": "Abrir Carpeta",
|
"logsFolder": "Abrir Carpeta",
|
||||||
"logsLoading": "Cargando registros..."
|
"logsLoading": "Cargando registros...",
|
||||||
|
"closeLauncher": "Comportamiento del Launcher",
|
||||||
|
"closeOnStart": "Cerrar Launcher al iniciar el juego",
|
||||||
|
"closeOnStartDescription": "Cierra automáticamente el launcher después de que Hytale se haya iniciado"
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"modalTitle": "Gestión de UUID",
|
"modalTitle": "Gestión de UUID",
|
||||||
|
|||||||
@@ -122,7 +122,10 @@
|
|||||||
"logsCopy": "Copiar",
|
"logsCopy": "Copiar",
|
||||||
"logsRefresh": "Atualizar",
|
"logsRefresh": "Atualizar",
|
||||||
"logsFolder": "Abrir Pasta",
|
"logsFolder": "Abrir Pasta",
|
||||||
"logsLoading": "Carregando registros..."
|
"logsLoading": "Carregando registros...",
|
||||||
|
"closeLauncher": "Comportamento do Lançador",
|
||||||
|
"closeOnStart": "Fechar Lançador ao iniciar o jogo",
|
||||||
|
"closeOnStartDescription": "Fechar automaticamente o lançador após o Hytale ter sido iniciado"
|
||||||
},
|
},
|
||||||
"uuid": {
|
"uuid": {
|
||||||
"modalTitle": "Gerenciamento de UUID",
|
"modalTitle": "Gerenciamento de UUID",
|
||||||
|
|||||||
@@ -156,6 +156,15 @@ function loadLanguage() {
|
|||||||
return config.language || 'en';
|
return config.language || 'en';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function saveCloseLauncherOnStart(enabled) {
|
||||||
|
saveConfig({ closeLauncherOnStart: !!enabled });
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadCloseLauncherOnStart() {
|
||||||
|
const config = loadConfig();
|
||||||
|
return config.closeLauncherOnStart !== undefined ? config.closeLauncherOnStart : false;
|
||||||
|
}
|
||||||
|
|
||||||
function saveModsToConfig(mods) {
|
function saveModsToConfig(mods) {
|
||||||
try {
|
try {
|
||||||
const config = loadConfig();
|
const config = loadConfig();
|
||||||
@@ -331,5 +340,8 @@ module.exports = {
|
|||||||
resetCurrentUserUuid,
|
resetCurrentUserUuid,
|
||||||
// GPU Preference exports
|
// GPU Preference exports
|
||||||
saveGpuPreference,
|
saveGpuPreference,
|
||||||
loadGpuPreference
|
loadGpuPreference,
|
||||||
|
// Close Launcher export
|
||||||
|
saveCloseLauncherOnStart,
|
||||||
|
loadCloseLauncherOnStart
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -17,6 +17,8 @@ const {
|
|||||||
loadDiscordRPC,
|
loadDiscordRPC,
|
||||||
saveLanguage,
|
saveLanguage,
|
||||||
loadLanguage,
|
loadLanguage,
|
||||||
|
saveCloseLauncherOnStart,
|
||||||
|
loadCloseLauncherOnStart,
|
||||||
saveModsToConfig,
|
saveModsToConfig,
|
||||||
loadModsFromConfig,
|
loadModsFromConfig,
|
||||||
getUuidForUser,
|
getUuidForUser,
|
||||||
@@ -124,6 +126,10 @@ module.exports = {
|
|||||||
saveLanguage,
|
saveLanguage,
|
||||||
loadLanguage,
|
loadLanguage,
|
||||||
|
|
||||||
|
// Close Launcher functions
|
||||||
|
saveCloseLauncherOnStart,
|
||||||
|
loadCloseLauncherOnStart,
|
||||||
|
|
||||||
// GPU Preference functions
|
// GPU Preference functions
|
||||||
saveGpuPreference,
|
saveGpuPreference,
|
||||||
loadGpuPreference,
|
loadGpuPreference,
|
||||||
|
|||||||
94
main.js
94
main.js
@@ -2,7 +2,8 @@ const path = require('path');
|
|||||||
require('dotenv').config({ path: path.join(__dirname, '.env') });
|
require('dotenv').config({ path: path.join(__dirname, '.env') });
|
||||||
const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron');
|
const { app, BrowserWindow, ipcMain, dialog, shell } = require('electron');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { launchGame, launchGameWithVersionCheck, installGame, saveUsername, loadUsername, saveChatUsername, loadChatUsername, saveChatColor, loadChatColor, saveJavaPath, loadJavaPath, saveInstallPath, loadInstallPath, saveDiscordRPC, loadDiscordRPC, saveLanguage, loadLanguage, isGameInstalled, uninstallGame, repairGame, getHytaleNews, handleFirstLaunchCheck, proposeGameUpdate, markAsLaunched } = require('./backend/launcher');
|
const { launchGame, launchGameWithVersionCheck, installGame, saveUsername, loadUsername, saveChatUsername, loadChatUsername, saveChatColor, loadChatColor, saveJavaPath, loadJavaPath, saveInstallPath, loadInstallPath, saveDiscordRPC, loadDiscordRPC, saveLanguage, loadLanguage, saveCloseLauncherOnStart, loadCloseLauncherOnStart, isGameInstalled, uninstallGame, repairGame, getHytaleNews, handleFirstLaunchCheck, proposeGameUpdate, markAsLaunched } = require('./backend/launcher');
|
||||||
|
|
||||||
const UpdateManager = require('./backend/updateManager');
|
const UpdateManager = require('./backend/updateManager');
|
||||||
const logger = require('./backend/logger');
|
const logger = require('./backend/logger');
|
||||||
const profileManager = require('./backend/managers/profileManager');
|
const profileManager = require('./backend/managers/profileManager');
|
||||||
@@ -186,10 +187,21 @@ function createWindow() {
|
|||||||
if (input.key === 'F12') {
|
if (input.key === 'F12') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
if (input.key === 'F5') {
|
if (input.key === 'F5') {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
// Close application shortcuts
|
||||||
|
const isMac = process.platform === 'darwin';
|
||||||
|
const quitShortcut = (isMac && input.meta && input.key.toLowerCase() === 'q') ||
|
||||||
|
(!isMac && input.control && input.key.toLowerCase() === 'q') ||
|
||||||
|
(!isMac && input.alt && input.key === 'F4');
|
||||||
|
|
||||||
|
if (quitShortcut) {
|
||||||
|
app.quit();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mainWindow.webContents.on('context-menu', (e) => {
|
mainWindow.webContents.on('context-menu', (e) => {
|
||||||
@@ -333,15 +345,14 @@ app.on('before-quit', () => {
|
|||||||
cleanupDiscordRPC();
|
cleanupDiscordRPC();
|
||||||
});
|
});
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
console.log('=== LAUNCHER CLOSING ===');
|
console.log('=== LAUNCHER CLOSING ===');
|
||||||
|
|
||||||
cleanupDiscordRPC();
|
cleanupDiscordRPC();
|
||||||
|
|
||||||
if (process.platform !== 'darwin') {
|
app.quit();
|
||||||
app.quit();
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.handle('launch-game', async (event, playerName, javaPath, installPath, gpuPreference) => {
|
ipcMain.handle('launch-game', async (event, playerName, javaPath, installPath, gpuPreference) => {
|
||||||
try {
|
try {
|
||||||
@@ -358,9 +369,20 @@ ipcMain.handle('launch-game', async (event, playerName, javaPath, installPath, g
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const result = await launchGameWithVersionCheck(playerName, progressCallback, javaPath, installPath, gpuPreference);
|
const result = await launchGameWithVersionCheck(playerName, progressCallback, javaPath, installPath, gpuPreference);
|
||||||
|
|
||||||
return result;
|
if (result.success && result.launched) {
|
||||||
|
const closeOnStart = loadCloseLauncherOnStart();
|
||||||
|
if (closeOnStart) {
|
||||||
|
console.log('Close Launcher on start enabled, quitting application...');
|
||||||
|
setTimeout(() => {
|
||||||
|
app.quit();
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Launch error:', error);
|
console.error('Launch error:', error);
|
||||||
const errorMessage = error.message || error.toString();
|
const errorMessage = error.message || error.toString();
|
||||||
@@ -475,11 +497,21 @@ ipcMain.handle('save-language', (event, language) => {
|
|||||||
return { success: true };
|
return { success: true };
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('load-language', () => {
|
ipcMain.handle('load-language', () => {
|
||||||
return loadLanguage();
|
return loadLanguage();
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('select-install-path', async () => {
|
ipcMain.handle('save-close-launcher', (event, enabled) => {
|
||||||
|
saveCloseLauncherOnStart(enabled);
|
||||||
|
return { success: true };
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('load-close-launcher', () => {
|
||||||
|
return loadCloseLauncherOnStart();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('select-install-path', async () => {
|
||||||
|
|
||||||
const result = await dialog.showOpenDialog(mainWindow, {
|
const result = await dialog.showOpenDialog(mainWindow, {
|
||||||
properties: ['openDirectory'],
|
properties: ['openDirectory'],
|
||||||
title: 'Select Installation Folder'
|
title: 'Select Installation Folder'
|
||||||
@@ -804,11 +836,10 @@ ipcMain.handle('open-download-page', async () => {
|
|||||||
try {
|
try {
|
||||||
await shell.openExternal(updateManager.getDownloadUrl());
|
await shell.openExternal(updateManager.getDownloadUrl());
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
app.quit();
|
||||||
mainWindow.close();
|
}, 1000);
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
return { success: true };
|
return { success: true };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -850,11 +881,10 @@ ipcMain.handle('get-detected-gpu', () => {
|
|||||||
return global.detectedGpu;
|
return global.detectedGpu;
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.handle('window-close', () => {
|
ipcMain.handle('window-close', () => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
app.quit();
|
||||||
mainWindow.close();
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.handle('window-minimize', () => {
|
ipcMain.handle('window-minimize', () => {
|
||||||
if (mainWindow && !mainWindow.isDestroyed()) {
|
if (mainWindow && !mainWindow.isDestroyed()) {
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "hytale-f2p-launcherv2",
|
"name": "hytale-f2p-launcher",
|
||||||
"version": "2.0.2b",
|
"version": "2.0.2b",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "hytale-f2p-launcherv2",
|
"name": "hytale-f2p-launcher",
|
||||||
"version": "2.0.2b",
|
"version": "2.0.2b",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||||||
loadDiscordRPC: () => ipcRenderer.invoke('load-discord-rpc'),
|
loadDiscordRPC: () => ipcRenderer.invoke('load-discord-rpc'),
|
||||||
saveLanguage: (language) => ipcRenderer.invoke('save-language', language),
|
saveLanguage: (language) => ipcRenderer.invoke('save-language', language),
|
||||||
loadLanguage: () => ipcRenderer.invoke('load-language'),
|
loadLanguage: () => ipcRenderer.invoke('load-language'),
|
||||||
|
saveCloseLauncher: (enabled) => ipcRenderer.invoke('save-close-launcher', enabled),
|
||||||
|
loadCloseLauncher: () => ipcRenderer.invoke('load-close-launcher'),
|
||||||
selectInstallPath: () => ipcRenderer.invoke('select-install-path'),
|
selectInstallPath: () => ipcRenderer.invoke('select-install-path'),
|
||||||
browseJavaPath: () => ipcRenderer.invoke('browse-java-path'),
|
browseJavaPath: () => ipcRenderer.invoke('browse-java-path'),
|
||||||
isGameInstalled: () => ipcRenderer.invoke('is-game-installed'),
|
isGameInstalled: () => ipcRenderer.invoke('is-game-installed'),
|
||||||
|
|||||||
Reference in New Issue
Block a user