Repository navigation
Settings and Shell
English · Español
The shell is the frame of the app: the top bar (view switcher, deck name, save indicator, update button, Settings button), the three resizable panels of the deck view, and the boot hooks that open the last deck and start autosave. The Settings dialog holds interface language, in-app updates, the optional multilingual-names index and the whole appearance system. This page documents both, what each setting does and where it is persisted.
Code: src/features/shell/ and src/features/settings/.
| File | Responsibility |
|---|---|
app-shell.tsx |
AppShell: header + main area; NombreDeck (inline deck-name input). |
use-deck-inicial.ts |
useDeckInicial(): boot of deck, autosave, plan, undo/redo keys. |
save-indicator.tsx |
SaveIndicator: "Saved / Saving... / Unsaved / Couldn't save". |
actualizacion-automatica.tsx |
Auto-update loop, update toasts, BotonActualizar, PuntoActualizacion, useAvisoAjustes. |
Left to right:
- Logo and title ("Proxy Builder", subtitle "Scryfall . print-ready").
- A single-select
ToggleGroupbound touseUi().vista: Deck, Design ("Diseñar"), Library ("Biblioteca"). Only these three values are accepted byonValueChange(clicking the active item returns an empty value that is ignored, so one is always selected). -
NombreDeck(hidden in Library view): anInputthat editsdeck.name. Commit on blur or Enter, Escape reverts; an empty value reverts; changes go throughuseDeck.setSinHistorial({ name })(saved, not undoable). - Right side:
SaveIndicator,BotonActualizar, the Settings button.
SaveIndicator reads useDeck().guardado / errorGuardado; it renders nothing until a deck is open, and on error wraps the label in a tooltip with mensaje(error).
vista === "deck": ResizablePanelGroup horizontal with izquierda (decklist, default 22 %, min 260 px), centro (preview, min 360 px), derecha (export, default 22 %, min 260 px) and two handles with grips. Sizes persist in localStorage["proxybuilder.paneles"] through useDefaultLayout. disenar and biblioteca render their screen directly. The window minimum is 960 x 640 and the default 1440 x 900 (src-tauri/tauri.conf.json).
-
iniciarAutoguardado()andiniciarPlan()(see State Stores). - A
useDeck.subscribethat, whenever the open deck id changes, callsrehacerMiniaturas()(src/features/disenar/renumerar.ts) to re-render design thumbnails made stale by a changed collection, font or engine. -
abrirDeckInicial(t("Deck sin título")): reopenlast_deck_idor create a new deck. The returned error (if any) is stored in the hook's state. - Separately, a
keydownlistener forCtrl/Cmd+Z(undo) andShiftvariant (redo), disabled while typing in an input, textarea orcontenteditable.
Decision: the window is created hidden with a dark background colour and shown as soon as possible, to avoid a white flash.
-
tauri.conf.json:"visible": false,"backgroundColor": "#1d1b19". -
src-tauri/src/lib.rs: the window-state plugin saves size/position/maximised state of all flags exceptVISIBLE(otherwise the saved state could show the window before it is painted).on_page_loadshows the window onPageLoadEvent::Finished; a background thread shows it after 3 s if it is still hidden (page never loaded). -
src/main.tsxalso callsgetCurrentWindow().show()right afterrender(it does not wait for a frame: WebKitGTK does not deliverrequestAnimationFrameto hidden windows), andponerTemaAntesDeMontar()already set the right colours, so there is no light flash. See Frontend Architecture and Themes and Skins.
Opened by the Settings button (AppShell keeps open in local state). DialogContent is sm:max-w-3xl with cambiosSinGuardar={false} (nothing to lose when closing). The header shows the version read once with getVersion() from @tauri-apps/api/app ("Proxy Builder v2.5.3") and, when an update is downloaded, the ReiniciarParaActualizar button.
Body, top to bottom:
| Section | Component | Effect | Persistence |
|---|---|---|---|
| Language | inline ToggleGroup ("Español" / "English") |
Interface language, immediate, no reload. |
localStorage["proxybuilder.lang"]; see Internationalization. |
| Updates |
Actualizaciones (actualizaciones.tsx) |
Check now, download, restart; the auto-update switch. | Switch: useUi().actualizarSola in proxybuilder.preferencias. State machine in memory. |
| Names in other languages |
NombresIdiomas (nombres-idiomas.tsx) |
Optional download of the MTGJSON name index. | On disk by Rust (see below). |
| Appearance |
Appearance (appearance.tsx) |
Mode, scale, smooth scroll, skin, filigree, background, material, effects, colour theme, "More themes...". |
localStorage keys listed in Themes and Skins. |
- Calls
useActualizacion.iniciar()on mount. Ifsoportada === falseit shows "Only in the installed app: this copy does not come from an installer (for example, in development)." and nothing else. - "Check now" (
buscar) is disabled while busy; if a version is found and auto-update is on, it downloads straight away (like at startup). - When a version is available and auto is off: a "Download vX" button. When downloaded (
lista/instalando): "Restart and update" button (dismisses the"actualizacion"toast, callsinstalar(), and toasts the error if it fails). - A
Progressbar appears while downloading; the last error is printed withmensaje(error); the release notes (Markdown text, English) appear in aScrollAreawhen present; "You have the latest version (vX)" when up to date. - The status line says that on
.deb/.rpminstalls the system will ask for the password on restart (ActualizacionInfo.pidePermiso).
State machine details are in State Stores; the Rust updater, signature checks and release format are in Releases and Auto Updates. Updating is refused with Busy while a long job runs, and the deck is saved first (guardarAhora()).
Optional download (about the size shown on the button, "Download (about N MB)") of the MTGJSON per-language name index, stored as SQLite by Rust, so cards typed by their Spanish (or other language) printed name that Scryfall lacks can be found locally, both in the list and when linking. Without it the app asks magicthegathering.io online, which is slower. Commands: names_index_info, names_index_download (progress event names://progress with phases; during the "reading" phase the bar is full and the text says "Preparing the index..."), names_index_remove. Shows the count of downloaded names. See External Sources and Card Identification and OCR.
Documented control by control in Themes and Skins (mode, size 70 to 150 %, smooth scroll, Plano/Zeus/Hera, filigree, background, material, blur/grain/shadow, "Include the side panels", theme grid, "More themes...").
Smooth scroll (proxybuilder.smoothScroll, default on) mounts SmoothScroll (src/lib/SmoothScroll.ts) through SmoothScrollClient: the wheel animates the native scrollTop of the nearest scrollable ancestor. Turning it off destroys the instance.
| Piece | Behaviour |
|---|---|
useActualizacionAutomatica() |
Only when useUi().actualizarSola is true (default). After 8 s (PRIMERA_MS) and then every 6 h (CADA_MS): iniciar(); if unsupported stop; buscar(); if a version exists, bajar(). Network failures or no release are silent. Timers are cleared when the switch is turned off. |
useAvisosActualizacion() |
One useActualizacion.subscribe, mounted once in App: a loading toast "Downloading Proxy Builder X..." with the percentage as description while bajando; a persistent success toast "Proxy Builder X is ready" with a Restart action when download completes (once per version); an error toast "Couldn't download the update" with the mapped error if the download fails. All use toast id "actualizacion" so they replace each other. |
BotonActualizar |
Top-bar outline button "Update to X" visible only in lista/instalando; spinner while installing; tooltip says whether the system will ask for a password. |
PuntoActualizacion |
Small dot on the Settings button: amber and pulsing while bajando; theme-primary when lista/instalando. |
useAvisoAjustes() |
Tooltip/aria text for the Settings button while an update is in progress ("Downloading X..." / "X is ready: restart from Settings."). |
The toast strings read the current language through a ref (textos.current = lang), so a language change mid-download is respected without resubscribing.
| Setting | UI location | Stored in |
|---|---|---|
| Interface language | Settings |
localStorage proxybuilder.lang
|
| Theme, mode, skin, background, material, blur, noise, shadow, scale, flags, smooth scroll | Settings > Appearance |
localStorage proxybuilder.theme / .mode / .skin / .bg / .material / .blur / .noise / .shadow / .scale / .fxSidebar / .heraFiligree / .smoothScroll
|
| Installed tweakcn themes | Settings > More themes | Rust files under the app data folder temas/, mirrored in proxybuilder.temasInstalados
|
| Auto-update | Settings > Updates |
useUi().actualizarSola (proxybuilder.preferencias) |
| MTGJSON names index | Settings | Rust (downloaded file, SQLite index) |
| Card language, image policy, add tokens, preview quality, ask before replacing | Decklist panel > Options |
useUi() (proxybuilder.preferencias) |
| Preview zoom, card info overlay | Preview toolbar |
useUi() (proxybuilder.preferencias); "Show backs" is not persisted |
| Panel widths | drag the handles |
localStorage proxybuilder.paneles, .panel-lista, .paneles.disenar
|
| Section open/closed | section headers |
localStorage proxybuilder.seccion.<id>
|
| Library view, sort, grouping, size | Library toolbar |
localStorage proxybuilder.biblioteca (filters not stored) |
| Last deck opened | automatic | Rust app_settings key last_deck_id
|
| Last import folder / last export folder | automatic | Rust app_settings keys carpeta_importar, carpeta_exportar
|
| Window size, position, maximised | automatic |
tauri-plugin-window-state (visibility excluded) |
| Print settings (page size, card size, margins, bleed, cut guides, etc.) and export presets | Export panel | Inside the deck (Deck.settings, saved with the deck); presets in Rust (preset_* commands). See Export. |
Factory values worth knowing (they are product decisions, not accidents): interface language English; theme Amber Minimal in dark mode with matte material; preview zoom 80 %; preview quality 488 px; "ask before replacing cards" on; auto-update on. Print defaults (2 mm gap, bleed 0, cut guides off, "Fill corners" off) live in the layout/export code, see Layout Engine.
All file dialogs go through src/lib/dialogos.ts; never call @tauri-apps/plugin-dialog directly.
| Function | Use |
|---|---|
abrirParaImportar(opciones) |
Open dialog starting in the last import folder; returns the paths (array) or null; remembers the folder of the first path. |
guardarParaExportar(opciones, nombre) |
Save dialog starting in the last export folder with nombre as proposed file name. |
elegirCarpetaParaExportar() |
Directory picker (loose image export), also remembers the export folder. |
recordar(tipo, ruta) |
Fire-and-forget remember; used when files are dragged onto the app. |
Mechanics: carpeta_inicial({ tipo, nombre }) (Rust src-tauri/src/commands/carpetas.rs) returns the stored folder if it still exists (joined with nombre if given), otherwise nombre or null. carpeta_recordar({ tipo, ruta }) stores the directory of the path (the path itself if it is a directory, else its parent) under carpeta_importar or carpeta_exportar in app_settings. TipoCarpeta is "importar" | "exportar" (generated type). Import and export folders are deliberately separate, so exporting a PDF to Desktop does not redirect the next image import. Failures of either command are swallowed (the dialog just opens at its default location). Used by features/decklist/acciones.ts, features/export/acciones.ts, features/export/menu-exportar.tsx, features/library/library-screen.tsx and the designer dialogs. Tests: src/lib/__tests__/dialogos.test.ts and commands/carpetas.rs unit test la_carpeta_de_una_ruta.
There is no "storage" section in the Settings dialog. Two maintenance actions live where they are relevant:
-
Clear thumbnail cache: in the decklist panel (
decklist-panel.tsx), a confirmation dialog shows size and file count fromcache_statsand thencache_clearempties only the derived renders cache; deck images are never touched. -
Free unused images: in the Library screen,
blob_gcremoves blobs no deck references (the Rust side keeps recent ones for 24 h); the toast reports count and megabytes.
Rationale: deck images live in the blob store (they are data), the cache only holds derivatives and can always be deleted. See Storage and Blobs.
| Situation | Behaviour |
|---|---|
localStorage blocked or corrupt |
Every read/write is in try/catch; defaults apply for the session. |
getVersion() fails |
The version chip is simply not shown. |
| Update check fails (offline, no release, no package for this installer) | Silent in the background; manual "Check now" shows the mapped error (Network, NotFound...). |
| Install fails (e.g. password prompt cancelled) | State returns to lista, error toast; can retry without re-downloading. |
| Update while a PDF export runs | Rust returns Busy. |
| Selected installed theme no longer exists |
SincronizarTemas resets to Amber Minimal. |
- New setting: if it affects the look, add to
ThemeProvider-adjacent code only through new CSS/tema-inicial.ts(the provider itself is read-only); if it is a list/preview preference, add it touseUiPreferencias(State Stores); if the backend must know it across sessions, useapp_setting_get/setor a dedicated command. - New Settings section: add a card component in
src/features/settings/and render it inSettingsDialog; text throught(); scrolling is already provided byDialogCuerpo.
Use and build · Uso y desarrollo
- User-Guide · Guía de usuario
- Development-Setup · Preparación del entorno de desarrollo
- Testing-and-CI · Tests y CI
- Releases-and-Auto-Updates · Versiones y actualizaciones automáticas
- Conventions · Convenciones
Architecture · Arquitectura
- Architecture · Arquitectura
- IPC-and-Error-Handling · IPC y manejo de errores
- Rust-App-Layer · Capa de aplicación Rust
Data · Datos
- Deck-Model · Modelo del mazo
- Storage-and-Blobs · Almacenamiento y blobs
- Deck-Package-Format · Formato del paquete de mazo
- Deck-Library · Biblioteca de mazos
Getting cards · Conseguir cartas
- Decklist-Parsing · Parseo de la lista del mazo
- Scryfall-Integration · Integración con Scryfall
- External-Sources · Fuentes externas
- Card-Identification-and-OCR · Identificación de cartas y OCR
Layout, images, PDF · Maquetación, imagen y PDF
- Layout-Engine · Motor de maquetación
- Imaging-and-PDF · Imagen y PDF
- Export · Exportación
- Live-Preview · Vista previa en vivo
- Statistics · Estadísticas
Card designer · Diseñador de cartas
- Designer-Overview · Visión general del diseñador
- Designer-Engine · Motor del diseñador
- Designer-Composition · Composición del diseñador
- Frame-Packs · Packs de marcos
- Designer-App-Layer · Capa de aplicación del diseñador
- Designer-UI · Interfaz del diseñador
- Card-Editor-Dialog · Diálogo Editar carta
Game table · Mesa de juego
Frontend · Frontend
- Frontend-Architecture · Arquitectura del frontend
- State-Stores · Stores de estado
- Internationalization · Internacionalización
- Themes-and-Skins · Temas y skins
- Settings-and-Shell · Ajustes y shell
- Tutorials · Tutoriales
- Decklist-Panel · Panel de la lista del mazo
- Add-Card-and-Variants · Añadir carta y variantes
- Set-Browser · Explorador de sets
Reference · Referencia