This commit is contained in:
pavel 2026-02-25 14:57:46 +01:00
commit 63d8aa9fe3
6 changed files with 4536 additions and 517 deletions

3
.gitignore vendored
View file

@ -1,3 +1,4 @@
/target /target
.env .env
node_modules node_modules
dist

View file

@ -33,8 +33,26 @@ const state = {
}; };
// --- Desktop Backend Configuration --- // --- Desktop Backend Configuration ---
const urlParams = new URLSearchParams(window.location.search); let API_BASE_URL = ''; // Will be initialized via IPC
const API_BASE_URL = urlParams.get('backend') || ''; // Absolute URL to the remote server
async function initializeConfig() {
try {
const config = await window.electronAPI.getConfig();
API_BASE_URL = config.backendUrl;
console.log(`Backend initialized: ${API_BASE_URL}`);
// Start the app now that config is ready
init();
} catch (err) {
console.error("Failed to fetch config via IPC", err);
// Fallback to URL search params if IPC fails (unlikely in desktop app)
const urlParams = new URLSearchParams(window.location.search);
API_BASE_URL = urlParams.get('backend') || '';
}
}
// Start config fetch immediately
initializeConfig();
function getWsUrl(path) { function getWsUrl(path) {
let urlStr; let urlStr;
@ -1625,4 +1643,5 @@ async function init() {
} }
} }
init(); // Config fetcher will trigger init()
initializeConfig();

View file

@ -1,5 +1,6 @@
const { contextBridge, ipcRenderer } = require('electron'); const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', { contextBridge.exposeInMainWorld('electronAPI', {
copyToClipboard: (text) => ipcRenderer.invoke('clipboard-write', text) copyToClipboard: (text) => ipcRenderer.invoke('clipboard-write', text),
getConfig: () => ipcRenderer.invoke('get-config')
}); });

59
main.js
View file

@ -19,6 +19,15 @@ function createWindow() {
} }
}); });
win.setAutoHideMenuBar(true);
win.setMenuBarVisibility(false);
ipcMain.handle('get-config', () => {
return {
backendUrl: (process.env.CHATTZ_URL || 'https://discord.flegr.me').replace(/\/$/, '')
};
});
ipcMain.handle('clipboard-write', (event, text) => { ipcMain.handle('clipboard-write', (event, text) => {
clipboard.writeText(text); clipboard.writeText(text);
return true; return true;
@ -60,20 +69,25 @@ function createWindow() {
const backendUrl = (process.env.CHATTZ_URL || 'https://discord.flegr.me').replace(/\/$/, ''); const backendUrl = (process.env.CHATTZ_URL || 'https://discord.flegr.me').replace(/\/$/, '');
const indexPath = path.join(__dirname, 'desktop', 'index.html'); const indexPath = path.join(__dirname, 'desktop', 'index.html');
// Construct the local file URL with the backend parameter
const localUrl = url.format({
pathname: indexPath,
protocol: 'file:',
slashes: true,
query: { backend: backendUrl }
});
console.log(`Loading desktop app from: ${localUrl}`);
const loadDesktopApp = (queryParams = '') => { const loadDesktopApp = (queryParams = '') => {
const fullUrl = queryParams ? `${localUrl}&${queryParams}` : localUrl; const options = {};
win.loadURL(fullUrl).catch((err) => { if (queryParams) {
console.error(`Failed to load desktop file: ${err}`); try {
options.query = Object.fromEntries(new URLSearchParams(queryParams));
} catch (e) {
console.error("Failed to parse query params", e);
}
}
// Use setImmediate to ensure the current navigation tick is cleared,
// which prevents ERR_ABORTED (-3) on some platforms when interrupting a redirect.
setImmediate(() => {
if (win.isDestroyed()) return;
win.loadFile(indexPath, options).catch((err) => {
// Ignore aborted errors as they often happen during fast redirects
if (err.toString().includes('-3') || err.code === -3) return;
console.error(`Failed to load desktop file: ${err}`);
});
}); });
}; };
@ -82,26 +96,19 @@ function createWindow() {
try { try {
const urlObj = new URL(navigatedUrl); const urlObj = new URL(navigatedUrl);
const backendObj = new URL(backendUrl); const backendObj = new URL(backendUrl);
// Detect the redirect back to the home page with a token
if (urlObj.origin === backendObj.origin && urlObj.pathname === '/') { if (urlObj.origin === backendObj.origin && urlObj.pathname === '/') {
console.log("Detected remote landing (login success), returning to desktop UI..."); if (urlObj.searchParams.has('token')) {
event.preventDefault(); console.log("Detected login success redirect, returning to desktop UI...");
loadDesktopApp(urlObj.search.slice(1)); event.preventDefault();
loadDesktopApp(urlObj.search.slice(1));
}
} }
} catch (e) { } catch (e) {
console.error(e); console.error(e);
} }
}); });
win.webContents.on('did-navigate', (event, navigatedUrl) => {
try {
const urlObj = new URL(navigatedUrl);
const backendObj = new URL(backendUrl);
if (urlObj.origin === backendObj.origin && urlObj.pathname === '/') {
loadDesktopApp(urlObj.search.slice(1));
}
} catch (e) { }
});
loadDesktopApp(); loadDesktopApp();
// Uncomment to debug // Uncomment to debug

3971
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,12 +2,40 @@
"name": "chattz-electron", "name": "chattz-electron",
"version": "0.1.0", "version": "0.1.0",
"description": "Electron frontend for Chattz", "description": "Electron frontend for Chattz",
"author": "Pavel Flegr <pavelflegr@gmail.com>",
"homepage": "https://discord.flegr.me",
"main": "main.js", "main": "main.js",
"scripts": { "scripts": {
"start": "electron .", "start": "electron .",
"dev": "electron ." "dev": "electron .",
"dist": "electron-builder -l"
},
"build": {
"appId": "me.flegr.chattz",
"productName": "Chattz",
"linux": {
"target": [
"rpm"
]
},
"win": {
"target": [
"nsis"
]
},
"files": [
"main.js",
"package.json",
"desktop/",
"static/",
"!dist"
],
"directories": {
"output": "dist"
}
}, },
"devDependencies": { "devDependencies": {
"electron": "^34.5.8" "electron": "^34.5.8",
"electron-builder": "^25.1.8"
} }
} }