Skip to content
TwinScope0.3.10

Preferences

Four short groups rather than every option at once. Theme, comparison defaults that seed each new run, and a window that reopens where you left it.

Click to enlarge
Progressive disclosure. The privacy switches are fixed on purpose — they are facts, not controls.

Theme#

Three choices: System, Dark, Light. The default is dark, not system — TwinScope is dark-mode first. ⌘⇧L toggles dark ↔ light from anywhere.

Both themes are first-class. Choosing System follows prefers-color-scheme live, so changing the OS appearance changes the app without a restart.

Comparison defaults#

Defaults are per engine, keyed by engine id, and they seed every new comparison:

DefaultEngineEffect
Ignore whitespacetextLeading, trailing and run-length whitespace differences stop counting
Collapse unchanged sectionstextLong unchanged runs fold, keeping 3 lines of context
Ignore JSON key orderjsonKey order stops being a difference — recommended for API responses

Being keyed by engine matters: { text: { ignoreWhitespace: false } } affects the text engine and nothing else.

Defaults seed, they do not override#

When a comparison runs, your saved defaults go in first and anything the engine view has already changed for this pair wins:

src/renderer/src/stores/compare.tsts
// The user's saved defaults seed the run; anything the engine view has
// already changed for this pair still wins.
const merged = { ...defaultsFor(engineId ?? engineFor({ a, b })), ...options };

So flipping a toolbar toggle on one comparison does not quietly rewrite your default, and your default does not fight a choice you just made. Loading a new input clears the per-pair options — a different pair may not even use the same engine.

Privacy rows#

Two switches in the Privacy group are shown off and disabled:

  • Telemetry — there is none, and no crash reporter either.
  • Check for updates — off by default. Turned on, it asks GitHub for the latest version number once per launch and tells you; it never downloads or installs anything. It is the only network call the app makes. See Update checks.
  • Store file contents in history — off. History keeps paths, types, sizes and settings only.

They are displayed as facts rather than hidden, so you can see the answer instead of taking it on trust. A switch that pretended to control something already guaranteed would be worse than no switch.

Window geometry#

The window remembers its size, its position and whether it was maximised.

Default size1440 × 900
Minimum size1080 × 640
Written onresize and move, debounced by 400 ms, and again on close
Position restoredonly if a display still covers that point

Resize and move fire continuously while you drag, so the writes are debounced rather than issued per event. A saved position on a monitor you have since unplugged is discarded and the window opens at the default position instead of off-screen.

Where preferences live#

A plain JSON file, settings.json, in Electron's user-data directory:

Terminalbash
# macOS
~/Library/Application\ Support/TwinScope/settings.json
settings.jsonjson
{
"version": 1,
"window": { "width": 1440, "height": 900, "x": 120, "y": 80, "maximized": false },
"preferences": {
  "theme": "dark",
  "engineDefaults": { "text": { "ignoreWhitespace": true } },
  "checkUpdates": true
}
}

It is read at boot, before anything else happens, because the window has to size itself first. That is also why preferences live here and comparison history lives in SQLite: this file stays tiny so startup never waits on a database.