Skip to content

feat: light mode and customizable shortcuts#3

Open
shashank-sn wants to merge 2 commits into
antiwork:mainfrom
shashank-sn:feat/light-mode-and-shortcuts
Open

feat: light mode and customizable shortcuts#3
shashank-sn wants to merge 2 commits into
antiwork:mainfrom
shashank-sn:feat/light-mode-and-shortcuts

Conversation

@shashank-sn

Copy link
Copy Markdown

Two features, one commit (+122/−36 lines in main.swift):

Light mode — Chromeless now follows the system appearance by default. Light-mode Mac users get light Chromeless. Users can override with:

defaults write com.chromeless.app appearance dark   # force dark
defaults write com.chromeless.app appearance light  # force light
defaults delete com.chromeless.app appearance       # follow system

The start page HTML uses @media (prefers-color-scheme: dark) with light colors as the default. Window and webview backgrounds use system-adaptive .windowBackgroundColor instead of hardcoded near-black.

Customizable shortcuts — every chromeless-specific shortcut is now stored in a UserDefaults plist dictionary. Customize with:

defaults write com.chromeless.app shortcuts -dict openLocation "k" reloadPage "r"
defaults delete com.chromeless.app shortcuts  # reset to defaults

Customizable actions: openLocation, saveSnapshot, reloadPage, hardReload, zoomIn, zoomOut, actualSize, goBack, goForward, togglePin, copyURL, showHelp. Standard Cocoa shortcuts (Cmd-C, Cmd-V, Cmd-Q, Cmd-W, Cmd-M, Cmd-H) are not customizable. Changes take effect on app relaunch.

Both features stay within the zero-dependency, single-file philosophy.

Validation

Built with ./build.sh on macOS 26 (arm64):

  • System light mode → light Chromeless window, light start page
  • defaults write com.chromeless.app appearance dark → relaunch → dark Chromeless
  • --snap /tmp/test.png --size 800x600 → saved successfully
  • open Chromeless.app → Cmd-L HUD works, Esc returns to start page

- Follow system appearance by default (light mode users get light Chromeless)
- Allow override via `defaults write com.chromeless.app appearance dark|light|system`
- Start page HTML uses `@media (prefers-color-scheme: dark)` for dual mode
- Window/webview backgrounds use system-adaptive .windowBackgroundColor
- All chromeless-specific shortcuts now customizable via UserDefaults plist
- Standard Cocoa shortcuts (Cmd-C, Cmd-V, Cmd-Q) remain non-customizable
- Shortcut changes take effect on app relaunch - no live rebinding

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
@greptile-apps

greptile-apps Bot commented Jul 4, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds light-mode support and customizable app shortcuts. The main changes are:

  • System-following window and start page appearance.
  • UserDefaults overrides for light, dark, or system appearance.
  • UserDefaults-backed shortcuts for chromeless-specific menu actions.
  • README documentation for the new defaults commands.

Confidence Score: 4/5

This is close, but the shortcut collision cases should be fixed before merging.

  • Reserved Cocoa shortcuts can still be assigned to custom actions.
  • The reload and hard-reload actions can still end up with the same keyboard binding.
  • The modifier-order parsing fix appears to handle the originally broken ordering cases.

main.swift

Important Files Changed

Filename Overview
main.swift Adds appearance resolution and customizable menu shortcuts, with remaining shortcut collision handling needed.
README.md Documents the new appearance and shortcut defaults commands.

Reviews (2): Last reviewed commit: "fix: improve shortcut modifier parsing, ..." | Re-trigger Greptile

Comment thread main.swift Outdated
Comment thread main.swift
Comment on lines +848 to 849
let (snapKey, snapMods) = resolveShortcut("saveSnapshot", defaultKey: "s", defaultModifiers: [.command, .shift])
let snap = fileMenu.addItem(withTitle: "Save Snapshot to Desktop",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Custom Binding Shadows Paste

When saveSnapshot is set to cmd+v, this File-menu item is registered before Edit > Paste with the same ⌘V equivalent. Pressing ⌘V in a page or text field can run saveSnapshot(_:) instead of paste(_:), even though the standard Cocoa shortcut is meant to remain non-customizable.

Comment thread main.swift
Comment on lines +876 to +879
let (hrKey, hrMods) = resolveShortcut("hardReload", defaultKey: "r", defaultModifiers: [.command, .shift])
let hardReload = viewMenu.addItem(withTitle: "Reload Ignoring Cache",
action: #selector(BrowserWindowController.hardReloadPage(_:)), keyEquivalent: "r")
hardReload.keyEquivalentModifierMask = [.command, .shift]
action: #selector(BrowserWindowController.hardReloadPage(_:)), keyEquivalent: hrKey)
hardReload.keyEquivalentModifierMask = hrMods

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Hard Reload Loses Shortcut

When hardReload is configured as cmd+r, this item gets the same ⌘R equivalent as Reload Page, which is added just above it in the same menu. AppKit will match the first enabled item, so the keyboard shortcut performs a normal reload and hard reload becomes unreachable from the keyboard.

…cuts in README

- Fix resolveShortcut() compound modifier parsing with while-loop re-scan
- Start modifiers as empty set so non-Cmd shortcuts are possible
- Guard against empty key after modifier-only input
- Add README sections for appearance override and customizable shortcuts

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
Comment thread main.swift
}
if key.isEmpty { return (defaultKey, defaultModifiers) }
if modifiers.isEmpty { modifiers = defaultModifiers }
return (key, modifiers)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Reserved shortcuts still bind The parser returns user-provided bindings even when they match standard Cocoa shortcuts. For example, defaults write com.chromeless.app shortcuts -dict openLocation "cmd+q" resolves to q with the command modifier, and the menu then installs Open Location on the same shortcut as Quit. The same path can take cmd+w, cmd+h, or cmd+m, so core app and window commands can stop working from the keyboard even though those shortcuts are meant to stay reserved.

Comment thread main.swift
Comment on lines +879 to +882
let (hrKey, hrMods) = resolveShortcut("hardReload", defaultKey: "r", defaultModifiers: [.command, .shift])
let hardReload = viewMenu.addItem(withTitle: "Reload Ignoring Cache",
action: #selector(BrowserWindowController.hardReloadPage(_:)), keyEquivalent: "r")
hardReload.keyEquivalentModifierMask = [.command, .shift]
action: #selector(BrowserWindowController.hardReloadPage(_:)), keyEquivalent: hrKey)
hardReload.keyEquivalentModifierMask = hrMods

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Hard reload can collide reloadPage can still be configured to the hard-reload shortcut. If the user sets reloadPage to shift+cmd+r, this menu item is added before Reload Ignoring Cache with the same key and modifier mask, so the normal reload item handles the shortcut first and hard reload is no longer reachable from the keyboard. The reload pair needs duplicate-binding handling before assigning both menu items.

Suggested change
let (hrKey, hrMods) = resolveShortcut("hardReload", defaultKey: "r", defaultModifiers: [.command, .shift])
let hardReload = viewMenu.addItem(withTitle: "Reload Ignoring Cache",
action: #selector(BrowserWindowController.hardReloadPage(_:)), keyEquivalent: "r")
hardReload.keyEquivalentModifierMask = [.command, .shift]
action: #selector(BrowserWindowController.hardReloadPage(_:)), keyEquivalent: hrKey)
hardReload.keyEquivalentModifierMask = hrMods
var (hrKey, hrMods) = resolveShortcut("hardReload", defaultKey: "r", defaultModifiers: [.command, .shift])
if hrKey == rlKey && hrMods == rlMods {
(hrKey, hrMods) = ("r", [.command, .shift])
}
let hardReload = viewMenu.addItem(withTitle: "Reload Ignoring Cache",
action: #selector(BrowserWindowController.hardReloadPage(_:)), keyEquivalent: hrKey)
hardReload.keyEquivalentModifierMask = hrMods

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant