diff --git a/.config/ags/config.js b/.config/ags/config.js index bf89b6c81..4341214f5 100644 --- a/.config/ags/config.js +++ b/.config/ags/config.js @@ -21,6 +21,7 @@ import Overview from './modules/overview/main.js'; import Session from './modules/session/main.js'; import SideLeft from './modules/sideleft/main.js'; import SideRight from './modules/sideright/main.js'; +import { WallpaperPicker, autoWallpaper } from './modules/wallpaper/main.js'; import { COMPILED_STYLE_DIR } from './init.js'; const range = (length, start = 1) => Array.from({ length }, (_, i) => i + start); @@ -35,9 +36,10 @@ function forMonitorsAsync(widget) { // Start stuff handleStyles(true); +autoWallpaper(); startAutoDarkModeService().catch(print); firstRunWelcome().catch(print); -startBatteryWarningService().catch(print) +startBatteryWarningService().catch(print); const Windows = () => [ // forMonitors(DesktopBackground), @@ -47,6 +49,7 @@ const Windows = () => [ forMonitors(Cheatsheet), SideLeft(), SideRight(), + // forMonitors(Dock), forMonitors(Osk), forMonitors(Session), ...(userOptions.dock.enabled ? [forMonitors(Dock)] : []), @@ -58,6 +61,7 @@ const Windows = () => [ forMonitors((id) => Corner(id, 'bottom right', userOptions.appearance.fakeScreenRounding !== 0)), forMonitors(BarCornerTopleft), forMonitors(BarCornerTopright), + forMonitors(WallpaperPicker), ]; const CLOSE_ANIM_TIME = 210; // Longer than actual anim time to make sure widgets animate fully diff --git a/.config/ags/modules/.configuration/user_options.js b/.config/ags/modules/.configuration/user_options.js index 686b9cbd7..3a039aa02 100644 --- a/.config/ags/modules/.configuration/user_options.js +++ b/.config/ags/modules/.configuration/user_options.js @@ -131,6 +131,13 @@ let configOptions = { 'dateInterval': 5000, 'dateFormat': "%d/%m", // On notif time }, + 'wallpaper': { + 'path': "$HOME/Pictures/wallpapers", // wallpaper folder + 'autoChange': false, // Changes wallpaper regularly + 'interval': 1800, // In seconds + 'smart': true, // sets dark / light mode based on wallpaper + 'popup': true, // Shows a color preview when changing wallpaper + }, 'weather': { 'city': "", 'preferredUnit': "C", // Either C or F diff --git a/.config/ags/modules/wallpaper/main.js b/.config/ags/modules/wallpaper/main.js new file mode 100644 index 000000000..b54660416 --- /dev/null +++ b/.config/ags/modules/wallpaper/main.js @@ -0,0 +1,118 @@ +import PopupWindow from '../.widgethacks/popupwindow.js'; +import * as Utils from 'resource:///com/github/Aylur/ags/utils.js' +import Widget from 'resource:///com/github/Aylur/ags/widget.js'; +import clickCloseRegion from '../.commonwidgets/clickcloseregion.js'; +const { Gio, GLib, Gtk, GdkPixbuf, Gdk } = imports.gi; + +const dir = userOptions.wallpaper.path; +const scriptDir = `${App.configDir}/scripts/color_generation/switchwall.sh`; + +function ImagesList(path, monitor, nb) { + if (!path || path.search("No such file or directory") != -1) return Widget.Label({ + class_name: 'wallpaperpicker-min', + label: "Wallpaper folder empty or nonexistent. Please add files of type .png/.jpg/.jpeg/.gif or change the path in `~/.config/ags/user_options.js`.", + }); + let basename = path.split("/").pop(); + // let variable = Variable(""); + let gif = basename.substr(basename.lastIndexOf(".") + 1, basename.length) == "gif"; + let variable = Variable(Widget.Label({ + //TODO find better way + class_name: gif ? "wallpaperpicker-min icon-material txt-gigantic" : "wallpaperpicker-min", + label: gif ? "gif_box" : "Image still loading", + })); + let child = variable.bind(); + return Widget.Box({ + class_name: 'wallpaperpicker-box', + vertical: true, + children: [ + Widget.Button({ + class_name: 'wallpaperpicker-button', + child: Widget.Box({ + class_name: 'wallpaperpicker-min', + child: child, + }), + onPrimaryClick: () => { + App.closeWindow(`wallpaperpicker${monitor}`); + setWallpaper(path); + }, + setup: () => { + if (!gif) { + // Utils.idle(() => { + let timeout = 500; + Utils.timeout(nb * timeout, () => { + let pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_scale(path, 160, 90, false); + Utils.timeout(timeout / 2, () => { + let image = Gtk.Image.new_from_pixbuf(pixbuf); + variable.value = Widget.Box({ + hpack: 'center', + child: image, + }); + }); + }); + } + }, + }), + Widget.Label({ + class_name: "wallpaperpicker-label", + label: basename, + truncate: `middle`, + }), + ], + }) +} + +const wallpaperScrollable = (id) => { + const files = Utils.exec(`bash -c "find ${dir} -type f | grep -E '.gif$|.jpg$|.jpeg$|.png$'"`); + let i = 0; + return Widget.Box({ + class_name: 'wallpaperpicker-bg', + child: Widget.Scrollable({ + class_name: 'wallpaperpicker-scroll', + hexpand: true, + hscroll: "always", + vscroll: "never", + child: Widget.Box({ + children: files.split("\n").map(path =>ImagesList(path, id, i++)), + }), + }), + }); +}; + +export const WallpaperPicker = (id) => { + return PopupWindow({ + name: `wallpaperpicker${id}`, + monitor: id, + anchor: ["top", "left", "right"], + layer: "overlay", + keymode: "on-demand", + child: Widget.Box({ + vertical: true, + children: [ + wallpaperScrollable(id), + clickCloseRegion({ name: `wallpaperpicker` , fillMonitor: `vertical`}), + ], + }), + }) +} + +export function autoWallpaper() { + let interval = userOptions.wallpaper.interval * 1000; + if (userOptions.wallpaper.autoChange) { + Utils.timeout(interval, () => { + Utils.interval(interval, () => { + randomWallpaper(); + }) + }) + } +} + +function setWallpaper(path) { + let smartflag = userOptions.wallpaper.smart ? '--smart' : ''; + let popupflag = userOptions.wallpaper.popup ? '' : '--no-popup'; + Utils.execAsync(['bash', '-c', `sh "${scriptDir}" "${path}" "${smartflag}" "${popupflag}"`]).catch(print); +} + +globalThis['randomWallpaper'] = () => { + let path= Utils.exec(`bash -c "find ${dir} -type f | grep -E '.gif$|.jpg$|.jpeg$|.png$' | shuf -n 1"`); + setWallpaper(path); +} diff --git a/.config/ags/scripts/color_generation/applycolor.sh b/.config/ags/scripts/color_generation/applycolor.sh index db056d436..b0c33d442 100755 --- a/.config/ags/scripts/color_generation/applycolor.sh +++ b/.config/ags/scripts/color_generation/applycolor.sh @@ -163,7 +163,9 @@ apply_gtk() { # Using gradience-cli apply_ags() { ags run-js "handleStyles(false);" - ags run-js 'openColorScheme.value = true; Utils.timeout(2000, () => openColorScheme.value = false);' + if [ "$popup" = true ]; then + ags run-js 'openColorScheme.value = true; Utils.timeout(2000, () => openColorScheme.value = false);' + fi } @@ -173,6 +175,12 @@ IFS=$'\n' colorlist=( $colornames ) # Array of color names colorvalues=( $colorstrings ) # Array of color values +popup=true +for arg in "$@"; do + if [ "$arg" = "--no-popup" ]; then + popup=false + fi +done apply_ags & apply_hyprland & apply_hyprlock & diff --git a/.config/ags/scripts/color_generation/colorgen.sh b/.config/ags/scripts/color_generation/colorgen.sh index 9a19d8eb2..eff2f1bd4 100755 --- a/.config/ags/scripts/color_generation/colorgen.sh +++ b/.config/ags/scripts/color_generation/colorgen.sh @@ -9,10 +9,23 @@ STATE_DIR="$XDG_STATE_HOME/ags" # check if no arguments if [ $# -eq 0 ]; then - echo "Usage: colorgen.sh /path/to/image (--apply)" + echo "Usage: colorgen.sh /path/to/image (--apply) (--smart) (--no-popup)" exit 1 fi +apply=false +popupflag='' +smartflag='' +for arg in "$@"; do + if [ "$arg" = "--apply" ]; then + apply=true + elif [ "$arg" = "--smart" ]; then + smartflag="--smart" + elif [ "$arg" = "--no-popup" ]; then + popupflag="--no-popup" + fi +done + # check if the file $STATE_DIR/user/colormode.txt exists. if not, create it. else, read it to $lightdark colormodefile="$STATE_DIR/user/colormode.txt" lightdark="dark" @@ -52,21 +65,17 @@ if [[ "$1" = "#"* ]]; then # this is a color > "$CACHE_DIR"/user/generated/material_colors.scss if [ "$2" = "--apply" ]; then cp "$CACHE_DIR"/user/generated/material_colors.scss "$STATE_DIR/scss/_material.scss" - color_generation/applycolor.sh + color_generation/applycolor.sh $popupflag fi elif [ "$backend" = "material" ]; then - smartflag='' - if [ "$3" = "--smart" ]; then - smartflag='--smart' - fi color_generation/generate_colors_material.py --path "$1" \ --mode "$lightdark" --scheme "$materialscheme" --transparency "$transparency" \ --termscheme $terminalscheme --blend_bg_fg \ --cache "$STATE_DIR/user/color.txt" $smartflag \ > "$CACHE_DIR"/user/generated/material_colors.scss - if [ "$2" = "--apply" ]; then + if [ "$apply" = true ]; then cp "$CACHE_DIR"/user/generated/material_colors.scss "$STATE_DIR/scss/_material.scss" - color_generation/applycolor.sh + color_generation/applycolor.sh $popupflag fi elif [ "$backend" = "pywal" ]; then # clear and generate @@ -76,7 +85,7 @@ elif [ "$backend" = "pywal" ]; then cp "$XDG_CACHE_HOME/wal/colors.scss" "$CACHE_DIR"/user/generated/material_colors.scss cat color_generation/pywal_to_material.scss >> "$CACHE_DIR"/user/generated/material_colors.scss - if [ "$2" = "--apply" ]; then + if [ "$apply" = true]; then sass -I "$STATE_DIR/scss" -I "$CONFIG_DIR/scss/fallback" "$CACHE_DIR"/user/generated/material_colors.scss "$CACHE_DIR"/user/generated/colors_classes.scss --style compressed sed -i "s/ { color//g" "$CACHE_DIR"/user/generated/colors_classes.scss sed -i "s/\./$/g" "$CACHE_DIR"/user/generated/colors_classes.scss @@ -89,6 +98,6 @@ elif [ "$backend" = "pywal" ]; then cp "$CACHE_DIR"/user/generated/colors_classes.scss "$STATE_DIR/scss/_material.scss" - color_generation/applycolor.sh + color_generation/applycolor.sh $popupflag fi fi diff --git a/.config/ags/scripts/color_generation/switchwall.sh b/.config/ags/scripts/color_generation/switchwall.sh index e2d68cab0..c92bede5e 100755 --- a/.config/ags/scripts/color_generation/switchwall.sh +++ b/.config/ags/scripts/color_generation/switchwall.sh @@ -17,6 +17,7 @@ switch() { exit 0 fi + #notify-send -t 2000 "cursorposx: $cursorposx" # ags run-js "wallpaper.set('')" # sleep 0.1 && ags run-js "wallpaper.set('${imgpath}')" & swww img "$imgpath" --transition-step 100 --transition-fps 120 \ @@ -24,7 +25,23 @@ switch() { --transition-pos "$cursorposx, $cursorposy_inverted" } -if [ "$1" == "--noswitch" ]; then +noswitch=false +smartflag='' +popupflag='' + +for arg in "$@"; do + if [ "$arg" == "--noswitch" ]; then + noswitch=true + fi + if [ "$arg" == "--no-popup" ]; then + popupflag='--no-popup' + fi + if [ "$arg" == "--smart" ]; then + smartflag='--smart' + fi +done + +if [ "$noswitch" == true ]; then imgpath=$(swww query | awk -F 'image: ' '{print $2}') # imgpath=$(ags run-js 'wallpaper.get(0)') elif [[ "$1" ]]; then @@ -37,4 +54,4 @@ else fi # Generate colors for ags n stuff -"$CONFIG_DIR"/scripts/color_generation/colorgen.sh "${imgpath}" --apply --smart +"$CONFIG_DIR"/scripts/color_generation/colorgen.sh "${imgpath}" --apply "$smartflag" "$popupflag" diff --git a/.config/ags/scss/_wallpaperpicker.scss b/.config/ags/scss/_wallpaperpicker.scss new file mode 100644 index 000000000..c6682937e --- /dev/null +++ b/.config/ags/scss/_wallpaperpicker.scss @@ -0,0 +1,44 @@ +.wallpaperpicker-bg { + @include normal-rounding; + @include elevation-border; + @include elevation2; + margin: 0.8rem; + background-color: $background; +} + +.wallpaperpicker-scroll { + margin: 0rem 1rem; +} + +.wallpaperpicker-box { + margin: 0.8rem 0.4rem; + border-radius: 0.6rem; + background-color: $layer1; +} + +.wallpaperpicker-button { + margin: 0.2rem 0rem; + padding: 0.4rem; + border-radius: 0.6rem; + transition: all 0.3s ease; +} + +.wallpaperpicker-button:hover { + background-color: mix($primary, $layer1Hover, 40%); +} + +.wallpaperpicker-label { + color: $onLayer1; + border-radius: 0.4rem; + margin: 0rem 0rem; + padding: 0.2rem 1rem; +} + +.wallpaperpicker-min { + min-width: 160px; + min-height: 90px; +} + +.icon-material { + @include icon-material; +} diff --git a/.config/ags/scss/main.scss b/.config/ags/scss/main.scss index 57938e81a..46925e28e 100644 --- a/.config/ags/scss/main.scss +++ b/.config/ags/scss/main.scss @@ -23,6 +23,7 @@ @import './sidebars'; @import './session'; @import './notifications'; +@import './wallpaperpicker'; // Music is put last as it might mess stuff up with pywal @import './music'; // Everything related to music is here diff --git a/.config/ags/variables.js b/.config/ags/variables.js index c9aa243dd..e07faa8c2 100644 --- a/.config/ags/variables.js +++ b/.config/ags/variables.js @@ -21,7 +21,7 @@ globalThis['currentMode'] = currentShellMode; globalThis['cycleMode'] = () => { if (currentShellMode.value === 'normal') { currentShellMode.value = 'focus'; - } + } else if (currentShellMode.value === 'focus') { currentShellMode.value = 'nothing'; } @@ -53,6 +53,7 @@ globalThis['closeEverything'] = () => { for (let i = 0; i < numMonitors; i++) { App.closeWindow(`cheatsheet${i}`); App.closeWindow(`session${i}`); + App.closeWindow(`wallpaperpicker${i}`); } App.closeWindow('sideleft'); App.closeWindow('sideright'); diff --git a/.gitignore b/.gitignore index 340da66f3..2e5d3477a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ # Ignore Python cache files __pycache__/ *.py[cod] + +.vscode/