mirror of
https://github.com/oobabooga/textgen.git
synced 2026-07-23 11:20:54 -05:00
Electron: Add a folder picker for the models directory
This commit is contained in:
2
.github/workflows/build-portable-release.yml
vendored
2
.github/workflows/build-portable-release.yml
vendored
@@ -207,7 +207,7 @@ jobs:
|
||||
chmod +x textgen
|
||||
fi
|
||||
|
||||
mv desktop/main.js desktop/package.json .
|
||||
mv desktop/main.js desktop/preload.js desktop/package.json .
|
||||
rm -rf desktop
|
||||
|
||||
# 5c. Restructure: textgen-VERSION/{textgen, user_data/, app/<everything else>}
|
||||
|
||||
@@ -145,6 +145,10 @@ div.svelte-iyf88w {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
.slim-textbox {
|
||||
padding: 0 !important;
|
||||
}
|
||||
|
||||
#download-label, #upload-label {
|
||||
min-height: 0
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { app, BrowserWindow, Menu, screen } = require("electron");
|
||||
const { app, BrowserWindow, Menu, dialog, ipcMain, screen } = require("electron");
|
||||
const { spawn } = require("child_process");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
@@ -111,7 +111,12 @@ function createWindow(port) {
|
||||
...bounds,
|
||||
title: TITLE,
|
||||
autoHideMenuBar: true,
|
||||
webPreferences: { nodeIntegration: false, contextIsolation: true, spellcheck: false },
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, "preload.js"),
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true,
|
||||
spellcheck: false,
|
||||
},
|
||||
});
|
||||
if (state && state.maximized) mainWindow.maximize();
|
||||
mainWindow.webContents.on("context-menu", (_, params) => {
|
||||
@@ -147,6 +152,11 @@ async function waitForPortAndOpen(port) {
|
||||
}, 500);
|
||||
}
|
||||
|
||||
ipcMain.handle("pick-directory", async () => {
|
||||
const result = await dialog.showOpenDialog(mainWindow, { properties: ["openDirectory"] });
|
||||
return result.canceled ? null : result.filePaths[0];
|
||||
});
|
||||
|
||||
app.whenReady().then(() => {
|
||||
serverProcess = spawn(python, ["server.py", "--portable", "--api", ...userArgs], {
|
||||
cwd: baseDir,
|
||||
@@ -159,6 +169,7 @@ app.whenReady().then(() => {
|
||||
PYTHONUNBUFFERED: "1",
|
||||
FORCE_COLOR: "1",
|
||||
TERM: "xterm-256color",
|
||||
TEXTGEN_ELECTRON: "1",
|
||||
},
|
||||
});
|
||||
if (!isWin) serverProcess.unref();
|
||||
|
||||
@@ -40,6 +40,7 @@ processing_message = ''
|
||||
gradio = {}
|
||||
persistent_interface_state = {}
|
||||
need_restart = False
|
||||
is_electron = os.environ.get('TEXTGEN_ELECTRON') == '1'
|
||||
|
||||
# Parser copied from https://github.com/vladmandic/automatic
|
||||
parser = argparse.ArgumentParser(description="TextGen", conflict_handler='resolve', add_help=True, formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=55, indent_increment=2, width=200))
|
||||
|
||||
@@ -248,6 +248,9 @@ def list_interface_input_elements():
|
||||
'include_past_attachments',
|
||||
]
|
||||
|
||||
if shared.is_electron:
|
||||
elements += ['model_dir']
|
||||
|
||||
if not shared.args.portable:
|
||||
# Image generation elements
|
||||
elements += [
|
||||
@@ -515,6 +518,9 @@ def setup_auto_save():
|
||||
|
||||
]
|
||||
|
||||
if shared.is_electron:
|
||||
change_elements += ['model_dir']
|
||||
|
||||
if not shared.args.portable:
|
||||
# Image generation tab (ui_image_generation.py)
|
||||
change_elements += [
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
from pathlib import Path
|
||||
|
||||
import gradio as gr
|
||||
|
||||
from modules import shared, ui, utils
|
||||
@@ -11,6 +13,10 @@ def create_ui():
|
||||
with gr.Column():
|
||||
gr.Markdown("## Settings")
|
||||
shared.gradio['toggle_dark_mode'] = gr.Button('Toggle light/dark theme 💡', elem_classes='refresh-button')
|
||||
if shared.is_electron:
|
||||
with gr.Row():
|
||||
shared.gradio['model_dir'] = gr.Textbox(label='Models directory', value=shared.settings['model_dir'], scale=4, elem_classes='slim-textbox')
|
||||
shared.gradio['model_dir_browse'] = gr.Button('Browse', elem_classes=['refresh-button', 'refresh-button-medium'])
|
||||
shared.gradio['show_two_notebook_columns'] = gr.Checkbox(label='Show two columns in the Notebook tab', value=shared.settings['show_two_notebook_columns'])
|
||||
shared.gradio['paste_to_attachment'] = gr.Checkbox(label='Turn long pasted text into attachments in the Chat tab', value=shared.settings['paste_to_attachment'], elem_id='paste_to_attachment')
|
||||
shared.gradio['include_past_attachments'] = gr.Checkbox(label='Include attachments/search results from previous messages in the chat prompt', value=shared.settings['include_past_attachments'])
|
||||
@@ -36,6 +42,13 @@ def create_ui():
|
||||
lambda x: 'dark' if x == 'light' else 'light', gradio('theme_state'), gradio('theme_state')).then(
|
||||
None, None, None, js=f'() => {{{ui.dark_theme_js}; toggleDarkMode(); localStorage.setItem("theme", document.body.classList.contains("dark") ? "dark" : "light")}}')
|
||||
|
||||
if shared.is_electron:
|
||||
shared.gradio['model_dir_browse'].click(
|
||||
None, gradio('model_dir'), gradio('model_dir'),
|
||||
js='async (current) => { const p = await window.electronAPI.pickDirectory(); return p === null ? current : p; }')
|
||||
|
||||
shared.gradio['model_dir'].change(apply_model_dir, gradio('model_dir'), None, show_progress=False)
|
||||
|
||||
shared.gradio['show_two_notebook_columns'].change(
|
||||
handle_default_to_notebook_change,
|
||||
gradio('show_two_notebook_columns', 'textbox-default', 'output_textbox', 'prompt_menu-default', 'textbox-notebook', 'prompt_menu-notebook'),
|
||||
@@ -86,6 +99,12 @@ def handle_default_to_notebook_change(show_two_columns, default_input, default_o
|
||||
]
|
||||
|
||||
|
||||
def apply_model_dir(value):
|
||||
shared.args.model_dir = value
|
||||
if Path(value).is_dir():
|
||||
shared.user_config = shared.load_user_config()
|
||||
|
||||
|
||||
def set_interface_arguments(extensions, bool_active):
|
||||
shared.args.extensions = extensions
|
||||
|
||||
|
||||
@@ -261,6 +261,10 @@ if __name__ == "__main__":
|
||||
if has_mcp_config():
|
||||
logger.warning(f"MCP stdio servers will be loaded from \"{shared.user_data_dir / 'mcp.json'}\"")
|
||||
|
||||
if shared.is_electron:
|
||||
shared.settings['model_dir'] = shared.args.model_dir
|
||||
shared.default_settings['model_dir'] = shared.args.model_dir
|
||||
|
||||
if settings_file is not None:
|
||||
logger.info(f"Loading settings from \"{settings_file}\"")
|
||||
with open(settings_file, 'r', encoding='utf-8') as f:
|
||||
@@ -269,6 +273,10 @@ if __name__ == "__main__":
|
||||
if new_settings:
|
||||
shared.settings.update(new_settings)
|
||||
|
||||
if shared.is_electron:
|
||||
shared.args.model_dir = shared.settings['model_dir']
|
||||
shared.user_config = shared.load_user_config()
|
||||
|
||||
# Apply CLI overrides for image model settings (CLI flags take precedence over saved settings)
|
||||
shared.apply_image_model_cli_overrides()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user