feat: theme zen browser

This commit is contained in:
2 * r + 2 * t 2025-06-16 19:46:19 +10:00
parent d26f95aee9
commit fe23648b15
10 changed files with 5088 additions and 1 deletions

View file

@ -6,6 +6,7 @@ argparse -n 'install.fish' -X 0 \
'spotify' \
'vscode=?!contains -- "$_flag_value" codium code' \
'discord' \
'zen' \
-- $argv
or exit
@ -20,6 +21,7 @@ if set -q _flag_h
echo ' --spotify install Spotify (Spicetify)'
echo ' --vscode=[codium|code] install VSCodium (or VSCode)'
echo ' --discord install Discord (OpenAsar + Equicord)'
echo ' --zen install Zen browser'
exit
end
@ -133,7 +135,7 @@ end
# Install metapackage for deps
log 'Installing metapackage...'
yay -S caelestia-meta $noconfirm
yay -S --needed caelestia-meta $noconfirm
# Install hypr* configs
if confirm-overwrite $config/hypr
@ -237,4 +239,37 @@ if set -q _flag_discord
yay -Rns equicord-installer-bin $noconfirm
end
# Install zen
if set -q _flag_zen
log 'Installing zen...'
yay -S --needed zen-browser-bin $noconfirm
# Install userChrome css
set -l chrome $HOME/.zen/*/chrome
if confirm-overwrite $chrome/userChrome.css
log 'Installing zen userChrome...'
ln -s (realpath zen/userChrome.css) $chrome/userChrome.css
end
# Install native app
set -l hosts $HOME/.zen/native-messaging-hosts
set -l lib $HOME/.local/lib/caelestia
if confirm-overwrite $hosts/caelestiafox.json
log 'Installing zen native app manifest...'
mkdir -p $hosts
cp zen/native_app/manifest.json $hosts/caelestiafox.json
sed -i "s|{{ \$lib }}|$lib|g" $hosts/caelestiafox.json
end
if confirm-overwrite $lib/caelestiafox
log 'Installing zen native app...'
mkdir -p $lib
ln -s (realpath zen/native_app/app.fish) $lib/caelestiafox
end
# Prompt user to install extension
log 'Please install the CaelestiaFox extension from https://addons.mozilla.org/en-US/firefox/addon/caelestiafox if you have not already done so.'
end
log 'Done!'

3
zen/.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules/
dist/
web-ext-artifacts/

View file

@ -0,0 +1,15 @@
{
"manifest_version": 2,
"name": "CaelestiaFox",
"version": "2.0",
"description": "A Firefox theme for the Caelestia dotfiles.",
"browser_specific_settings": {
"gecko": {
"id": "caelestiafox@caelestia.org"
}
},
"background": {
"scripts": ["dist/extension.js"]
},
"permissions": ["nativeMessaging", "theme"]
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,9 @@
{
"name": "caelestiafox",
"version": "0.0.1",
"license": "GPL-3.0-only",
"devDependencies": {
"@types/firefox-webext-browser": "^120.0.4",
"web-ext": "^8.4.0"
}
}

View file

@ -0,0 +1,155 @@
interface Colours {
rosewater: string;
flamingo: string;
pink: string;
mauve: string;
red: string;
maroon: string;
peach: string;
yellow: string;
green: string;
teal: string;
sky: string;
sapphire: string;
blue: string;
lavender: string;
primary_paletteKeyColor: string;
secondary_paletteKeyColor: string;
tertiary_paletteKeyColor: string;
neutral_paletteKeyColor: string;
neutral_variant_paletteKeyColor: string;
background: string;
onBackground: string;
surface: string;
surfaceDim: string;
surfaceBright: string;
surfaceContainerLowest: string;
surfaceContainerLow: string;
surfaceContainer: string;
surfaceContainerHigh: string;
surfaceContainerHighest: string;
onSurface: string;
surfaceVariant: string;
onSurfaceVariant: string;
inverseSurface: string;
inverseOnSurface: string;
outline: string;
outlineVariant: string;
shadow: string;
scrim: string;
surfaceTint: string;
primary: string;
onPrimary: string;
primaryContainer: string;
onPrimaryContainer: string;
inversePrimary: string;
secondary: string;
onSecondary: string;
secondaryContainer: string;
onSecondaryContainer: string;
tertiary: string;
onTertiary: string;
tertiaryContainer: string;
onTertiaryContainer: string;
error: string;
onError: string;
errorContainer: string;
onErrorContainer: string;
primaryFixed: string;
primaryFixedDim: string;
onPrimaryFixed: string;
onPrimaryFixedVariant: string;
secondaryFixed: string;
secondaryFixedDim: string;
onSecondaryFixed: string;
onSecondaryFixedVariant: string;
tertiaryFixed: string;
tertiaryFixedDim: string;
onTertiaryFixed: string;
onTertiaryFixedVariant: string;
}
interface Message {
name: string;
flavour: string;
mode: "dark" | "light";
variant: string;
colours: Colours;
}
const browserColours = (colours: Colours) => ({
bookmark_text: colours.onSurface,
button_background_hover: colours.surfaceContainerHigh,
button_background_active: colours.surfaceContainerHighest,
icons: colours.secondary,
icons_attention: colours.primary,
frame: colours.surfaceDim,
frame_inactive: colours.surfaceDim,
tab_text: colours.onSurface,
tab_loading: colours.primary,
tab_background_text: colours.outline,
tab_selected: colours.surfaceContainer,
tab_line: colours.surfaceContainer,
toolbar: colours.surfaceContainer,
toolbar_text: colours.onSurface,
toolbar_field: colours.surfaceBright,
toolbar_field_focus: colours.surfaceBright,
toolbar_field_border: colours.surfaceBright,
toolbar_field_border_focus: colours.primary,
toolbar_field_text: colours.onSurfaceVariant,
toolbar_field_text_focus: colours.onSurface,
toolbar_field_highlight: colours.primary,
toolbar_field_highlight_text: colours.onPrimary,
toolbar_field_separator: colours.surface,
toolbar_top_separator: colours.surfaceContainer,
toolbar_bottom_separator: colours.surface,
toolbar_vertical_separator: colours.secondaryContainer,
ntp_background: colours.surface,
ntp_card_background: colours.surfaceContainer,
ntp_text: colours.onSurface,
popup: colours.surfaceContainer,
popup_border: colours.outlineVariant,
popup_text: colours.onSurface,
popup_highlight: colours.primary,
popup_highlight_text: colours.onPrimary,
sidebar: colours.surfaceContainerHigh,
sidebar_border: colours.surfaceContainerHigh,
sidebar_text: colours.onSurface,
sidebar_highlight: colours.secondaryContainer,
sidebar_highlight_text: colours.onSecondaryContainer,
});
const darkReaderColours = (scheme: Message) => ({
mode: scheme.mode === "light" ? 0 : 1,
[`${scheme.mode}SchemeTextColor`]: `#${scheme.colours.onSurface}`,
[`${scheme.mode}SchemeBackgroundColor`]: `#${scheme.colours.surface}`,
});
let darkReader: browser.runtime.Port | null = browser.runtime.connect("addon@darkreader.org");
darkReader.onDisconnect.addListener(() => {
console.log("DarkReader disconnected:", darkReader?.error);
darkReader = null;
});
browser.runtime.connectNative("caelestiafox").onMessage.addListener(msg => {
console.log("Received message:", msg);
const res = msg as Message;
const colours = Object.fromEntries(Object.entries(res.colours).map(([n, c]) => [n, `#${c}`])) as unknown as Colours;
const theme: browser._manifest.ThemeType = {
colors: browserColours(colours),
properties: {
color_scheme: res.mode,
content_color_scheme: res.mode,
},
};
browser.theme.update(theme);
console.log("Theme updated:", theme);
if (darkReader !== null) {
darkReader.postMessage({ type: "setTheme", data: darkReaderColours(res) });
console.log("DarkReader theme updated.");
}
});
console.log("CaelestiaFox started.");

View file

@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "ES6",
"module": "ES2020",
"moduleResolution": "node",
"strict": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"outDir": "dist"
},
"include": ["src"]
}

19
zen/native_app/app.fish Executable file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env fish
function message -a msg
# The message length as 4 hex bytes
set -l x (printf '%08X' (string length -- $msg))
# Write each of the 4 bytes
printf '%b' "\\x$(string sub -s 7 -l 2 $x)\\x$(string sub -s 5 -l 2 $x)\\x$(string sub -s 3 -l 2 $x)\\x$(string sub -s 1 -l 2 $x)"
# Write the message itself
printf '%s' $msg
end
set -q XDG_STATE_HOME && set -l state $XDG_STATE_HOME || set -l state $HOME/.local/state
set -l scheme_path $state/caelestia/scheme.json
message (jq -c . $scheme_path)
inotifywait -q -e 'close_write,moved_to,create' -m (dirname $scheme_path) | while read dir events file
test "$dir$file" = $scheme_path && message (jq -c . $scheme_path)
end

View file

@ -0,0 +1,7 @@
{
"name": "caelestiafox",
"description": "Native app for CaelestiaFox extension.",
"path": "{{ $lib }}/caelestiafox",
"type": "stdio",
"allowed_extensions": ["caelestiafox@caelestia.org"]
}

212
zen/userChrome.css Normal file
View file

@ -0,0 +1,212 @@
:root {
--c-accent: var(--tab-loading-fill);
--c-text: var(--toolbar-color);
--c-mantle: var(--lwt-accent-color);
--c-base: var(--tabpanel-background-color);
--c-surface0: var(--tab-selected-bgcolor);
--c-surface1: var(--arrowpanel-border-color);
--zen-primary-color: var(--c-surface0) !important;
--zen-colors-primary: var(--c-accent) !important;
--zen-colors-secondary: var(--c-surface0) !important;
--zen-colors-tertiary: var(--c-base) !important;
--zen-colors-border: var(--c-surface1) !important;
--toolbarbutton-icon-fill: var(--c-accent) !important;
--toolbarbutton-icon-fill-attention: var(--c-accent) !important;
--toolbarbutton-icon-fill-attention-text-light: var(--c-text) !important;
--toolbarbutton-icon-fill-attention-text-dark: var(--c-base) !important;
--lwt-text-color: var(--c-text) !important;
--toolbar-field-color: color-mix(in srgb, var(--c-text), transparent 15%) !important;
--toolbar-field-focus-color: color-mix(in srgb, var(--c-text), transparent 10%) !important;
--arrowpanel-color: var(--c-text) !important;
--arrowpanel-background: var(--c-base) !important;
--lwt-sidebar-text-color: var(--c-text) !important;
--lwt-sidebar-background-color: var(--c-mantle) !important;
--toolbar-bgcolor: var(--c-surface0) !important;
--newtab-background-color: var(--c-base) !important;
--zen-themed-toolbar-bg: var(--c-mantle) !important;
--zen-main-browser-background: var(--c-mantle) !important;
--urlbarView-highlight-color: var(--c-text) !important;
--in-content-primary-button-text-color: var(--c-text) !important;
--in-content-primary-button-background: var(--toolbarbutton-hover-background) !important;
--in-content-primary-button-background-hover: var(--toolbarbutton-active-background) !important;
}
tooltip {
appearance: none !important;
background-color: var(--c-mantle) !important;
color: var(--c-text) !important;
border: 1px solid color-mix(in srgb, var(--c-accent), transparent 70%) !important;
border-radius: 8px !important;
}
#permissions-granted-icon {
color: var(--c-mantle) !important;
}
.sidebar-placesTree {
background-color: var(--c-base) !important;
}
#urlbar-background {
background-color: var(--c-surface0) !important;
}
#TabsToolbar {
background-color: var(--c-mantle) !important;
}
.content-shortcuts {
background-color: var(--c-base) !important;
border-color: var(--c-accent) !important;
}
.urlbarView-url {
color: var(--c-accent) !important;
}
#zenEditBookmarkPanelFaviconContainer {
background: var(--c-mantle) !important;
}
toolbarbutton {
fill: var(--c-accent) !important;
}
toolbar .toolbarbutton-1 {
&:not([disabled]) {
&:is([open], [checked]) > :is(.toolbarbutton-icon, .toolbarbutton-text, .toolbarbutton-badge-stack) {
fill: var(--c-mantle) !important;
}
}
}
#autoscroller {
width: 50px !important;
height: 50px !important;
}
#urlbar-container {
background: var(--c-mantle) !important;
}
/* Center url bar text when not focused */
#urlbar:not([focused]) .urlbar-input {
text-align: center !important;
}
/* Floating url bar appear animation + shift down */
@keyframes floating-urlbar-show {
0% {
opacity: 0;
scale: 0.8;
translate: -10% 0;
}
70% {
scale: 1.02;
translate: 1% 0;
}
100% {
opacity: 1;
scale: 1;
translate: 0 0;
}
}
#urlbar[breakout-extend] {
animation: 200ms floating-urlbar-show ease-out;
}
/* Blur menu popups */
#commonDialog,
.menupopup-arrowscrollbox {
border-radius: 10px !important;
border: 1px solid color-mix(in srgb, var(--arrowpanel-border-color), transparent 70%) !important;
background: color-mix(in srgb, var(--arrowpanel-background), transparent 15%) !important;
backdrop-filter: blur(25px) !important;
}
#commonDialog {
background: color-mix(in srgb, var(--zen-branding-bg), transparent 15%) !important;
}
/* Blur floating url bar */
#urlbar[zen-floating-urlbar][breakout][breakout-extend] > #urlbar-background {
border: 1px solid color-mix(in srgb, var(--zen-colors-border), transparent 70%) !important;
border-radius: 10px !important;
background: color-mix(in srgb, var(--zen-colors-tertiary), transparent 15%) !important;
backdrop-filter: blur(25px) !important;
}
#urlbar[breakout-extend] .urlbar-input-container {
padding-top: 7px !important;
padding-bottom: 0px !important;
}
.urlbarView-body-inner {
border: none !important;
}
/* Styles the search options */
.search-one-offs {
border-top: none !important;
padding: 4px !important;
margin: 0px 0px 7px 0px !important;
}
.searchbar-engine-one-off-item {
border-radius: 8px !important;
margin-right: 3px !important;
}
#urlbar-anon-search-settings {
margin-right: 0px !important;
}
/* Border/outline transition fix */
* {
border: 0px solid transparent;
outline: 0px solid transparent;
}
/* Dim unloaded tabs */
.tabbrowser-tab[pending] {
filter: grayscale(1);
opacity: 0.5;
}
/* Animations */
:is(
.tab-background,
.toolbarbutton-icon,
.toolbarbutton-badge-stack,
.toolbarbutton-1,
.bookmark-item,
.PanelUI-zen-profiles-item,
.download-state,
.urlbarView-row,
.urlbarView-action,
.searchbar-engine-one-off-item,
#urlbar-search-mode-indicator,
#tracking-protection-icon-container,
#page-action-buttons > *,
#identity-box > *,
toolbarbutton,
toolbaritem,
button,
menu,
menuitem,
tab
):not(#urlbar-container, #personal-bookmarks) {
transition: all 0.15s ease !important;
&:is(tab) {
transition: scale 0.15s ease !important;
}
&:is(:active, :not(tab)[open]) {
scale: 0.95 !important;
}
}