mirror of
https://github.com/caelestia-dots/cli.git
synced 2026-06-05 23:09:27 -05:00
Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d1c8c8fc09 | |||
| ad533a0dd4 | |||
| ccd2712982 | |||
| 1ea661859d | |||
| 64a5507e74 | |||
| 7fa3fc1bd0 | |||
| 7f30062670 | |||
| 04d286eaff | |||
| 2ce6213698 | |||
| 4b3ffcd644 | |||
| 2621724c55 | |||
| 7b8a4281aa | |||
| 7452974dc9 | |||
| 544b567668 | |||
| 1f523c7556 | |||
| a00e71d6b7 | |||
| 1ec969d9ec | |||
| 5273ed514f | |||
| f3b13affc3 | |||
| 5c9ce66c03 | |||
| c18f749f24 | |||
| 96fcdf5bce | |||
| eddee4deca | |||
| 68bc03bc17 | |||
| 023a30b83c | |||
| a192efae9c | |||
| 463f36544a | |||
| 5f1d008cce | |||
| 66bce26841 | |||
| e1531f3c9e | |||
| 7f59ca9656 | |||
| 4cf9e8603f | |||
| b4b26ab5d5 | |||
| b4758901f9 | |||
| 60284ca41e | |||
| a019c42244 | |||
| 950c40bbd4 | |||
| d054129db8 | |||
| e497ca87eb | |||
| e81b1b87f0 | |||
| 1b823554ad | |||
| 4538e9cb50 | |||
| e5c161d43a | |||
| 11bdbc9e80 | |||
| 5bb3276b14 | |||
| 3930ca09b9 | |||
| 305f02d8aa | |||
| 8c7eea556d | |||
| 6bb09e7703 | |||
| b023936e1d | |||
| 3cdc2ce464 | |||
| 534d11d66a | |||
| 0d8be30138 | |||
| 8c6d933267 | |||
| b00c601d0a | |||
| c930bd2604 | |||
| cc155cf432 | |||
| 6e59149fbf | |||
| 8d2b737f15 | |||
| 4bcd42f482 | |||
| 51cecd481c | |||
| c9312f3928 | |||
| bfaf4fc373 | |||
| 6e711ec289 | |||
| 7899f8348f | |||
| b0d68f0a1c | |||
| b0325a1898 | |||
| a6defd2921 | |||
| 0b9e416175 | |||
| 8ce97ea3f5 | |||
| 25c473c18e | |||
| c22916fe45 | |||
| 011989e3ca | |||
| d88cc7ff79 | |||
| a550eb79ed | |||
| d890f7c3af | |||
| bca7b12072 | |||
| fe8adde6c1 | |||
| 9c309473f4 | |||
| 6e5ab6db53 | |||
| 170405fbb0 | |||
| 6a91c7b990 | |||
| bdc5f91009 | |||
| 164bda5462 | |||
| fe071cb285 | |||
| 2d5bec14a5 | |||
| 2395347d36 | |||
| cf6092b77b | |||
| 6dad795297 | |||
| 016a566bb7 | |||
| 2240ad4adf | |||
| fccf32250e | |||
| 90fc2a981e | |||
| 6cdb131e3a | |||
| ecf0c6156a | |||
| 52a3a3c50e | |||
| 6b3f927d2c | |||
| 74ddac98eb | |||
| d09e36299a | |||
| 50c8f9c84d | |||
| 33fb69dc8c | |||
| 7de6c60631 | |||
| 0cd11ef665 | |||
| 64686104a1 | |||
| 08dc3e0e87 | |||
| 7900d05459 | |||
| 315f1daf9d | |||
| ad555d5129 | |||
| 70a8624eac | |||
| 86b0c94bd1 | |||
| 55d75a1175 | |||
| 55590bd9e4 | |||
| 337c711371 | |||
| f3ea42d43a | |||
| e33e6ccf72 | |||
| b049cb1749 | |||
| 78e0b9d795 | |||
| e9f3f00bb9 | |||
| 8c83ae1e6a | |||
| 10639b5de0 | |||
| e1efe59e55 | |||
| b1e4e92e98 | |||
| 3e59c5acc2 | |||
| 1eead86151 | |||
| 02442e0f85 | |||
| 5fa4d1b278 | |||
| c0813790c2 | |||
| ed12d4cb82 | |||
| 1e1edfcd38 | |||
| 0fdab31bc7 |
@@ -93,6 +93,45 @@ sudo python -m installer dist/*.whl
|
|||||||
sudo cp completions/caelestia.fish /usr/share/fish/vendor_completions.d/caelestia.fish
|
sudo cp completions/caelestia.fish /usr/share/fish/vendor_completions.d/caelestia.fish
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Additional steps
|
||||||
|
|
||||||
|
#### Auto folder colour theming
|
||||||
|
|
||||||
|
For automatic Papirus folder icon colour syncing, you must have [`papirus-folders`](https://github.com/PapirusDevelopmentTeam/papirus-folders)
|
||||||
|
installed, and `papirus-folders` must to be able to run with `sudo` without a password prompt.
|
||||||
|
|
||||||
|
You can allow this by creating a sudoers file:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
echo "$USER ALL=(ALL) NOPASSWD: $(which papirus-folders)" | sudo tee /etc/sudoers.d/papirus-folders
|
||||||
|
sudo chmod 440 /etc/sudoers.d/papirus-folders
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Chromium-based browser theming
|
||||||
|
|
||||||
|
For live Chromium-based browser theming, the CLI must be allowed to create certain directories in `/etc`
|
||||||
|
and write to them via `sudo` without a password prompt.
|
||||||
|
|
||||||
|
You can allow this by creating a sudoers file:
|
||||||
|
|
||||||
|
```fish
|
||||||
|
# Fish shell
|
||||||
|
for dir in /etc/chromium/policies/managed /etc/brave/policies/managed /etc/opt/chrome/policies/managed
|
||||||
|
echo "$USER ALL=(ALL) NOPASSWD: $(which mkdir) -p $dir" | sudo tee -a /etc/sudoers.d/caelestia-chromium
|
||||||
|
echo "$USER ALL=(ALL) NOPASSWD: $(which tee) $dir/caelestia.json" | sudo tee -a /etc/sudoers.d/caelestia-chromium
|
||||||
|
end
|
||||||
|
sudo chmod 440 /etc/sudoers.d/caelestia-chromium
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Bash/other shells
|
||||||
|
for dir in /etc/chromium/policies/managed /etc/brave/policies/managed /etc/opt/chrome/policies/managed; do
|
||||||
|
echo "$USER ALL=(ALL) NOPASSWD: $(which mkdir) -p $dir" | sudo tee -a /etc/sudoers.d/caelestia-chromium
|
||||||
|
echo "$USER ALL=(ALL) NOPASSWD: $(which tee) $dir/caelestia.json" | sudo tee -a /etc/sudoers.d/caelestia-chromium
|
||||||
|
done
|
||||||
|
sudo chmod 440 /etc/sudoers.d/caelestia-chromium
|
||||||
|
```
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
All subcommands/options can be explored via the help flag.
|
All subcommands/options can be explored via the help flag.
|
||||||
@@ -122,6 +161,24 @@ subcommands:
|
|||||||
resizer window resizer daemon
|
resizer window resizer daemon
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### User templates
|
||||||
|
|
||||||
|
Custom user templates can be defined in `~/.config/caelestia/templates/`.
|
||||||
|
|
||||||
|
#### Template syntax
|
||||||
|
|
||||||
|
`{{ <color>.<format> }}`
|
||||||
|
|
||||||
|
- `<color>` is a theme color role derived from the Material You color system (e.g. `primary`, `secondary`, `background`)
|
||||||
|
- `<format>` is the output format: `hex` or `rgb`
|
||||||
|
|
||||||
|
#### Examples
|
||||||
|
|
||||||
|
- `{{ primary.hex }}` outputs `3f4ba2`
|
||||||
|
- `{{ primary.rgb }}` outputs `rgb(193, 132, 207)`
|
||||||
|
|
||||||
|
Output files are written to `~/.local/state/caelestia/theme/`. You can symlink them to your desired locations.
|
||||||
|
|
||||||
## Configuring
|
## Configuring
|
||||||
|
|
||||||
All configuration options are in `~/.config/caelestia/cli.json`.
|
All configuration options are in `~/.config/caelestia/cli.json`.
|
||||||
@@ -134,17 +191,28 @@ All configuration options are in `~/.config/caelestia/cli.json`.
|
|||||||
"extraArgs": []
|
"extraArgs": []
|
||||||
},
|
},
|
||||||
"wallpaper": {
|
"wallpaper": {
|
||||||
"postHook": "echo $WALLPAPER_PATH"
|
"postHook": "echo $WALLPAPER_PATH $SCHEME_NAME $SCHEME_FLAVOUR $SCHEME_MODE $SCHEME_VARIANT $SCHEME_COLOURS"
|
||||||
},
|
},
|
||||||
"theme": {
|
"theme": {
|
||||||
"enableTerm": true,
|
"enableTerm": true,
|
||||||
"enableHypr": true,
|
"enableHypr": true,
|
||||||
"enableDiscord": true,
|
"enableDiscord": true,
|
||||||
"enableSpicetify": true,
|
"enableSpicetify": true,
|
||||||
|
"enablePandora": true,
|
||||||
"enableFuzzel": true,
|
"enableFuzzel": true,
|
||||||
"enableBtop": true,
|
"enableBtop": true,
|
||||||
|
"enableNvtop": true,
|
||||||
|
"enableHtop": true,
|
||||||
"enableGtk": true,
|
"enableGtk": true,
|
||||||
"enableQt": true
|
"enableQt": true,
|
||||||
|
"enableWarp": true,
|
||||||
|
"enableChromium": true,
|
||||||
|
"enableZed": true,
|
||||||
|
"enableCava": true,
|
||||||
|
"iconTheme": "Papirus-Dark",
|
||||||
|
"iconThemeLight": "Papirus-Light",
|
||||||
|
"iconThemeDark": "Papirus-Dark",
|
||||||
|
"postHook": "echo $SCHEME_NAME $SCHEME_FLAVOUR $SCHEME_MODE $SCHEME_VARIANT $SCHEME_COLOURS"
|
||||||
},
|
},
|
||||||
"toggles": {
|
"toggles": {
|
||||||
"communication": {
|
"communication": {
|
||||||
|
|||||||
@@ -105,6 +105,7 @@ complete -c caelestia -n "$seen screenshot" -s 'f' -l 'freeze' -d 'Freeze while
|
|||||||
# Record
|
# Record
|
||||||
complete -c caelestia -n "$seen record" -s 'r' -l 'region' -d 'Capture region'
|
complete -c caelestia -n "$seen record" -s 'r' -l 'region' -d 'Capture region'
|
||||||
complete -c caelestia -n "$seen record" -s 's' -l 'sound' -d 'Capture sound'
|
complete -c caelestia -n "$seen record" -s 's' -l 'sound' -d 'Capture sound'
|
||||||
|
complete -c caelestia -n "$seen record" -s 'c' -l 'clipboard' -d 'Copy recording path to clipboard'
|
||||||
|
|
||||||
# Clipboard
|
# Clipboard
|
||||||
complete -c caelestia -n "$seen clipboard" -s 'd' -l 'delete' -d 'Delete from cliboard history'
|
complete -c caelestia -n "$seen clipboard" -s 'd' -l 'delete' -d 'Delete from cliboard history'
|
||||||
|
|||||||
+2
-2
@@ -68,11 +68,11 @@ python3.pkgs.buildPythonApplication {
|
|||||||
# Use config bin instead of discord + fix todoist + fix app2unit
|
# Use config bin instead of discord + fix todoist + fix app2unit
|
||||||
substituteInPlace src/caelestia/subcommands/toggle.py \
|
substituteInPlace src/caelestia/subcommands/toggle.py \
|
||||||
--replace-fail 'discord' ${discordBin} \
|
--replace-fail 'discord' ${discordBin} \
|
||||||
--replace-fail 'todoist' 'todoist.desktop'\
|
--replace-fail '["todoist"]' '["todoist.desktop"]'\
|
||||||
--replace-fail 'app2unit' ${app2unit}/bin/app2unit
|
--replace-fail 'app2unit' ${app2unit}/bin/app2unit
|
||||||
|
|
||||||
# Use config style instead of darkly
|
# Use config style instead of darkly
|
||||||
substituteInPlace src/caelestia/data/templates/qtct.conf \
|
substituteInPlace src/caelestia/data/templates/qtengine.json \
|
||||||
--replace-fail 'Darkly' '${qtctStyle}'
|
--replace-fail 'Darkly' '${qtctStyle}'
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
|||||||
Generated
+10
-10
@@ -9,11 +9,11 @@
|
|||||||
"quickshell": "quickshell"
|
"quickshell": "quickshell"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1763974329,
|
"lastModified": 1780196414,
|
||||||
"narHash": "sha256-8bljTh08KrIzTwzJEM8rGCg56hGtIH6/oT0LctCPTOQ=",
|
"narHash": "sha256-iXmyWULTZuRd68xRL79e9GyYL9FZ6gfh6zl1PPlWX2A=",
|
||||||
"owner": "caelestia-dots",
|
"owner": "caelestia-dots",
|
||||||
"repo": "shell",
|
"repo": "shell",
|
||||||
"rev": "11282f6abe32f9671dc0a7ce49d64bc4f2d79e6b",
|
"rev": "63bb82762bb29ac9b7fcd5b97839abae721ce860",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -24,11 +24,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1763835633,
|
"lastModified": 1780243769,
|
||||||
"narHash": "sha256-HzxeGVID5MChuCPESuC0dlQL1/scDKu+MmzoVBJxulM=",
|
"narHash": "sha256-x5UQuRsH3MqI0U9afaXSNqzTPSeZlRLvFAav2Ux1pNw=",
|
||||||
"owner": "nixos",
|
"owner": "nixos",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "050e09e091117c3d7328c7b2b7b577492c43c134",
|
"rev": "331800de5053fcebacf6813adb5db9c9dca22a0c",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -46,11 +46,11 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1763629934,
|
"lastModified": 1779430452,
|
||||||
"narHash": "sha256-jWz10RbNAyylJbH4cUTLS/CsDjkd8gxfT8OsIgQIgEg=",
|
"narHash": "sha256-zTslhsxLqUlRTML506iougTGzyR38Fzhzn7t4KDEuuE=",
|
||||||
"ref": "refs/heads/master",
|
"ref": "refs/heads/master",
|
||||||
"rev": "ed036d514b0fdbce03158a0b331305be166f4555",
|
"rev": "4b4fca3224ab977dc515ac0bb78d00b3dfa71e00",
|
||||||
"revCount": 708,
|
"revCount": 819,
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
"url": "https://git.outfoxxed.me/outfoxxed/quickshell"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -0,0 +1,120 @@
|
|||||||
|
background 0a0f0f
|
||||||
|
onBackground dce8e6
|
||||||
|
surface 0a0f0f
|
||||||
|
surfaceDim 0a0f0f
|
||||||
|
surfaceBright 242e2d
|
||||||
|
surfaceContainerLowest 000000
|
||||||
|
surfaceContainerLow 0e1514
|
||||||
|
surfaceContainer 131b1a
|
||||||
|
surfaceContainerHigh 192120
|
||||||
|
surfaceContainerHighest 1d2827
|
||||||
|
onSurface dce8e6
|
||||||
|
surfaceVariant 1d2827
|
||||||
|
onSurfaceVariant a2adac
|
||||||
|
outline 6d7876
|
||||||
|
outlineVariant 3f4a49
|
||||||
|
inverseSurface f6faf9
|
||||||
|
inverseOnSurface 515655
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 9bd0cc
|
||||||
|
primary 9bd0cc
|
||||||
|
primaryDim 8ec2bf
|
||||||
|
onPrimary 0d4845
|
||||||
|
primaryContainer 255b58
|
||||||
|
onPrimaryContainer b8ede9
|
||||||
|
inversePrimary 336764
|
||||||
|
primaryFixed b7ede9
|
||||||
|
primaryFixedDim a9deda
|
||||||
|
onPrimaryFixed 0c4744
|
||||||
|
onPrimaryFixedVariant 306461
|
||||||
|
secondary b0ccc9
|
||||||
|
secondaryDim a3bebc
|
||||||
|
onSecondary 2c4543
|
||||||
|
secondaryContainer 27403e
|
||||||
|
onSecondaryContainer a9c5c2
|
||||||
|
secondaryFixed cce8e5
|
||||||
|
secondaryFixedDim bedad7
|
||||||
|
onSecondaryFixed 2b4442
|
||||||
|
onSecondaryFixedVariant 47605e
|
||||||
|
tertiary d5efff
|
||||||
|
tertiaryDim b6e3fe
|
||||||
|
onTertiary 2e5c72
|
||||||
|
tertiaryContainer b6e3fe
|
||||||
|
onTertiaryContainer 255369
|
||||||
|
tertiaryFixed b6e3fe
|
||||||
|
tertiaryFixedDim a8d5ef
|
||||||
|
onTertiaryFixed 0b4156
|
||||||
|
onTertiaryFixedVariant 2f5d73
|
||||||
|
error fa746f
|
||||||
|
errorDim c54d4a
|
||||||
|
onError 490006
|
||||||
|
errorContainer 871f21
|
||||||
|
onErrorContainer ff9993
|
||||||
|
primaryPaletteKeyColor 4c807d
|
||||||
|
secondaryPaletteKeyColor 627c7a
|
||||||
|
tertiaryPaletteKeyColor 517d94
|
||||||
|
neutralPaletteKeyColor 737877
|
||||||
|
neutralVariantPaletteKeyColor 6e7978
|
||||||
|
errorPaletteKeyColor c84f4c
|
||||||
|
primary_paletteKeyColor 4c807d
|
||||||
|
secondary_paletteKeyColor 627c7a
|
||||||
|
tertiary_paletteKeyColor 517d94
|
||||||
|
neutral_paletteKeyColor 737877
|
||||||
|
neutral_variant_paletteKeyColor 6e7978
|
||||||
|
term0 343434
|
||||||
|
term1 769e00
|
||||||
|
term2 56e2c0
|
||||||
|
term3 81fcce
|
||||||
|
term4 76b6b3
|
||||||
|
term5 7aaee9
|
||||||
|
term6 83d8c9
|
||||||
|
term7 cddcd3
|
||||||
|
term8 9aa59e
|
||||||
|
term9 85b900
|
||||||
|
term10 41f7d0
|
||||||
|
term11 cdffe9
|
||||||
|
term12 a3c8c3
|
||||||
|
term13 a2c0f7
|
||||||
|
term14 8bedd9
|
||||||
|
term15 ffffff
|
||||||
|
rosewater f1f3e5
|
||||||
|
flamingo e3e4c5
|
||||||
|
pink bae2ff
|
||||||
|
mauve 60cfe8
|
||||||
|
red 8ab5ff
|
||||||
|
maroon abbef0
|
||||||
|
peach a9daac
|
||||||
|
yellow d3fae8
|
||||||
|
green 8df1df
|
||||||
|
teal 9feee7
|
||||||
|
sky 93eae9
|
||||||
|
sapphire 70d7db
|
||||||
|
blue 57cdda
|
||||||
|
lavender 86d9e7
|
||||||
|
klink 00969e
|
||||||
|
klinkSelection 00969e
|
||||||
|
kvisited 008ca9
|
||||||
|
kvisitedSelection 008ca9
|
||||||
|
knegative 838f00
|
||||||
|
knegativeSelection 838f00
|
||||||
|
kneutral 34c359
|
||||||
|
kneutralSelection 34c359
|
||||||
|
kpositive 00beab
|
||||||
|
kpositiveSelection 00beab
|
||||||
|
text dce8e6
|
||||||
|
subtext1 a2adac
|
||||||
|
subtext0 6d7876
|
||||||
|
overlay2 5f6967
|
||||||
|
overlay1 505958
|
||||||
|
overlay0 434b4a
|
||||||
|
surface2 353d3c
|
||||||
|
surface1 282e2e
|
||||||
|
surface0 191f1e
|
||||||
|
base 0a0f0f
|
||||||
|
mantle 0a0f0f
|
||||||
|
crust 090e0e
|
||||||
|
success B5CCBA
|
||||||
|
onSuccess 213528
|
||||||
|
successContainer 374B3E
|
||||||
|
onSuccessContainer D1E9D6
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
background f6faf9
|
||||||
|
onBackground 2a3433
|
||||||
|
surface f6faf9
|
||||||
|
surfaceDim d1dcdb
|
||||||
|
surfaceBright f6faf9
|
||||||
|
surfaceContainerLowest ffffff
|
||||||
|
surfaceContainerLow eef5f3
|
||||||
|
surfaceContainer e7f0ee
|
||||||
|
surfaceContainerHigh e1eae8
|
||||||
|
surfaceContainerHighest d9e5e3
|
||||||
|
onSurface 2a3433
|
||||||
|
surfaceVariant d9e5e3
|
||||||
|
onSurfaceVariant 566160
|
||||||
|
outline 727d7c
|
||||||
|
outlineVariant a9b4b3
|
||||||
|
inverseSurface 0a0f0f
|
||||||
|
inverseOnSurface 999e9d
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 1c6a66
|
||||||
|
primary 1c6a66
|
||||||
|
primaryDim 045d5a
|
||||||
|
onPrimary e1fffc
|
||||||
|
primaryContainer a8f0eb
|
||||||
|
onPrimaryContainer 015c59
|
||||||
|
inversePrimary b0f8f3
|
||||||
|
primaryFixed a8f0eb
|
||||||
|
primaryFixedDim 9ae1dc
|
||||||
|
onPrimaryFixed 004845
|
||||||
|
onPrimaryFixedVariant 166663
|
||||||
|
secondary 4a6462
|
||||||
|
secondaryDim 3e5856
|
||||||
|
onSecondary e2fffc
|
||||||
|
secondaryContainer cce8e5
|
||||||
|
onSecondaryContainer 3d5654
|
||||||
|
secondaryFixed cce8e5
|
||||||
|
secondaryFixedDim bedad7
|
||||||
|
onSecondaryFixed 2b4442
|
||||||
|
onSecondaryFixedVariant 47605e
|
||||||
|
tertiary 37647b
|
||||||
|
tertiaryDim 2a586e
|
||||||
|
onTertiary f4faff
|
||||||
|
tertiaryContainer b6e3fe
|
||||||
|
onTertiaryContainer 255369
|
||||||
|
tertiaryFixed b6e3fe
|
||||||
|
tertiaryFixedDim a8d5ef
|
||||||
|
onTertiaryFixed 0b4156
|
||||||
|
onTertiaryFixedVariant 2f5d73
|
||||||
|
error a83836
|
||||||
|
errorDim 67040d
|
||||||
|
onError fff7f6
|
||||||
|
errorContainer fa746f
|
||||||
|
onErrorContainer 6e0a12
|
||||||
|
primaryPaletteKeyColor 3a827e
|
||||||
|
secondaryPaletteKeyColor 627c7a
|
||||||
|
tertiaryPaletteKeyColor 517d94
|
||||||
|
neutralPaletteKeyColor 737877
|
||||||
|
neutralVariantPaletteKeyColor 6e7978
|
||||||
|
errorPaletteKeyColor c84f4c
|
||||||
|
primary_paletteKeyColor 3a827e
|
||||||
|
secondary_paletteKeyColor 627c7a
|
||||||
|
tertiary_paletteKeyColor 517d94
|
||||||
|
neutral_paletteKeyColor 737877
|
||||||
|
neutral_variant_paletteKeyColor 6e7978
|
||||||
|
term0 9a9b99
|
||||||
|
term1 005bcc
|
||||||
|
term2 00907c
|
||||||
|
term3 427d3b
|
||||||
|
term4 269a7a
|
||||||
|
term5 0071a3
|
||||||
|
term6 128f8d
|
||||||
|
term7 1f2324
|
||||||
|
term8 0f0f0f
|
||||||
|
term9 0071fa
|
||||||
|
term10 00b49c
|
||||||
|
term11 5d9954
|
||||||
|
term12 52be9c
|
||||||
|
term13 008cca
|
||||||
|
term14 45b0ae
|
||||||
|
term15 25292a
|
||||||
|
rosewater 6b8647
|
||||||
|
flamingo 6f7c1e
|
||||||
|
pink 0085c0
|
||||||
|
mauve 005d6c
|
||||||
|
red 515900
|
||||||
|
maroon 606c00
|
||||||
|
peach 198900
|
||||||
|
yellow 008f67
|
||||||
|
green 007d6d
|
||||||
|
teal 007573
|
||||||
|
sky 00878d
|
||||||
|
sapphire 008080
|
||||||
|
blue 00636d
|
||||||
|
lavender 007e8b
|
||||||
|
klink 00969d
|
||||||
|
klinkSelection 00969e
|
||||||
|
kvisited 008ca9
|
||||||
|
kvisitedSelection 008ca9
|
||||||
|
knegative 838f00
|
||||||
|
knegativeSelection 838f00
|
||||||
|
kneutral 34c359
|
||||||
|
kneutralSelection 34c359
|
||||||
|
kpositive 00beab
|
||||||
|
kpositiveSelection 00beac
|
||||||
|
text 2a3433
|
||||||
|
subtext1 566160
|
||||||
|
subtext0 727d7c
|
||||||
|
overlay2 828c8b
|
||||||
|
overlay1 949d9c
|
||||||
|
overlay0 a5aead
|
||||||
|
surface2 b8bfbe
|
||||||
|
surface1 cbd1d0
|
||||||
|
surface0 e1e6e5
|
||||||
|
base f6faf9
|
||||||
|
mantle eef1f0
|
||||||
|
crust e9eceb
|
||||||
|
success 4F6354
|
||||||
|
onSuccess FFFFFF
|
||||||
|
successContainer D1E8D5
|
||||||
|
onSuccessContainer 0C1F13
|
||||||
@@ -4,7 +4,7 @@ tertiary_paletteKeyColor 376942
|
|||||||
neutral_paletteKeyColor 1E1E26
|
neutral_paletteKeyColor 1E1E26
|
||||||
neutral_variant_paletteKeyColor 23252D
|
neutral_variant_paletteKeyColor 23252D
|
||||||
background 23262D
|
background 23262D
|
||||||
onBackground 02200B
|
onBackground F5F5F6
|
||||||
surface 050505
|
surface 050505
|
||||||
surfaceDim 1E1E24
|
surfaceDim 1E1E24
|
||||||
surfaceBright 1E1E24
|
surfaceBright 1E1E24
|
||||||
@@ -82,6 +82,16 @@ sky cefb97
|
|||||||
sapphire 85ef77
|
sapphire 85ef77
|
||||||
blue 65eea0
|
blue 65eea0
|
||||||
lavender 90f79e
|
lavender 90f79e
|
||||||
|
klink 65eea0
|
||||||
|
klinkSelection 65eea0
|
||||||
|
kvisited 73fa90
|
||||||
|
kvisitedSelection 73fa90
|
||||||
|
knegative 8affab
|
||||||
|
knegativeSelection 8affab
|
||||||
|
kneutral d0f9f4
|
||||||
|
kneutralSelection d0f9f4
|
||||||
|
kpositive 8af797
|
||||||
|
kpositiveSelection 8af797
|
||||||
text e0e3e4
|
text e0e3e4
|
||||||
subtext1 bec8cc
|
subtext1 bec8cc
|
||||||
subtext0 889296
|
subtext0 889296
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ tertiary_paletteKeyColor 376942
|
|||||||
neutral_paletteKeyColor 1E1E26
|
neutral_paletteKeyColor 1E1E26
|
||||||
neutral_variant_paletteKeyColor 23252D
|
neutral_variant_paletteKeyColor 23252D
|
||||||
background 23262D
|
background 23262D
|
||||||
onBackground 02200B
|
onBackground F5F5F6
|
||||||
surface 1E1E24
|
surface 1E1E24
|
||||||
surfaceDim 1E1E24
|
surfaceDim 1E1E24
|
||||||
surfaceBright 1E1E24
|
surfaceBright 1E1E24
|
||||||
@@ -82,6 +82,16 @@ sky cefb97
|
|||||||
sapphire 85ef77
|
sapphire 85ef77
|
||||||
blue 65eea0
|
blue 65eea0
|
||||||
lavender 90f79e
|
lavender 90f79e
|
||||||
|
klink 65eea0
|
||||||
|
klinkSelection 65eea0
|
||||||
|
kvisited 73fa90
|
||||||
|
kvisitedSelection 73fa90
|
||||||
|
knegative 8affab
|
||||||
|
knegativeSelection 8affab
|
||||||
|
kneutral d0f9f4
|
||||||
|
kneutralSelection d0f9f4
|
||||||
|
kpositive 8af797
|
||||||
|
kpositiveSelection 8af797
|
||||||
text e0e3e4
|
text e0e3e4
|
||||||
subtext1 bec8cc
|
subtext1 bec8cc
|
||||||
subtext0 889296
|
subtext0 889296
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor BD93F9
|
||||||
|
secondary_paletteKeyColor 50FA7B
|
||||||
|
tertiary_paletteKeyColor FF79C6
|
||||||
|
neutral_paletteKeyColor 282A36
|
||||||
|
neutral_variant_paletteKeyColor 44475A
|
||||||
|
background 282A36
|
||||||
|
onBackground F8F8F2
|
||||||
|
surface 343746
|
||||||
|
surfaceDim 21222C
|
||||||
|
surfaceBright 4D4F66
|
||||||
|
surfaceContainerLowest 191A21
|
||||||
|
surfaceContainerLow 3C3F4E
|
||||||
|
surfaceContainer 3E4153
|
||||||
|
surfaceContainerHigh 4D4F66
|
||||||
|
surfaceContainerHighest 565970
|
||||||
|
onSurface F8F8F2
|
||||||
|
surfaceVariant 3E4153
|
||||||
|
onSurfaceVariant F8F8F2
|
||||||
|
inverseSurface F8F8F2
|
||||||
|
inverseOnSurface 282A36
|
||||||
|
outline 6272A4
|
||||||
|
outlineVariant 4D4F66
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint BD93F9
|
||||||
|
primary BD93F9
|
||||||
|
onPrimary 282A36
|
||||||
|
primaryContainer 4D4F66
|
||||||
|
onPrimaryContainer BD93F9
|
||||||
|
inversePrimary 9D73D9
|
||||||
|
secondary 50FA7B
|
||||||
|
onSecondary 282A36
|
||||||
|
secondaryContainer 4D4F66
|
||||||
|
onSecondaryContainer 50FA7B
|
||||||
|
tertiary FF79C6
|
||||||
|
onTertiary 282A36
|
||||||
|
tertiaryContainer 4D4F66
|
||||||
|
onTertiaryContainer FF79C6
|
||||||
|
error FF5555
|
||||||
|
onError 282A36
|
||||||
|
errorContainer 4C3743
|
||||||
|
onErrorContainer FF5555
|
||||||
|
primaryFixed BD93F9
|
||||||
|
primaryFixedDim 9D73D9
|
||||||
|
onPrimaryFixed 282A36
|
||||||
|
onPrimaryFixedVariant 3E4153
|
||||||
|
secondaryFixed 50FA7B
|
||||||
|
secondaryFixedDim 30DA5B
|
||||||
|
onSecondaryFixed 282A36
|
||||||
|
onSecondaryFixedVariant 3E4153
|
||||||
|
tertiaryFixed FF79C6
|
||||||
|
tertiaryFixedDim DF59A6
|
||||||
|
onTertiaryFixed 282A36
|
||||||
|
onTertiaryFixedVariant 3E4153
|
||||||
|
term0 282A36
|
||||||
|
term1 FF5555
|
||||||
|
term2 50FA7B
|
||||||
|
term3 F1FA8C
|
||||||
|
term4 BD93F9
|
||||||
|
term5 FF79C6
|
||||||
|
term6 8BE9FD
|
||||||
|
term7 F8F8F2
|
||||||
|
term8 6272A4
|
||||||
|
term9 FF6E6E
|
||||||
|
term10 69FF94
|
||||||
|
term11 FFFFA5
|
||||||
|
term12 D6ACFF
|
||||||
|
term13 FF92DF
|
||||||
|
term14 A4FFFF
|
||||||
|
term15 FFFFFF
|
||||||
|
rosewater F8F8F2
|
||||||
|
flamingo FFB86C
|
||||||
|
pink FF79C6
|
||||||
|
mauve BD93F9
|
||||||
|
red FF5555
|
||||||
|
maroon FF6E6E
|
||||||
|
peach FFB86C
|
||||||
|
yellow F1FA8C
|
||||||
|
green 50FA7B
|
||||||
|
teal 8BE9FD
|
||||||
|
sky 8BE9FD
|
||||||
|
sapphire 8BE9FD
|
||||||
|
blue BD93F9
|
||||||
|
lavender BD93F9
|
||||||
|
klink BD93F9
|
||||||
|
klinkSelection BD93F9
|
||||||
|
kvisited FF79C6
|
||||||
|
kvisitedSelection FF79C6
|
||||||
|
knegative FF5555
|
||||||
|
knegativeSelection FF5555
|
||||||
|
kneutral F1FA8C
|
||||||
|
kneutralSelection F1FA8C
|
||||||
|
kpositive 50FA7B
|
||||||
|
kpositiveSelection 50FA7B
|
||||||
|
text F8F8F2
|
||||||
|
subtext1 F8F8F2
|
||||||
|
subtext0 E6E6E6
|
||||||
|
overlay2 A0A0A0
|
||||||
|
overlay1 8A8A8A
|
||||||
|
overlay0 6272A4
|
||||||
|
surface2 3E4153
|
||||||
|
surface1 343746
|
||||||
|
surface0 282A36
|
||||||
|
base 282A36
|
||||||
|
mantle 21222C
|
||||||
|
crust 191A21
|
||||||
|
success 50FA7B
|
||||||
|
onSuccess 282A36
|
||||||
|
successContainer 4D4F66
|
||||||
|
onSuccessContainer F8F8F2
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor 8CCFB0
|
||||||
|
secondary_paletteKeyColor E5C76B
|
||||||
|
tertiary_paletteKeyColor E5A5C5
|
||||||
|
neutral_paletteKeyColor 2D3139
|
||||||
|
neutral_variant_paletteKeyColor 3A3F4B
|
||||||
|
background 141B1E
|
||||||
|
onBackground E8E8E8
|
||||||
|
surface 232A2D
|
||||||
|
surfaceDim 0F1416
|
||||||
|
surfaceBright 3A4145
|
||||||
|
surfaceContainerLowest 0A0E10
|
||||||
|
surfaceContainerLow 2A3235
|
||||||
|
surfaceContainer 2E3538
|
||||||
|
surfaceContainerHigh 3A4145
|
||||||
|
surfaceContainerHighest 434A4E
|
||||||
|
onSurface E8E8E8
|
||||||
|
surfaceVariant 2E3538
|
||||||
|
onSurfaceVariant B3B9BE
|
||||||
|
inverseSurface E8E8E8
|
||||||
|
inverseOnSurface 141B1E
|
||||||
|
outline 8A8F94
|
||||||
|
outlineVariant 3A4145
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 8CCFB0
|
||||||
|
primary 8CCFB0
|
||||||
|
onPrimary 141B1E
|
||||||
|
primaryContainer 3A4145
|
||||||
|
onPrimaryContainer 8CCFB0
|
||||||
|
inversePrimary 6FA98C
|
||||||
|
secondary E5C76B
|
||||||
|
onSecondary 141B1E
|
||||||
|
secondaryContainer 3A4145
|
||||||
|
onSecondaryContainer E5C76B
|
||||||
|
tertiary E5A5C5
|
||||||
|
onTertiary 141B1E
|
||||||
|
tertiaryContainer 3A4145
|
||||||
|
onTertiaryContainer E5A5C5
|
||||||
|
error E57474
|
||||||
|
onError 141B1E
|
||||||
|
errorContainer 4A2C2C
|
||||||
|
onErrorContainer E57474
|
||||||
|
primaryFixed 8CCFB0
|
||||||
|
primaryFixedDim 6FA98C
|
||||||
|
onPrimaryFixed 141B1E
|
||||||
|
onPrimaryFixedVariant 3A3F4B
|
||||||
|
secondaryFixed E5C76B
|
||||||
|
secondaryFixedDim C4A855
|
||||||
|
onSecondaryFixed 141B1E
|
||||||
|
onSecondaryFixedVariant 3A3F4B
|
||||||
|
tertiaryFixed E5A5C5
|
||||||
|
tertiaryFixedDim C888A4
|
||||||
|
onTertiaryFixed 141B1E
|
||||||
|
onTertiaryFixedVariant 3A3F4B
|
||||||
|
term0 141B1E
|
||||||
|
term1 E57474
|
||||||
|
term2 8CCFB0
|
||||||
|
term3 E5C76B
|
||||||
|
term4 67B0E8
|
||||||
|
term5 C47FD5
|
||||||
|
term6 6CBFBF
|
||||||
|
term7 E8E8E8
|
||||||
|
term8 8A8F94
|
||||||
|
term9 E57474
|
||||||
|
term10 8CCFB0
|
||||||
|
term11 E5C76B
|
||||||
|
term12 67B0E8
|
||||||
|
term13 C47FD5
|
||||||
|
term14 6CBFBF
|
||||||
|
term15 E8E8E8
|
||||||
|
rosewater E8E8E8
|
||||||
|
flamingo E5A5C5
|
||||||
|
pink E5A5C5
|
||||||
|
mauve C47FD5
|
||||||
|
red E57474
|
||||||
|
maroon E57474
|
||||||
|
peach E59A84
|
||||||
|
yellow E5C76B
|
||||||
|
green 8CCFB0
|
||||||
|
teal 6CBFBF
|
||||||
|
sky 67B0E8
|
||||||
|
sapphire 67B0E8
|
||||||
|
blue 67B0E8
|
||||||
|
lavender 67B0E8
|
||||||
|
klink 67B0E8
|
||||||
|
klinkSelection 67B0E8
|
||||||
|
kvisited C47FD5
|
||||||
|
kvisitedSelection C47FD5
|
||||||
|
knegative E57474
|
||||||
|
knegativeSelection E57474
|
||||||
|
kneutral E5C76B
|
||||||
|
kneutralSelection E5C76B
|
||||||
|
kpositive 8CCFB0
|
||||||
|
kpositiveSelection 8CCFB0
|
||||||
|
text E8E8E8
|
||||||
|
subtext1 B3B9BE
|
||||||
|
subtext0 8A8F94
|
||||||
|
overlay2 7A7F84
|
||||||
|
overlay1 6A6F74
|
||||||
|
overlay0 5A5F64
|
||||||
|
surface2 2E3538
|
||||||
|
surface1 232A2D
|
||||||
|
surface0 1A2023
|
||||||
|
base 141B1E
|
||||||
|
mantle 0F1416
|
||||||
|
crust 0A0E10
|
||||||
|
success 8CCFB0
|
||||||
|
onSuccess 141B1E
|
||||||
|
successContainer 3A4145
|
||||||
|
onSuccessContainer E8E8E8
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor 7FBBB3
|
||||||
|
secondary_paletteKeyColor 83C092
|
||||||
|
tertiary_paletteKeyColor A7C080
|
||||||
|
neutral_paletteKeyColor 2E383C
|
||||||
|
neutral_variant_paletteKeyColor 374145
|
||||||
|
background 1E2326
|
||||||
|
onBackground D3C6AA
|
||||||
|
surface 252B2E
|
||||||
|
surfaceDim 15191C
|
||||||
|
surfaceBright 343E43
|
||||||
|
surfaceContainerLowest 11161A
|
||||||
|
surfaceContainerLow 2A3338
|
||||||
|
surfaceContainer 2E383C
|
||||||
|
surfaceContainerHigh 343E43
|
||||||
|
surfaceContainerHighest 3A4448
|
||||||
|
onSurface D3C6AA
|
||||||
|
surfaceVariant 374145
|
||||||
|
onSurfaceVariant 9DA9A0
|
||||||
|
inverseSurface D3C6AA
|
||||||
|
inverseOnSurface 1E2326
|
||||||
|
outline 859289
|
||||||
|
outlineVariant 414B50
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 7FBBB3
|
||||||
|
primary 7FBBB3
|
||||||
|
onPrimary 1E2326
|
||||||
|
primaryContainer 414B50
|
||||||
|
onPrimaryContainer A7C080
|
||||||
|
inversePrimary 5A9A8F
|
||||||
|
secondary 83C092
|
||||||
|
onSecondary 1E2326
|
||||||
|
secondaryContainer 414B50
|
||||||
|
onSecondaryContainer A7C080
|
||||||
|
tertiary A7C080
|
||||||
|
onTertiary 1E2326
|
||||||
|
tertiaryContainer 414B50
|
||||||
|
onTertiaryContainer D3C6AA
|
||||||
|
error E67E80
|
||||||
|
onError 1E2326
|
||||||
|
errorContainer 4C3743
|
||||||
|
onErrorContainer E67E80
|
||||||
|
primaryFixed 7FBBB3
|
||||||
|
primaryFixedDim 5A9A8F
|
||||||
|
onPrimaryFixed 1E2326
|
||||||
|
onPrimaryFixedVariant 374145
|
||||||
|
secondaryFixed 83C092
|
||||||
|
secondaryFixedDim 5F8C6F
|
||||||
|
onSecondaryFixed 1E2326
|
||||||
|
onSecondaryFixedVariant 374145
|
||||||
|
tertiaryFixed A7C080
|
||||||
|
tertiaryFixedDim 7F9D5F
|
||||||
|
onTertiaryFixed 1E2326
|
||||||
|
onTertiaryFixedVariant 374145
|
||||||
|
term0 1E2326
|
||||||
|
term1 E67E80
|
||||||
|
term2 A7C080
|
||||||
|
term3 DBBC7F
|
||||||
|
term4 7FBBB3
|
||||||
|
term5 D699B6
|
||||||
|
term6 83C092
|
||||||
|
term7 D3C6AA
|
||||||
|
term8 859289
|
||||||
|
term9 E67E80
|
||||||
|
term10 A7C080
|
||||||
|
term11 DBBC7F
|
||||||
|
term12 7FBBB3
|
||||||
|
term13 D699B6
|
||||||
|
term14 83C092
|
||||||
|
term15 D3C6AA
|
||||||
|
rosewater D3C6AA
|
||||||
|
flamingo D699B6
|
||||||
|
pink D699B6
|
||||||
|
mauve D699B6
|
||||||
|
red E67E80
|
||||||
|
maroon E67E80
|
||||||
|
peach E69875
|
||||||
|
yellow DBBC7F
|
||||||
|
green A7C080
|
||||||
|
teal 83C092
|
||||||
|
sky 7FBBB3
|
||||||
|
sapphire 7FBBB3
|
||||||
|
blue 7FBBB3
|
||||||
|
lavender 7FBBB3
|
||||||
|
klink 7FBBB3
|
||||||
|
klinkSelection 7FBBB3
|
||||||
|
kvisited 83C092
|
||||||
|
kvisitedSelection 83C092
|
||||||
|
knegative E67E80
|
||||||
|
knegativeSelection E67E80
|
||||||
|
kneutral DBBC7F
|
||||||
|
kneutralSelection DBBC7F
|
||||||
|
kpositive A7C080
|
||||||
|
kpositiveSelection A7C080
|
||||||
|
text D3C6AA
|
||||||
|
subtext1 9DA9A0
|
||||||
|
subtext0 859289
|
||||||
|
overlay2 7A8478
|
||||||
|
overlay1 6F7A6F
|
||||||
|
overlay0 5F6A5F
|
||||||
|
surface2 2E383C
|
||||||
|
surface1 252B2E
|
||||||
|
surface0 1E2326
|
||||||
|
base 1E2326
|
||||||
|
mantle 15191C
|
||||||
|
crust 11161A
|
||||||
|
success A7C080
|
||||||
|
onSuccess 1E2326
|
||||||
|
successContainer 414B50
|
||||||
|
onSuccessContainer D3C6AA
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor 7FBBB3
|
||||||
|
secondary_paletteKeyColor 83C092
|
||||||
|
tertiary_paletteKeyColor A7C080
|
||||||
|
neutral_paletteKeyColor 2E383C
|
||||||
|
neutral_variant_paletteKeyColor 374145
|
||||||
|
background 2D353B
|
||||||
|
onBackground D3C6AA
|
||||||
|
surface 343F44
|
||||||
|
surfaceDim 232A2E
|
||||||
|
surfaceBright 475258
|
||||||
|
surfaceContainerLowest 1E2326
|
||||||
|
surfaceContainerLow 3B474E
|
||||||
|
surfaceContainer 3D484D
|
||||||
|
surfaceContainerHigh 475258
|
||||||
|
surfaceContainerHighest 4C5258
|
||||||
|
onSurface D3C6AA
|
||||||
|
surfaceVariant 3D484D
|
||||||
|
onSurfaceVariant 9DA9A0
|
||||||
|
inverseSurface D3C6AA
|
||||||
|
inverseOnSurface 2D353B
|
||||||
|
outline 859289
|
||||||
|
outlineVariant 475258
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 7FBBB3
|
||||||
|
primary 7FBBB3
|
||||||
|
onPrimary 2D353B
|
||||||
|
primaryContainer 475258
|
||||||
|
onPrimaryContainer A7C080
|
||||||
|
inversePrimary 5A9A8F
|
||||||
|
secondary 83C092
|
||||||
|
onSecondary 2D353B
|
||||||
|
secondaryContainer 475258
|
||||||
|
onSecondaryContainer A7C080
|
||||||
|
tertiary A7C080
|
||||||
|
onTertiary 2D353B
|
||||||
|
tertiaryContainer 475258
|
||||||
|
onTertiaryContainer D3C6AA
|
||||||
|
error E67E80
|
||||||
|
onError 2D353B
|
||||||
|
errorContainer 4C3743
|
||||||
|
onErrorContainer E67E80
|
||||||
|
primaryFixed 7FBBB3
|
||||||
|
primaryFixedDim 5A9A8F
|
||||||
|
onPrimaryFixed 2D353B
|
||||||
|
onPrimaryFixedVariant 374145
|
||||||
|
secondaryFixed 83C092
|
||||||
|
secondaryFixedDim 5F8C6F
|
||||||
|
onSecondaryFixed 2D353B
|
||||||
|
onSecondaryFixedVariant 374145
|
||||||
|
tertiaryFixed A7C080
|
||||||
|
tertiaryFixedDim 7F9D5F
|
||||||
|
onTertiaryFixed 2D353B
|
||||||
|
onTertiaryFixedVariant 374145
|
||||||
|
term0 2D353B
|
||||||
|
term1 E67E80
|
||||||
|
term2 A7C080
|
||||||
|
term3 DBBC7F
|
||||||
|
term4 7FBBB3
|
||||||
|
term5 D699B6
|
||||||
|
term6 83C092
|
||||||
|
term7 D3C6AA
|
||||||
|
term8 859289
|
||||||
|
term9 E67E80
|
||||||
|
term10 A7C080
|
||||||
|
term11 DBBC7F
|
||||||
|
term12 7FBBB3
|
||||||
|
term13 D699B6
|
||||||
|
term14 83C092
|
||||||
|
term15 D3C6AA
|
||||||
|
rosewater D3C6AA
|
||||||
|
flamingo D699B6
|
||||||
|
pink D699B6
|
||||||
|
mauve D699B6
|
||||||
|
red E67E80
|
||||||
|
maroon E67E80
|
||||||
|
peach E69875
|
||||||
|
yellow DBBC7F
|
||||||
|
green A7C080
|
||||||
|
teal 83C092
|
||||||
|
sky 7FBBB3
|
||||||
|
sapphire 7FBBB3
|
||||||
|
blue 7FBBB3
|
||||||
|
lavender 7FBBB3
|
||||||
|
klink 7FBBB3
|
||||||
|
klinkSelection 7FBBB3
|
||||||
|
kvisited 83C092
|
||||||
|
kvisitedSelection 83C092
|
||||||
|
knegative E67E80
|
||||||
|
knegativeSelection E67E80
|
||||||
|
kneutral DBBC7F
|
||||||
|
kneutralSelection DBBC7F
|
||||||
|
kpositive A7C080
|
||||||
|
kpositiveSelection A7C080
|
||||||
|
text D3C6AA
|
||||||
|
subtext1 9DA9A0
|
||||||
|
subtext0 859289
|
||||||
|
overlay2 7A8478
|
||||||
|
overlay1 6F7A6F
|
||||||
|
overlay0 5F6A5F
|
||||||
|
surface2 3D484D
|
||||||
|
surface1 343F44
|
||||||
|
surface0 2D353B
|
||||||
|
base 2D353B
|
||||||
|
mantle 232A2E
|
||||||
|
crust 1E2326
|
||||||
|
success A7C080
|
||||||
|
onSuccess 2D353B
|
||||||
|
successContainer 475258
|
||||||
|
onSuccessContainer D3C6AA
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor 3A94C5
|
||||||
|
secondary_paletteKeyColor 35A77C
|
||||||
|
tertiary_paletteKeyColor 8DA101
|
||||||
|
neutral_paletteKeyColor E6E2CC
|
||||||
|
neutral_variant_paletteKeyColor E0DCC7
|
||||||
|
background FDF6E3
|
||||||
|
onBackground 5C6A72
|
||||||
|
surface F3EAD3
|
||||||
|
surfaceDim FDF6E3
|
||||||
|
surfaceBright FFFBF0
|
||||||
|
surfaceContainerLowest FFFBF0
|
||||||
|
surfaceContainerLow FDF6E3
|
||||||
|
surfaceContainer F3EAD3
|
||||||
|
surfaceContainerHigh EAE4CA
|
||||||
|
surfaceContainerHighest E0DCC7
|
||||||
|
onSurface 5C6A72
|
||||||
|
surfaceVariant EAE4CA
|
||||||
|
onSurfaceVariant 6F7C84
|
||||||
|
inverseSurface 5C6A72
|
||||||
|
inverseOnSurface FDF6E3
|
||||||
|
outline 939F91
|
||||||
|
outlineVariant E0DCC7
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 3A94C5
|
||||||
|
primary 3A94C5
|
||||||
|
onPrimary FFFBF0
|
||||||
|
primaryContainer E0DCC7
|
||||||
|
onPrimaryContainer 8DA101
|
||||||
|
inversePrimary 5FAFD7
|
||||||
|
secondary 35A77C
|
||||||
|
onSecondary FFFBF0
|
||||||
|
secondaryContainer E0DCC7
|
||||||
|
onSecondaryContainer 8DA101
|
||||||
|
tertiary 8DA101
|
||||||
|
onTertiary FFFBF0
|
||||||
|
tertiaryContainer E0DCC7
|
||||||
|
onTertiaryContainer 5C6A72
|
||||||
|
error F85552
|
||||||
|
onError FFFBF0
|
||||||
|
errorContainer E6E2CC
|
||||||
|
onErrorContainer F85552
|
||||||
|
primaryFixed 3A94C5
|
||||||
|
primaryFixedDim 5FAFD7
|
||||||
|
onPrimaryFixed FFFBF0
|
||||||
|
onPrimaryFixedVariant E0DCC7
|
||||||
|
secondaryFixed 35A77C
|
||||||
|
secondaryFixedDim 5FC198
|
||||||
|
onSecondaryFixed FFFBF0
|
||||||
|
onSecondaryFixedVariant E0DCC7
|
||||||
|
tertiaryFixed 8DA101
|
||||||
|
tertiaryFixedDim A7C080
|
||||||
|
onTertiaryFixed FFFBF0
|
||||||
|
onTertiaryFixedVariant E0DCC7
|
||||||
|
term0 5C6A72
|
||||||
|
term1 F85552
|
||||||
|
term2 8DA101
|
||||||
|
term3 DFA000
|
||||||
|
term4 3A94C5
|
||||||
|
term5 DF69BA
|
||||||
|
term6 35A77C
|
||||||
|
term7 5C6A72
|
||||||
|
term8 939F91
|
||||||
|
term9 F85552
|
||||||
|
term10 8DA101
|
||||||
|
term11 DFA000
|
||||||
|
term12 3A94C5
|
||||||
|
term13 DF69BA
|
||||||
|
term14 35A77C
|
||||||
|
term15 5C6A72
|
||||||
|
rosewater 5C6A72
|
||||||
|
flamingo DF69BA
|
||||||
|
pink DF69BA
|
||||||
|
mauve DF69BA
|
||||||
|
red F85552
|
||||||
|
maroon F85552
|
||||||
|
peach E66868
|
||||||
|
yellow DFA000
|
||||||
|
green 8DA101
|
||||||
|
teal 35A77C
|
||||||
|
sky 3A94C5
|
||||||
|
sapphire 3A94C5
|
||||||
|
blue 3A94C5
|
||||||
|
lavender 3A94C5
|
||||||
|
klink 3A94C5
|
||||||
|
klinkSelection 3A94C5
|
||||||
|
kvisited 35A77C
|
||||||
|
kvisitedSelection 35A77C
|
||||||
|
knegative F85552
|
||||||
|
knegativeSelection F85552
|
||||||
|
kneutral DFA000
|
||||||
|
kneutralSelection DFA000
|
||||||
|
kpositive 8DA101
|
||||||
|
kpositiveSelection 8DA101
|
||||||
|
text 5C6A72
|
||||||
|
subtext1 6F7C84
|
||||||
|
subtext0 939F91
|
||||||
|
overlay2 A6B0A0
|
||||||
|
overlay1 B9C0B0
|
||||||
|
overlay0 CCD3C2
|
||||||
|
surface2 EAE4CA
|
||||||
|
surface1 F3EAD3
|
||||||
|
surface0 FDF6E3
|
||||||
|
base FDF6E3
|
||||||
|
mantle FFFBF0
|
||||||
|
crust FFFEF9
|
||||||
|
success 8DA101
|
||||||
|
onSuccess FFFBF0
|
||||||
|
successContainer E0DCC7
|
||||||
|
onSuccessContainer 5C6A72
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor 7FBBB3
|
||||||
|
secondary_paletteKeyColor 83C092
|
||||||
|
tertiary_paletteKeyColor A7C080
|
||||||
|
neutral_paletteKeyColor 2E383C
|
||||||
|
neutral_variant_paletteKeyColor 374145
|
||||||
|
background 323C41
|
||||||
|
onBackground D3C6AA
|
||||||
|
surface 3A454A
|
||||||
|
surfaceDim 282F34
|
||||||
|
surfaceBright 4D585D
|
||||||
|
surfaceContainerLowest 232A2E
|
||||||
|
surfaceContainerLow 414D54
|
||||||
|
surfaceContainer 434E53
|
||||||
|
surfaceContainerHigh 4D585D
|
||||||
|
surfaceContainerHighest 525C61
|
||||||
|
onSurface D3C6AA
|
||||||
|
surfaceVariant 434E53
|
||||||
|
onSurfaceVariant 9DA9A0
|
||||||
|
inverseSurface D3C6AA
|
||||||
|
inverseOnSurface 323C41
|
||||||
|
outline 859289
|
||||||
|
outlineVariant 4D585D
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 7FBBB3
|
||||||
|
primary 7FBBB3
|
||||||
|
onPrimary 323C41
|
||||||
|
primaryContainer 4D585D
|
||||||
|
onPrimaryContainer A7C080
|
||||||
|
inversePrimary 5A9A8F
|
||||||
|
secondary 83C092
|
||||||
|
onSecondary 323C41
|
||||||
|
secondaryContainer 4D585D
|
||||||
|
onSecondaryContainer A7C080
|
||||||
|
tertiary A7C080
|
||||||
|
onTertiary 323C41
|
||||||
|
tertiaryContainer 4D585D
|
||||||
|
onTertiaryContainer D3C6AA
|
||||||
|
error E67E80
|
||||||
|
onError 323C41
|
||||||
|
errorContainer 4C3743
|
||||||
|
onErrorContainer E67E80
|
||||||
|
primaryFixed 7FBBB3
|
||||||
|
primaryFixedDim 5A9A8F
|
||||||
|
onPrimaryFixed 323C41
|
||||||
|
onPrimaryFixedVariant 374145
|
||||||
|
secondaryFixed 83C092
|
||||||
|
secondaryFixedDim 5F8C6F
|
||||||
|
onSecondaryFixed 323C41
|
||||||
|
onSecondaryFixedVariant 374145
|
||||||
|
tertiaryFixed A7C080
|
||||||
|
tertiaryFixedDim 7F9D5F
|
||||||
|
onTertiaryFixed 323C41
|
||||||
|
onTertiaryFixedVariant 374145
|
||||||
|
term0 323C41
|
||||||
|
term1 E67E80
|
||||||
|
term2 A7C080
|
||||||
|
term3 DBBC7F
|
||||||
|
term4 7FBBB3
|
||||||
|
term5 D699B6
|
||||||
|
term6 83C092
|
||||||
|
term7 D3C6AA
|
||||||
|
term8 859289
|
||||||
|
term9 E67E80
|
||||||
|
term10 A7C080
|
||||||
|
term11 DBBC7F
|
||||||
|
term12 7FBBB3
|
||||||
|
term13 D699B6
|
||||||
|
term14 83C092
|
||||||
|
term15 D3C6AA
|
||||||
|
rosewater D3C6AA
|
||||||
|
flamingo D699B6
|
||||||
|
pink D699B6
|
||||||
|
mauve D699B6
|
||||||
|
red E67E80
|
||||||
|
maroon E67E80
|
||||||
|
peach E69875
|
||||||
|
yellow DBBC7F
|
||||||
|
green A7C080
|
||||||
|
teal 83C092
|
||||||
|
sky 7FBBB3
|
||||||
|
sapphire 7FBBB3
|
||||||
|
blue 7FBBB3
|
||||||
|
lavender 7FBBB3
|
||||||
|
klink 7FBBB3
|
||||||
|
klinkSelection 7FBBB3
|
||||||
|
kvisited 83C092
|
||||||
|
kvisitedSelection 83C092
|
||||||
|
knegative E67E80
|
||||||
|
knegativeSelection E67E80
|
||||||
|
kneutral DBBC7F
|
||||||
|
kneutralSelection DBBC7F
|
||||||
|
kpositive A7C080
|
||||||
|
kpositiveSelection A7C080
|
||||||
|
text D3C6AA
|
||||||
|
subtext1 9DA9A0
|
||||||
|
subtext0 859289
|
||||||
|
overlay2 7A8478
|
||||||
|
overlay1 6F7A6F
|
||||||
|
overlay0 5F6A5F
|
||||||
|
surface2 434E53
|
||||||
|
surface1 3A454A
|
||||||
|
surface0 323C41
|
||||||
|
base 323C41
|
||||||
|
mantle 282F34
|
||||||
|
crust 232A2E
|
||||||
|
success A7C080
|
||||||
|
onSuccess 323C41
|
||||||
|
successContainer 4D585D
|
||||||
|
onSuccessContainer D3C6AA
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor 88C0D0
|
||||||
|
secondary_paletteKeyColor 81A1C1
|
||||||
|
tertiary_paletteKeyColor 5E81AC
|
||||||
|
neutral_paletteKeyColor 3B4252
|
||||||
|
neutral_variant_paletteKeyColor 434C5E
|
||||||
|
background 2E3440
|
||||||
|
onBackground ECEFF4
|
||||||
|
surface 3B4252
|
||||||
|
surfaceDim 242933
|
||||||
|
surfaceBright 4C566A
|
||||||
|
surfaceContainerLowest 1F232C
|
||||||
|
surfaceContainerLow 424A5E
|
||||||
|
surfaceContainer 434C5E
|
||||||
|
surfaceContainerHigh 4C566A
|
||||||
|
surfaceContainerHighest 55606E
|
||||||
|
onSurface ECEFF4
|
||||||
|
surfaceVariant 434C5E
|
||||||
|
onSurfaceVariant D8DEE9
|
||||||
|
inverseSurface ECEFF4
|
||||||
|
inverseOnSurface 2E3440
|
||||||
|
outline 616E88
|
||||||
|
outlineVariant 4C566A
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 88C0D0
|
||||||
|
primary 88C0D0
|
||||||
|
onPrimary 2E3440
|
||||||
|
primaryContainer 4C566A
|
||||||
|
onPrimaryContainer 88C0D0
|
||||||
|
inversePrimary 6FA3B3
|
||||||
|
secondary 81A1C1
|
||||||
|
onSecondary 2E3440
|
||||||
|
secondaryContainer 4C566A
|
||||||
|
onSecondaryContainer 81A1C1
|
||||||
|
tertiary 5E81AC
|
||||||
|
onTertiary 2E3440
|
||||||
|
tertiaryContainer 4C566A
|
||||||
|
onTertiaryContainer 5E81AC
|
||||||
|
error BF616A
|
||||||
|
onError 2E3440
|
||||||
|
errorContainer 4C3743
|
||||||
|
onErrorContainer BF616A
|
||||||
|
primaryFixed 88C0D0
|
||||||
|
primaryFixedDim 6FA3B3
|
||||||
|
onPrimaryFixed 2E3440
|
||||||
|
onPrimaryFixedVariant 434C5E
|
||||||
|
secondaryFixed 81A1C1
|
||||||
|
secondaryFixedDim 6A84A4
|
||||||
|
onSecondaryFixed 2E3440
|
||||||
|
onSecondaryFixedVariant 434C5E
|
||||||
|
tertiaryFixed 5E81AC
|
||||||
|
tertiaryFixedDim 4A6A8F
|
||||||
|
onTertiaryFixed 2E3440
|
||||||
|
onTertiaryFixedVariant 434C5E
|
||||||
|
term0 3B4252
|
||||||
|
term1 BF616A
|
||||||
|
term2 A3BE8C
|
||||||
|
term3 EBCB8B
|
||||||
|
term4 81A1C1
|
||||||
|
term5 B48EAD
|
||||||
|
term6 88C0D0
|
||||||
|
term7 E5E9F0
|
||||||
|
term8 4C566A
|
||||||
|
term9 BF616A
|
||||||
|
term10 A3BE8C
|
||||||
|
term11 EBCB8B
|
||||||
|
term12 81A1C1
|
||||||
|
term13 B48EAD
|
||||||
|
term14 8FBCBB
|
||||||
|
term15 ECEFF4
|
||||||
|
rosewater ECEFF4
|
||||||
|
flamingo B48EAD
|
||||||
|
pink B48EAD
|
||||||
|
mauve B48EAD
|
||||||
|
red BF616A
|
||||||
|
maroon BF616A
|
||||||
|
peach D08770
|
||||||
|
yellow EBCB8B
|
||||||
|
green A3BE8C
|
||||||
|
teal 8FBCBB
|
||||||
|
sky 88C0D0
|
||||||
|
sapphire 81A1C1
|
||||||
|
blue 5E81AC
|
||||||
|
lavender 5E81AC
|
||||||
|
klink 88C0D0
|
||||||
|
klinkSelection 88C0D0
|
||||||
|
kvisited 81A1C1
|
||||||
|
kvisitedSelection 81A1C1
|
||||||
|
knegative BF616A
|
||||||
|
knegativeSelection BF616A
|
||||||
|
kneutral EBCB8B
|
||||||
|
kneutralSelection EBCB8B
|
||||||
|
kpositive A3BE8C
|
||||||
|
kpositiveSelection A3BE8C
|
||||||
|
text ECEFF4
|
||||||
|
subtext1 D8DEE9
|
||||||
|
subtext0 616E88
|
||||||
|
overlay2 5A677E
|
||||||
|
overlay1 4F5B73
|
||||||
|
overlay0 434C5E
|
||||||
|
surface2 434C5E
|
||||||
|
surface1 3B4252
|
||||||
|
surface0 2E3440
|
||||||
|
base 2E3440
|
||||||
|
mantle 242933
|
||||||
|
crust 1F232C
|
||||||
|
success A3BE8C
|
||||||
|
onSuccess 2E3440
|
||||||
|
successContainer 4C566A
|
||||||
|
onSuccessContainer ECEFF4
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor 268BD2
|
||||||
|
secondary_paletteKeyColor 2AA198
|
||||||
|
tertiary_paletteKeyColor 6C71C4
|
||||||
|
neutral_paletteKeyColor 002B36
|
||||||
|
neutral_variant_paletteKeyColor 073642
|
||||||
|
background 002B36
|
||||||
|
onBackground FDF6E3
|
||||||
|
surface 073642
|
||||||
|
surfaceDim 001F29
|
||||||
|
surfaceBright 0D4250
|
||||||
|
surfaceContainerLowest 00151D
|
||||||
|
surfaceContainerLow 0A404E
|
||||||
|
surfaceContainer 094B59
|
||||||
|
surfaceContainerHigh 0D4250
|
||||||
|
surfaceContainerHighest 11505E
|
||||||
|
onSurface FDF6E3
|
||||||
|
surfaceVariant 094B59
|
||||||
|
onSurfaceVariant 93A1A1
|
||||||
|
inverseSurface FDF6E3
|
||||||
|
inverseOnSurface 002B36
|
||||||
|
outline 586E75
|
||||||
|
outlineVariant 0D4250
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 268BD2
|
||||||
|
primary 268BD2
|
||||||
|
onPrimary 002B36
|
||||||
|
primaryContainer 0D4250
|
||||||
|
onPrimaryContainer 268BD2
|
||||||
|
inversePrimary 2075B2
|
||||||
|
secondary 2AA198
|
||||||
|
onSecondary 002B36
|
||||||
|
secondaryContainer 0D4250
|
||||||
|
onSecondaryContainer 2AA198
|
||||||
|
tertiary 6C71C4
|
||||||
|
onTertiary 002B36
|
||||||
|
tertiaryContainer 0D4250
|
||||||
|
onTertiaryContainer 6C71C4
|
||||||
|
error DC322F
|
||||||
|
onError 002B36
|
||||||
|
errorContainer 4C3743
|
||||||
|
onErrorContainer DC322F
|
||||||
|
primaryFixed 268BD2
|
||||||
|
primaryFixedDim 2075B2
|
||||||
|
onPrimaryFixed 002B36
|
||||||
|
onPrimaryFixedVariant 094B59
|
||||||
|
secondaryFixed 2AA198
|
||||||
|
secondaryFixedDim 228178
|
||||||
|
onSecondaryFixed 002B36
|
||||||
|
onSecondaryFixedVariant 094B59
|
||||||
|
tertiaryFixed 6C71C4
|
||||||
|
tertiaryFixedDim 5C61A4
|
||||||
|
onTertiaryFixed 002B36
|
||||||
|
onTertiaryFixedVariant 094B59
|
||||||
|
term0 002B36
|
||||||
|
term1 DC322F
|
||||||
|
term2 859900
|
||||||
|
term3 B58900
|
||||||
|
term4 268BD2
|
||||||
|
term5 D33682
|
||||||
|
term6 2AA198
|
||||||
|
term7 EEE8D5
|
||||||
|
term8 586E75
|
||||||
|
term9 CB4B16
|
||||||
|
term10 859900
|
||||||
|
term11 B58900
|
||||||
|
term12 268BD2
|
||||||
|
term13 6C71C4
|
||||||
|
term14 2AA198
|
||||||
|
term15 FDF6E3
|
||||||
|
rosewater FDF6E3
|
||||||
|
flamingo EEE8D5
|
||||||
|
pink D33682
|
||||||
|
mauve 6C71C4
|
||||||
|
red DC322F
|
||||||
|
maroon CB4B16
|
||||||
|
peach CB4B16
|
||||||
|
yellow B58900
|
||||||
|
green 859900
|
||||||
|
teal 2AA198
|
||||||
|
sky 2AA198
|
||||||
|
sapphire 268BD2
|
||||||
|
blue 268BD2
|
||||||
|
lavender 6C71C4
|
||||||
|
klink 268BD2
|
||||||
|
klinkSelection 268BD2
|
||||||
|
kvisited 6C71C4
|
||||||
|
kvisitedSelection 6C71C4
|
||||||
|
knegative DC322F
|
||||||
|
knegativeSelection DC322F
|
||||||
|
kneutral B58900
|
||||||
|
kneutralSelection B58900
|
||||||
|
kpositive 859900
|
||||||
|
kpositiveSelection 859900
|
||||||
|
text FDF6E3
|
||||||
|
subtext1 93A1A1
|
||||||
|
subtext0 839496
|
||||||
|
overlay2 657B83
|
||||||
|
overlay1 586E75
|
||||||
|
overlay0 073642
|
||||||
|
surface2 094B59
|
||||||
|
surface1 073642
|
||||||
|
surface0 002B36
|
||||||
|
base 002B36
|
||||||
|
mantle 001F29
|
||||||
|
crust 00151D
|
||||||
|
success 859900
|
||||||
|
onSuccess 002B36
|
||||||
|
successContainer 0D4250
|
||||||
|
onSuccessContainer FDF6E3
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
primary_paletteKeyColor 7AA2F7
|
||||||
|
secondary_paletteKeyColor 9ECE6A
|
||||||
|
tertiary_paletteKeyColor BB9AF7
|
||||||
|
neutral_paletteKeyColor 1A1B26
|
||||||
|
neutral_variant_paletteKeyColor 292E42
|
||||||
|
background 1A1B26
|
||||||
|
onBackground C0CAF5
|
||||||
|
surface 24283B
|
||||||
|
surfaceDim 16161E
|
||||||
|
surfaceBright 3B4261
|
||||||
|
surfaceContainerLowest 0F0F14
|
||||||
|
surfaceContainerLow 2B3048
|
||||||
|
surfaceContainer 2A2F41
|
||||||
|
surfaceContainerHigh 3B4261
|
||||||
|
surfaceContainerHighest 414868
|
||||||
|
onSurface C0CAF5
|
||||||
|
surfaceVariant 2A2F41
|
||||||
|
onSurfaceVariant A9B1D6
|
||||||
|
inverseSurface C0CAF5
|
||||||
|
inverseOnSurface 1A1B26
|
||||||
|
outline 565F89
|
||||||
|
outlineVariant 3B4261
|
||||||
|
shadow 000000
|
||||||
|
scrim 000000
|
||||||
|
surfaceTint 7AA2F7
|
||||||
|
primary 7AA2F7
|
||||||
|
onPrimary 1A1B26
|
||||||
|
primaryContainer 3B4261
|
||||||
|
onPrimaryContainer 7AA2F7
|
||||||
|
inversePrimary 5A7FD7
|
||||||
|
secondary 9ECE6A
|
||||||
|
onSecondary 1A1B26
|
||||||
|
secondaryContainer 3B4261
|
||||||
|
onSecondaryContainer 9ECE6A
|
||||||
|
tertiary BB9AF7
|
||||||
|
onTertiary 1A1B26
|
||||||
|
tertiaryContainer 3B4261
|
||||||
|
onTertiaryContainer BB9AF7
|
||||||
|
error F7768E
|
||||||
|
onError 1A1B26
|
||||||
|
errorContainer 4C3743
|
||||||
|
onErrorContainer F7768E
|
||||||
|
primaryFixed 7AA2F7
|
||||||
|
primaryFixedDim 5A7FD7
|
||||||
|
onPrimaryFixed 1A1B26
|
||||||
|
onPrimaryFixedVariant 2A2F41
|
||||||
|
secondaryFixed 9ECE6A
|
||||||
|
secondaryFixedDim 7EAE4A
|
||||||
|
onSecondaryFixed 1A1B26
|
||||||
|
onSecondaryFixedVariant 2A2F41
|
||||||
|
tertiaryFixed BB9AF7
|
||||||
|
tertiaryFixedDim 9B7AD7
|
||||||
|
onTertiaryFixed 1A1B26
|
||||||
|
onTertiaryFixedVariant 2A2F41
|
||||||
|
term0 1A1B26
|
||||||
|
term1 F7768E
|
||||||
|
term2 9ECE6A
|
||||||
|
term3 E0AF68
|
||||||
|
term4 7AA2F7
|
||||||
|
term5 BB9AF7
|
||||||
|
term6 7DCFFF
|
||||||
|
term7 C0CAF5
|
||||||
|
term8 565F89
|
||||||
|
term9 F7768E
|
||||||
|
term10 9ECE6A
|
||||||
|
term11 E0AF68
|
||||||
|
term12 7AA2F7
|
||||||
|
term13 BB9AF7
|
||||||
|
term14 7DCFFF
|
||||||
|
term15 C0CAF5
|
||||||
|
rosewater C0CAF5
|
||||||
|
flamingo BB9AF7
|
||||||
|
pink F7768E
|
||||||
|
mauve BB9AF7
|
||||||
|
red F7768E
|
||||||
|
maroon E0AF68
|
||||||
|
peach FF9E64
|
||||||
|
yellow E0AF68
|
||||||
|
green 9ECE6A
|
||||||
|
teal 1ABC9C
|
||||||
|
sky 7DCFFF
|
||||||
|
sapphire 2AC3DE
|
||||||
|
blue 7AA2F7
|
||||||
|
lavender 7DCFFF
|
||||||
|
klink 7AA2F7
|
||||||
|
klinkSelection 7AA2F7
|
||||||
|
kvisited BB9AF7
|
||||||
|
kvisitedSelection BB9AF7
|
||||||
|
knegative F7768E
|
||||||
|
knegativeSelection F7768E
|
||||||
|
kneutral E0AF68
|
||||||
|
kneutralSelection E0AF68
|
||||||
|
kpositive 9ECE6A
|
||||||
|
kpositiveSelection 9ECE6A
|
||||||
|
text C0CAF5
|
||||||
|
subtext1 A9B1D6
|
||||||
|
subtext0 9AA5CE
|
||||||
|
overlay2 787C99
|
||||||
|
overlay1 696D85
|
||||||
|
overlay0 565F89
|
||||||
|
surface2 2A2F41
|
||||||
|
surface1 24283B
|
||||||
|
surface0 1A1B26
|
||||||
|
base 1A1B26
|
||||||
|
mantle 16161E
|
||||||
|
crust 0F0F14
|
||||||
|
success 9ECE6A
|
||||||
|
onSuccess 1A1B26
|
||||||
|
successContainer 3B4261
|
||||||
|
onSuccessContainer C0CAF5
|
||||||
@@ -2,8 +2,6 @@
|
|||||||
# Optimized for smooth and responsive visualization
|
# Optimized for smooth and responsive visualization
|
||||||
|
|
||||||
[general]
|
[general]
|
||||||
# Number of bars (20-200) - fewer bars = better performance
|
|
||||||
bars = 64
|
|
||||||
# Framerate (1-144) - higher = smoother but more CPU intensive
|
# Framerate (1-144) - higher = smoother but more CPU intensive
|
||||||
framerate = 60
|
framerate = 60
|
||||||
|
|
||||||
|
|||||||
@@ -15,8 +15,10 @@
|
|||||||
@import url("https://refact0r.github.io/midnight-discord/build/midnight.css");
|
@import url("https://refact0r.github.io/midnight-discord/build/midnight.css");
|
||||||
|
|
||||||
body {
|
body {
|
||||||
/* font, change to '' for default discord font */
|
/* font options */
|
||||||
--font: "figtree";
|
--font: "figtree"; /* change to '' for default discord font */
|
||||||
|
--code-font: "JetBrainsMono NF"; /* change to '' for default discord font */
|
||||||
|
font-weight: 400; /* normal text font weight. DOES NOT AFFECT BOLD TEXT */
|
||||||
|
|
||||||
/* sizes */
|
/* sizes */
|
||||||
--gap: 12px; /* spacing between panels */
|
--gap: 12px; /* spacing between panels */
|
||||||
@@ -27,13 +29,14 @@ body {
|
|||||||
--animations: on; /* turn off to disable all midnight animations/transitions */
|
--animations: on; /* turn off to disable all midnight animations/transitions */
|
||||||
--list-item-transition: 0.2s ease; /* transition for list items */
|
--list-item-transition: 0.2s ease; /* transition for list items */
|
||||||
--dms-icon-svg-transition: 0.4s ease; /* transition for the dms icon */
|
--dms-icon-svg-transition: 0.4s ease; /* transition for the dms icon */
|
||||||
|
--border-hover-transition: 0.2s ease; /* transition for borders when hovered */
|
||||||
|
|
||||||
/* top bar options */
|
/* top bar options */
|
||||||
--top-bar-height: var(
|
--top-bar-height: var(
|
||||||
--gap
|
--gap
|
||||||
); /* height of the titlebar/top bar (discord default is 36px, 24px recommended if moving/hiding top bar buttons) */
|
); /* height of the titlebar/top bar (discord default is 36px, 24px recommended if moving/hiding top bar buttons) */
|
||||||
--top-bar-button-position: hide; /* off: default position, hide: hide inbox/support buttons completely, serverlist: move inbox button to server list, titlebar: move inbox button to titlebar (will hide title) */
|
--top-bar-button-position: titlebar; /* off: default position, hide: hide inbox/support buttons completely, serverlist: move inbox button to server list, titlebar: move inbox button to titlebar (will hide title) */
|
||||||
--top-bar-title-position: hide; /* off: default centered position, hide: hide title completely, left: left align title (like old discord) */
|
--top-bar-title-position: off; /* off: default centered position, hide: hide title completely, left: left align title (like old discord) */
|
||||||
--subtle-top-bar-title: off; /* off: default, on: hide the icon and use subtle text color (like old discord) */
|
--subtle-top-bar-title: off; /* off: default, on: hide the icon and use subtle text color (like old discord) */
|
||||||
|
|
||||||
/* window controls */
|
/* window controls */
|
||||||
@@ -42,9 +45,9 @@ body {
|
|||||||
|
|
||||||
/* dms button icon options */
|
/* dms button icon options */
|
||||||
--custom-dms-icon: custom; /* off: use default discord icon, hide: remove icon entirely, custom: use custom icon */
|
--custom-dms-icon: custom; /* off: use default discord icon, hide: remove icon entirely, custom: use custom icon */
|
||||||
--dms-icon-svg-url: url("https://upload.wikimedia.org/wikipedia/commons/c/c4/Font_Awesome_5_solid_moon.svg"); /* icon svg url. MUST BE A SVG. */
|
--dms-icon-svg-url: url("https://refact0r.github.io/midnight-discord/assets/Font_Awesome_5_solid_moon.svg"); /* icon svg url. MUST BE A SVG. */
|
||||||
--dms-icon-svg-size: 90%; /* size of the svg (css mask-size) */
|
--dms-icon-svg-size: 90%; /* size of the svg (css mask-size) */
|
||||||
--dms-icon-color-before: var(--icon-secondary); /* normal icon color */
|
--dms-icon-color-before: var(--icon-subtle); /* normal icon color */
|
||||||
--dms-icon-color-after: var(--white); /* icon color when button is hovered/selected */
|
--dms-icon-color-after: var(--white); /* icon color when button is hovered/selected */
|
||||||
|
|
||||||
/* dms button background options */
|
/* dms button background options */
|
||||||
@@ -71,12 +74,11 @@ body {
|
|||||||
--bg-floating: #{c.$surface}; /* you can set this to a more opaque color if floating panels look too transparent */
|
--bg-floating: #{c.$surface}; /* you can set this to a more opaque color if floating panels look too transparent */
|
||||||
|
|
||||||
/* chatbar options */
|
/* chatbar options */
|
||||||
--custom-chatbar: aligned; /* off: default chatbar, aligned: chatbar aligned with the user panel, separated: chatbar separated from chat */
|
--custom-chatbar: off; /* off: default chatbar, separated: chatbar separated from chat */
|
||||||
--chatbar-height: 47px; /* height of the chatbar (52px by default, 47px recommended for aligned, 56px recommended for separated) */
|
--chatbar-height: 47px; /* height of the chatbar (56px by default, 47px to align with user panel, 56px recommended for separated) */
|
||||||
--chatbar-padding: 8px; /* padding of the chatbar. only applies in aligned mode. */
|
|
||||||
|
|
||||||
/* other options */
|
/* other options */
|
||||||
--small-user-panel: off; /* turn on to make the user panel smaller like in old discord */
|
--small-user-panel: off; /* off: default user panel, on: smaller user panel like in old discord */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* color options */
|
/* color options */
|
||||||
|
|||||||
@@ -15,3 +15,7 @@
|
|||||||
@define-color sidebar_fg_color @window_fg_color;
|
@define-color sidebar_fg_color @window_fg_color;
|
||||||
@define-color sidebar_border_color @window_bg_color;
|
@define-color sidebar_border_color @window_bg_color;
|
||||||
@define-color sidebar_backdrop_color @window_bg_color;
|
@define-color sidebar_backdrop_color @window_bg_color;
|
||||||
|
@define-color theme_selected_bg_color alpha(@accent_color, 0.15);
|
||||||
|
@define-color theme_selected_fg_color @primary;
|
||||||
|
|
||||||
|
@import "thunar.css";
|
||||||
|
|||||||
@@ -0,0 +1,162 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://github.com/longbridge/gpui-component/raw/refs/heads/main/.theme-schema.json",
|
||||||
|
"name": "Caelestia",
|
||||||
|
"author": "Unrectified",
|
||||||
|
"url": "https://github.com/caelestia-dots/cli",
|
||||||
|
"themes": [
|
||||||
|
{
|
||||||
|
"name": "Caelestia",
|
||||||
|
"mode": "{{ $mode }}",
|
||||||
|
"colors": {
|
||||||
|
"accent.background": "{{ $surfaceContainerHigh }}",
|
||||||
|
"accent.foreground": "{{ $onSurface }}",
|
||||||
|
"background": "{{ $background }}",
|
||||||
|
"border": "{{ $outlineVariant }}",
|
||||||
|
"danger.background": "{{ $error }}",
|
||||||
|
"foreground": "{{ $onBackground }}",
|
||||||
|
"input.border": "{{ $outline }}",
|
||||||
|
"link.active.foreground": "{{ $primary }}",
|
||||||
|
"link.foreground": "{{ $primary }}",
|
||||||
|
"link.hover.foreground": "{{ $primaryFixed }}",
|
||||||
|
"list.active.background": "{{ $secondaryContainer }}",
|
||||||
|
"list.active.border": "{{ $secondary }}",
|
||||||
|
"list.even.background": "{{ $surfaceContainerLowest }}",
|
||||||
|
"muted.background": "{{ $surfaceVariant }}",
|
||||||
|
"muted.foreground": "{{ $onSurfaceVariant }}",
|
||||||
|
"panel.background": "{{ $surfaceContainer }}",
|
||||||
|
"popover.background": "{{ $surfaceContainerHigh }}",
|
||||||
|
"popover.foreground": "{{ $onSurface }}",
|
||||||
|
"primary.active.background": "{{ $primaryFixedDim }}",
|
||||||
|
"primary.background": "{{ $primary }}",
|
||||||
|
"primary.foreground": "{{ $onPrimary }}",
|
||||||
|
"primary.hover.background": "{{ $primaryFixed }}",
|
||||||
|
"scrollbar.background": "{{ $surface }}",
|
||||||
|
"scrollbar.thumb.background": "{{ $outline }}",
|
||||||
|
"secondary.background": "{{ $secondaryContainer }}",
|
||||||
|
"secondary.active.background": "{{ $secondaryFixedDim }}",
|
||||||
|
"secondary.foreground": "{{ $onSecondary }}",
|
||||||
|
"secondary.hover.background": "{{ $secondaryFixed }}",
|
||||||
|
"tab.active.background": "{{ $surface }}",
|
||||||
|
"tab.active.foreground": "{{ $onSurface }}",
|
||||||
|
"tab.background": "{{ $surfaceContainerLowest }}",
|
||||||
|
"tab.foreground": "{{ $onSurfaceVariant }}",
|
||||||
|
"tab_bar.background": "{{ $surface }}",
|
||||||
|
"table.background": "{{ $surfaceContainer }}",
|
||||||
|
"table.head.foreground": "{{ $onSurfaceVariant }}",
|
||||||
|
"table.row.border": "{{ $outlineVariant }}",
|
||||||
|
"title_bar.background": "{{ $surfaceDim }}",
|
||||||
|
"ring": "{{ $primary }}",
|
||||||
|
"base.red": "{{ $red }}",
|
||||||
|
"base.red.light": "{{ $peach }}",
|
||||||
|
"base.green": "{{ $green }}",
|
||||||
|
"base.green.light": "{{ $teal }}",
|
||||||
|
"base.blue": "{{ $blue }}",
|
||||||
|
"base.blue.light": "{{ $sky }}",
|
||||||
|
"base.cyan": "{{ $teal }}",
|
||||||
|
"base.cyan.light": "{{ $sky }}",
|
||||||
|
"base.magenta": "{{ $mauve }}",
|
||||||
|
"base.magenta.light": "{{ $pink }}",
|
||||||
|
"base.yellow": "{{ $yellow }}",
|
||||||
|
"base.yellow.light": "{{ $peach }}"
|
||||||
|
},
|
||||||
|
"highlight": {
|
||||||
|
"editor.foreground": "{{ $onSurface }}",
|
||||||
|
"editor.background": "{{ $surface }}",
|
||||||
|
"editor.active_line.background": "{{ $surfaceContainerLow }}",
|
||||||
|
"editor.line_number": "{{ $onSurfaceVariant }}",
|
||||||
|
"editor.active_line_number": "{{ $onSurface }}",
|
||||||
|
"editor.invisible": "{{ $outlineVariant }}",
|
||||||
|
"conflict": "{{ $red }}",
|
||||||
|
"created": "{{ $green }}",
|
||||||
|
"deleted": "{{ $red }}",
|
||||||
|
"error": "{{ $error }}",
|
||||||
|
"hidden": "{{ $outline }}",
|
||||||
|
"hint": "{{ $success }}",
|
||||||
|
"ignored": "{{ $outline }}",
|
||||||
|
"info": "{{ $blue }}",
|
||||||
|
"modified": "{{ $yellow }}",
|
||||||
|
"predictive": "{{ $overlay1 }}",
|
||||||
|
"renamed": "{{ $green }}",
|
||||||
|
"success": "{{ $success }}",
|
||||||
|
"unreachable": "{{ $outlineVariant }}",
|
||||||
|
"warning": "{{ $yellow }}",
|
||||||
|
"syntax": {
|
||||||
|
"attribute": {
|
||||||
|
"color": "{{ $yellow }}"
|
||||||
|
},
|
||||||
|
"boolean": {
|
||||||
|
"color": "{{ $green }}"
|
||||||
|
},
|
||||||
|
"comment": {
|
||||||
|
"color": "{{ $subtext0 }}",
|
||||||
|
"font_style": "italic"
|
||||||
|
},
|
||||||
|
"comment.doc": {
|
||||||
|
"color": "{{ $subtext0 }}",
|
||||||
|
"font_style": "italic"
|
||||||
|
},
|
||||||
|
"constant": {
|
||||||
|
"color": "{{ $red }}"
|
||||||
|
},
|
||||||
|
"constructor": {
|
||||||
|
"color": "{{ $yellow }}"
|
||||||
|
},
|
||||||
|
"embedded": {
|
||||||
|
"color": "{{ $onSurface }}"
|
||||||
|
},
|
||||||
|
"function": {
|
||||||
|
"color": "{{ $green }}"
|
||||||
|
},
|
||||||
|
"keyword": {
|
||||||
|
"color": "{{ $mauve }}"
|
||||||
|
},
|
||||||
|
"link_text": {
|
||||||
|
"color": "{{ $sky }}",
|
||||||
|
"font_style": "normal"
|
||||||
|
},
|
||||||
|
"link_uri": {
|
||||||
|
"color": "{{ $klink }}",
|
||||||
|
"font_style": "italic"
|
||||||
|
},
|
||||||
|
"number": {
|
||||||
|
"color": "{{ $red }}"
|
||||||
|
},
|
||||||
|
"string": {
|
||||||
|
"color": "{{ $green }}"
|
||||||
|
},
|
||||||
|
"string.escape": {
|
||||||
|
"color": "{{ $green }}"
|
||||||
|
},
|
||||||
|
"string.regex": {
|
||||||
|
"color": "{{ $green }}"
|
||||||
|
},
|
||||||
|
"string.special": {
|
||||||
|
"color": "{{ $yellow }}"
|
||||||
|
},
|
||||||
|
"string.special.symbol": {
|
||||||
|
"color": "{{ $yellow }}"
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"color": "{{ $yellow }}"
|
||||||
|
},
|
||||||
|
"text.literal": {
|
||||||
|
"color": "{{ $red }}"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"color": "{{ $sky }}",
|
||||||
|
"font_weight": 600
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"color": "{{ $yellow }}"
|
||||||
|
},
|
||||||
|
"property": {
|
||||||
|
"color": "{{ $onSurface }}"
|
||||||
|
},
|
||||||
|
"variable.special": {
|
||||||
|
"color": "{{ $red }}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
[Appearance]
|
|
||||||
color_scheme_path={{ $config }}/colors/caelestia.colors
|
|
||||||
custom_palette=true
|
|
||||||
icon_theme=Papirus-{{ $mode }}
|
|
||||||
standard_dialogs=default
|
|
||||||
style=Darkly
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"theme": {
|
||||||
|
"colorScheme": "~/.config/qtengine/caelestia.colors",
|
||||||
|
"iconTheme": "Papirus-{{ $mode }}",
|
||||||
|
"style": "Darkly",
|
||||||
|
"font": {
|
||||||
|
"family": "Sans Serif",
|
||||||
|
"size": 12,
|
||||||
|
"weight": -1
|
||||||
|
},
|
||||||
|
"fontFixed": {
|
||||||
|
"family": "Monospace",
|
||||||
|
"size": 12,
|
||||||
|
"weight": -1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"misc": {
|
||||||
|
"menusHaveIcons": true,
|
||||||
|
"singleClickActivate": false,
|
||||||
|
"shortcutsForContextMenus": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,202 @@
|
|||||||
|
/* Thunar theme */
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Global Resets
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
.thunar * {
|
||||||
|
outline: none;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Window & Background
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
.thunar.background {
|
||||||
|
background: {{ $surface }};
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .titlebar {
|
||||||
|
background: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .titlebutton.close {
|
||||||
|
margin: 0 15px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Layout Containers
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
/* Paned separator between sidebar and main view */
|
||||||
|
.thunar paned > separator {
|
||||||
|
min-width: 4px;
|
||||||
|
margin-right: -7px;
|
||||||
|
margin-left: -7px;
|
||||||
|
background: none;
|
||||||
|
background-image: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Main file view frame */
|
||||||
|
.thunar .frame.standard-view {
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 15px 0 0;
|
||||||
|
border-radius: 15px;
|
||||||
|
background-color: {{ $surfaceContainerLow }};
|
||||||
|
animation: fading 400ms ease forwards;
|
||||||
|
opacity: 0;
|
||||||
|
animation-delay: 250ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .frame.standard-view .view:not(.rubberband),
|
||||||
|
.thunar .frame.standard-view .view *:not(.rubberband) {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .frame.standard-view .view *:selected {
|
||||||
|
color: {{ $primary }};
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .rubberband {
|
||||||
|
background-color: alpha({{ $primary }}, 0.15);
|
||||||
|
border: 1px solid alpha({{ $primary }}, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Tabs */
|
||||||
|
.thunar header.top {
|
||||||
|
background: none;
|
||||||
|
padding: 0 10px 0 0;
|
||||||
|
margin: 3px 0 -3px -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar header.top tabs .reorderable-page {
|
||||||
|
margin: 0;
|
||||||
|
transition: all ease 300ms;
|
||||||
|
}
|
||||||
|
.thunar header.top tabs .reorderable-page + .reorderable-page {
|
||||||
|
margin: 0 0 0 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar header.top tabs .reorderable-page:hover {
|
||||||
|
background-color: alpha({{ $primary }}, 0.08);
|
||||||
|
|
||||||
|
}
|
||||||
|
.thunar header.top tabs .reorderable-page:checked {
|
||||||
|
color: {{ $primary }};
|
||||||
|
background-color: alpha({{ $primary }}, 0.15);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Sidebar Navigation
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
.thunar .sidebar {
|
||||||
|
padding: 0 20px;
|
||||||
|
background: none;
|
||||||
|
animation: fading 600ms ease forwards;
|
||||||
|
animation-delay: 100ms;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .sidebar .view {
|
||||||
|
padding: 8px 4px;
|
||||||
|
border-radius: 10px;
|
||||||
|
background: none;
|
||||||
|
transition: all ease 300ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .sidebar .view:hover {
|
||||||
|
background: alpha({{ $onSurface }}, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .sidebar .view:selected {
|
||||||
|
background: alpha({{ $primary }}, 0.15);
|
||||||
|
color: {{ $primary }};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Path Bar & Location Buttons
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
.thunar .path-bar-button {
|
||||||
|
margin: 0;
|
||||||
|
padding: 8px 5px;
|
||||||
|
transition: all ease 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .location-button.toggle:checked,
|
||||||
|
.thunar .path-bar-button.toggle:checked {
|
||||||
|
padding: 8px 25px;
|
||||||
|
background: alpha({{ $primary }}, 0.15);
|
||||||
|
color: {{ $primary }};
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .location-button.path-bar-button:not(:checked) {
|
||||||
|
background-color: {{ $surfaceContainerLow }};
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .location-button.path-bar-button:not(:checked):hover {
|
||||||
|
background: alpha({{ $primary }}, 0.08);
|
||||||
|
color: alpha({{ $primary }}, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .location-button.toggle+.location-button.toggle:checked {
|
||||||
|
margin-left: 0px;
|
||||||
|
padding: 0 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .titlebar {
|
||||||
|
padding: 15px 0 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Buttons
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
.thunar button.toggle:checked {
|
||||||
|
color: {{ $primary }};
|
||||||
|
}
|
||||||
|
|
||||||
|
.thunar .image-button {
|
||||||
|
padding: 8px;
|
||||||
|
margin: 0 0 0 8px;
|
||||||
|
transition: all ease 0.4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Status Bar
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
.thunar statusbar {
|
||||||
|
background-color: {{ $surfaceContainerLow }};
|
||||||
|
border-radius: 15px;
|
||||||
|
padding: 10px 10px;
|
||||||
|
margin: 15px 5px 15px -10px;
|
||||||
|
color: {{ $onSurface }};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Image preview
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
.thunar box.vertical .image {
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* =============================================================================
|
||||||
|
Animation
|
||||||
|
============================================================================= */
|
||||||
|
|
||||||
|
@keyframes fading {
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,457 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://zed.dev/schema/themes/v0.2.0.json",
|
||||||
|
"name": "Caelestia",
|
||||||
|
"author": "Caelestia",
|
||||||
|
"themes": [
|
||||||
|
{
|
||||||
|
"name": "Caelestia",
|
||||||
|
"appearance": "{{ mode }}",
|
||||||
|
"style": {
|
||||||
|
"background": "#{{ surface.hex }}",
|
||||||
|
"border": "#{{ outlineVariant.hex }}40",
|
||||||
|
"border.variant": "#{{ outlineVariant.hex }}60",
|
||||||
|
"border.focused": "#{{ primary.hex }}",
|
||||||
|
"border.selected": "#{{ primary.hex }}80",
|
||||||
|
"border.transparent": "#00000000",
|
||||||
|
"border.disabled": "#{{ outlineVariant.hex }}30",
|
||||||
|
|
||||||
|
"elevated_surface.background": "#{{ surfaceContainerHigh.hex }}",
|
||||||
|
"surface.background": "#{{ surface.hex }}",
|
||||||
|
|
||||||
|
"element.background": "#{{ outlineVariant.hex }}40",
|
||||||
|
"element.hover": "#{{ outlineVariant.hex }}60",
|
||||||
|
"element.active": "#{{ primary.hex }}30",
|
||||||
|
"element.selected": "#{{ primary.hex }}20",
|
||||||
|
"element.disabled": "#{{ outlineVariant.hex }}20",
|
||||||
|
|
||||||
|
"drop_target.background": "#{{ primary.hex }}20",
|
||||||
|
|
||||||
|
"ghost_element.background": "#00000000",
|
||||||
|
"ghost_element.hover": "#{{ outlineVariant.hex }}40",
|
||||||
|
"ghost_element.active": "#{{ primary.hex }}30",
|
||||||
|
"ghost_element.selected": "#{{ primary.hex }}20",
|
||||||
|
"ghost_element.disabled": "#{{ outlineVariant.hex }}20",
|
||||||
|
|
||||||
|
"text": "#{{ onSurface.hex }}",
|
||||||
|
"text.muted": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"text.placeholder": "#{{ outline.hex }}",
|
||||||
|
"text.disabled": "#{{ outline.hex }}80",
|
||||||
|
"text.accent": "#{{ primary.hex }}",
|
||||||
|
|
||||||
|
"icon": "#{{ onSurface.hex }}",
|
||||||
|
"icon.muted": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"icon.disabled": "#{{ outlineVariant.hex }}60",
|
||||||
|
"icon.placeholder": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"icon.accent": "#{{ primary.hex }}",
|
||||||
|
|
||||||
|
"status_bar.background": "#{{ surface.hex }}",
|
||||||
|
"title_bar.background": "#{{ surface.hex }}",
|
||||||
|
"title_bar.inactive_background": "#{{ surface.hex }}",
|
||||||
|
"toolbar.background": "#{{ surface.hex }}",
|
||||||
|
"tab_bar.background": "#{{ surface.hex }}",
|
||||||
|
"tab.inactive_background": "#{{ surface.hex }}",
|
||||||
|
"tab.active_background": "#{{ surfaceContainerHigh.hex }}",
|
||||||
|
|
||||||
|
"search.match_background": "#{{ yellow.hex }}40",
|
||||||
|
|
||||||
|
"panel.background": "#{{ surface.hex }}",
|
||||||
|
"panel.focused_border": "#{{ primary.hex }}",
|
||||||
|
|
||||||
|
"pane.focused_border": "#{{ primary.hex }}",
|
||||||
|
|
||||||
|
"scrollbar.thumb.background": "#{{ outlineVariant.hex }}30",
|
||||||
|
"scrollbar.thumb.hover_background": "#{{ outlineVariant.hex }}60",
|
||||||
|
"scrollbar.thumb.border": "#{{ outlineVariant.hex }}20",
|
||||||
|
"scrollbar.track.background": "#00000000",
|
||||||
|
"scrollbar.track.border": "#00000000",
|
||||||
|
|
||||||
|
"editor.foreground": "#{{ onSurface.hex }}",
|
||||||
|
"editor.background": "#{{ surface.hex }}",
|
||||||
|
"editor.gutter.background": "#{{ surface.hex }}",
|
||||||
|
"editor.subheader.background": "#{{ surfaceContainer.hex }}",
|
||||||
|
"editor.active_line.background": "#{{ surfaceContainerHigh.hex }}60",
|
||||||
|
"editor.highlighted_line.background": "#{{ primary.hex }}15",
|
||||||
|
"editor.line_number": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"editor.active_line_number": "#{{ onSurface.hex }}",
|
||||||
|
"editor.invisible": "#{{ outlineVariant.hex }}40",
|
||||||
|
"editor.wrap_guide": "#{{ outlineVariant.hex }}30",
|
||||||
|
"editor.active_wrap_guide": "#{{ outlineVariant.hex }}60",
|
||||||
|
"editor.document_highlight.read_background": "#{{ primary.hex }}20",
|
||||||
|
"editor.document_highlight.write_background": "#{{ primary.hex }}30",
|
||||||
|
|
||||||
|
"terminal.background": "#{{ surface.hex }}",
|
||||||
|
"terminal.foreground": "#{{ onSurface.hex }}",
|
||||||
|
"terminal.bright_foreground": "#{{ onSurface.hex }}",
|
||||||
|
"terminal.dim_foreground": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"terminal.ansi.black": "#{{ surface.hex }}",
|
||||||
|
"terminal.ansi.bright_black": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"terminal.ansi.dim_black": "#{{ surface.hex }}80",
|
||||||
|
"terminal.ansi.red": "#{{ red.hex }}",
|
||||||
|
"terminal.ansi.bright_red": "#{{ maroon.hex }}",
|
||||||
|
"terminal.ansi.dim_red": "#{{ red.hex }}80",
|
||||||
|
"terminal.ansi.green": "#{{ green.hex }}",
|
||||||
|
"terminal.ansi.bright_green": "#{{ teal.hex }}",
|
||||||
|
"terminal.ansi.dim_green": "#{{ green.hex }}80",
|
||||||
|
"terminal.ansi.yellow": "#{{ yellow.hex }}",
|
||||||
|
"terminal.ansi.bright_yellow": "#{{ peach.hex }}",
|
||||||
|
"terminal.ansi.dim_yellow": "#{{ yellow.hex }}80",
|
||||||
|
"terminal.ansi.blue": "#{{ blue.hex }}",
|
||||||
|
"terminal.ansi.bright_blue": "#{{ sapphire.hex }}",
|
||||||
|
"terminal.ansi.dim_blue": "#{{ blue.hex }}80",
|
||||||
|
"terminal.ansi.magenta": "#{{ mauve.hex }}",
|
||||||
|
"terminal.ansi.bright_magenta": "#{{ pink.hex }}",
|
||||||
|
"terminal.ansi.dim_magenta": "#{{ mauve.hex }}80",
|
||||||
|
"terminal.ansi.cyan": "#{{ teal.hex }}",
|
||||||
|
"terminal.ansi.bright_cyan": "#{{ sky.hex }}",
|
||||||
|
"terminal.ansi.dim_cyan": "#{{ teal.hex }}80",
|
||||||
|
"terminal.ansi.white": "#{{ onSurface.hex }}",
|
||||||
|
"terminal.ansi.bright_white": "#{{ onSurface.hex }}",
|
||||||
|
"terminal.ansi.dim_white": "#{{ onSurface.hex }}80",
|
||||||
|
|
||||||
|
"link_text.hover": "#{{ primary.hex }}",
|
||||||
|
|
||||||
|
"conflict": "#{{ yellow.hex }}",
|
||||||
|
"conflict.background": "#{{ yellow.hex }}15",
|
||||||
|
"conflict.border": "#{{ yellow.hex }}",
|
||||||
|
|
||||||
|
"created": "#{{ green.hex }}",
|
||||||
|
"created.background": "#{{ green.hex }}15",
|
||||||
|
"created.border": "#{{ green.hex }}",
|
||||||
|
|
||||||
|
"deleted": "#{{ red.hex }}",
|
||||||
|
"deleted.background": "#{{ red.hex }}15",
|
||||||
|
"deleted.border": "#{{ red.hex }}",
|
||||||
|
|
||||||
|
"error": "#{{ error.hex }}",
|
||||||
|
"error.background": "#{{ error.hex }}15",
|
||||||
|
"error.border": "#{{ error.hex }}",
|
||||||
|
|
||||||
|
"hidden": "#{{ outline.hex }}",
|
||||||
|
"hidden.background": "#{{ outline.hex }}15",
|
||||||
|
"hidden.border": "#{{ outline.hex }}",
|
||||||
|
|
||||||
|
"hint": "#{{ success.hex }}",
|
||||||
|
"hint.background": "#{{ success.hex }}15",
|
||||||
|
"hint.border": "#{{ success.hex }}",
|
||||||
|
|
||||||
|
"ignored": "#{{ outline.hex }}",
|
||||||
|
"ignored.background": "#{{ outline.hex }}15",
|
||||||
|
"ignored.border": "#{{ outline.hex }}",
|
||||||
|
|
||||||
|
"info": "#{{ blue.hex }}",
|
||||||
|
"info.background": "#{{ blue.hex }}15",
|
||||||
|
"info.border": "#{{ blue.hex }}",
|
||||||
|
|
||||||
|
"modified": "#{{ peach.hex }}",
|
||||||
|
"modified.background": "#{{ peach.hex }}15",
|
||||||
|
"modified.border": "#{{ peach.hex }}",
|
||||||
|
|
||||||
|
"predictive": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"predictive.background": "#{{ onSurfaceVariant.hex }}15",
|
||||||
|
"predictive.border": "#{{ outlineVariant.hex }}40",
|
||||||
|
|
||||||
|
"renamed": "#{{ teal.hex }}",
|
||||||
|
"renamed.background": "#{{ teal.hex }}15",
|
||||||
|
"renamed.border": "#{{ teal.hex }}",
|
||||||
|
|
||||||
|
"success": "#{{ success.hex }}",
|
||||||
|
"success.background": "#{{ success.hex }}15",
|
||||||
|
"success.border": "#{{ success.hex }}",
|
||||||
|
|
||||||
|
"unreachable": "#{{ outline.hex }}",
|
||||||
|
"unreachable.background": "#{{ outline.hex }}15",
|
||||||
|
"unreachable.border": "#{{ outline.hex }}",
|
||||||
|
|
||||||
|
"warning": "#{{ yellow.hex }}",
|
||||||
|
"warning.background": "#{{ yellow.hex }}15",
|
||||||
|
"warning.border": "#{{ yellow.hex }}",
|
||||||
|
|
||||||
|
"players": [
|
||||||
|
{
|
||||||
|
"cursor": "#{{ onSurface.hex }}",
|
||||||
|
"selection": "#{{ onSurface.hex }}60",
|
||||||
|
"background": "#{{ primary.hex }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cursor": "#{{ teal.hex }}",
|
||||||
|
"selection": "#{{ teal.hex }}40",
|
||||||
|
"background": "#{{ teal.hex }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cursor": "#{{ pink.hex }}",
|
||||||
|
"selection": "#{{ pink.hex }}40",
|
||||||
|
"background": "#{{ pink.hex }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cursor": "#{{ yellow.hex }}",
|
||||||
|
"selection": "#{{ yellow.hex }}40",
|
||||||
|
"background": "#{{ yellow.hex }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cursor": "#{{ green.hex }}",
|
||||||
|
"selection": "#{{ green.hex }}40",
|
||||||
|
"background": "#{{ green.hex }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cursor": "#{{ red.hex }}",
|
||||||
|
"selection": "#{{ red.hex }}40",
|
||||||
|
"background": "#{{ red.hex }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cursor": "#{{ blue.hex }}",
|
||||||
|
"selection": "#{{ blue.hex }}40",
|
||||||
|
"background": "#{{ blue.hex }}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cursor": "#{{ maroon.hex }}",
|
||||||
|
"selection": "#{{ maroon.hex }}40",
|
||||||
|
"background": "#{{ maroon.hex }}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
"syntax": {
|
||||||
|
"attribute": {
|
||||||
|
"color": "#{{ yellow.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"boolean": {
|
||||||
|
"color": "#{{ peach.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"comment": {
|
||||||
|
"color": "#{{ subtext0.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"comment.doc": {
|
||||||
|
"color": "#{{ subtext0.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"constant": {
|
||||||
|
"color": "#{{ peach.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"constructor": {
|
||||||
|
"color": "#{{ yellow.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"embedded": {
|
||||||
|
"color": "#{{ onSurface.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"emphasis": {
|
||||||
|
"color": "#{{ red.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"emphasis.strong": {
|
||||||
|
"color": "#{{ red.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": 700
|
||||||
|
},
|
||||||
|
"enum": {
|
||||||
|
"color": "#{{ yellow.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"function": {
|
||||||
|
"color": "#{{ blue.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"function.builtin": {
|
||||||
|
"color": "#{{ teal.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"function.definition": {
|
||||||
|
"color": "#{{ blue.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"function.method": {
|
||||||
|
"color": "#{{ blue.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"function.special.definition": {
|
||||||
|
"color": "#{{ blue.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"hint": {
|
||||||
|
"color": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"keyword": {
|
||||||
|
"color": "#{{ pink.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"color": "#{{ yellow.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"link_text": {
|
||||||
|
"color": "#{{ blue.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"link_uri": {
|
||||||
|
"color": "#{{ teal.hex }}",
|
||||||
|
"font_style": "underline",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"number": {
|
||||||
|
"color": "#{{ peach.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"operator": {
|
||||||
|
"color": "#{{ sapphire.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"predictive": {
|
||||||
|
"color": "#{{ onSurfaceVariant.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"preproc": {
|
||||||
|
"color": "#{{ teal.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"primary": {
|
||||||
|
"color": "#{{ onSurface.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"property": {
|
||||||
|
"color": "#{{ teal.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"punctuation": {
|
||||||
|
"color": "#{{ subtext1.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"punctuation.bracket": {
|
||||||
|
"color": "#{{ subtext1.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"punctuation.delimiter": {
|
||||||
|
"color": "#{{ subtext1.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"punctuation.list_marker": {
|
||||||
|
"color": "#{{ teal.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"punctuation.special": {
|
||||||
|
"color": "#{{ sapphire.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"string": {
|
||||||
|
"color": "#{{ green.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"string.escape": {
|
||||||
|
"color": "#{{ pink.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"string.regex": {
|
||||||
|
"color": "#{{ sky.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"string.special": {
|
||||||
|
"color": "#{{ green.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"string.special.symbol": {
|
||||||
|
"color": "#{{ teal.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"tag": {
|
||||||
|
"color": "#{{ yellow.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"text.literal": {
|
||||||
|
"color": "#{{ green.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"color": "#{{ blue.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": 700
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"color": "#{{ yellow.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"type.builtin": {
|
||||||
|
"color": "#{{ onSurface.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"type.interface": {
|
||||||
|
"color": "#{{ yellow.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"type.super": {
|
||||||
|
"color": "#{{ yellow.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"variable": {
|
||||||
|
"color": "#{{ onSurface.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"variable.member": {
|
||||||
|
"color": "#{{ teal.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"variable.parameter": {
|
||||||
|
"color": "#{{ teal.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"variable.special": {
|
||||||
|
"color": "#{{ onSurface.hex }}",
|
||||||
|
"font_style": "italic",
|
||||||
|
"font_weight": null
|
||||||
|
},
|
||||||
|
"variant": {
|
||||||
|
"color": "#{{ peach.hex }}",
|
||||||
|
"font_style": null,
|
||||||
|
"font_weight": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -6,7 +6,7 @@ from caelestia.utils.scheme import get_scheme_names, scheme_variants
|
|||||||
from caelestia.utils.wallpaper import get_wallpaper
|
from caelestia.utils.wallpaper import get_wallpaper
|
||||||
|
|
||||||
|
|
||||||
def parse_args() -> (argparse.ArgumentParser, argparse.Namespace):
|
def parse_args() -> tuple[argparse.ArgumentParser, argparse.Namespace]:
|
||||||
parser = argparse.ArgumentParser(prog="caelestia", description="Main control script for the Caelestia dotfiles")
|
parser = argparse.ArgumentParser(prog="caelestia", description="Main control script for the Caelestia dotfiles")
|
||||||
parser.add_argument("-v", "--version", action="store_true", help="print the current version")
|
parser.add_argument("-v", "--version", action="store_true", help="print the current version")
|
||||||
|
|
||||||
@@ -71,6 +71,7 @@ def parse_args() -> (argparse.ArgumentParser, argparse.Namespace):
|
|||||||
record_parser.add_argument("-r", "--region", nargs="?", const="slurp", help="record a region")
|
record_parser.add_argument("-r", "--region", nargs="?", const="slurp", help="record a region")
|
||||||
record_parser.add_argument("-s", "--sound", action="store_true", help="record audio")
|
record_parser.add_argument("-s", "--sound", action="store_true", help="record audio")
|
||||||
record_parser.add_argument("-p", "--pause", action="store_true", help="pause/resume the recording")
|
record_parser.add_argument("-p", "--pause", action="store_true", help="pause/resume the recording")
|
||||||
|
record_parser.add_argument("-c", "--clipboard", action="store_true", help="copy recording path to clipboard")
|
||||||
|
|
||||||
# Create parser for clipboard opts
|
# Create parser for clipboard opts
|
||||||
clipboard_parser = command_parser.add_parser("clipboard", help="open clipboard history")
|
clipboard_parser = command_parser.add_parser("clipboard", help="open clipboard history")
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import subprocess
|
|||||||
import time
|
import time
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from caelestia.utils import hypr
|
||||||
from caelestia.utils.notify import close_notification, notify
|
from caelestia.utils.notify import close_notification, notify
|
||||||
from caelestia.utils.paths import recording_notif_path, recording_path, recordings_dir, user_config_path
|
from caelestia.utils.paths import recording_notif_path, recording_path, recordings_dir, user_config_path
|
||||||
|
|
||||||
@@ -35,7 +37,7 @@ class Command:
|
|||||||
def start(self) -> None:
|
def start(self) -> None:
|
||||||
args = ["-w"]
|
args = ["-w"]
|
||||||
|
|
||||||
monitors = json.loads(subprocess.check_output(["hyprctl", "monitors", "-j"]))
|
monitors = hypr.message("monitors")
|
||||||
if self.args.region:
|
if self.args.region:
|
||||||
if self.args.region == "slurp":
|
if self.args.region == "slurp":
|
||||||
region = subprocess.check_output(["slurp", "-f", "%wx%h+%x+%y"], text=True)
|
region = subprocess.check_output(["slurp", "-f", "%wx%h+%x+%y"], text=True)
|
||||||
@@ -108,6 +110,10 @@ class Command:
|
|||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
if self.args.clipboard:
|
||||||
|
file_uri = Path(new_path).resolve().as_uri() + "\n"
|
||||||
|
subprocess.run(["wl-copy", "--type", "text/uri-list"], input=file_uri.encode())
|
||||||
|
|
||||||
action = notify(
|
action = notify(
|
||||||
"--action=watch=Watch",
|
"--action=watch=Watch",
|
||||||
"--action=open=Open",
|
"--action=open=Open",
|
||||||
|
|||||||
@@ -26,11 +26,29 @@ class Command:
|
|||||||
self.timeout_tracker: dict[str, float] = {}
|
self.timeout_tracker: dict[str, float] = {}
|
||||||
self.window_rules = self._load_window_rules()
|
self.window_rules = self._load_window_rules()
|
||||||
|
|
||||||
|
def _make_resize_cmd(self, width: int | str, height: int | str, address: str) -> str:
|
||||||
|
if hypr.is_lua_config():
|
||||||
|
return f'dispatch hl.dsp.window.resize({{x = {width}, y = {height}, exact = true, window = "address:{address}"}})'
|
||||||
|
return f"dispatch resizewindowpixel exact {width} {height},address:{address}"
|
||||||
|
|
||||||
|
def _make_move_cmd(self, x: int, y: int, address: str) -> str:
|
||||||
|
if hypr.is_lua_config():
|
||||||
|
return f'dispatch hl.dsp.window.move({{x = {x}, y = {y}, window = "address:{address}"}})'
|
||||||
|
return f"dispatch movewindowpixel exact {x} {y},address:{address}"
|
||||||
|
|
||||||
|
def _make_float_cmd(self, address: str) -> str:
|
||||||
|
if hypr.is_lua_config():
|
||||||
|
return f'dispatch hl.dsp.window.float({{action = "toggle", window = "address:{address}"}})'
|
||||||
|
return f"dispatch togglefloating address:{address}"
|
||||||
|
|
||||||
|
def _make_center_cmd(self) -> str:
|
||||||
|
if hypr.is_lua_config():
|
||||||
|
return "dispatch hl.dsp.window.center()"
|
||||||
|
return "dispatch centerwindow"
|
||||||
|
|
||||||
def _load_window_rules(self) -> list[WindowRule]:
|
def _load_window_rules(self) -> list[WindowRule]:
|
||||||
default_rules = [
|
default_rules = [
|
||||||
WindowRule("(Bitwarden", "titleContains", "20%", "54%", ["float", "center"]),
|
WindowRule("(Bitwarden", "titleContains", "20%", "54%", ["float", "center"]),
|
||||||
WindowRule("Sign in - Google Accounts", "titleContains", "35%", "65%", ["float", "center"]),
|
|
||||||
WindowRule("oauth", "titleContains", "30%", "60%", ["float", "center"]),
|
|
||||||
WindowRule("^[Pp]icture(-| )in(-| )[Pp]icture$", "titleRegex", "", "", ["pip"]),
|
WindowRule("^[Pp]icture(-| )in(-| )[Pp]icture$", "titleRegex", "", "", ["pip"]),
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -140,7 +158,10 @@ class Command:
|
|||||||
monitor_x = monitor.get("x")
|
monitor_x = monitor.get("x")
|
||||||
monitor_y = monitor.get("y")
|
monitor_y = monitor.get("y")
|
||||||
|
|
||||||
if not all(isinstance(x, (int, float)) for x in [monitor_height, monitor_width, monitor_scale, monitor_x, monitor_y]):
|
if not all(
|
||||||
|
isinstance(x, (int, float))
|
||||||
|
for x in [monitor_height, monitor_width, monitor_scale, monitor_x, monitor_y]
|
||||||
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
monitor_height = monitor_height / monitor_scale
|
monitor_height = monitor_height / monitor_scale
|
||||||
@@ -163,8 +184,8 @@ class Command:
|
|||||||
move_x = monitor_x + monitor_width - scaled_width - offset
|
move_x = monitor_x + monitor_width - scaled_width - offset
|
||||||
move_y = monitor_y + monitor_height - scaled_height - offset
|
move_y = monitor_y + monitor_height - scaled_height - offset
|
||||||
|
|
||||||
command1 = f"dispatch resizewindowpixel exact {scaled_width} {scaled_height},address:{address}"
|
command1 = self._make_resize_cmd(scaled_width, scaled_height, address)
|
||||||
command2 = f"dispatch movewindowpixel exact {int(move_x)} {int(move_y)},address:{address}"
|
command2 = self._make_move_cmd(int(move_x), int(move_y), address)
|
||||||
hypr.batch(command1, command2)
|
hypr.batch(command1, command2)
|
||||||
|
|
||||||
log_message(
|
log_message(
|
||||||
@@ -180,16 +201,16 @@ class Command:
|
|||||||
if "float" in actions:
|
if "float" in actions:
|
||||||
window_info = self._get_window_info(window_id)
|
window_info = self._get_window_info(window_id)
|
||||||
if window_info and not window_info.get("floating", False):
|
if window_info and not window_info.get("floating", False):
|
||||||
dispatch_commands.append(f"dispatch togglefloating address:0x{window_id}")
|
dispatch_commands.append(self._make_float_cmd(f"0x{window_id}"))
|
||||||
|
|
||||||
if "pip" in actions:
|
if "pip" in actions:
|
||||||
self._apply_pip_action(window_id)
|
self._apply_pip_action(window_id)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
dispatch_commands.append(f"dispatch resizewindowpixel exact {width} {height},address:0x{window_id}")
|
dispatch_commands.append(self._make_resize_cmd(width, height, f"0x{window_id}"))
|
||||||
|
|
||||||
if "center" in actions:
|
if "center" in actions:
|
||||||
dispatch_commands.append("dispatch centerwindow")
|
dispatch_commands.append(self._make_center_cmd())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
hypr.batch(*dispatch_commands)
|
hypr.batch(*dispatch_commands)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import subprocess
|
|||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
from caelestia.utils import hypr
|
||||||
from caelestia.utils.notify import notify
|
from caelestia.utils.notify import notify
|
||||||
from caelestia.utils.paths import screenshots_cache_dir, screenshots_dir
|
from caelestia.utils.paths import screenshots_cache_dir, screenshots_dir
|
||||||
|
|
||||||
@@ -26,11 +27,19 @@ class Command:
|
|||||||
else:
|
else:
|
||||||
sc_data = subprocess.check_output(["grim", "-l", "0", "-g", self.args.region.strip(), "-"])
|
sc_data = subprocess.check_output(["grim", "-l", "0", "-g", self.args.region.strip(), "-"])
|
||||||
swappy = subprocess.Popen(["swappy", "-f", "-"], stdin=subprocess.PIPE, start_new_session=True)
|
swappy = subprocess.Popen(["swappy", "-f", "-"], stdin=subprocess.PIPE, start_new_session=True)
|
||||||
|
|
||||||
|
# Ensure stdin is not None for the type checker
|
||||||
|
if swappy.stdin:
|
||||||
swappy.stdin.write(sc_data)
|
swappy.stdin.write(sc_data)
|
||||||
swappy.stdin.close()
|
swappy.stdin.close()
|
||||||
|
|
||||||
def fullscreen(self) -> None:
|
def fullscreen(self) -> None:
|
||||||
sc_data = subprocess.check_output(["grim", "-"])
|
cmd = ["grim"]
|
||||||
|
focused_monitor = next(monitor for monitor in hypr.message("monitors") if monitor["focused"])
|
||||||
|
if focused_monitor:
|
||||||
|
cmd += ["-o", focused_monitor["name"]]
|
||||||
|
cmd += ["-"]
|
||||||
|
sc_data = subprocess.check_output(cmd)
|
||||||
|
|
||||||
subprocess.run(["wl-copy"], input=sc_data)
|
subprocess.run(["wl-copy"], input=sc_data)
|
||||||
|
|
||||||
|
|||||||
@@ -33,11 +33,14 @@ class Command:
|
|||||||
subprocess.run(args)
|
subprocess.run(args)
|
||||||
else:
|
else:
|
||||||
shell = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True)
|
shell = subprocess.Popen(args, stdout=subprocess.PIPE, universal_newlines=True)
|
||||||
|
|
||||||
|
# Ensure stdout is not None for the type checker
|
||||||
|
if shell.stdout:
|
||||||
for line in shell.stdout:
|
for line in shell.stdout:
|
||||||
if self.filter_log(line):
|
if self.filter_log(line):
|
||||||
print(line, end="")
|
print(line, end="")
|
||||||
|
|
||||||
def shell(self, *args: list[str]) -> str:
|
def shell(self, *args: str) -> str:
|
||||||
return subprocess.check_output(["qs", "-c", "caelestia", *args], text=True)
|
return subprocess.check_output(["qs", "-c", "caelestia", *args], text=True)
|
||||||
|
|
||||||
def filter_log(self, line: str) -> bool:
|
def filter_log(self, line: str) -> bool:
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import shlex
|
|||||||
import shutil
|
import shutil
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from collections import ChainMap
|
from collections import ChainMap
|
||||||
|
from typing import Any, Callable, cast
|
||||||
|
|
||||||
from caelestia.utils import hypr
|
from caelestia.utils import hypr
|
||||||
from caelestia.utils.paths import user_config_path
|
from caelestia.utils.paths import user_config_path
|
||||||
@@ -52,8 +53,8 @@ class DeepChainMap(ChainMap):
|
|||||||
|
|
||||||
class Command:
|
class Command:
|
||||||
args: Namespace
|
args: Namespace
|
||||||
cfg: dict[str, dict[str, dict[str, any]]] | DeepChainMap
|
cfg: dict[str, dict[str, dict[str, Any]]] | DeepChainMap
|
||||||
clients: list[dict[str, any]] = None
|
clients: list[dict[str, Any]] | None = None
|
||||||
|
|
||||||
def __init__(self, args: Namespace) -> None:
|
def __init__(self, args: Namespace) -> None:
|
||||||
self.args = args
|
self.args = args
|
||||||
@@ -120,27 +121,27 @@ class Command:
|
|||||||
if not spawned:
|
if not spawned:
|
||||||
hypr.dispatch("togglespecialworkspace", self.args.workspace)
|
hypr.dispatch("togglespecialworkspace", self.args.workspace)
|
||||||
|
|
||||||
def get_clients(self) -> list[dict[str, any]]:
|
def get_clients(self) -> list[dict[str, Any]]:
|
||||||
if self.clients is None:
|
if self.clients is None:
|
||||||
self.clients = hypr.message("clients")
|
self.clients = cast(list[dict[str, Any]], hypr.message("clients"))
|
||||||
|
|
||||||
return self.clients
|
return self.clients
|
||||||
|
|
||||||
def move_client(self, selector: callable, workspace: str) -> None:
|
def move_client(self, selector: Callable, workspace: str) -> None:
|
||||||
for client in self.get_clients():
|
for client in self.get_clients():
|
||||||
if selector(client) and client["workspace"]["name"] != f"special:{workspace}":
|
if selector(client) and client["workspace"]["name"] != f"special:{workspace}":
|
||||||
hypr.dispatch("movetoworkspacesilent", f"special:{workspace},address:{client['address']}")
|
hypr.dispatch("movetoworkspacesilent", f"special:{workspace},address:{client['address']}")
|
||||||
|
|
||||||
def spawn_client(self, selector: callable, spawn: list[str]) -> bool:
|
def spawn_client(self, selector: Callable, spawn: list[str]) -> bool:
|
||||||
if (spawn[0].endswith(".desktop") or shutil.which(spawn[0])) and not any(
|
if (spawn[0].endswith(".desktop") or shutil.which(spawn[0])) and not any(
|
||||||
selector(client) for client in self.get_clients()
|
selector(client) for client in self.get_clients()
|
||||||
):
|
):
|
||||||
hypr.dispatch("exec", f"[workspace special:{self.args.workspace}] app2unit -- {shlex.join(spawn)}")
|
hypr.dispatch("exec", f"[workspace special:{self.args.workspace}] app2unit -- {shlex.join(spawn)}")
|
||||||
return True
|
return True
|
||||||
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def handle_client_config(self, client: dict[str, any]) -> bool:
|
def handle_client_config(self, client: dict[str, Any]) -> bool:
|
||||||
def selector(c: dict[str, any]) -> bool:
|
def selector(c: dict[str, Any]) -> bool:
|
||||||
# Each match is or, inside matches is and
|
# Each match is or, inside matches is and
|
||||||
for match in client["match"]:
|
for match in client["match"]:
|
||||||
if is_subset(c, match):
|
if is_subset(c, match):
|
||||||
@@ -156,5 +157,8 @@ class Command:
|
|||||||
return spawned
|
return spawned
|
||||||
|
|
||||||
def specialws(self) -> None:
|
def specialws(self) -> None:
|
||||||
special = next(m for m in hypr.message("monitors") if m["focused"])["specialWorkspace"]["name"]
|
monitors = cast(list[dict[str, Any]], hypr.message("monitors"))
|
||||||
hypr.dispatch("togglespecialworkspace", special[8:] or "special")
|
target = next((m for m in monitors if m.get("focused")), None)
|
||||||
|
if target:
|
||||||
|
special = target.get("specialWorkspace", {}).get("name", "")[8:] or "special"
|
||||||
|
hypr.dispatch("togglespecialworkspace", special)
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ def stddev(values: list[float], mean_val: float) -> float:
|
|||||||
return math.sqrt(sum((x - mean_val) ** 2 for x in values) / len(values)) if values else 0
|
return math.sqrt(sum((x - mean_val) ** 2 for x in values) / len(values)) if values else 0
|
||||||
|
|
||||||
|
|
||||||
def calc_colourfulness(image: Image) -> float:
|
def calc_colourfulness(image: Image.Image) -> float:
|
||||||
width, height = image.size
|
|
||||||
pixels = list(image.getdata()) # List of (R, G, B) tuples
|
pixels = list(image.getdata()) # List of (R, G, B) tuples
|
||||||
|
|
||||||
rg_diffs = []
|
rg_diffs = []
|
||||||
@@ -32,7 +31,7 @@ def calc_colourfulness(image: Image) -> float:
|
|||||||
return math.sqrt(std_rg**2 + std_yb**2) + 0.3 * math.sqrt(mean_rg**2 + mean_yb**2)
|
return math.sqrt(std_rg**2 + std_yb**2) + 0.3 * math.sqrt(mean_rg**2 + mean_yb**2)
|
||||||
|
|
||||||
|
|
||||||
def get_variant(image: Image) -> str:
|
def get_variant(image: Image.Image) -> str:
|
||||||
colourfulness = calc_colourfulness(image)
|
colourfulness = calc_colourfulness(image)
|
||||||
|
|
||||||
if colourfulness < 10:
|
if colourfulness < 10:
|
||||||
|
|||||||
+44
-10
@@ -1,17 +1,19 @@
|
|||||||
import json as j
|
import json
|
||||||
import os
|
import os
|
||||||
import socket
|
import socket
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
socket_base = f"{os.getenv('XDG_RUNTIME_DIR')}/hypr/{os.getenv('HYPRLAND_INSTANCE_SIGNATURE')}"
|
socket_base = f"{os.getenv('XDG_RUNTIME_DIR')}/hypr/{os.getenv('HYPRLAND_INSTANCE_SIGNATURE')}"
|
||||||
socket_path = f"{socket_base}/.socket.sock"
|
socket_path = f"{socket_base}/.socket.sock"
|
||||||
socket2_path = f"{socket_base}/.socket2.sock"
|
socket2_path = f"{socket_base}/.socket2.sock"
|
||||||
|
|
||||||
|
_lua_config_cache: bool | None = None
|
||||||
|
|
||||||
def message(msg: str, json: bool = True) -> str | dict[str, any]:
|
def message(msg: str, is_json: bool = True) -> str | dict[str, Any]:
|
||||||
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
|
with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
|
||||||
sock.connect(socket_path)
|
sock.connect(socket_path)
|
||||||
|
|
||||||
if json:
|
if is_json:
|
||||||
msg = f"j/{msg}"
|
msg = f"j/{msg}"
|
||||||
sock.send(msg.encode())
|
sock.send(msg.encode())
|
||||||
|
|
||||||
@@ -22,14 +24,46 @@ def message(msg: str, json: bool = True) -> str | dict[str, any]:
|
|||||||
break
|
break
|
||||||
resp += new_resp.decode()
|
resp += new_resp.decode()
|
||||||
|
|
||||||
return j.loads(resp) if json else resp
|
return json.loads(resp) if is_json else resp
|
||||||
|
|
||||||
|
|
||||||
def dispatch(dispatcher: str, *args: list[any]) -> bool:
|
def is_lua_config() -> bool:
|
||||||
return message(f"dispatch {dispatcher} {' '.join(map(str, args))}".rstrip(), json=False) == "ok"
|
global _lua_config_cache
|
||||||
|
if _lua_config_cache is not None:
|
||||||
|
return _lua_config_cache
|
||||||
|
try:
|
||||||
|
result = message("systeminfo", is_json=False)
|
||||||
|
for line in result.splitlines():
|
||||||
|
if "configProvider:" in line:
|
||||||
|
_lua_config_cache = "lua" in line.lower()
|
||||||
|
return _lua_config_cache
|
||||||
|
_lua_config_cache = False
|
||||||
|
return False
|
||||||
|
except Exception:
|
||||||
|
_lua_config_cache = False
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
def batch(*msgs: list[str], json: bool = False) -> str | dict[str, any]:
|
DISPATCHER_MAP_LUA = {
|
||||||
if json:
|
"togglespecialworkspace": lambda *a: f'hl.dsp.workspace.toggle_special("{a[0]}")' if a else 'hl.dsp.workspace.toggle_special()',
|
||||||
msgs = (f"j/{m.strip()}" for m in msgs)
|
"movetoworkspacesilent": lambda *a: (
|
||||||
return message(f"[[BATCH]]{';'.join(msgs)}", json=False)
|
f'hl.dsp.window.move({{window = "address:{a[0].split(",")[1].replace("address:", "")}", workspace = "{a[0].split(",")[0]}", follow = false}})'
|
||||||
|
),
|
||||||
|
"exec": lambda *a: 'hl.dsp.exec_cmd("' + ' '.join(a).replace('\\', '\\\\').replace('"', '\\"') + '")',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def dispatch(dispatcher: str, *args: str) -> bool:
|
||||||
|
if is_lua_config() and dispatcher in DISPATCHER_MAP_LUA:
|
||||||
|
lua_dispatch = DISPATCHER_MAP_LUA[dispatcher](*args)
|
||||||
|
return message(f"dispatch {lua_dispatch}", is_json=False) == "ok"
|
||||||
|
return message(f"dispatch {dispatcher} {' '.join(map(str, args))}".rstrip(), is_json=False) == "ok"
|
||||||
|
|
||||||
|
|
||||||
|
def batch(*msgs: str, is_json: bool = False) -> str | dict[str, Any]:
|
||||||
|
formatted_msgs = msgs
|
||||||
|
|
||||||
|
if is_json:
|
||||||
|
formatted_msgs = [f"j/{m.strip()}" for m in msgs]
|
||||||
|
|
||||||
|
return message(f"[[BATCH]]{';'.join(formatted_msgs)}", is_json=False)
|
||||||
|
|||||||
@@ -12,9 +12,11 @@ def log_exception(func):
|
|||||||
Used by the `apply_()` functions so that an exception, when applying
|
Used by the `apply_()` functions so that an exception, when applying
|
||||||
a theme, does not prevent the other themes from being applied.
|
a theme, does not prevent the other themes from being applied.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
try:
|
try:
|
||||||
func(*args, **kwargs)
|
func(*args, **kwargs)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log_message(f'Error during execution of "{func.__name__}()": {str(e)}')
|
log_message(f'Error during execution of "{func.__name__}()": {str(e)}')
|
||||||
|
|
||||||
return wrapper
|
return wrapper
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ def get_colours_for_image(image: Path | str = wallpaper_thumbnail_path, scheme=N
|
|||||||
scheme = get_scheme()
|
scheme = get_scheme()
|
||||||
|
|
||||||
cache_base = scheme_cache_dir / compute_hash(image)
|
cache_base = scheme_cache_dir / compute_hash(image)
|
||||||
cache = (cache_base / scheme.variant / scheme.mode).with_suffix(".json")
|
cache = (cache_base / scheme.variant / scheme.flavour / scheme.mode).with_suffix(".json")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with cache.open("r") as f:
|
with cache.open("r") as f:
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
from materialyoucolor.blend import Blend
|
from materialyoucolor.blend import Blend
|
||||||
from materialyoucolor.dynamiccolor.material_dynamic_colors import (
|
from materialyoucolor.dynamiccolor.material_dynamic_colors import MaterialDynamicColors
|
||||||
DynamicScheme,
|
|
||||||
MaterialDynamicColors,
|
|
||||||
)
|
|
||||||
from materialyoucolor.hct import Hct
|
from materialyoucolor.hct import Hct
|
||||||
from materialyoucolor.scheme.scheme_content import SchemeContent
|
from materialyoucolor.scheme.scheme_content import SchemeContent
|
||||||
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive
|
from materialyoucolor.scheme.scheme_expressive import SchemeExpressive
|
||||||
@@ -14,6 +11,19 @@ from materialyoucolor.scheme.scheme_rainbow import SchemeRainbow
|
|||||||
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot
|
from materialyoucolor.scheme.scheme_tonal_spot import SchemeTonalSpot
|
||||||
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant
|
from materialyoucolor.scheme.scheme_vibrant import SchemeVibrant
|
||||||
from materialyoucolor.utils.math_utils import difference_degrees, rotation_direction, sanitize_degrees_double
|
from materialyoucolor.utils.math_utils import difference_degrees, rotation_direction, sanitize_degrees_double
|
||||||
|
from typing import Protocol, Any
|
||||||
|
|
||||||
|
|
||||||
|
# The base DynamicScheme class requires a 'variant' argument, but the specific
|
||||||
|
# subclasses in get_scheme() handle that internally. This Protocol tells the type
|
||||||
|
# checker to expect our specific 3-argument setup instead of the base class signature.
|
||||||
|
class SchemeConstructor(Protocol):
|
||||||
|
def __call__(self, source_color_hct: Any, is_dark: bool, contrast_level: float) -> "DynamicScheme": ...
|
||||||
|
|
||||||
|
try:
|
||||||
|
from materialyoucolor.dynamiccolor.dynamic_scheme import DynamicScheme
|
||||||
|
except ImportError:
|
||||||
|
from materialyoucolor.scheme.dynamic_scheme import DynamicScheme
|
||||||
|
|
||||||
|
|
||||||
def hex_to_hct(hex: str) -> Hct:
|
def hex_to_hct(hex: str) -> Hct:
|
||||||
@@ -142,10 +152,10 @@ def lighten(colour: Hct, amount: float) -> Hct:
|
|||||||
|
|
||||||
def darken(colour: Hct, amount: float) -> Hct:
|
def darken(colour: Hct, amount: float) -> Hct:
|
||||||
diff = colour.tone * amount
|
diff = colour.tone * amount
|
||||||
return Hct.from_hct(colour.hue, colour.chroma + diff / 5, colour.tone - diff)
|
return Hct.from_hct(colour.hue, colour.chroma - diff / 5, colour.tone - diff)
|
||||||
|
|
||||||
|
|
||||||
def get_scheme(scheme: str) -> DynamicScheme:
|
def get_scheme(scheme: str) -> SchemeConstructor:
|
||||||
if scheme == "content":
|
if scheme == "content":
|
||||||
return SchemeContent
|
return SchemeContent
|
||||||
if scheme == "expressive":
|
if scheme == "expressive":
|
||||||
@@ -166,45 +176,62 @@ def get_scheme(scheme: str) -> DynamicScheme:
|
|||||||
|
|
||||||
|
|
||||||
def gen_scheme(scheme, primary: Hct) -> dict[str, str]:
|
def gen_scheme(scheme, primary: Hct) -> dict[str, str]:
|
||||||
light = scheme.mode == "light"
|
is_light = scheme.mode == "light"
|
||||||
|
|
||||||
colours = {}
|
colours = {}
|
||||||
|
|
||||||
# Material colours
|
# Material colours
|
||||||
primary_scheme = get_scheme(scheme.variant)(primary, not light, 0)
|
primary_scheme = get_scheme(scheme.variant)(source_color_hct=primary, is_dark=not is_light, contrast_level=0.0)
|
||||||
|
if hasattr(MaterialDynamicColors, "all_colors"): # materialyoucolor-python >= 3.0.0
|
||||||
|
dyn_colours = MaterialDynamicColors()
|
||||||
|
for colour in dyn_colours.all_colors:
|
||||||
|
colours[colour.name] = colour.get_hct(primary_scheme)
|
||||||
|
else:
|
||||||
for colour in vars(MaterialDynamicColors).keys():
|
for colour in vars(MaterialDynamicColors).keys():
|
||||||
colour_name = getattr(MaterialDynamicColors, colour)
|
colour_name = getattr(MaterialDynamicColors, colour)
|
||||||
if hasattr(colour_name, "get_hct"):
|
if hasattr(colour_name, "get_hct"):
|
||||||
colours[colour] = colour_name.get_hct(primary_scheme)
|
colours[colour] = colour_name.get_hct(primary_scheme)
|
||||||
|
|
||||||
|
# Backwards compatibility with old colour names
|
||||||
|
if "primaryPaletteKeyColor" in colours: # materialyoucolor-python >= 3.0.0
|
||||||
|
for colour in "primary", "secondary", "tertiary", "neutral":
|
||||||
|
colours[f"{colour}_paletteKeyColor"] = colours[f"{colour}PaletteKeyColor"]
|
||||||
|
colours["neutral_variant_paletteKeyColor"] = colours["neutralVariantPaletteKeyColor"]
|
||||||
|
|
||||||
# Harmonize terminal colours
|
# Harmonize terminal colours
|
||||||
for i, hct in enumerate(light_gruvbox if light else dark_gruvbox):
|
for i, hct in enumerate(light_gruvbox if is_light else dark_gruvbox):
|
||||||
if scheme.variant == "monochrome":
|
if scheme.variant == "monochrome":
|
||||||
colours[f"term{i}"] = grayscale(hct, light)
|
colours[f"term{i}"] = grayscale(hct, is_light)
|
||||||
else:
|
else:
|
||||||
colours[f"term{i}"] = harmonize(
|
colours[f"term{i}"] = harmonize(
|
||||||
hct, colours["primary_paletteKeyColor"], (0.35 if i < 8 else 0.2) * (-1 if light else 1)
|
hct, colours["primary_paletteKeyColor"], (0.35 if i < 8 else 0.2) * (-1 if is_light else 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
# Harmonize named colours
|
# Harmonize named colours
|
||||||
for i, hct in enumerate(light_catppuccin if light else dark_catppuccin):
|
for i, hct in enumerate(light_catppuccin if is_light else dark_catppuccin):
|
||||||
if scheme.variant == "monochrome":
|
if scheme.variant == "monochrome":
|
||||||
colours[colour_names[i]] = grayscale(hct, light)
|
colours[colour_names[i]] = grayscale(hct, is_light)
|
||||||
else:
|
else:
|
||||||
colours[colour_names[i]] = harmonize(hct, colours["primary_paletteKeyColor"], (-0.2 if light else 0.05))
|
colours[colour_names[i]] = harmonize(hct, colours["primary_paletteKeyColor"], (-0.2 if is_light else 0.05))
|
||||||
|
|
||||||
# KColours
|
# KColours
|
||||||
for colour in kcolours:
|
for colour in kcolours:
|
||||||
colours[colour["name"]] = harmonize(colour["hct"], colours["primary"], 0.1)
|
colours[colour["name"]] = harmonize(colour["hct"], colours["primary"], 0.1)
|
||||||
colours[f"{colour['name']}Selection"] = harmonize(colour["hct"], colours["onPrimaryFixedVariant"], 0.1)
|
colours[f"{colour['name']}Selection"] = harmonize(colour["hct"], colours["onPrimaryFixedVariant"], 0.1)
|
||||||
if scheme.variant == "monochrome":
|
if scheme.variant == "monochrome":
|
||||||
colours[colour["name"]] = grayscale(colours[colour["name"]], light)
|
colours[colour["name"]] = grayscale(colours[colour["name"]], is_light)
|
||||||
colours[f"{colour['name']}Selection"] = grayscale(colours[f"{colour['name']}Selection"], light)
|
colours[f"{colour['name']}Selection"] = grayscale(colours[f"{colour['name']}Selection"], is_light)
|
||||||
|
|
||||||
if scheme.variant == "neutral":
|
if scheme.variant == "neutral":
|
||||||
for name, hct in colours.items():
|
for name, hct in colours.items():
|
||||||
colours[name].chroma -= 15
|
colours[name].chroma -= 15
|
||||||
|
|
||||||
|
# Darken surfaces for hard flavour
|
||||||
|
if scheme.flavour == "hard":
|
||||||
|
for colour in "background", *(k for k in colours.keys() if k.startswith("surface")):
|
||||||
|
colours[colour] = lighten(colours[colour], 0.4) if is_light else darken(colours[colour], 0.8)
|
||||||
|
colours["term0"] = lighten(colours["term0"], 0.4) if is_light else darken(colours["term0"], 0.9)
|
||||||
|
|
||||||
# FIXME: deprecated stuff
|
# FIXME: deprecated stuff
|
||||||
colours["text"] = colours["onBackground"]
|
colours["text"] = colours["onBackground"]
|
||||||
colours["subtext1"] = colours["onSurfaceVariant"]
|
colours["subtext1"] = colours["onSurfaceVariant"]
|
||||||
@@ -219,13 +246,25 @@ def gen_scheme(scheme, primary: Hct) -> dict[str, str]:
|
|||||||
colours["mantle"] = darken(colours["surface"], 0.03)
|
colours["mantle"] = darken(colours["surface"], 0.03)
|
||||||
colours["crust"] = darken(colours["surface"], 0.05)
|
colours["crust"] = darken(colours["surface"], 0.05)
|
||||||
|
|
||||||
|
# More darkening if hard flavour
|
||||||
|
if scheme.flavour == "hard":
|
||||||
|
for colour in "base", "mantle", "crust":
|
||||||
|
colours[colour] = lighten(colours[colour], 0.4) if is_light else darken(colours[colour], 0.9)
|
||||||
|
for i in range(3):
|
||||||
|
colours[f"overlay{i}"] = (
|
||||||
|
lighten(colours[f"overlay{i}"], 0.4) if is_light else darken(colours[f"overlay{i}"], 0.8)
|
||||||
|
)
|
||||||
|
colours[f"surface{i}"] = (
|
||||||
|
lighten(colours[f"surface{i}"], 0.4) if is_light else darken(colours[f"surface{i}"], 0.8)
|
||||||
|
)
|
||||||
|
|
||||||
# For debugging
|
# For debugging
|
||||||
# print("\n".join(["{}: \x1b[48;2;{};{};{}m \x1b[0m".format(n, *c.to_rgba()[:3]) for n, c in colours.items()]))
|
# print("\n".join(["{}: \x1b[48;2;{};{};{}m \x1b[0m".format(n, *c.to_rgba()[:3]) for n, c in colours.items()]))
|
||||||
|
|
||||||
colours = {k: hex(v.to_int())[4:] for k, v in colours.items()}
|
colours = {k: hex(v.to_int())[4:] for k, v in colours.items()}
|
||||||
|
|
||||||
# Extended material
|
# Extended material
|
||||||
if light:
|
if is_light:
|
||||||
colours["success"] = "4F6354"
|
colours["success"] = "4F6354"
|
||||||
colours["onSuccess"] = "FFFFFF"
|
colours["onSuccess"] = "FFFFFF"
|
||||||
colours["successContainer"] = "D1E8D5"
|
colours["successContainer"] = "D1E8D5"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
def notify(*args: list[str]) -> str:
|
def notify(*args: str) -> str:
|
||||||
return subprocess.check_output(["notify-send", "-a", "caelestia-cli", *args], text=True).strip()
|
return subprocess.check_output(["notify-send", "-a", "caelestia-cli", *args], text=True).strip()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -4,41 +4,42 @@ import os
|
|||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
config_dir = Path(os.getenv("XDG_CONFIG_HOME", Path.home() / ".config"))
|
config_dir: Path = Path(os.getenv("XDG_CONFIG_HOME", Path.home() / ".config"))
|
||||||
data_dir = Path(os.getenv("XDG_DATA_HOME", Path.home() / ".local/share"))
|
data_dir: Path = Path(os.getenv("XDG_DATA_HOME", Path.home() / ".local/share"))
|
||||||
state_dir = Path(os.getenv("XDG_STATE_HOME", Path.home() / ".local/state"))
|
state_dir: Path = Path(os.getenv("XDG_STATE_HOME", Path.home() / ".local/state"))
|
||||||
cache_dir = Path(os.getenv("XDG_CACHE_HOME", Path.home() / ".cache"))
|
cache_dir: Path = Path(os.getenv("XDG_CACHE_HOME", Path.home() / ".cache"))
|
||||||
pictures_dir = Path(os.getenv("XDG_PICTURES_DIR", Path.home() / "Pictures"))
|
pictures_dir: Path = Path(os.getenv("XDG_PICTURES_DIR", Path.home() / "Pictures"))
|
||||||
videos_dir = Path(os.getenv("XDG_VIDEOS_DIR", Path.home() / "Videos"))
|
videos_dir: Path = Path(os.getenv("XDG_VIDEOS_DIR", Path.home() / "Videos"))
|
||||||
|
|
||||||
c_config_dir = config_dir / "caelestia"
|
c_config_dir: Path = config_dir / "caelestia"
|
||||||
c_data_dir = data_dir / "caelestia"
|
c_data_dir: Path = data_dir / "caelestia"
|
||||||
c_state_dir = state_dir / "caelestia"
|
c_state_dir: Path = state_dir / "caelestia"
|
||||||
c_cache_dir = cache_dir / "caelestia"
|
c_cache_dir: Path = cache_dir / "caelestia"
|
||||||
|
|
||||||
user_config_path = c_config_dir / "cli.json"
|
user_config_path: Path = c_config_dir / "cli.json"
|
||||||
cli_data_dir = Path(__file__).parent.parent / "data"
|
cli_data_dir: Path = Path(__file__).parent.parent / "data"
|
||||||
templates_dir = cli_data_dir / "templates"
|
templates_dir: Path = cli_data_dir / "templates"
|
||||||
user_templates_dir = c_config_dir / "templates"
|
user_templates_dir: Path = c_config_dir / "templates"
|
||||||
theme_dir = c_state_dir / "theme"
|
theme_dir: Path = c_state_dir / "theme"
|
||||||
|
|
||||||
scheme_path = c_state_dir / "scheme.json"
|
scheme_path: Path = c_state_dir / "scheme.json"
|
||||||
scheme_data_dir = cli_data_dir / "schemes"
|
scheme_data_dir: Path = cli_data_dir / "schemes"
|
||||||
scheme_cache_dir = c_cache_dir / "schemes"
|
scheme_cache_dir: Path = c_cache_dir / "schemes"
|
||||||
|
|
||||||
wallpapers_dir = os.getenv("CAELESTIA_WALLPAPERS_DIR", pictures_dir / "Wallpapers")
|
wallpapers_dir: Path = Path(os.getenv("CAELESTIA_WALLPAPERS_DIR", pictures_dir / "Wallpapers"))
|
||||||
wallpaper_path_path = c_state_dir / "wallpaper/path.txt"
|
wallpaper_path_path: Path = c_state_dir / "wallpaper/path.txt"
|
||||||
wallpaper_link_path = c_state_dir / "wallpaper/current"
|
wallpaper_link_path: Path = c_state_dir / "wallpaper/current"
|
||||||
wallpaper_thumbnail_path = c_state_dir / "wallpaper/thumbnail.jpg"
|
wallpaper_thumbnail_path: Path = c_state_dir / "wallpaper/thumbnail.jpg"
|
||||||
wallpapers_cache_dir = c_cache_dir / "wallpapers"
|
wallpapers_cache_dir: Path = c_cache_dir / "wallpapers"
|
||||||
|
|
||||||
screenshots_dir = os.getenv("CAELESTIA_SCREENSHOTS_DIR", pictures_dir / "Screenshots")
|
screenshots_dir: Path = Path(os.getenv("CAELESTIA_SCREENSHOTS_DIR", pictures_dir / "Screenshots"))
|
||||||
screenshots_cache_dir = c_cache_dir / "screenshots"
|
screenshots_cache_dir: Path = c_cache_dir / "screenshots"
|
||||||
|
|
||||||
recordings_dir = os.getenv("CAELESTIA_RECORDINGS_DIR", videos_dir / "Recordings")
|
recordings_dir: Path = Path(os.getenv("CAELESTIA_RECORDINGS_DIR", videos_dir / "Recordings"))
|
||||||
recording_path = c_state_dir / "record/recording.mp4"
|
recording_path: Path = c_state_dir / "record/recording.mp4"
|
||||||
recording_notif_path = c_state_dir / "record/notifid.txt"
|
recording_notif_path: Path = c_state_dir / "record/notifid.txt"
|
||||||
|
|
||||||
|
|
||||||
def compute_hash(path: Path | str) -> str:
|
def compute_hash(path: Path | str) -> str:
|
||||||
@@ -51,7 +52,7 @@ def compute_hash(path: Path | str) -> str:
|
|||||||
return sha.hexdigest()
|
return sha.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def atomic_dump(path: Path, content: dict[str, any]) -> None:
|
def atomic_dump(path: Path, content: dict[str, Any]) -> None:
|
||||||
with tempfile.NamedTemporaryFile("w") as f:
|
with tempfile.NamedTemporaryFile("w") as f:
|
||||||
json.dump(content, f)
|
json.dump(content, f)
|
||||||
f.flush()
|
f.flush()
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import json
|
import json
|
||||||
import random
|
import random
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from caelestia.utils.notify import notify
|
from caelestia.utils.notify import notify
|
||||||
from caelestia.utils.paths import atomic_dump, scheme_data_dir, scheme_path
|
from caelestia.utils.paths import atomic_dump, scheme_data_dir, scheme_path
|
||||||
@@ -14,19 +15,19 @@ class Scheme:
|
|||||||
_colours: dict[str, str]
|
_colours: dict[str, str]
|
||||||
notify: bool
|
notify: bool
|
||||||
|
|
||||||
def __init__(self, json: dict[str, any] | None) -> None:
|
def __init__(self, scheme_json: dict[str, Any] | None) -> None:
|
||||||
if json is None:
|
if scheme_json is None:
|
||||||
self._name = "catppuccin"
|
self._name = "catppuccin"
|
||||||
self._flavour = "mocha"
|
self._flavour = "mocha"
|
||||||
self._mode = "dark"
|
self._mode = "dark"
|
||||||
self._variant = "tonalspot"
|
self._variant = "tonalspot"
|
||||||
self._colours = read_colours_from_file(self.get_colours_path())
|
self._colours = read_colours_from_file(self.get_colours_path())
|
||||||
else:
|
else:
|
||||||
self._name = json["name"]
|
self._name = scheme_json["name"]
|
||||||
self._flavour = json["flavour"]
|
self._flavour = scheme_json["flavour"]
|
||||||
self._mode = json["mode"]
|
self._mode = scheme_json["mode"]
|
||||||
self._variant = json["variant"]
|
self._variant = scheme_json["variant"]
|
||||||
self._colours = json["colours"]
|
self._colours = scheme_json["colours"]
|
||||||
self.notify = False
|
self.notify = False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -196,7 +197,7 @@ scheme_variants = [
|
|||||||
"content",
|
"content",
|
||||||
]
|
]
|
||||||
|
|
||||||
scheme: Scheme = None
|
scheme: Scheme | None = None
|
||||||
|
|
||||||
|
|
||||||
def read_colours_from_file(path: Path) -> dict[str, str]:
|
def read_colours_from_file(path: Path) -> dict[str, str]:
|
||||||
@@ -225,18 +226,20 @@ def get_scheme_names() -> list[str]:
|
|||||||
return [*(f.name for f in scheme_data_dir.iterdir() if f.is_dir()), "dynamic"]
|
return [*(f.name for f in scheme_data_dir.iterdir() if f.is_dir()), "dynamic"]
|
||||||
|
|
||||||
|
|
||||||
def get_scheme_flavours(name: str = None) -> list[str]:
|
def get_scheme_flavours(name: str | None = None) -> list[str]:
|
||||||
if name is None:
|
if name is None:
|
||||||
name = get_scheme().name
|
name = get_scheme().name
|
||||||
|
|
||||||
return ["default"] if name == "dynamic" else [f.name for f in (scheme_data_dir / name).iterdir() if f.is_dir()]
|
return (
|
||||||
|
["default", "hard"] if name == "dynamic" else [f.name for f in (scheme_data_dir / name).iterdir() if f.is_dir()]
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_scheme_modes(name: str = None, flavour: str = None) -> list[str]:
|
def get_scheme_modes(name: str | None = None, flavour: str | None = None) -> list[str]:
|
||||||
if name is None:
|
if name is None or flavour is None:
|
||||||
scheme = get_scheme()
|
scheme = get_scheme()
|
||||||
name = scheme.name
|
name = name or scheme.name
|
||||||
flavour = scheme.flavour
|
flavour = flavour or scheme.flavour
|
||||||
|
|
||||||
if name == "dynamic":
|
if name == "dynamic":
|
||||||
return ["light", "dark"]
|
return ["light", "dark"]
|
||||||
|
|||||||
+288
-69
@@ -1,6 +1,10 @@
|
|||||||
|
import fcntl
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import tempfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from caelestia.utils.colour import get_dynamic_colours
|
from caelestia.utils.colour import get_dynamic_colours
|
||||||
@@ -14,6 +18,8 @@ from caelestia.utils.paths import (
|
|||||||
user_config_path,
|
user_config_path,
|
||||||
user_templates_dir,
|
user_templates_dir,
|
||||||
)
|
)
|
||||||
|
from caelestia.utils.scheme import get_scheme
|
||||||
|
from caelestia.utils.hypr import is_lua_config
|
||||||
|
|
||||||
|
|
||||||
def gen_conf(colours: dict[str, str]) -> str:
|
def gen_conf(colours: dict[str, str]) -> str:
|
||||||
@@ -22,6 +28,12 @@ def gen_conf(colours: dict[str, str]) -> str:
|
|||||||
conf += f"${name} = {colour}\n"
|
conf += f"${name} = {colour}\n"
|
||||||
return conf
|
return conf
|
||||||
|
|
||||||
|
def gen_lua(colours: dict[str, str]) -> str:
|
||||||
|
lua = "return {\n"
|
||||||
|
for name, colour in colours.items():
|
||||||
|
lua += f' {name} = "{colour}",\n'
|
||||||
|
lua += "}"
|
||||||
|
return lua
|
||||||
|
|
||||||
def gen_scss(colours: dict[str, str]) -> str:
|
def gen_scss(colours: dict[str, str]) -> str:
|
||||||
scss = ""
|
scss = ""
|
||||||
@@ -31,13 +43,13 @@ def gen_scss(colours: dict[str, str]) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def gen_replace(colours: dict[str, str], template: Path, hash: bool = False) -> str:
|
def gen_replace(colours: dict[str, str], template: Path, hash: bool = False) -> str:
|
||||||
template = template.read_text()
|
new_template = template.read_text()
|
||||||
for name, colour in colours.items():
|
for name, colour in colours.items():
|
||||||
template = template.replace(f"{{{{ ${name} }}}}", f"#{colour}" if hash else colour)
|
new_template = new_template.replace(f"{{{{ ${name} }}}}", f"#{colour}" if hash else colour)
|
||||||
return template
|
return new_template
|
||||||
|
|
||||||
|
|
||||||
def gen_replace_dynamic(colours: dict[str, str], template: Path) -> str:
|
def gen_replace_dynamic(colours: dict[str, str], template: Path, mode: str) -> str:
|
||||||
def fill_colour(match: re.Match) -> str:
|
def fill_colour(match: re.Match) -> str:
|
||||||
data = match.group(1).strip().split(".")
|
data = match.group(1).strip().split(".")
|
||||||
if len(data) != 2:
|
if len(data) != 2:
|
||||||
@@ -48,15 +60,21 @@ def gen_replace_dynamic(colours: dict[str, str], template: Path) -> str:
|
|||||||
return getattr(colours_dyn[col], form)
|
return getattr(colours_dyn[col], form)
|
||||||
|
|
||||||
# match atomic {{ . }} pairs
|
# match atomic {{ . }} pairs
|
||||||
field = r"\{\{((?:(?!\{\{|\}\}).)*)\}\}"
|
dotField = r"\{\{((?:(?!\{\{|\}\}).)*)\}\}"
|
||||||
|
|
||||||
|
# match {{ mode }}
|
||||||
|
modeField = r"\{\{\s*mode\s*\}\}"
|
||||||
|
|
||||||
colours_dyn = get_dynamic_colours(colours)
|
colours_dyn = get_dynamic_colours(colours)
|
||||||
template_content = template.read_text()
|
template_content = template.read_text()
|
||||||
template_filled = re.sub(field, fill_colour, template_content)
|
|
||||||
|
template_filled = re.sub(dotField, fill_colour, template_content)
|
||||||
|
template_filled = re.sub(modeField, mode, template_filled)
|
||||||
|
|
||||||
return template_filled
|
return template_filled
|
||||||
|
|
||||||
|
|
||||||
def c2s(c: str, *i: list[int]) -> str:
|
def hex_to_ansi(c: str, *i: int) -> str:
|
||||||
"""Hex to ANSI sequence (e.g. ffffff, 11 -> \x1b]11;rgb:ff/ff/ff\x1b\\)"""
|
"""Hex to ANSI sequence (e.g. ffffff, 11 -> \x1b]11;rgb:ff/ff/ff\x1b\\)"""
|
||||||
return f"\x1b]{';'.join(map(str, i))};rgb:{c[0:2]}/{c[2:4]}/{c[4:6]}\x1b\\"
|
return f"\x1b]{';'.join(map(str, i))};rgb:{c[0:2]}/{c[2:4]}/{c[4:6]}\x1b\\"
|
||||||
|
|
||||||
@@ -73,35 +91,39 @@ def gen_sequences(colours: dict[str, str]) -> str:
|
|||||||
16+: 256 colours
|
16+: 256 colours
|
||||||
"""
|
"""
|
||||||
return (
|
return (
|
||||||
c2s(colours["onSurface"], 10)
|
hex_to_ansi(colours["onSurface"], 10)
|
||||||
+ c2s(colours["surface"], 11)
|
+ hex_to_ansi(colours["surface"], 11)
|
||||||
+ c2s(colours["secondary"], 12)
|
+ hex_to_ansi(colours["secondary"], 12)
|
||||||
+ c2s(colours["secondary"], 17)
|
+ hex_to_ansi(colours["secondary"], 17)
|
||||||
+ c2s(colours["term0"], 4, 0)
|
+ hex_to_ansi(colours["term0"], 4, 0)
|
||||||
+ c2s(colours["term1"], 4, 1)
|
+ hex_to_ansi(colours["term1"], 4, 1)
|
||||||
+ c2s(colours["term2"], 4, 2)
|
+ hex_to_ansi(colours["term2"], 4, 2)
|
||||||
+ c2s(colours["term3"], 4, 3)
|
+ hex_to_ansi(colours["term3"], 4, 3)
|
||||||
+ c2s(colours["term4"], 4, 4)
|
+ hex_to_ansi(colours["term4"], 4, 4)
|
||||||
+ c2s(colours["term5"], 4, 5)
|
+ hex_to_ansi(colours["term5"], 4, 5)
|
||||||
+ c2s(colours["term6"], 4, 6)
|
+ hex_to_ansi(colours["term6"], 4, 6)
|
||||||
+ c2s(colours["term7"], 4, 7)
|
+ hex_to_ansi(colours["term7"], 4, 7)
|
||||||
+ c2s(colours["term8"], 4, 8)
|
+ hex_to_ansi(colours["term8"], 4, 8)
|
||||||
+ c2s(colours["term9"], 4, 9)
|
+ hex_to_ansi(colours["term9"], 4, 9)
|
||||||
+ c2s(colours["term10"], 4, 10)
|
+ hex_to_ansi(colours["term10"], 4, 10)
|
||||||
+ c2s(colours["term11"], 4, 11)
|
+ hex_to_ansi(colours["term11"], 4, 11)
|
||||||
+ c2s(colours["term12"], 4, 12)
|
+ hex_to_ansi(colours["term12"], 4, 12)
|
||||||
+ c2s(colours["term13"], 4, 13)
|
+ hex_to_ansi(colours["term13"], 4, 13)
|
||||||
+ c2s(colours["term14"], 4, 14)
|
+ hex_to_ansi(colours["term14"], 4, 14)
|
||||||
+ c2s(colours["term15"], 4, 15)
|
+ hex_to_ansi(colours["term15"], 4, 15)
|
||||||
+ c2s(colours["primary"], 4, 16)
|
+ hex_to_ansi(colours["primary"], 4, 16)
|
||||||
+ c2s(colours["secondary"], 4, 17)
|
+ hex_to_ansi(colours["secondary"], 4, 17)
|
||||||
+ c2s(colours["tertiary"], 4, 18)
|
+ hex_to_ansi(colours["tertiary"], 4, 18)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def write_file(path: Path, content: str) -> None:
|
def write_file(path: Path, content: str) -> None:
|
||||||
path.parent.mkdir(parents=True, exist_ok=True)
|
path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
path.write_text(content)
|
|
||||||
|
with tempfile.NamedTemporaryFile("w") as f:
|
||||||
|
f.write(content)
|
||||||
|
f.flush()
|
||||||
|
shutil.move(f.name, path)
|
||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
@@ -114,15 +136,23 @@ def apply_terms(sequences: str) -> None:
|
|||||||
for pt in pts_path.iterdir():
|
for pt in pts_path.iterdir():
|
||||||
if pt.name.isdigit():
|
if pt.name.isdigit():
|
||||||
try:
|
try:
|
||||||
with pt.open("a") as f:
|
# Use non-blocking write with timeout to prevent hangs
|
||||||
f.write(sequences)
|
import os
|
||||||
except PermissionError:
|
|
||||||
|
fd = os.open(str(pt), os.O_WRONLY | os.O_NONBLOCK | os.O_NOCTTY)
|
||||||
|
try:
|
||||||
|
os.write(fd, sequences.encode())
|
||||||
|
finally:
|
||||||
|
os.close(fd)
|
||||||
|
except (PermissionError, OSError, BlockingIOError):
|
||||||
|
# Skip terminals that are busy, closed, or inaccessible
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
def apply_hypr(conf: str) -> None:
|
def apply_hypr(conf: str) -> None:
|
||||||
write_file(config_dir / "hypr/scheme/current.conf", conf)
|
ext = "lua" if is_lua_config() else "conf"
|
||||||
|
write_file(config_dir / f"hypr/scheme/current.{ext}", conf)
|
||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
@@ -137,6 +167,13 @@ def apply_discord(scss: str) -> None:
|
|||||||
write_file(config_dir / client / "themes/caelestia.theme.css", conf)
|
write_file(config_dir / client / "themes/caelestia.theme.css", conf)
|
||||||
|
|
||||||
|
|
||||||
|
@log_exception
|
||||||
|
def apply_pandora(colours: dict[str, str], mode: str) -> None:
|
||||||
|
template = gen_replace(colours, templates_dir / "pandora.json", hash=True)
|
||||||
|
template = template.replace("{{ $mode }}", mode)
|
||||||
|
write_file(data_dir / "PandoraLauncher/themes/caelestia.json", template)
|
||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
def apply_spicetify(colours: dict[str, str], mode: str) -> None:
|
def apply_spicetify(colours: dict[str, str], mode: str) -> None:
|
||||||
template = gen_replace(colours, templates_dir / f"spicetify-{mode}.ini")
|
template = gen_replace(colours, templates_dir / f"spicetify-{mode}.ini")
|
||||||
@@ -169,42 +206,139 @@ def apply_htop(colours: dict[str, str]) -> None:
|
|||||||
subprocess.run(["killall", "-USR2", "htop"], stderr=subprocess.DEVNULL)
|
subprocess.run(["killall", "-USR2", "htop"], stderr=subprocess.DEVNULL)
|
||||||
|
|
||||||
|
|
||||||
|
def sync_papirus_colors(hex_color: str) -> None:
|
||||||
|
"""Sync Papirus folder icon colors using hue/saturation analysis"""
|
||||||
|
try:
|
||||||
|
result = subprocess.run(["which", "papirus-folders"], capture_output=True, check=False)
|
||||||
|
if result.returncode != 0:
|
||||||
|
return
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
|
||||||
|
papirus_paths = [
|
||||||
|
Path("/usr/share/icons/Papirus"),
|
||||||
|
Path("/usr/share/icons/Papirus-Dark"),
|
||||||
|
Path.home() / ".local/share/icons/Papirus",
|
||||||
|
Path.home() / ".icons/Papirus",
|
||||||
|
]
|
||||||
|
|
||||||
|
if not any(p.exists() for p in papirus_paths):
|
||||||
|
return
|
||||||
|
|
||||||
|
r = int(hex_color[0:2], 16)
|
||||||
|
g = int(hex_color[2:4], 16)
|
||||||
|
b = int(hex_color[4:6], 16)
|
||||||
|
|
||||||
|
# Brightness and saturation
|
||||||
|
max_val = max(r, g, b)
|
||||||
|
min_val = min(r, g, b)
|
||||||
|
brightness = max_val
|
||||||
|
saturation = 0 if max_val == 0 else ((max_val - min_val) * 100) // max_val
|
||||||
|
|
||||||
|
# Low saturation = grayscale
|
||||||
|
if saturation < 20:
|
||||||
|
if brightness < 85:
|
||||||
|
color = "black"
|
||||||
|
elif brightness < 170:
|
||||||
|
color = "grey"
|
||||||
|
else:
|
||||||
|
color = "white"
|
||||||
|
# Medium-low saturation with high brightness = pale variants
|
||||||
|
elif saturation < 60 and brightness > 180:
|
||||||
|
use_pale = True
|
||||||
|
color = _determine_hue_color(r, g, b, brightness, use_pale)
|
||||||
|
else:
|
||||||
|
color = _determine_hue_color(r, g, b, brightness, False)
|
||||||
|
|
||||||
|
try:
|
||||||
|
subprocess.Popen(
|
||||||
|
["sudo", "-n", "papirus-folders", "-C", color, "-u"],
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
start_new_session=True,
|
||||||
|
)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def _determine_hue_color(r: int, g: int, b: int, brightness: int, use_pale: bool) -> str:
|
||||||
|
if b > r and b > g:
|
||||||
|
# Blue dominant
|
||||||
|
r_ratio = (r * 100) // b if b > 0 else 0
|
||||||
|
g_ratio = (g * 100) // b if b > 0 else 0
|
||||||
|
rg_diff = abs(r - g)
|
||||||
|
|
||||||
|
if r_ratio > 70 and g_ratio > 70:
|
||||||
|
# Both R and G high relative to B = light blue/periwinkle
|
||||||
|
if rg_diff < 15:
|
||||||
|
return "blue"
|
||||||
|
elif r > g:
|
||||||
|
return "violet"
|
||||||
|
else:
|
||||||
|
return "cyan"
|
||||||
|
elif r_ratio > 60 and r > g:
|
||||||
|
return "violet"
|
||||||
|
elif g_ratio > 60 and g > r:
|
||||||
|
return "cyan"
|
||||||
|
else:
|
||||||
|
return "blue"
|
||||||
|
elif r > g and r > b:
|
||||||
|
# Red dominant
|
||||||
|
if g > b + 30:
|
||||||
|
# Orange/yellow-ish/brown
|
||||||
|
rg_ratio = (g * 100) // r if r > 0 else 0
|
||||||
|
if use_pale:
|
||||||
|
if rg_ratio > 70 and brightness < 220:
|
||||||
|
return "palebrown"
|
||||||
|
else:
|
||||||
|
return "paleorange"
|
||||||
|
else:
|
||||||
|
if rg_ratio > 70 and brightness < 180:
|
||||||
|
return "brown"
|
||||||
|
else:
|
||||||
|
return "orange"
|
||||||
|
elif b > g + 20:
|
||||||
|
return "pink"
|
||||||
|
else:
|
||||||
|
return "pink" if use_pale else "red"
|
||||||
|
elif g > r and g > b:
|
||||||
|
# Green dominant
|
||||||
|
if r > b + 30:
|
||||||
|
return "yellow"
|
||||||
|
else:
|
||||||
|
return "green"
|
||||||
|
else:
|
||||||
|
return "grey"
|
||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
def apply_gtk(colours: dict[str, str], mode: str) -> None:
|
def apply_gtk(colours: dict[str, str], mode: str, icon_theme: str | None = None) -> None:
|
||||||
template = gen_replace(colours, templates_dir / "gtk.css", hash=True)
|
gtk_template = gen_replace(colours, templates_dir / "gtk.css", hash=True)
|
||||||
write_file(config_dir / "gtk-3.0/gtk.css", template)
|
thunar_template = gen_replace(colours, templates_dir / "thunar.css", hash=True)
|
||||||
write_file(config_dir / "gtk-4.0/gtk.css", template)
|
|
||||||
|
for gtk_version in ["gtk-3.0", "gtk-4.0"]:
|
||||||
|
gtk_config_dir = config_dir / gtk_version
|
||||||
|
write_file(gtk_config_dir / "gtk.css", gtk_template)
|
||||||
|
write_file(gtk_config_dir / "thunar.css", thunar_template)
|
||||||
|
|
||||||
subprocess.run(["dconf", "write", "/org/gnome/desktop/interface/gtk-theme", "'adw-gtk3-dark'"])
|
subprocess.run(["dconf", "write", "/org/gnome/desktop/interface/gtk-theme", "'adw-gtk3-dark'"])
|
||||||
subprocess.run(["dconf", "write", "/org/gnome/desktop/interface/color-scheme", f"'prefer-{mode}'"])
|
subprocess.run(["dconf", "write", "/org/gnome/desktop/interface/color-scheme", f"'prefer-{mode}'"])
|
||||||
subprocess.run(["dconf", "write", "/org/gnome/desktop/interface/icon-theme", f"'Papirus-{mode.capitalize()}'"])
|
gtk_icon_theme = icon_theme if icon_theme is not None else f"Papirus-{mode.capitalize()}"
|
||||||
|
subprocess.run(["dconf", "write", "/org/gnome/desktop/interface/icon-theme", f"'{gtk_icon_theme}'"])
|
||||||
|
|
||||||
|
sync_papirus_colors(colours["primary"])
|
||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
def apply_qt(colours: dict[str, str], mode: str) -> None:
|
def apply_qt(colours: dict[str, str], mode: str, icon_theme: str | None = None) -> None:
|
||||||
template = gen_replace(colours, templates_dir / f"qt{mode}.colors", hash=True)
|
colours = gen_replace(colours, templates_dir / f"qt{mode}.colors", hash=True)
|
||||||
write_file(config_dir / "qt5ct/colors/caelestia.colors", template)
|
write_file(config_dir / "qtengine/caelestia.colors", colours)
|
||||||
write_file(config_dir / "qt6ct/colors/caelestia.colors", template)
|
|
||||||
|
|
||||||
qtct = (templates_dir / "qtct.conf").read_text()
|
config = (templates_dir / "qtengine.json").read_text()
|
||||||
qtct = qtct.replace("{{ $mode }}", mode.capitalize())
|
config = config.replace("{{ $mode }}", mode.capitalize())
|
||||||
|
if icon_theme is not None:
|
||||||
for ver in 5, 6:
|
config = config.replace(f'"iconTheme": "Papirus-{mode.capitalize()}"', f'"iconTheme": "{icon_theme}"')
|
||||||
conf = qtct.replace("{{ $config }}", str(config_dir / f"qt{ver}ct"))
|
write_file(config_dir / "qtengine/config.json", config)
|
||||||
|
|
||||||
if ver == 5:
|
|
||||||
conf += """
|
|
||||||
[Fonts]
|
|
||||||
fixed="Monospace,12,-1,5,50,0,0,0,0,0"
|
|
||||||
general="Sans Serif,12,-1,5,50,0,0,0,0,0"
|
|
||||||
"""
|
|
||||||
else:
|
|
||||||
conf += """
|
|
||||||
[Fonts]
|
|
||||||
fixed="Monospace,12,-1,5,400,0,0,0,0,0,0,0,0,0,0,1"
|
|
||||||
general="Sans Serif,12,-1,5,400,0,0,0,0,0,0,0,0,0,0,1"
|
|
||||||
"""
|
|
||||||
write_file(config_dir / f"qt{ver}ct/qt{ver}ct.conf", conf)
|
|
||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
@@ -216,6 +350,51 @@ def apply_warp(colours: dict[str, str], mode: str) -> None:
|
|||||||
write_file(data_dir / "warp-terminal/themes/caelestia.yaml", template)
|
write_file(data_dir / "warp-terminal/themes/caelestia.yaml", template)
|
||||||
|
|
||||||
|
|
||||||
|
@log_exception
|
||||||
|
def apply_chromium(colours: dict[str, str]) -> None:
|
||||||
|
surface_hex = colours["surface"]
|
||||||
|
theme_color = f"#{surface_hex}"
|
||||||
|
browsers = [
|
||||||
|
("chromium", Path("/etc/chromium/policies/managed")),
|
||||||
|
("brave", Path("/etc/brave/policies/managed")),
|
||||||
|
("google-chrome-stable", Path("/etc/opt/chrome/policies/managed")),
|
||||||
|
]
|
||||||
|
|
||||||
|
for cmd, policy_dir in browsers:
|
||||||
|
if shutil.which(cmd) is None:
|
||||||
|
continue
|
||||||
|
if not policy_dir.is_dir():
|
||||||
|
subprocess.run(["sudo", "-n", "mkdir", "-p", str(policy_dir)], stderr=subprocess.DEVNULL)
|
||||||
|
if not policy_dir.is_dir():
|
||||||
|
print(f"Unable to create {policy_dir} directory")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Use tee instead of write_file cause we need sudo
|
||||||
|
subprocess.run(
|
||||||
|
["sudo", "-n", "tee", str(policy_dir / "caelestia.json")],
|
||||||
|
input=json.dumps({"BrowserThemeColor": theme_color, "BrowserColorScheme": "device"}),
|
||||||
|
text=True,
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
subprocess.run(
|
||||||
|
[cmd, "--refresh-platform-policy", "--no-startup-window"],
|
||||||
|
stdout=subprocess.DEVNULL,
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def apply_zed(colours: dict[str, str], mode: str) -> None:
|
||||||
|
theme_path = config_dir / "zed/themes/caelestia.json"
|
||||||
|
# Zed's file watcher does not detect changes through symlinks,
|
||||||
|
# so resolve to a regular file before writing
|
||||||
|
if theme_path.is_symlink():
|
||||||
|
theme_path.unlink()
|
||||||
|
|
||||||
|
content = gen_replace_dynamic(colours, templates_dir / "zed.json", mode)
|
||||||
|
write_file(theme_path, content)
|
||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
def apply_cava(colours: dict[str, str]) -> None:
|
def apply_cava(colours: dict[str, str]) -> None:
|
||||||
template = gen_replace(colours, templates_dir / "cava.conf", hash=True)
|
template = gen_replace(colours, templates_dir / "cava.conf", hash=True)
|
||||||
@@ -224,17 +403,28 @@ def apply_cava(colours: dict[str, str]) -> None:
|
|||||||
|
|
||||||
|
|
||||||
@log_exception
|
@log_exception
|
||||||
def apply_user_templates(colours: dict[str, str]) -> None:
|
def apply_user_templates(colours: dict[str, str], mode: str) -> None:
|
||||||
if not user_templates_dir.is_dir():
|
if not user_templates_dir.is_dir():
|
||||||
return
|
return
|
||||||
|
|
||||||
for file in user_templates_dir.iterdir():
|
for file in user_templates_dir.iterdir():
|
||||||
if file.is_file():
|
if file.is_file():
|
||||||
content = gen_replace_dynamic(colours, file)
|
content = gen_replace_dynamic(colours, file, mode)
|
||||||
write_file(theme_dir / file.name, content)
|
write_file(theme_dir / file.name, content)
|
||||||
|
|
||||||
|
|
||||||
def apply_colours(colours: dict[str, str], mode: str) -> None:
|
def apply_colours(colours: dict[str, str], mode: str) -> None:
|
||||||
|
# Use file-based lock to prevent concurrent theme changes
|
||||||
|
lock_file = c_state_dir / "theme.lock"
|
||||||
|
c_state_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(lock_file, "w") as lock_fd:
|
||||||
|
try:
|
||||||
|
fcntl.flock(lock_fd.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB)
|
||||||
|
except BlockingIOError:
|
||||||
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cfg = json.loads(user_config_path.read_text())["theme"]
|
cfg = json.loads(user_config_path.read_text())["theme"]
|
||||||
except (FileNotFoundError, json.JSONDecodeError, KeyError):
|
except (FileNotFoundError, json.JSONDecodeError, KeyError):
|
||||||
@@ -246,11 +436,13 @@ def apply_colours(colours: dict[str, str], mode: str) -> None:
|
|||||||
if check("enableTerm"):
|
if check("enableTerm"):
|
||||||
apply_terms(gen_sequences(colours))
|
apply_terms(gen_sequences(colours))
|
||||||
if check("enableHypr"):
|
if check("enableHypr"):
|
||||||
apply_hypr(gen_conf(colours))
|
apply_hypr(gen_lua(colours) if is_lua_config() else gen_conf(colours))
|
||||||
if check("enableDiscord"):
|
if check("enableDiscord"):
|
||||||
apply_discord(gen_scss(colours))
|
apply_discord(gen_scss(colours))
|
||||||
if check("enableSpicetify"):
|
if check("enableSpicetify"):
|
||||||
apply_spicetify(colours, mode)
|
apply_spicetify(colours, mode)
|
||||||
|
if check("enablePandora"):
|
||||||
|
apply_pandora(colours, mode)
|
||||||
if check("enableFuzzel"):
|
if check("enableFuzzel"):
|
||||||
apply_fuzzel(colours)
|
apply_fuzzel(colours)
|
||||||
if check("enableBtop"):
|
if check("enableBtop"):
|
||||||
@@ -259,12 +451,39 @@ def apply_colours(colours: dict[str, str], mode: str) -> None:
|
|||||||
apply_nvtop(colours)
|
apply_nvtop(colours)
|
||||||
if check("enableHtop"):
|
if check("enableHtop"):
|
||||||
apply_htop(colours)
|
apply_htop(colours)
|
||||||
|
icon_theme = cfg.get(f"iconTheme{mode.capitalize()}") or cfg.get("iconTheme")
|
||||||
if check("enableGtk"):
|
if check("enableGtk"):
|
||||||
apply_gtk(colours, mode)
|
apply_gtk(colours, mode, icon_theme)
|
||||||
if check("enableQt"):
|
if check("enableQt"):
|
||||||
apply_qt(colours, mode)
|
apply_qt(colours, mode, icon_theme)
|
||||||
if check("enableWarp"):
|
if check("enableWarp"):
|
||||||
apply_warp(colours, mode)
|
apply_warp(colours, mode)
|
||||||
|
if check("enableChromium"):
|
||||||
|
apply_chromium(colours)
|
||||||
|
if check("enableZed"):
|
||||||
|
apply_zed(colours, mode)
|
||||||
if check("enableCava"):
|
if check("enableCava"):
|
||||||
apply_cava(colours)
|
apply_cava(colours)
|
||||||
apply_user_templates(colours)
|
apply_user_templates(colours, mode)
|
||||||
|
|
||||||
|
if post_hook := cfg.get("postHook"):
|
||||||
|
scheme = get_scheme()
|
||||||
|
subprocess.run(
|
||||||
|
post_hook,
|
||||||
|
shell=True,
|
||||||
|
env={
|
||||||
|
**os.environ,
|
||||||
|
"SCHEME_NAME": scheme.name,
|
||||||
|
"SCHEME_FLAVOUR": scheme.flavour,
|
||||||
|
"SCHEME_MODE": scheme.mode,
|
||||||
|
"SCHEME_VARIANT": scheme.variant,
|
||||||
|
"SCHEME_COLOURS": json.dumps(scheme.colours),
|
||||||
|
},
|
||||||
|
stderr=subprocess.DEVNULL,
|
||||||
|
)
|
||||||
|
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
lock_file.unlink()
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|||||||
@@ -2,8 +2,10 @@ import json
|
|||||||
import os
|
import os
|
||||||
import random
|
import random
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
from argparse import Namespace
|
from argparse import Namespace
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import cast
|
||||||
|
|
||||||
from materialyoucolor.hct import Hct
|
from materialyoucolor.hct import Hct
|
||||||
from materialyoucolor.utils.color_utils import argb_from_rgb
|
from materialyoucolor.utils.color_utils import argb_from_rgb
|
||||||
@@ -11,6 +13,7 @@ from PIL import Image
|
|||||||
|
|
||||||
from caelestia.utils.hypr import message
|
from caelestia.utils.hypr import message
|
||||||
from caelestia.utils.material import get_colours_for_image
|
from caelestia.utils.material import get_colours_for_image
|
||||||
|
from caelestia.utils.colourfulness import get_variant
|
||||||
from caelestia.utils.paths import (
|
from caelestia.utils.paths import (
|
||||||
compute_hash,
|
compute_hash,
|
||||||
user_config_path,
|
user_config_path,
|
||||||
@@ -24,7 +27,7 @@ from caelestia.utils.theme import apply_colours
|
|||||||
|
|
||||||
|
|
||||||
def is_valid_image(path: Path) -> bool:
|
def is_valid_image(path: Path) -> bool:
|
||||||
return path.is_file() and path.suffix in [".jpg", ".jpeg", ".png", ".webp", ".tif", ".tiff"]
|
return path.is_file() and path.suffix in [".jpg", ".jpeg", ".png", ".webp", ".tif", ".tiff", ".gif"]
|
||||||
|
|
||||||
|
|
||||||
def check_wall(wall: Path, filter_size: tuple[int, int], threshold: float) -> bool:
|
def check_wall(wall: Path, filter_size: tuple[int, int], threshold: float) -> bool:
|
||||||
@@ -33,7 +36,7 @@ def check_wall(wall: Path, filter_size: tuple[int, int], threshold: float) -> bo
|
|||||||
return width >= filter_size[0] * threshold and height >= filter_size[1] * threshold
|
return width >= filter_size[0] * threshold and height >= filter_size[1] * threshold
|
||||||
|
|
||||||
|
|
||||||
def get_wallpaper() -> str:
|
def get_wallpaper() -> str | None:
|
||||||
try:
|
try:
|
||||||
return wallpaper_path_path.read_text()
|
return wallpaper_path_path.read_text()
|
||||||
except IOError:
|
except IOError:
|
||||||
@@ -41,16 +44,16 @@ def get_wallpaper() -> str:
|
|||||||
|
|
||||||
|
|
||||||
def get_wallpapers(args: Namespace) -> list[Path]:
|
def get_wallpapers(args: Namespace) -> list[Path]:
|
||||||
dir = Path(args.random)
|
directory = Path(args.random)
|
||||||
if not dir.is_dir():
|
if not directory.is_dir():
|
||||||
return []
|
return []
|
||||||
|
|
||||||
walls = [f for f in dir.rglob("*") if is_valid_image(f)]
|
walls = [f for f in directory.rglob("*") if is_valid_image(f)]
|
||||||
|
|
||||||
if args.no_filter:
|
if args.no_filter:
|
||||||
return walls
|
return walls
|
||||||
|
|
||||||
monitors = message("monitors")
|
monitors = cast(list[dict[str, int]], message("monitors"))
|
||||||
filter_size = min(m["width"] for m in monitors), min(m["height"] for m in monitors)
|
filter_size = min(m["width"] for m in monitors), min(m["height"] for m in monitors)
|
||||||
|
|
||||||
return [f for f in walls if check_wall(f, filter_size, args.threshold)]
|
return [f for f in walls if check_wall(f, filter_size, args.threshold)]
|
||||||
@@ -62,14 +65,14 @@ def get_thumb(wall: Path, cache: Path) -> Path:
|
|||||||
if not thumb.exists():
|
if not thumb.exists():
|
||||||
with Image.open(wall) as img:
|
with Image.open(wall) as img:
|
||||||
img = img.convert("RGB")
|
img = img.convert("RGB")
|
||||||
img.thumbnail((128, 128), Image.NEAREST)
|
img.thumbnail((128, 128), Image.Resampling.NEAREST)
|
||||||
thumb.parent.mkdir(parents=True, exist_ok=True)
|
thumb.parent.mkdir(parents=True, exist_ok=True)
|
||||||
img.save(thumb, "JPEG")
|
img.save(thumb, "JPEG")
|
||||||
|
|
||||||
return thumb
|
return thumb
|
||||||
|
|
||||||
|
|
||||||
def get_smart_opts(wall: Path, cache: Path) -> str:
|
def get_smart_opts(wall: Path, cache: Path) -> dict:
|
||||||
opts_cache = cache / "smart.json"
|
opts_cache = cache / "smart.json"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -77,15 +80,16 @@ def get_smart_opts(wall: Path, cache: Path) -> str:
|
|||||||
except (IOError, json.JSONDecodeError):
|
except (IOError, json.JSONDecodeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from caelestia.utils.colourfulness import get_variant
|
|
||||||
|
|
||||||
opts = {}
|
opts = {}
|
||||||
|
|
||||||
with Image.open(get_thumb(wall, cache)) as img:
|
with Image.open(get_thumb(wall, cache)) as img:
|
||||||
opts["variant"] = get_variant(img)
|
opts["variant"] = get_variant(img)
|
||||||
|
img.thumbnail((1, 1), Image.Resampling.LANCZOS)
|
||||||
|
|
||||||
|
# Cast the pixel to a tuple of 3 integers to safely unpack it
|
||||||
|
pixel = cast(tuple[int, int, int], img.getpixel((0, 0)))
|
||||||
|
hct = Hct.from_int(argb_from_rgb(*pixel))
|
||||||
|
|
||||||
img.thumbnail((1, 1), Image.LANCZOS)
|
|
||||||
hct = Hct.from_int(argb_from_rgb(*img.getpixel((0, 0))))
|
|
||||||
opts["mode"] = "light" if hct.tone > 60 else "dark"
|
opts["mode"] = "light" if hct.tone > 60 else "dark"
|
||||||
|
|
||||||
opts_cache.parent.mkdir(parents=True, exist_ok=True)
|
opts_cache.parent.mkdir(parents=True, exist_ok=True)
|
||||||
@@ -96,9 +100,13 @@ def get_smart_opts(wall: Path, cache: Path) -> str:
|
|||||||
|
|
||||||
|
|
||||||
def get_colours_for_wall(wall: Path | str, no_smart: bool) -> None:
|
def get_colours_for_wall(wall: Path | str, no_smart: bool) -> None:
|
||||||
|
wall = Path(wall)
|
||||||
scheme = get_scheme()
|
scheme = get_scheme()
|
||||||
cache = wallpapers_cache_dir / compute_hash(wall)
|
cache = wallpapers_cache_dir / compute_hash(wall)
|
||||||
|
|
||||||
|
if wall.suffix.lower() == ".gif":
|
||||||
|
wall = convert_gif(wall)
|
||||||
|
|
||||||
name = "dynamic"
|
name = "dynamic"
|
||||||
|
|
||||||
if not no_smart:
|
if not no_smart:
|
||||||
@@ -106,7 +114,7 @@ def get_colours_for_wall(wall: Path | str, no_smart: bool) -> None:
|
|||||||
scheme = Scheme(
|
scheme = Scheme(
|
||||||
{
|
{
|
||||||
"name": name,
|
"name": name,
|
||||||
"flavour": "default",
|
"flavour": scheme.flavour,
|
||||||
"mode": smart_opts["mode"],
|
"mode": smart_opts["mode"],
|
||||||
"variant": smart_opts["variant"],
|
"variant": smart_opts["variant"],
|
||||||
"colours": scheme.colours,
|
"colours": scheme.colours,
|
||||||
@@ -115,20 +123,41 @@ def get_colours_for_wall(wall: Path | str, no_smart: bool) -> None:
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
"name": name,
|
"name": name,
|
||||||
"flavour": "default",
|
"flavour": scheme.flavour,
|
||||||
"mode": scheme.mode,
|
"mode": scheme.mode,
|
||||||
"variant": scheme.variant,
|
"variant": scheme.variant,
|
||||||
"colours": get_colours_for_image(get_thumb(wall, cache), scheme),
|
"colours": get_colours_for_image(get_thumb(wall, cache), scheme),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def set_wallpaper(wall: Path | str, no_smart: bool) -> None:
|
def convert_gif(wall: Path) -> Path:
|
||||||
|
cache = wallpapers_cache_dir / compute_hash(wall)
|
||||||
|
output_path = cache / "first_frame.png"
|
||||||
|
|
||||||
|
if not output_path.exists():
|
||||||
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with Image.open(wall) as img:
|
||||||
|
try:
|
||||||
|
img.seek(0)
|
||||||
|
except EOFError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
img = img.convert("RGB")
|
||||||
|
img.save(output_path, "PNG")
|
||||||
|
|
||||||
|
return output_path
|
||||||
|
|
||||||
|
|
||||||
|
def set_wallpaper(wall: Path, no_smart: bool) -> None:
|
||||||
# Make path absolute
|
# Make path absolute
|
||||||
wall = Path(wall).resolve()
|
wall = Path(wall).resolve()
|
||||||
|
|
||||||
if not is_valid_image(wall):
|
if not is_valid_image(wall):
|
||||||
raise ValueError(f'"{wall}" is not a valid image')
|
raise ValueError(f'"{wall}" is not a valid image')
|
||||||
|
|
||||||
|
# Use gif's 1st frame for thumb only
|
||||||
|
wall_cache = convert_gif(wall) if wall.suffix.lower() == ".gif" else wall
|
||||||
|
|
||||||
# Update files
|
# Update files
|
||||||
wallpaper_path_path.parent.mkdir(parents=True, exist_ok=True)
|
wallpaper_path_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
wallpaper_path_path.write_text(str(wall))
|
wallpaper_path_path.write_text(str(wall))
|
||||||
@@ -136,10 +165,10 @@ def set_wallpaper(wall: Path | str, no_smart: bool) -> None:
|
|||||||
wallpaper_link_path.unlink(missing_ok=True)
|
wallpaper_link_path.unlink(missing_ok=True)
|
||||||
wallpaper_link_path.symlink_to(wall)
|
wallpaper_link_path.symlink_to(wall)
|
||||||
|
|
||||||
cache = wallpapers_cache_dir / compute_hash(wall)
|
cache = wallpapers_cache_dir / compute_hash(wall_cache)
|
||||||
|
|
||||||
# Generate thumbnail or get from cache
|
# Generate thumbnail or get from cache
|
||||||
thumb = get_thumb(wall, cache)
|
thumb = get_thumb(wall_cache, cache)
|
||||||
wallpaper_thumbnail_path.parent.mkdir(parents=True, exist_ok=True)
|
wallpaper_thumbnail_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
wallpaper_thumbnail_path.unlink(missing_ok=True)
|
wallpaper_thumbnail_path.unlink(missing_ok=True)
|
||||||
wallpaper_thumbnail_path.symlink_to(thumb)
|
wallpaper_thumbnail_path.symlink_to(thumb)
|
||||||
@@ -148,7 +177,7 @@ def set_wallpaper(wall: Path | str, no_smart: bool) -> None:
|
|||||||
|
|
||||||
# Change mode and variant based on wallpaper colour
|
# Change mode and variant based on wallpaper colour
|
||||||
if scheme.name == "dynamic" and not no_smart:
|
if scheme.name == "dynamic" and not no_smart:
|
||||||
smart_opts = get_smart_opts(wall, cache)
|
smart_opts = get_smart_opts(wall_cache, cache)
|
||||||
scheme.mode = smart_opts["mode"]
|
scheme.mode = smart_opts["mode"]
|
||||||
scheme.variant = smart_opts["variant"]
|
scheme.variant = smart_opts["variant"]
|
||||||
|
|
||||||
@@ -163,7 +192,16 @@ def set_wallpaper(wall: Path | str, no_smart: bool) -> None:
|
|||||||
subprocess.run(
|
subprocess.run(
|
||||||
post_hook,
|
post_hook,
|
||||||
shell=True,
|
shell=True,
|
||||||
env={**os.environ, "WALLPAPER_PATH": str(wall)},
|
env={
|
||||||
|
**os.environ,
|
||||||
|
"WALLPAPER_PATH": str(wall),
|
||||||
|
"SCHEME_NAME": scheme.name,
|
||||||
|
"SCHEME_FLAVOUR": scheme.flavour,
|
||||||
|
"SCHEME_MODE": scheme.mode,
|
||||||
|
"SCHEME_VARIANT": scheme.variant,
|
||||||
|
"SCHEME_COLOURS": json.dumps(scheme.colours),
|
||||||
|
"THUMBNAIL_PATH": str(thumb),
|
||||||
|
},
|
||||||
stderr=subprocess.DEVNULL,
|
stderr=subprocess.DEVNULL,
|
||||||
)
|
)
|
||||||
except (FileNotFoundError, json.JSONDecodeError):
|
except (FileNotFoundError, json.JSONDecodeError):
|
||||||
|
|||||||
Reference in New Issue
Block a user