WallRizz Documentation

repository·main·Indexed 18 days ago

https://github.com/5hubham5ingh/wallrizz

A lightweight, terminal-based Linux utility built with QuickJS for managing wallpapers and automatically synchronizing system themes across applications like Kitty, VSCode, NeoVim, Firefox, and Jiffy. It features automated theming via the ColorJs library, an extensible script system for custom application themes, and a comprehensive CLI for controlling wallpaper directories, grid displays, and periodic randomization.

Tokens
5.9K
Snippets
15
Records
20
Agent score
62%

What's inside WallRizz

  1. Overview of WallRizz

    main

    WallRizz is a terminal-based wallpaper and system theme manager designed for Linux. It allows users to manage wallpapers and automatically generate/apply system themes to various applications based on the selected wallpaper.

    Key Capabilities:

    • Wallpaper Management: Select wallpapers via terminal-based grid or list menus. Includes online browsing and downloading capabilities.
    • Automated Theming: Generates themes from wallpapers and applies them to supported applications (e.g., Kitty, VSCode, NeoVim, Firefox, Jiffy).
    • Extensibility: Users can write custom theming scripts for different applications or use an extension template to create new extensions.
    • High Precision: Uses the ColorJs library and supports custom color generation backends for fine-grained control over colors and themes.
    • Performance: Built with QuickJS, resulting in a lightweight, fast-starting, standalone executable with minimal resource usage.
  2. Extend WallRizz with custom application themes

    main
    WallRizz is extensible via scripts. You can write or edit theming scripts to support different applications. The project provides an extension template that allows you to create new extensions using a single command, ensuring your custom theme logic integrates correctly with the WallRizz workflow.
  3. Create theme extensions using JavaScript scripts

    main

    WallRizz supports theme extensions via JavaScript scripts located in ${HOME_DIR}/.config/WallRizz/themeExtensionScripts/. To create a new theme generator, place a .js file in that directory.

    An extension script is expected to be compatible with the workerPromise handler and should implement the following logic (conceptually):

    1. getThemes(colors, wallpaperPath, cacheDirs): This method is called to generate theme configurations.

      • colors: An array of hex color strings extracted from the wallpaper.
      • wallpaperPath: The absolute path to the wallpaper file.
      • cacheDirs: An array containing two paths: [darkThemeCachePath, lightThemeCachePath]. The script should write its generated configuration files to these locations.
    2. setTheme(cachedThemePath, wallpaperPath): This method is called when a theme is being applied to a specific wallpaper.

      • cachedThemePath: The path to the already generated .conf file.
      • wallpaperPath: The path to the wallpaper file.

    Note: The Theme class automatically discovers these scripts by scanning the directory for .js files that do not start with a dot (.).

    // Conceptual structure of a theme extension script
    // The Theme class interacts with these via workerPromise
    
    // getThemes is called to generate the .conf files
    export async function getThemes(colors, wallpaperPath, [darkCache, lightCache]) {
      // Logic to generate theme configuration based on colors
      // and save them to darkCache and lightCache
    }
    
    // setTheme is called to apply the theme
    export async function setTheme(cachedThemePath, wallpaperPath) {
      // Logic to apply the theme to the system
    }
  4. Configure WallRizz via command-line arguments

    main

    The WallRizz class uses parseArguments() to populate its config object. The behavior of the run() method is determined by several configuration flags. Based on the run() implementation, the following flags trigger specific workflows:

    • showKeyMap: Displays keymaps via UserInterface.printKeyMaps() and exits.
    • update: Checks for application updates via checkForUpdate() and exits.
    • test: Runs extension tests via testExtensions() and exits.
    • downloadThemeExtensionScripts: Triggers the ThemeExtensionScriptsDownloadManager to initialize.
    • downloadWallpaperDaemonHandlerScript: Triggers the WallpaperDaemonHandlerScriptDownloadManager to initialize.
    • inspection: If truthy, the application configuration is printed to the console upon completion.
  5. Configure color extraction command

    main

    The Theme class relies on an external command to extract colors from wallpaper files. You must provide this command in your configuration object under the colorExtractionCommand key. The command must use {} as a placeholder for the wallpaper file path.

    If the command fails to return valid color strings, the system will throw a SystemError stating: "Make sure the backend is extracting colors correctly."

    // Example configuration structure
    const config = {
      colorExtractionCommand: 'some-color-tool --path {}',
      processLimit: 4,
      wallpapersDirectory: '/path/to/wallpapers/',
      enableLightTheme: true
    };
  6. Use the set-interval-callback for conditional logic

    main

    The --set-interval-callback (or -f) flag allows you to provide a JavaScript IIFE (Immediately Invoked Function Expression) that runs at every interval. This callback can be used to dynamically modify the application's arguments, such as toggling the light theme based on the time of day.

    The callback has access to globalThis.USER_ARGUMENTS.

    # Example: Switch to light theme between 6 AM and 6 PM
    wallrizz -v 3600000 -f "(globalThis.USER_ARGUMENTS ??= {})[ 'enableLightTheme' ] = ((h) => h >= 6 && h < 18)(new Date().getHours())"
  7. Initialize the UserInterface

    main

    The UserInterface class manages the terminal-based display modes for Wallrizz. It supports two distinct view modes determined by the previewMode configuration key:

    1. List Mode (previewMode: 'list'): Uses FzfView to provide a fuzzy-searchable list of wallpapers.
    2. Gallery Mode (default): Uses GalleryView to provide a visual gallery interface.

    To initialize the UI, call the init() method. This method is asynchronous and will render the appropriate view based on your configuration.

    // Example initialization logic
    const ui = new UserInterface(
      wallpaperList,
      wallpapersDirectory,
      handleSelection,
      getWallpaperPath,
      handleFocus,
      { previewMode: 'list' } // or 'gallery'
    );
    
    await ui.init();
  8. Manage wallpaper color caches

    main

    The Theme class maintains a cache of extracted colors to avoid redundant processing.

    • Cache Location: The global color cache is stored at ${HOME_DIR}/.cache/WallRizz/colours.json.
    • getCachedColours(cacheName): Retrieves the array of hex color strings for a specific wallpaper using its uniqueId. If the color is not in memory, it attempts to load it from the colours.json file.
    • createColoursCacheFromWallpapers(): An internal process that runs the colorExtractionCommand for wallpapers that do not yet have entries in the cache. It uses promiseQueueWithLimit (configured via config.processLimit) to manage concurrency.
  9. Apply themes to a wallpaper with `setThemes()`

    main

    Use the setThemes(wallpaperId, wallpaperName) method to apply a generated theme to a specific wallpaper. This method iterates through all available theme extension scripts and attempts to apply the cached theme configuration for that wallpaper.

    • wallpaperId: The unique identifier for the wallpaper (used to locate the cached .conf file).
    • wallpaperName: The name/path of the wallpaper file.

    Upon successful application, a "Theme applied." notification is triggered.

    // Assuming a Theme instance has been initialized
    await themeInstance.setThemes('unique-wp-id', 'wallpaper_image.jpg');
  10. Use the WallRizz class to run the application

    main

    The WallRizz class is the primary entrypoint for the application. It orchestrates the application lifecycle, including argument parsing, updates, extension testing, script downloads, and wallpaper management.

    When instantiated, it parses command-line arguments and stores them in this.config. Calling the run() method executes the application's workflow based on the provided configuration flags.

    import { WallRizz } from './src/main.js';
    
    const app = new WallRizz();
    await app.run();
  11. Handle system-level failures with SystemError

    main

    When encountering system-level failures, Wallrizz uses the SystemError class. This error type extends the standard Error class and includes a description for context and a body for detailed error information (such as stack traces or raw error objects).

    You can use the .log() method to print a formatted, colorized error message to stderr. By default, it prints the name and description. If you pass true to the inspect parameter, it will also print the body of the error.

    import { SystemError } from './src/core/errors.js';
    
    try {
      // ... some operation
    } catch (err) {
      const systemErr = new SystemError(
        'FILE_NOT_FOUND',
        'The requested configuration file was not found.',
        err
      );
      
      // Logs name and description
      systemErr.log();
      
      // Logs name, description, and the detailed error body
      systemErr.log(true);
    }
  12. Test extensions using testExtensions

    main

    The testExtensions function is a utility designed to validate the current working directory as a valid extension environment.

    It attempts to import a main.js file from the current working directory and execute its main() function. If main.js is not found, it provides an interactive CLI prompt (using fzf) allowing the user to automatically fetch and extract an extension template from the WallRizz repository via curl and unzip.

    Requirements for template creation:

    • curl must be installed.
    • unzip must be installed and available in the system path.
    import { testExtensions } from './src/extensions/ExtensionHandler.js';
    
    // This will attempt to run main.js in the current directory
    // or prompt to create a template if it's missing.
    await testExtensions();