auto-git:

[add] README.md
 [add] backend/libraries/punk/library.json
 [add] backend/libraries/punk/stage/19f1e5d2ceaab5fd1f1dc58ff07422388f156610d16dfdea2bdb35a5b9e70813--GeorgeJordac-TheVoiceOfHumanJustice.pdf
 [add] backend/libraries/punk/stage/85fce554ff7685f7bccb136aff5768e54b9ba8361672fe45dbce599598c4be4b--4_Strings_-_Take_Me_Away_Into_The_Night_Vocal_Radio_Mix_.mp3
 [add] backend/libraries/punk/stage/e816ca61aebd84159747d248fedd6d5ff318c471c36bcc31b1ac6bf9aebcd3c1--The_Evolution_of_Cooperation_Robert_Axelrod_liber3.pdf
 [add] backend/local_rag.py
 [add] backend/rag/__init__.py
 [add] backend/rag/corpus_builder.py
 [add] backend/rag/corpus_enricher.py
 [add] backend/rag/index_builder.py
 [add] backend/rag/unified_rag.py
 [add] dist/assets/index-Cc0DLWqA.css
 [add] dist/assets/index-DKAz6gtp.js
 [add] dist/index.html
 [add] src/LibraryManager.jsx
 [add] wheelcheck2117/pydantic-2.11.7-py3-none-any.whl
 [add] wheelcheck274/pydantic-2.7.4-py3-none-any.whl
 [change] backend/main.py
 [change] backend/requirements.txt
 [change] backend/schemas.py
 [change] electron/main.cjs
 [change] electron/preload.cjs
 [change] package.json
 [change] run.sh
 [change] src/App.jsx
 [change] src/InterfaceSettings.jsx
 [change] src/colorSchemes.js
 [change] src/main.jsx
 [change] src/styles.css
This commit is contained in:
2026-03-19 21:07:22 +01:00
parent 9c6143a55a
commit 795f4d272a
29 changed files with 6023 additions and 359 deletions

View File

@@ -1,5 +1,4 @@
const { app, BrowserWindow, Menu, ipcMain, shell } = require('electron')
const { app, BrowserWindow, Menu, dialog, ipcMain, shell } = require('electron')
const path = require('path')
const { is } = require('@electron-toolkit/utils')
const fs = require('fs')
@@ -9,12 +8,36 @@ let settingsWindow = null
const settingsFilePath = path.join(app.getPath('userData'), 'settings.json')
let appSettings = {}
const DEFAULT_UI_SCALE = 1
const MIN_UI_SCALE = 0.7
const MAX_UI_SCALE = 1.3
// Default settings
const defaultSettings = {
ollamaApiUrl: 'http://127.0.0.1:8000',
colorScheme: 'Default',
chatModel: 'llama3' // Set a default model here
uiScale: DEFAULT_UI_SCALE,
chatModel: 'llama3',
}
function normalizeUiScale(value) {
const numericValue = Number(value)
if (!Number.isFinite(numericValue)) {
return DEFAULT_UI_SCALE
}
return Math.min(MAX_UI_SCALE, Math.max(MIN_UI_SCALE, Math.round(numericValue * 100) / 100))
}
function applyUiScaleToWindow(window) {
if (!window || window.isDestroyed()) {
return
}
window.webContents.setZoomFactor(normalizeUiScale(appSettings.uiScale))
}
function applyUiScaleToAllWindows() {
BrowserWindow.getAllWindows().forEach(applyUiScaleToWindow)
}
function loadSettings() {
@@ -24,8 +47,9 @@ function loadSettings() {
appSettings = { ...defaultSettings, ...JSON.parse(data) }
} else {
appSettings = { ...defaultSettings }
saveSettings() // Create the file with default settings
saveSettings()
}
appSettings.uiScale = normalizeUiScale(appSettings.uiScale)
} catch (error) {
console.error('Failed to load settings:', error)
appSettings = { ...defaultSettings }
@@ -40,7 +64,7 @@ function saveSettings() {
}
}
async function createMainWindow () {
async function createMainWindow() {
mainWindow = new BrowserWindow({
width: 1000,
height: 720,
@@ -50,17 +74,23 @@ async function createMainWindow () {
webPreferences: {
preload: path.join(__dirname, 'preload.cjs'),
contextIsolation: true,
nodeIntegration: false
}
nodeIntegration: false,
},
})
applyUiScaleToWindow(mainWindow)
mainWindow.on('ready-to-show', () => {
mainWindow.show()
})
mainWindow.webContents.on('did-finish-load', () => {
applyUiScaleToWindow(mainWindow)
})
mainWindow.on('focus', () => {
mainWindow.webContents.send('window-focused');
});
mainWindow.webContents.send('window-focused')
})
if (is.dev && process.env.VITE_DEV_SERVER_URL) {
await mainWindow.loadURL(process.env.VITE_DEV_SERVER_URL)
@@ -70,12 +100,12 @@ async function createMainWindow () {
}
mainWindow.webContents.setWindowOpenHandler(({ url }) => {
shell.openExternal(url);
return { action: 'deny' };
});
shell.openExternal(url)
return { action: 'deny' }
})
}
async function createSettingsWindow () {
async function createSettingsWindow() {
if (settingsWindow) {
settingsWindow.focus()
return
@@ -91,14 +121,20 @@ async function createSettingsWindow () {
webPreferences: {
preload: path.join(__dirname, 'preload.cjs'),
contextIsolation: true,
nodeIntegration: false
}
nodeIntegration: false,
},
})
applyUiScaleToWindow(settingsWindow)
settingsWindow.on('ready-to-show', () => {
settingsWindow.show()
})
settingsWindow.webContents.on('did-finish-load', () => {
applyUiScaleToWindow(settingsWindow)
})
settingsWindow.on('closed', () => {
settingsWindow = null
})
@@ -112,7 +148,7 @@ async function createSettingsWindow () {
}
app.whenReady().then(() => {
loadSettings() // Load settings when the app is ready
loadSettings()
createMainWindow()
const menuTemplate = [
@@ -122,11 +158,11 @@ app.whenReady().then(() => {
{
label: 'Settings',
accelerator: 'CmdOrCtrl+,',
click: createSettingsWindow
click: createSettingsWindow,
},
{ type: 'separator' },
{ role: 'quit' }
]
{ role: 'quit' },
],
},
{
label: 'Edit',
@@ -139,8 +175,8 @@ app.whenReady().then(() => {
{ role: 'paste' },
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
]
{ role: 'selectAll' },
],
},
{
label: 'View',
@@ -153,9 +189,9 @@ app.whenReady().then(() => {
{ role: 'zoomin' },
{ role: 'zoomout' },
{ type: 'separator' },
{ role: 'togglefullscreen' }
]
}
{ role: 'togglefullscreen' },
],
},
]
const menu = Menu.buildFromTemplate(menuTemplate)
@@ -166,23 +202,40 @@ app.whenReady().then(() => {
})
})
// IPC handlers for settings
ipcMain.handle('get-settings', () => {
return appSettings
})
ipcMain.handle('get-settings', () => appSettings)
ipcMain.handle('set-setting', (event, key, value) => {
appSettings[key] = value
appSettings[key] = key === 'uiScale' ? normalizeUiScale(value) : value
saveSettings()
if (key === 'uiScale') {
applyUiScaleToAllWindows()
}
return true
})
ipcMain.handle('update-settings', (event, settings) => {
appSettings = { ...appSettings, ...settings }
appSettings.uiScale = normalizeUiScale(appSettings.uiScale)
saveSettings()
if (Object.prototype.hasOwnProperty.call(settings, 'uiScale')) {
applyUiScaleToAllWindows()
}
return true
})
ipcMain.handle('pick-paths', async () => {
const result = await dialog.showOpenDialog(mainWindow, {
properties: ['openFile', 'openDirectory', 'multiSelections'],
})
return result.canceled ? [] : result.filePaths
})
ipcMain.handle('open-path', async (event, filePath) => {
if (!filePath) return false
const err = await shell.openPath(filePath)
return err === ''
})
ipcMain.on('open-external-link', (event, url) => {
shell.openExternal(url)
})

View File

@@ -6,6 +6,8 @@ contextBridge.exposeInMainWorld('electronAPI', {
getSettings: () => ipcRenderer.invoke('get-settings'),
setSetting: (key, value) => ipcRenderer.invoke('set-setting', key, value),
updateSettings: (settings) => ipcRenderer.invoke('update-settings', settings),
pickPaths: () => ipcRenderer.invoke('pick-paths'),
openPath: (filePath) => ipcRenderer.invoke('open-path', filePath),
openExternalLink: (event) => {
event.preventDefault();
const url = event.currentTarget.href;