-
-
Notifications
You must be signed in to change notification settings - Fork 164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
treewide: implement image editor #477
Conversation
I'm reluctant to merge this because, as previously discussed, it goes beyond Stylix's goal of "take these theming items, and apply them everywhere". If we were to instead provide the palette generator as a function, then you could simply call the palette generator with your original wallpaper, do whatever editing based on that palette, then set the final image as In extension to this, removing the generated palette as the default for Assuming both of the above changes were made, the following combinations would be possible:
With the palette generator as a function, we could potentially move it to its own repository - it's only part of Stylix because it's been here since the very beginning. Image editor functions such as All of the above can be implemented in two phases:
So in the end, Stylix would handle purely the "applying" tasks, and the "generating" would be a separate project. @LovingMelody @trueNAHO what do you think? |
Think this sounds good to me, unsure what this would look like or how this would affect users. Think the project has been known to have say palette generation by default. |
The original idea of Stylix was "give it an image, and everything else happens automatically" hence the palette generator exists, but I think we've strayed from that by adding more options and so on. If we avoid any big changes, just providing the palette generator as a function should remove the need for this PR. |
Foreword
Body
IMHO, replacing the current mono repo architecture does not add much benefit, especially, when the only use case for those micro repositories is Stylix. Managing these separately does not seem worth it for now.
Initially, I had the same opinion. However, considering that this PR will be replaced in the future anyway, I don't have any strong feelings about this PR:
Your proposal does not seem #63 future proof:
Actually, I have been thinking about this problem for a while now. What follows is my prototype draft proposal with #63, #442, and the palette extension roadmap in consideration. I hope it is somewhat understandable: scheme = mkOption {
# Another example would be:
#
# example = "./image";
example = "${pkgs.base16-schemes}/share/themes/catppuccin-latte.yaml";
# TODO: This option should accept two types of values from which the schemes
# will be generated:
#
# - 'pkgs.base16-schemes' file: Extract scheme from file
# - image path: Generate scheme from image
type = null;
}
slideshow = {
enable = mkEnableOption "slideshow";
timer = mkOption {
# This value should be directly passed to the internal systemd service
# periodically selecting random file from 'stylix.source'.
#
# This value defines the update interval.
}
};
source = {
path = mkOption {
default = null;
description = ''
Directory containing background sources, including images, videos, GIFs,
etc.
This value may be any valid Bash expression.
'';
example = "$XDG_RUNTIME_DIR/wallpapers";
type = types.nullOr types.str;
};
# TODO: Potentially better rename this option.
modifier = mkOption {
default = null;
description = ''
This is the the body of a function, where the first argument is the path
of the random path found by the systemd service. The second argument is
the file, where the modified file should be written to.
'';
example = "${pkgs.lutgen}/bin/lutgen apply "$1" --output "$2" -- ${colors}";
type = types.nullOr types.str;
}
# TODO: In case, Stylix supports an application's wallpaper can only be set
# through an option like 'wallpaper=<PATH>' and a systemd service (even a
# one-shot one) is unable to set the wallpaper, this option should be used.
# However, if Stylix does not have any such cases, then there is no need for
# this option.
wallpaperFallback = mkOption {};
}; Due to application color limitations, Stylix should internally provide and generate the following schemes: scheme = {
base16 = {
0 = "<VALUE>";
1 = "<VALUE>";
2 = "<VALUE>";
3 = "<VALUE>";
4 = "<VALUE>";
5 = "<VALUE>";
6 = "<VALUE>";
7 = "<VALUE>";
8 = "<VALUE>";
9 = "<VALUE>";
10 = "<VALUE>";
11 = "<VALUE>";
12 = "<VALUE>";
13 = "<VALUE>";
14 = "<VALUE>";
15 = "<VALUE>";
};
base24 = {
0 = "<VALUE>";
1 = "<VALUE>";
2 = "<VALUE>";
3 = "<VALUE>";
4 = "<VALUE>";
5 = "<VALUE>";
6 = "<VALUE>";
7 = "<VALUE>";
8 = "<VALUE>";
9 = "<VALUE>";
10 = "<VALUE>";
11 = "<VALUE>";
12 = "<VALUE>";
13 = "<VALUE>";
14 = "<VALUE>";
15 = "<VALUE>";
16 = "<VALUE>";
17 = "<VALUE>";
18 = "<VALUE>";
19 = "<VALUE>";
20 = "<VALUE>";
21 = "<VALUE>";
22 = "<VALUE>";
23 = "<VALUE>";
};
highlight = { /* VIM highlight groups */};
}; Depending on the If # TODO: For brevity, this example assumes that all 'stylix.source' files are
# images.
modifier() {
${stylix.scheme.modifier}
}
# This operation finds a random image from 'stylix.source'.
#
# NOTE: In my experience 'find | shuf -n 1' is not random enough and results in
# only a small subset of files ever being shown. But I have never actually
# measured this. I only noticed this.
#
# NOTE: This function is only here to simplify the pseudo-code.
find_random_image() {
# TODO: Implement.
}
# TODO: Depending on the user environment (like X or Wayland), this function
# abstracts how to set the background source.
#
# Additionally, in order to avoid "bloating" Stylix size, users should be able
# to set some Stylix option (not included or mentioned anywhere else in this
# message) saying what tool should set the background source.
#
# For example, if Stylix uses package 'A' by default to set the background
# source depending on the user environment, but the user does not use package
# 'A', then they might want to force Stylix to use package 'B', which they
# already use. This would reduce overall Stylix install size.
#
# NOTE: This abstraction could be implemented in Stylix, to avoid this logic
# from happening at runtime. Instead, the correct code could be generated by
# Nix, and then simply injected into this Bash script. This could somewhat
# improve performance and complexity.
set_stylix_source() {
# TODO: Implement.
}
# This 'file="$(mktemp)"; <OPERATION> "$file"; rm "$file"' pattern avoids
# arbitrary and fragile tests to ensure that we are not overwriting or falsely
# removing the original user files located in 'stylix.source'.
#
# NOTE: If 'stylix.scheme.modifier' is set to 'null', then the logic could be
# simplified to 'set_stylix_source "$(find_random_image)"'. This case should be
# handled in Nix, and accordingly, the correct code should be injected into this
# Bash script. Also note that the previous 'modifier' Bash function in this case
# is no longer necessary.
file="$(mktemp)"
set_stylix_source "$(modifier "$(find_random_image)" "$file")"
rm "$file" Note that we could add Stylix |
Theres no reason to generate a base16 scheme & a base24 scheme when we can just use a fallback table for base24 -> base16 |
This is faster, but less accurate. Unless
However, a given scheme, like
Since I have not yet looked deeper into VIM highlight groups, I am unsure how its upscaling or downscaling would be performed. I assume a combination of value repetition and interpolation, depending on the highlight group's purpose. Extending
|
As a user that based his nix flake config around stylix and treats it as a source of truth for theming I was waiting for this PR to be merged for some time as I am very interested in the said feature. I don't know if my user feedback is welcome here and is free to be ignored, As far as I understand stylix now works like this:
This is where I would take stylix if I was the one to direct it's development:
stylix = {
# Modifies the image or images set by stylix.image and
# stylix.additionalImages before they ever reach hyprpaper, grub, etc ...
imageEditor = {
# If explicitly enabled by the user while no color scheme was explicitly provided by the user
# will use base24Scheme extracted from the image and apply it to the image before it reaches hyprpaper, grub, etc...
# Enabled by default if the color scheme is set explicitly.
# if the user set the color scheme explicitly but does not want the image to be modified the user can disable imageEditor.
enable = true;
# the only image editor at the moment. lib.types.enum [ "lutgen" ];
editor = "lutgen";
};
};
stylix = {
# used for sourcing color scheme in case user does not set one,
# if the color scheme is set and image editor is enabled, the image is modified,
# if the image editor is disabled the image is not modified.
image = ./primary_image.png
# defaults to empty list, slideshow disabled, is optional
additionalImages = [
# not used to generate the color scheme
# if imageEditor is enabled they are modified, if disabled they stay unmodified
./additional_image_1.png
./additional_image_2.png
];
}; |
Actually, #102 already proposed some of this functionality, although it has essentially been abandoned due to the PR being too large.
Yes, discussing the public API is a good idea.
Exactly.
According to #200 and #442, declaring a background source should be optional.
Ideally, VIM highlight groups should become the primary Stylix scheme format:
To avoid inconsistent module-specific
I am unsure whether Stylix should enforce this behaviour with
It might be annoying for to declare the same scheme in
Downscaling or upscaling would be far more convenient. Additionally, this ensures scheme consistency, avoiding nasty incorrect coloring.
It might be better that the scheme is extracted from a single source of truth from which all other schemes are generated.
Personally, re-coloring background sources to the Stylix theme sounds neat. However, I am sure many people would not want this.
Compare this to my proposal.
This does not scale well, as the sources are copied to the Nix store:
|
This could be problematic since the palette generator is pseudo-random, so each format could have a completely different set of colors, leading to inconsistency between applications. IMO, we should generate |
7689816
to
91111b3
Compare
I don't mind merging this neat functionality for the time being as it will be replaced in the future anyway:
If @danth approves, I would be happy to review and test this PR again. Otherwise, we close this PR and keep it for future reference. |
@trueNAHO Could you clarify what you meant by this? (Sorry, I've lost track of the conversation since it's been a while) |
No worries. Essentially, this PR does not scale once #63 is resolved as the number of modified input files would be unbounded:
In the future, an implementation based on my prototype draft proposal would replace the architecture introduced by this PR:
Ultimately, the public option introduced by this PR would be removed in the future. However, considering that this might take a while to happen, I am fine with merging the functionality introduced by this PR for now. I leave the decision up to you:
|
I don't see a real reason to add this if it's just going to get removed. Your draft PR overall seems fine, but I'm not fond of the systemd service's implementation that you have outlined. The directory should probably cached & linked to a generation in case the modifier is computationally expensive. |
As mentioned, I don't have strong feelings on merging this, but avoiding another breaking change would be ultimately better.
I already considered caching, but did not mention it in the prototype. As mentioned, linking input or output directories to a Nix generation in the Nix store is not ideal due to storage duplication. When I implemented my custom wallpaper setter, I already considered caching, but never implemented it due to reasonably fast execution time. However, since the Caching could be implemented by preemptively selecting, modifying, and caching the next Additionally, benchmarking and caching the |
In your prototype, every time the service triggers it creates a new temp directory and creates the file there leading to more duplication than there would be in the nix store, which may even be desired behavior for it to be stored in the store ( I agree it shouldn't be the default ). The reason I point to generations is so that files outside of that generation can be removed when it's no longer valid as well and not just on reboot similar to agenix. |
Are you referring to the following snippet:
In this case,
What exactly do you mean by generations and what would be removed? Are you referring to garbage collecting the Nix store? AFAIK, the agenix cache defaults to My prototype (without the caching mechanism) leaves the input sources stored on the filesystem untouched and creates no files living longer than a second. |
fa1e252
to
8ea23f7
Compare
8ea23f7
to
91daf77
Compare
91daf77
to
2e93e9b
Compare
IIRC, the plan was to replace this PR with a general solution based on the previously proposed prototype once we reach this stage in the Roadmap in order to avoid additional breaking changes. What should we do about this PR? Merge or close? |
This can be closed, I'll continue maintaining this fork till we get there |
This PR implements #473