Skip to content

Commit 97ed07b

Browse files
committed
fe: dress the app as windows 11 there, it read as a web page in a window
1 parent d055c34 commit 97ed07b

15 files changed

Lines changed: 351 additions & 31 deletions

File tree

‎CLAUDE.md‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ log found in one line what two rounds of guessing had missed.
2323

2424
Never enable the inspector outside `-debug`.
2525

26+
`make debug` asks which OS to look like, so the Windows or Linux theme can be checked from a Mac. It sets `ADMINER_DESKTOP_SIMULATE_OS`, ignored without `-debug`. It changes the look and the window only (`Os::look()`): the engine stays WKWebView, and without Segoe the font falls back.
27+
2628
PHP fatal errors reach `~/Library/Logs/Adminer Desktop/adminer-desktop.log`, but only
2729
because `app/php/desktop.ini` turns `log_errors` on — frankenphp's default sends them to
2830
the page and nowhere else. `make logs` or the Open Logs menu item opens the folder.
@@ -176,7 +178,7 @@ into components pulled in by `@import`: `tokens`, `base`, `tables`, `forms`, `si
176178
`settings`. `light-dark()` is colour-only, so the one non-colour scheme difference —
177179
inverting adminer's sprite icons on the dark surface — lives in `base.css` and keys off the
178180
`theme-auto`/`theme-dark` body class instead. `system-ui` gives the native OS font with no
179-
branching; the `theme-*`, `os-mac`/`os-windows`/`os-linux` and `density-compact`/`-cozy`/
181+
branching; the `theme-*`, `mac-os`/`windows-os`/`linux-os` and `density-compact`/`-cozy`/
180182
`-comfortable` body classes come from `AdminerDesktop::bodyClass()` and are the hooks for
181183
appearance, per-OS and per-density tweaks. oxfmt owns the formatting — one declaration per
182184
line.

‎Makefile‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -328,8 +328,8 @@ qa: fetch app/vendor i18n mcp-bridge-data ## Run every static check (php, go, j
328328
|| { echo "launcher: no non-darwin definition of $$f() (menu_other.go stub, or *_linux.go + *_other.go or *_windows.go split)"; exit 1; }; \
329329
done && echo "platform stubs ok"
330330
@command -v shellcheck >/dev/null \
331-
&& { shellcheck check.sh cli/compile-adminer.sh cli/dresscode.sh cli/kill-orphans.sh cli/demo-mysql.sh tests/cli/dresscode-test.sh tests/cli/dresscode-hook-test.sh tests/cli/kill-orphans-test.sh tests/launcher/downloads.sh && echo "shellcheck ok"; } \
332-
|| { sh -n check.sh && sh -n cli/compile-adminer.sh && sh -n cli/dresscode.sh && sh -n cli/kill-orphans.sh && sh -n cli/demo-mysql.sh && echo "sh ok (shellcheck not installed)"; }
331+
&& { shellcheck check.sh cli/pick-os.sh tests/cli/pick-os-test.sh cli/compile-adminer.sh cli/dresscode.sh cli/kill-orphans.sh cli/demo-mysql.sh tests/cli/dresscode-test.sh tests/cli/dresscode-hook-test.sh tests/cli/kill-orphans-test.sh tests/launcher/downloads.sh && echo "shellcheck ok"; } \
332+
|| { sh -n check.sh && sh -n cli/pick-os.sh && sh -n tests/cli/pick-os-test.sh && sh -n cli/compile-adminer.sh && sh -n cli/dresscode.sh && sh -n cli/kill-orphans.sh && sh -n cli/demo-mysql.sh && echo "sh ok (shellcheck not installed)"; }
333333
@# Native-shell strings: the `i18n` prerequisite already generated the real files (which is
334334
@# also what makes i18n_gen.h exist before `go vet` compiles the cgo launcher above). Assert the
335335
@# generator's output quality and lint the emitted plists. `make i18n-check` reports coverage.
@@ -338,6 +338,7 @@ qa: fetch app/vendor i18n mcp-bridge-data ## Run every static check (php, go, j
338338
./bin/frankenphp$(EXE) php-cli tests/shortcuts/ShortcutsTest.php
339339
./bin/frankenphp$(EXE) php-cli tests/cli/WindowsIcoTest.php
340340
./bin/frankenphp$(EXE) php-cli tests/cli/I18nTest.php
341+
@sh tests/cli/pick-os-test.sh
341342
@sh tests/cli/kill-orphans-test.sh
342343
@sh tests/cli/dresscode-test.sh
343344
@sh tests/cli/dresscode-hook-test.sh
@@ -459,8 +460,9 @@ editor: build ## Run in editor mode
459460
# Brings up the e2e's seeded mysql beside it, so there is a database to point it at; no
460461
# docker skips it rather than refusing to debug.
461462
debug: build ## Run with Safari's Web Inspector attached, and a seeded mysql (docker)
462-
@./cli/demo-mysql.sh $(DEMO_MYSQL) || echo "no mysql: docker is not running"
463-
./build.noindex/adminer-desktop$(EXE) -debug
463+
@os=$$(./cli/pick-os.sh); \
464+
./cli/demo-mysql.sh $(DEMO_MYSQL) || echo "no mysql: docker is not running"; \
465+
ADMINER_DESKTOP_SIMULATE_OS=$$os ./build.noindex/adminer-desktop$(EXE) -debug
464466

465467
# The app in dev mode against seeded demo data, for clicking around by hand. Brings up
466468
# (or reuses) the same throwaway postgres the e2e uses, reseeds it, and opens the app

‎app/AdminerDesktop.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ function csp(array &$csp): void {
310310
* @return void
311311
*/
312312
function bodyClass(): void {
313-
echo " " . Os::current()->bodyClass();
313+
echo " " . Os::look()->bodyClass();
314314
// The launcher sets this under -debug; the desktop scripts read it to stand down so
315315
// the web inspector's own behaviour is unobstructed.
316316
if (Env::Debug->get()) {

‎app/src/Assets/javascript/scrollers.js‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
* launcher marks <html> with ad-legacy-scrollers) the panels' thumbs are ours too, only always on
1313
* screen and as thick as Mail's: WebKit's own took a column of the panel, and the toolbar inside
1414
* #content, its hairline and its search, stopped that column short of the window's edge. The
15-
* inner scrollers keep WebKit's legacy ones. macOS only, as base.css's rules are.
15+
* inner scrollers keep WebKit's legacy ones. macOS and Windows, whose own bars fade the same way
16+
* (windows-os.css); Linux keeps its own.
1617
*/
1718

1819
{
@@ -29,7 +30,8 @@
2930
// Our design only, which hides WebKit's bars and styles the thumb (base.css); --ad-accent is
3031
// defined by it alone, as table-nav.js tells it.
3132
const ours = () =>
32-
document.body?.classList.contains("os-mac") &&
33+
(document.body?.classList.contains("mac-os") ||
34+
document.body?.classList.contains("windows-os")) &&
3335
getComputedStyle(document.documentElement)
3436
.getPropertyValue("--ad-accent")
3537
.trim() !== "";

‎app/src/Env.php‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ enum Env: string {
1414
case DataDir = 'ADMINER_DESKTOP_DATA';
1515
/** Set under -debug: turns on Tracy and the web inspector's own affordances. */
1616
case Debug = 'ADMINER_DESKTOP_DEBUG';
17+
/** Which OS the UI dresses as under -debug, an Os case (Os::look). Ignored without -debug. */
18+
case SimulateOs = 'ADMINER_DESKTOP_SIMULATE_OS';
1719
/** `make demo` only: the throwaway connection demo-login.js fills and submits. */
1820
case Demo = 'ADMINER_DESKTOP_DEMO';
1921
/** The launcher's own path (Go's os.Executable), so the MCP panel can print the exact

‎app/src/Os.php‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,16 @@ static function current(): self {
2828
};
2929
}
3030

31+
/** The OS the UI dresses as: the real one, unless -debug asks for another (Env::SimulateOs).
32+
* Only for how the page looks. Paths and printed commands stay on current(). */
33+
static function look(): self {
34+
$simulated = Env::Debug->get() ? self::tryFrom((string) Env::SimulateOs->get()) : null;
35+
return $simulated ?? self::current();
36+
}
37+
3138
/** The class on <body> the theme keys off (AdminerDesktop::bodyClass). */
3239
function bodyClass(): string {
33-
return 'os-' . $this->value;
40+
return $this->value . '-os';
3441
}
3542

3643
/** The name a person recognises, for the settings UI. */

‎app/src/Settings/Theme/Theme.php‎

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
namespace Desktop\Settings\Theme;
55

66
use Desktop\Latte;
7+
use Desktop\Os;
78
use Desktop\SettingKey;
89
use Desktop\UserSettings;
910

@@ -15,6 +16,9 @@
1516
* (include/plugins.inc.php:33), so a helper called AdminerTheme would quietly become one.
1617
*/
1718
class Theme {
19+
private const string OWN_DESIGN = "src/Settings/Theme/designs/adminer-desktop/adminer.css";
20+
private const string WINDOWS_SHEET = "src/Settings/Theme/designs/adminer-desktop/windows-os.css";
21+
1822
private \AdminerDesktop $desktop;
1923
private UserSettings $settings;
2024

@@ -60,7 +64,27 @@ function designs(Mode $mode): array {
6064
* @return array<string,string>
6165
*/
6266
function cssMap(): array {
63-
$self = "src/Settings/Theme/designs/adminer-desktop/adminer.css";
67+
$map = $this->designMap();
68+
if (Os::look() !== Os::Windows) {
69+
return $map;
70+
}
71+
// Right after ours and tagged the same, so it applies wherever ours does and never over a
72+
// gallery design.
73+
$return = [];
74+
foreach ($map as $path => $mode) {
75+
$return[$path] = $mode;
76+
if ($path === self::OWN_DESIGN) {
77+
$return[self::WINDOWS_SHEET] = $mode;
78+
}
79+
}
80+
return $return;
81+
}
82+
83+
/** Which design each side uses, before anything per-OS is added to it.
84+
* @return array<string,string>
85+
*/
86+
private function designMap(): array {
87+
$self = self::OWN_DESIGN;
6488
$sides = [];
6589
foreach (Mode::cases() as $mode) {
6690
$design = (string) $this->settings->get($mode->designKey(), "");

‎app/src/Settings/Theme/designs/adminer-desktop/README.md‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pulled in by native `@import` from `adminer.css`:
99
- `tables.css` — the data grid
1010
- `forms.css` — inputs and buttons
1111
- `sidebar.css` — the menu and breadcrumb
12+
- `windows-os.css` — Windows 11's tokens and controls under `windows-os`, with values from WinUI's resources; `Theme::cssMap()` loads it on Windows only, not this file
1213

1314
One file carrying both schemes: every scheme difference is a `light-dark(light, dark)`
1415
token, and the used `color-scheme` picks the side. Adminer sets that from its
@@ -19,7 +20,7 @@ dark surface, keys off the `theme-auto` / `theme-dark` body class instead (`base
1920
It is excluded from the gallery (`Theme::designs()`) because it is the default, offered as
2021
the empty "Adminer Desktop" option on each side rather than one entry among the rest.
2122

22-
Per-OS adaptation is mostly `system-ui` (the OS UI font, no branching); the `os-mac` /
23-
`os-windows` / `os-linux` body class from `AdminerDesktop::bodyClass()` is the hook for
23+
Per-OS adaptation is mostly `system-ui` (the OS UI font, no branching); the `mac-os` /
24+
`windows-os` / `linux-os` body class from `AdminerDesktop::bodyClass()` is the hook for
2425
the rest. Row density (`density-compact` / `-cozy` / `-comfortable`) comes from the same
2526
place.

‎app/src/Settings/Theme/designs/adminer-desktop/base.css‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ kbd,
8181

8282
/* macOS renders system-ui (San Francisco) best antialiased; Windows and Linux stay on
8383
the OS default, where forcing this only thins the text. .os-* comes from bodyClass. */
84-
.os-mac body {
84+
.mac-os body {
8585
-webkit-font-smoothing: antialiased;
8686
}
8787

@@ -206,28 +206,28 @@ body.theme-dark .icon {
206206
* system set to hide them — so the panels wore two grey bars at all times. Transparent until
207207
* hovered (`:hover` holds for every element under the pointer, so the scroller it is in), and
208208
* thin, as an overlay scrollbar is, and while it scrolls (.ad-scrolling, scrollers.js), as an
209-
* overlay one appears then. macOS only: Windows and Linux keep theirs on screen natively.
209+
* overlay one appears then. Windows has the same in windows-os.css; Linux keeps its own on screen.
210210
*
211211
* Only while the system draws overlay scrollbars. With a mouse plugged in, or System Settings set
212212
* to Always, macOS draws legacy ones that stay on screen, and so does every native app — Mail
213213
* included; the launcher says which (ad-legacy-scrollers on <html>, installScrollerStyle), and then
214214
* WebKit's own are left as they are, except the panels' (below). A plain browser is never told,
215215
* and keeps the overlay behaviour. */
216-
:root:not(.ad-legacy-scrollers) .os-mac * {
216+
:root:not(.ad-legacy-scrollers) .mac-os * {
217217
scrollbar-width: thin;
218218
scrollbar-color: transparent transparent;
219219
}
220220

221-
:root:not(.ad-legacy-scrollers) .os-mac :is(:hover, .ad-scrolling) {
221+
:root:not(.ad-legacy-scrollers) .mac-os :is(:hover, .ad-scrolling) {
222222
scrollbar-color: color-mix(in srgb, var(--fg) 35%, transparent) transparent;
223223
}
224224

225225
/* Even transparent, that bar keeps its width, so every rule in the two panels stopped one
226226
scrollbar short of the right edge. A legacy one takes the same column, and the toolbar's
227227
hairline and search stopped short of it. So the panels' bars are scrollers.js's in both modes;
228228
the scrollers inside them keep theirs. */
229-
.os-mac #menu,
230-
.os-mac #content {
229+
.mac-os #menu,
230+
.mac-os #content {
231231
scrollbar-width: none;
232232
}
233233

‎app/src/Settings/Theme/designs/adminer-desktop/tables.css‎

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,30 +24,30 @@ th,
2424
* finds the true first and last row whether or not the table has a header.
2525
*
2626
* macOS only, because a rounded grid is a macOS idiom rather than a house style: Windows and
27-
* Linux keep the square corners their own tables have, which is what os-mac not matching
27+
* Linux keep the square corners their own tables have, which is what mac-os not matching
2828
* leaves them with. */
29-
.os-mac table {
29+
.mac-os table {
3030
border-radius: var(--ad-radius);
3131
}
3232

33-
.os-mac table > :first-child > tr:first-child > :first-child {
33+
.mac-os table > :first-child > tr:first-child > :first-child {
3434
border-top-left-radius: var(--ad-radius);
3535
}
3636

37-
.os-mac table > :first-child > tr:first-child > :last-child {
37+
.mac-os table > :first-child > tr:first-child > :last-child {
3838
border-top-right-radius: var(--ad-radius);
3939
}
4040

41-
.os-mac table > :last-child > tr:last-child > :first-child {
41+
.mac-os table > :last-child > tr:last-child > :first-child {
4242
border-bottom-left-radius: var(--ad-radius);
4343
}
4444

45-
.os-mac table > :last-child > tr:last-child > :last-child {
45+
.mac-os table > :last-child > tr:last-child > :last-child {
4646
border-bottom-right-radius: var(--ad-radius);
4747
}
4848

4949
/* A settings table's corners, which everything drawing them reads from --ad-radius. */
50-
.os-mac #desktop-panels table {
50+
.mac-os #desktop-panels table {
5151
--ad-radius: var(--ad-card-radius);
5252
}
5353

@@ -371,17 +371,17 @@ span.ad-page-step {
371371
}
372372

373373
/* A notice inside the settings dialog, rounded as its tables are. */
374-
.os-mac dialog#desktop-settings :is(.message, .error) {
374+
.mac-os dialog#desktop-settings :is(.message, .error) {
375375
border-radius: var(--ad-card-radius);
376376
padding: 1.2em 1.5em;
377377
}
378378

379379
/* A select in a dialog's body only: the sidebar's and the pages' keep the UI's tighter corners. */
380-
.os-mac .ad-modal-body select {
380+
.mac-os .ad-modal-body select {
381381
border-radius: 10px;
382382
}
383383

384384
/* The saved connections on the index. */
385-
.os-mac :is(.ad-card, #ad-new-connection) {
385+
.mac-os :is(.ad-card, #ad-new-connection) {
386386
border-radius: var(--ad-card-radius);
387387
}

0 commit comments

Comments
 (0)