feat: v1.6.0 — theme system fix, new themes, session restore, native frame mode, tab UX#170
Merged
Conversation
Replace the built-in zoomIn/zoomOut/resetZoom menu roles with explicit handlers using CmdOrCtrl+= / CmdOrCtrl+- / CmdOrCtrl+0 accelerators. The default 'Plus' accelerator binds to the layout's '+' key, which on Spanish (and other) layouts requires a modifier the user shouldn't have to press. Using '=' as the primary key works across layouts, with a hidden CmdOrCtrl+Shift+= alias so US users pressing Ctrl++ still trigger zoom in. Also retarget the zoom calls from the BrowserWindow's webContents (the tab bar) to the active tab's WebContentsView so the Notion content actually scales. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Redux subscriber that drives tab-bar IPC updates only watched state.tabs.tabs and ignored state.windows.windows[*].activeTabId, so clicking a tab updated the WebContentsView but never resent the tab-activated event. The highlight stayed on the previously active tab until something else (new tab, title change, etc.) caused a tab-data diff. Track active-tab IDs across windows in a separate snapshot and notify when either snapshot changes. Fix #156: enable drag-and-drop tab reordering The IPC handler tab-bar:reorder-tabs and the preload bridge were both already in place, but the renderer never wired any drag handlers, so the documented reorder feature simply did nothing. Add native HTML5 drag-and-drop on tab elements with before/after drop indicators and an optimistic local reorder before the IPC roundtrip. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add an opt-in "Restore Tabs on Startup" toggle (in the logo popup menu) that persists each window's tabs and restores them on next launch. Implementation: - AppController: debounced Redux subscriber writes a session snapshot to electron-store on every state change. Saving on before-quit doesn't work because clicking the window's X fires window-closed first, which wipes Redux state and empties windowControllers, so before-quit had nothing left to save. - TabController: also listen for did-navigate-in-page so Notion's pushState-based routing keeps the saved URL in sync with the page the user is actually on. - WindowController: dispatch addWindow BEFORE createInitialTab. The reverse order silently dropped the first tab from tabIds (since addTabToWindow no-ops when the window entry doesn't exist yet). This bug pre-dated session restore — it was just invisible with one tab because the tab bar still showed the "+" button. Restore made it visible by trying to add subsequent tabs that *did* register. - index.js: localStore default for restoreTabsOnStartup, and a ✓-prefixed toggle item in the logo popup menu (the standard Electron menu bar is hidden by design in Lotion). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the ✓-prefix and emoji-decoration pattern with native Electron menu controls and a cleaner hierarchy: - App version header at the top - type:'checkbox' for Spell Check and Restore Tabs on Startup (proper native checkmark instead of a text prefix that flipped the label) - type:'radio' for theme selection (mutually exclusive) - Themes grouped in a submenu - About Lotion dialog with version and a button to open GitHub - Help & GitHub submenu collects external links (Star, Follow, Report Issue) - Spell-check tab application extracted into a small helper for clarity Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch the tab bar's overflow behavior from "show a native horizontal scrollbar" to a hybrid that matches mainstream tabbed apps: 1. Tabs shrink first (min-width 100→80px) so moderate tab counts fit without scrolling at all — Chrome/Firefox behavior. 2. When even shrunk tabs overflow, the scrollbar is styled thin and transparent until hover, so it's not visually intrusive. 3. Mouse-wheel over the tab list scrolls horizontally (vertical wheel translates to scrollLeft) so users can navigate without aiming for the hidden scrollbar. 4. A soft fade mask appears on whichever edge has hidden tabs as a discoverable "more tabs that way" cue — toggled live on scroll and on resize. Also move the "+" button out of the scrolling .tab-list so it stays pinned next to the window controls instead of scrolling out of view when the bar overflows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a Use Native Window Decorations toggle (logo menu + standard menu bar's Lotion submenu) that swaps the frameless custom-tab-bar window for a native-frame single-tab window. Trade-off is deliberate: combining tabs with native decorations would mean stacking two title bars, so native mode drops the tab bar entirely. Settings/navigation in native mode go through the standard Electron menu bar (which is already wired up, just hidden in custom mode). The session-restore feature still works as one-tab-per-window. The Electron `frame` option is fixed at BrowserWindow creation, so toggling shows a Restart Now / Later dialog rather than trying to hot-swap. WindowController reads the setting in its constructor, conditionally skips the tab bar, sets `frame`/`titleBarStyle`, makes the menu bar visible, and uses a 0-height tab-bar offset so the active tab fills the content area. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the user toggled "Use Native Window Decorations" and Lotion relaunched, the WM-reported window bounds on Linux were sometimes stale at the moment we computed view bounds (especially with DE decorations enabled), leaving a gap below the WebContentsView so the Notion content didn't fill the window. Hook the BrowserWindow 'show' event to re-run updateViewBounds, with a second pass 100ms later to catch WMs that report final geometry only after a frame or two of compositing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 7 named themes (Dracula, Nord, Gruvbox Dark, 4 Catppuccin variants) were listed in the menu but never shipped any CSS — the injector looked under ~/.config/Lotion/themes/<name>.css and silently no-oped when nothing was there. That's why every reporter in #150 said theming was broken regardless of OS. Ship 10 themes as bundled assets and fall back to them when no user override is present. New themes added beyond the original 7: Monokai (classic Sublime palette), Noir (high-contrast B&W + blood red), and Sakura (pastel pink Hello-Kitty light theme). Three follow-ups that fell out of getting the themes to actually paint: - Notion no longer uses the --theme--* variable convention from the old notion-enhancer era — it uses obfuscated --c-* names declared on .notion-dark-theme / .notion-light-theme (on <body>). CSS custom properties inherit from the closest defining ancestor, so a :root override is shadowed for everything inside <body>. Each theme declares on :root + body + .notion-dark-theme + .notion-light-theme + .notion-app-inner with !important so our values win regardless of where Notion (or a Notion update) puts the source. - nativeTheme.themeSource is set to match each theme's mode ('light' / 'dark' / 'system') so Notion's "use system setting" appearance preference auto-flips its own light/dark when the user picks a Sakura-style light theme or a Dracula-style dark theme. Initialized at app startup from the saved theme so launches are consistent before any window opens. - Tab bar (separate WebContentsView, not reached by injected CSS) gets matching color classes for the 3 new themes and the class-removal list is kept in sync so themes don't leak across switches. Menu fixes that came out of polishing the Theme submenu: - Switch from type:'radio' to type:'checkbox' for theme items — Electron's radio behavior in popup menus on Linux/GTK was leaking selected state across menu instances, so users saw 3+ themes marked as "active" after a few switches. Also fix a hang on the Use-Native-Window-Decorations restart: the old code did app.exit(0) right after the dialog .then() returned, bypassing graceful BrowserWindow teardown and orphaning renderer processes. Defer to setImmediate then call app.quit() so WebContents cleanup runs first. dumpNotionCSSVars() is kept on TabController (gated behind LOTION_DUMP_VARS=1) for future investigations when Notion next changes their CSS variable naming. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Minor-version bump for the post-1.5.1 feature batch: 10-theme system fix, Monokai/Noir/Sakura additions, system-theme sync, session restore, native window decorations toggle, tab UX fixes, and the logo menu redesign. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous PKGBUILD built from source by running `npm install` + `npm run package` inside makepkg. That's exactly what the user in #146 was complaining about: hundreds of npm warnings, deprecated packages, "12 vulnerabilities (4 low, 4 moderate, 4 high)" on a fresh install. The vulnerabilities aren't really Lotion's fault — they're inherent to building any Electron app from source — but we shouldn't be forcing that experience on people who just want to install Lotion. Switch to a lotion-bin style PKGBUILD: it downloads the .deb produced by our build-and-release workflow and extracts it into the system. Same binary that ships in the official release, ~30s install instead of ~5min, no npm chain on the user's machine. - PKGBUILD: -bin style, separate source_x86_64 / source_aarch64 pulling lotion_${pkgver}_${arch}.deb from the GitHub release. package() just calls bsdtar to extract the .deb. Declares Electron runtime deps (gtk3, nss, libxss, libsecret, libnotify, alsa-lib, xdg-utils) explicitly. - PKGBUILD.md: documents the new approach + update workflow. - knol/AUR_SUBMISSION.md: rewritten for lotion-bin naming and the release-artifact-driven release flow. - install-arch.sh: deleted. The "bash <(curl ...)" pattern is security-flagged and was solving a problem (one-line install) that AUR / makepkg solves better. - test-arch-install.yml: replaced source-build / install-arch.sh checks with assertions that the PKGBUILD stays binary-only — fails CI if the source array drifts off .deb or if npm calls sneak back in. Note: the lotion-bin package isn't actually published on the AUR yet — README is updated to reflect that. The PKGBUILD works locally via `makepkg -si` from this repo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Substantial overhaul. The previous README had drifted out of sync with reality across several axes — the AUR section claimed `yay -S lotion` worked when the package isn't on the AUR; the Themes section listed 8 themes when v1.6.0 ships 10; the Electron version badge was three majors behind; `.deb` / `.rpm` install examples used 1.0.0 filenames; and there were broken references (`portable.sh`, root-level `AUR_SUBMISSION.md`) that didn't exist. Rewritten so it reflects what actually ships: - Version badge bumped to 1.6.0, Electron badge to 41.7.0. - Features section restructured into Window/Tabs, Theming, Other. Calls out the v1.6.0 additions explicitly: session restore (opt-in), native window decorations toggle, shrink-then-fade tab overflow, layout-independent zoom shortcuts. - Themes section lists all 10 in a dark/light table, including the new Monokai / Noir / Sakura, and mentions the system-theme sync behavior (light theme → Notion flips its "use system" appearance to light, dark theme → dark). - Custom themes example rewritten against Notion's current --c-* variable convention with the right selector list (Notion declares these on .notion-dark-theme on <body>, so :root alone isn't enough). Points readers at assets/themes/ for a complete template. - Arch install section is honest: lotion-bin isn't on the AUR yet, here's how to build from the PKGBUILD locally. - Other install examples use 1.6.0 filenames. - Removes references to nonexistent files (portable.sh, root-level AUR_SUBMISSION.md) and fixes the actual path to knol/. - Adds a proper keyboard shortcuts table (zoom, navigation, prefs, devtools). - Adds a configuration section listing where user data lives (~/.config/Lotion/) and pointer to the logo menu for preferences. - Development section trimmed: file tree updated to reflect current layout (assets/themes/, managers/, etc.), and includes a small note on how to dump Notion CSS variables when their naming changes in the future (LOTION_DUMP_VARS=1). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Unsigned Electron apps on Apple Silicon get the misleading "Lotion
is damaged and can't be opened" Gatekeeper error rather than the
clearer "unidentified developer" warning Intel macs used to show.
It's not actually damaged — macOS just refuses to validate the
missing signature.
Two fixes in this change:
1. Add `osxSign: { identity: "-" }` to packagerConfig so the build
does an ad-hoc signature. Doesn't satisfy Gatekeeper (no Apple
Developer cert involved), but does change the error from
"damaged" to "unidentified developer" — meaning the user can
right-click → Open to bypass it interactively. No money or Apple
account required.
2. README macOS section explains why it happens, links the GitHub
Sponsors page for if someone wants to fund the $99/year Developer
Program, and gives the two user-side workarounds (xattr -cr on
the .zip before extraction, or on the extracted .app). Also adds
a brief Windows SmartScreen note for symmetry.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Arch Linux container's default GitHub Actions shell is `sh -e`,
where `source` doesn't exist (POSIX uses `.`) and bash array
expansions like ${source_x86_64[@]} aren't valid syntax. The
"Verify lotion-bin-style PKGBUILD shape" step failed with
"source: PKGBUILD: file not found" because of that.
Set defaults.run.shell=bash at the job level so all run steps use
bash. Cleaner than scattering shell: bash on individual steps and
leaves room for future bashisms in the validation logic without
having to remember the shell override each time.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Post-v1.5.1 feature batch + packaging/docs overhaul. 12 commits, bumps to v1.6.0.
🎨 Themes (closes #150)
assets/themes/and override Notion's current--c-*variable convention with!importanton.notion-dark-theme/.notion-light-theme.nativeTheme.themeSource; dark themes flip it back.🪟 Window & Tab UX
activeTabIdchanges).addTabToWindowwas dispatched beforeaddWindowso it silently no-oped — fixed init order.+button stays pinned.🎛️ Logo Menu
Native checkboxes instead of emoji + text-prefix hacks; About dialog; Help & GitHub submenu.
📦 Arch packaging (closes the root cause of #146)
PKGBUILDaslotion-bin— downloads the official.debfrom the GitHub release and extracts it. Same binary as the official build, ~30s install, nonpm installchain on the user's machine (that was the source of the 950 packages + vulnerability output the user in Severe issues with Arch install? #146 complained about).install-arch.sh(bash <(curl …)pattern, security-flagged, redundant with makepkg).PKGBUILD.mdandknol/AUR_SUBMISSION.mdfor the new flow..debsources or ifnpmcalls sneak back in.📝 README rewrite
Drifted out of sync over time — version badge was 1.5.0, Electron 34.3.2, themes list missed 5 themes,
.debexample used 1.0.0, broken references toportable.shand a root-levelAUR_SUBMISSION.mdthat didn't exist. Rewritten end to end:--c-*selectors that actually work🔧 Fixes that fell out
app.exit(0)→setImmediate + app.quit()).Commits
Test plan
Ctrl+=,Ctrl+-,Ctrl+0zoom shortcuts (andCtrl++on US layouts)git clonethis branch,cd lotion,makepkg -si— lotion installs from the release.debwithout running npm,lotioncommand worksNot included
AUR follow-up (not in this PR)
Once this merges and the v1.6.0 release builds, someone with AUR access can publish
lotion-binto the AUR using the workflow inknol/AUR_SUBMISSION.md. Until then, users build from the included PKGBUILD.🤖 Generated with Claude Code