a
This commit is contained in:
parent
a4abbf7844
commit
63d8aa9fe3
6 changed files with 4536 additions and 517 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,3 +1,4 @@
|
||||||
/target
|
/target
|
||||||
.env
|
.env
|
||||||
node_modules
|
node_modules
|
||||||
|
dist
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
|
||||||
|
|
@ -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')
|
||||||
});
|
});
|
||||||
|
|
|
||||||
53
main.js
53
main.js
|
|
@ -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,21 +69,26 @@ 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) {
|
||||||
|
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}`);
|
console.error(`Failed to load desktop file: ${err}`);
|
||||||
});
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Use a navigation listener to detect when the remote login is complete
|
// Use a navigation listener to detect when the remote login is complete
|
||||||
|
|
@ -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')) {
|
||||||
|
console.log("Detected login success redirect, returning to desktop UI...");
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
loadDesktopApp(urlObj.search.slice(1));
|
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
3971
package-lock.json
generated
File diff suppressed because it is too large
Load diff
32
package.json
32
package.json
|
|
@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue