refactor: move theme to uad-gui; drop core gui deps; mark PmCommand must-use

This commit is contained in:
Angel J 2026-04-25 10:21:16 -07:00
commit 02ba6e2cca
No known key found for this signature in database
GPG key ID: 4CE6C8BA718B9657
14 changed files with 205 additions and 309 deletions

2
Cargo.lock generated
View file

@ -4558,10 +4558,8 @@ version = "1.2.0"
dependencies = [ dependencies = [
"chrono", "chrono",
"csv", "csv",
"dark-light",
"dirs", "dirs",
"flate2", "flate2",
"iced",
"log", "log",
"retry", "retry",
"serde", "serde",

View file

@ -44,7 +44,6 @@ format_push_string = "warn"
large_include_file = "warn" large_include_file = "warn"
shadow_unrelated = "warn" shadow_unrelated = "warn"
struct_field_names = "allow" # annoying struct_field_names = "allow" # annoying
module_name_repetitions = "allow" # annoying
disallowed_types = "deny" disallowed_types = "deny"
disallowed_methods = "deny" disallowed_methods = "deny"

View file

@ -191,7 +191,7 @@ uad completions powershell > uad.ps1
## Examples ## Examples
### Remove all Facebook packages ### Remove Facebook packages
```bash ```bash
uad list --search facebook uad list --search facebook

View file

@ -12,7 +12,6 @@ edition.workspace = true
[features] [features]
default = [] default = []
gui = ["dep:iced", "dep:dark-light"]
self-update = ["dep:flate2", "dep:tar"] self-update = ["dep:flate2", "dep:tar"]
[dependencies] [dependencies]
@ -25,8 +24,6 @@ dirs.workspace = true
ureq.workspace = true ureq.workspace = true
retry.workspace = true retry.workspace = true
csv.workspace = true csv.workspace = true
iced = { workspace = true, optional = true }
dark-light = { workspace = true, optional = true }
flate2 = { workspace = true, optional = true } flate2 = { workspace = true, optional = true }
tar = { workspace = true, optional = true } tar = { workspace = true, optional = true }
@ -47,7 +44,6 @@ format_push_string = "warn"
large_include_file = "warn" large_include_file = "warn"
shadow_unrelated = "warn" shadow_unrelated = "warn"
struct_field_names = "allow" # annoying struct_field_names = "allow" # annoying
module_name_repetitions = "allow" # annoying
disallowed_types = "deny" disallowed_types = "deny"
disallowed_methods = "deny" disallowed_methods = "deny"

View file

@ -229,7 +229,6 @@ impl Default for ACommand {
pub struct ShellCommand(ACommand); pub struct ShellCommand(ACommand);
impl ShellCommand { impl ShellCommand {
/// `pm` command builder /// `pm` command builder
#[must_use]
pub fn pm(mut self) -> PmCommand { pub fn pm(mut self) -> PmCommand {
self.0.0.arg("pm"); self.0.0.arg("pm");
PmCommand(self) PmCommand(self)
@ -335,6 +334,7 @@ pub const PM_CLEAR_PACK: &str = "pm clear";
/// Builder object for an Android Package Manager command. /// Builder object for an Android Package Manager command.
/// <https://developer.android.com/tools/adb#pm> /// <https://developer.android.com/tools/adb#pm>
#[derive(Debug)] #[derive(Debug)]
#[must_use]
pub struct PmCommand(ShellCommand); pub struct PmCommand(ShellCommand);
impl PmCommand { impl PmCommand {
/// `list packages -s` sub-command, [`PACK_PREFIX`] stripped. /// `list packages -s` sub-command, [`PACK_PREFIX`] stripped.

View file

@ -1,13 +1,15 @@
use crate::CACHE_DIR; use crate::CACHE_DIR;
use crate::CONFIG_DIR; use crate::CONFIG_DIR;
use crate::sync::User;
use crate::utils::DisplayablePath; use crate::utils::DisplayablePath;
use crate::{sync::User, theme::Theme};
use log::error; use log::error;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::LazyLock; use std::sync::LazyLock;
const DEFAULT_THEME: &str = "Auto (follow system theme)";
#[derive(Default, Debug, Serialize, Deserialize, Clone)] #[derive(Default, Debug, Serialize, Deserialize, Clone)]
pub struct Config { pub struct Config {
pub general: GeneralSettings, pub general: GeneralSettings,
@ -44,7 +46,7 @@ pub struct DeviceSettings {
impl Default for GeneralSettings { impl Default for GeneralSettings {
fn default() -> Self { fn default() -> Self {
Self { Self {
theme: Theme::default().to_string(), theme: DEFAULT_THEME.to_string(),
expert_mode: false, expert_mode: false,
backup_folder: CACHE_DIR.join("backups"), backup_folder: CACHE_DIR.join("backups"),
} }
@ -114,7 +116,7 @@ mod tests {
let config = Config::load_configuration_file(); let config = Config::load_configuration_file();
// non-deterministic // non-deterministic
//assert_eq!(config.devices.len(), 0); //assert_eq!(config.devices.len(), 0);
assert_eq!(config.general.theme, Theme::default().to_string()); assert_eq!(config.general.theme, DEFAULT_THEME);
assert!(!config.general.expert_mode); assert!(!config.general.expert_mode);
assert_eq!(config.general.backup_folder, CACHE_DIR.join("backups")); assert_eq!(config.general.backup_folder, CACHE_DIR.join("backups"));
} }
@ -136,7 +138,7 @@ mod tests {
fn test_default_config() { fn test_default_config() {
let config = Config::default(); let config = Config::default();
assert_eq!(config.devices.len(), 0); assert_eq!(config.devices.len(), 0);
assert_eq!(config.general.theme, Theme::default().to_string()); assert_eq!(config.general.theme, DEFAULT_THEME);
assert!(!config.general.expert_mode); assert!(!config.general.expert_mode);
assert_eq!(config.general.backup_folder, CACHE_DIR.join("backups")); assert_eq!(config.general.backup_folder, CACHE_DIR.join("backups"));
} }

View file

@ -11,7 +11,6 @@ pub mod adb;
pub mod config; pub mod config;
pub mod save; pub mod save;
pub mod sync; pub mod sync;
pub mod theme;
pub mod uad_lists; pub mod uad_lists;
pub mod update; pub mod update;
pub mod utils; pub mod utils;

View file

@ -1,231 +0,0 @@
#[cfg(feature = "gui")]
use dark_light;
#[cfg(feature = "gui")]
use iced::theme::{self, Mode, Palette, Style};
#[cfg(feature = "gui")]
use iced::{Color, color};
#[cfg(feature = "gui")]
use std::sync::LazyLock;
/*
In-memory caching.
This fixes the perf bug
caused by Iced repeatedly calling `palette`.
Coincidentally, this also ensures consistent colors across the GUI,
at the cost of requiring a restart to update the palette.
(this is just a patch, not a fix)
*/
#[cfg(feature = "gui")]
pub static OS_COLOR_SCHEME: LazyLock<dark_light::Mode> =
LazyLock::new(|| dark_light::detect().unwrap_or(dark_light::Mode::Unspecified));
#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
/// Color scheme
pub enum Theme {
#[default]
/// `Dark` or `Light`, according to `dark_light`
Auto,
/// `Dark`-ish and purple
Lupin,
/// white on black
Dark,
/// black on white
Light,
}
#[cfg(feature = "gui")]
#[derive(Debug, Clone, Copy)]
pub struct BaseColors {
pub background: Color,
pub foreground: Color,
}
#[cfg(feature = "gui")]
#[derive(Debug, Clone, Copy)]
pub struct NormalColors {
pub primary: Color,
#[allow(dead_code, reason = "Reserved for future palette updates")]
pub secondary: Color,
pub surface: Color,
pub error: Color,
}
#[cfg(feature = "gui")]
#[derive(Debug, Clone, Copy)]
pub struct BrightColors {
pub primary: Color,
pub secondary: Color,
pub surface: Color,
pub error: Color,
}
#[cfg(feature = "gui")]
#[derive(Debug, Clone, Copy)]
pub struct ColorPalette {
pub base: BaseColors,
pub normal: NormalColors,
pub bright: BrightColors,
}
impl Theme {
pub const ALL: [Self; 4] = [Self::Auto, Self::Lupin, Self::Dark, Self::Light];
#[allow(
clippy::unreadable_literal,
reason = "https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/pull/578#discussion_r1759653408"
)]
/// This `fn` _could_ be `const`,
/// but `deref`ing a lazy-`static` is non-`const`.
#[must_use]
#[cfg(feature = "gui")]
pub fn palette(self) -> ColorPalette {
const DARK: ColorPalette = ColorPalette {
base: BaseColors {
background: color!(0x111111),
foreground: color!(0x1C1C1C),
},
normal: NormalColors {
primary: color!(0x5E4266),
secondary: color!(0x386E50),
surface: color!(0x828282),
error: color!(0x992B2B),
},
bright: BrightColors {
primary: color!(0xBA84FC),
secondary: color!(0x49EB7A),
surface: color!(0xE0E0E0),
error: color!(0xC13047),
},
};
const LIGHT: ColorPalette = ColorPalette {
base: BaseColors {
background: color!(0xEEEEEE),
foreground: color!(0xE0E0E0),
},
normal: NormalColors {
primary: color!(0x818181),
secondary: color!(0xF9D659),
surface: color!(0x818181),
error: color!(0x992B2B),
},
bright: BrightColors {
primary: color!(0x673AB7),
secondary: color!(0x3797A4),
surface: color!(0x000000),
error: color!(0xC13047),
},
};
const LUPIN: ColorPalette = ColorPalette {
base: BaseColors {
background: color!(0x282A36),
foreground: color!(0x353746),
},
normal: NormalColors {
primary: color!(0x58406F),
secondary: color!(0x386E50),
surface: color!(0xA2A4A3),
error: color!(0xA13034),
},
bright: BrightColors {
primary: color!(0xBD94F9),
secondary: color!(0x49EB7A),
surface: color!(0xF4F8F3),
error: color!(0xE63E6D),
},
};
match self {
Self::Dark => DARK,
Self::Light => LIGHT,
Self::Lupin => LUPIN,
Self::Auto => match *OS_COLOR_SCHEME {
dark_light::Mode::Light => LIGHT,
dark_light::Mode::Dark | dark_light::Mode::Unspecified => DARK,
},
}
}
}
impl std::fmt::Display for Theme {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
Self::Dark => "Dark",
Self::Light => "Light",
Self::Lupin => "Lupin",
Self::Auto => "Auto (follow system theme)",
}
)
}
}
/// Converts a string to the GUI's Theme type
#[must_use]
pub fn string_to_theme(theme: &str) -> Theme {
match theme {
"Lupin" => Theme::Lupin,
"Dark" => Theme::Dark,
"Light" => Theme::Light,
_ => Theme::Auto,
}
}
#[cfg(feature = "gui")]
impl theme::Base for Theme {
fn default(preference: Mode) -> Self {
match preference {
Mode::Light => Self::Light,
Mode::Dark => Self::Dark,
Mode::None => match *OS_COLOR_SCHEME {
dark_light::Mode::Light => Self::Light,
dark_light::Mode::Dark | dark_light::Mode::Unspecified => Self::Dark,
},
}
}
fn mode(&self) -> Mode {
let resolved = match self {
Self::Auto => match *OS_COLOR_SCHEME {
dark_light::Mode::Light => Self::Light,
dark_light::Mode::Dark | dark_light::Mode::Unspecified => Self::Dark,
},
other => *other,
};
match resolved {
Self::Light => Mode::Light,
_ => Mode::Dark,
}
}
fn base(&self) -> Style {
let p = Self::palette(*self);
Style {
background_color: p.base.background,
text_color: p.bright.surface,
}
}
fn palette(&self) -> Option<Palette> {
let p = Self::palette(*self);
Some(Palette {
background: p.base.background,
text: p.bright.surface,
primary: p.normal.primary,
success: p.bright.secondary,
warning: p.normal.surface,
danger: p.normal.error,
})
}
fn name(&self) -> &str {
match self {
Self::Dark => "Dark",
Self::Light => "Light",
Self::Lupin => "Lupin",
Self::Auto => "Auto",
}
}
}

View file

@ -3,7 +3,6 @@
use crate::{ use crate::{
adb::{ACommand as AdbCommand, PmListPacksFlag}, adb::{ACommand as AdbCommand, PmListPacksFlag},
sync::{CorePackage, User}, sync::{CorePackage, User},
theme::Theme,
uad_lists::{PackageHashMap, PackageState, Removal, UadList}, uad_lists::{PackageHashMap, PackageState, Removal, UadList},
}; };
use chrono::{DateTime, offset::Utc}; use chrono::{DateTime, offset::Utc};
@ -128,22 +127,10 @@ pub fn fetch_packages(
}; };
user_package.push(package); user_package.push(package);
} }
user_package.sort_by_key(|a| a.name.to_lowercase()); user_package.sort_by_key(|package| package.name.to_lowercase());
user_package user_package
} }
#[must_use]
pub fn string_to_theme(theme: &str) -> Theme {
match theme {
"Dark" => Theme::Dark,
"Light" => Theme::Light,
"Lupin" => Theme::Lupin,
// Auto uses `Display`, so it doesn't have a canonical repr
t if t.starts_with("Auto") => Theme::Auto,
_ => Theme::default(),
}
}
#[must_use] #[must_use]
pub fn setup_uad_dir(dir: &Path) -> PathBuf { pub fn setup_uad_dir(dir: &Path) -> PathBuf {
let dir = dir.join("uad"); let dir = dir.join("uad");

View file

@ -22,7 +22,7 @@ no-self-update = []
img = ["image", "iced/image"] img = ["image", "iced/image"]
[dependencies] [dependencies]
uad-core = { path = "../uad-core", features = ["gui", "self-update"] } uad-core = { path = "../uad-core", features = ["self-update"] }
iced.workspace = true iced.workspace = true
image = { workspace = true, optional = true } image = { workspace = true, optional = true }
rfd.workspace = true rfd.workspace = true
@ -54,7 +54,6 @@ format_push_string = "warn"
large_include_file = "warn" large_include_file = "warn"
shadow_unrelated = "warn" shadow_unrelated = "warn"
struct_field_names = "allow" # annoying struct_field_names = "allow" # annoying
module_name_repetitions = "allow" # annoying
disallowed_types = "deny" disallowed_types = "deny"
disallowed_methods = "deny" disallowed_methods = "deny"

View file

@ -1,7 +1,7 @@
use crate::theme::string_to_theme;
#[cfg(feature = "img")] #[cfg(feature = "img")]
use crate::theme::OS_COLOR_SCHEME; use crate::theme::OS_COLOR_SCHEME;
use crate::theme::Theme; use crate::theme::Theme;
use crate::theme::string_to_theme;
use crate::views::about::{About as AboutView, Message as AboutMessage}; use crate::views::about::{About as AboutView, Message as AboutMessage};
use crate::views::list::{ use crate::views::list::{
List as AppsView, LoadingState as ListLoadingState, Message as AppsMessage, List as AppsView, LoadingState as ListLoadingState, Message as AppsMessage,
@ -9,13 +9,13 @@ use crate::views::list::{
use crate::views::settings::{Message as SettingsMessage, Settings as SettingsView}; use crate::views::settings::{Message as SettingsMessage, Settings as SettingsView};
use crate::widgets::navigation_menu::nav_menu; use crate::widgets::navigation_menu::nav_menu;
use iced::font; use iced::font;
use iced::widget::column;
#[cfg(feature = "img")] #[cfg(feature = "img")]
use iced::window::icon; use iced::window::icon;
#[cfg(feature = "img")]
use image::ImageFormat;
use iced::widget::column;
use iced::{Alignment, Element, Length, Settings, Task, window::Settings as Window}; use iced::{Alignment, Element, Length, Settings, Task, window::Settings as Window};
use iced::{Subscription, event, keyboard}; use iced::{Subscription, event, keyboard};
#[cfg(feature = "img")]
use image::ImageFormat;
use log::{debug, error, info}; use log::{debug, error, info};
#[cfg(feature = "self-update")] #[cfg(feature = "self-update")]
use std::path::PathBuf; use std::path::PathBuf;
@ -434,7 +434,7 @@ impl UadGui {
pub fn start() -> iced::Result { pub fn start() -> iced::Result {
#[cfg(feature = "img")] #[cfg(feature = "img")]
let logo: &[u8] = match *OS_COLOR_SCHEME { let logo: &[u8] = match *OS_COLOR_SCHEME {
// remember to keep `Unspecified` in sync with `src/core/theme` // remember to keep `Unspecified` in sync with `src/theme`
dark_light::Mode::Dark | dark_light::Mode::Unspecified => { dark_light::Mode::Dark | dark_light::Mode::Unspecified => {
include_bytes!("../../../resources/assets/logo-dark.png") include_bytes!("../../../resources/assets/logo-dark.png")
} }

View file

@ -1,72 +1,219 @@
use iced::theme::{self, Mode, Palette, Style}; use iced::theme::{self, Mode, Palette, Style};
use iced::{Color, color};
use std::sync::LazyLock;
pub use uad_core::theme::{BaseColors, BrightColors, ColorPalette, NormalColors, OS_COLOR_SCHEME}; /*
In-memory caching.
This fixes the perf bug
caused by Iced repeatedly calling `palette`.
/// GUI-local wrapper around the core Theme to satisfy orphan rules for Coincidentally, this also ensures consistent colors across the GUI,
/// iced's Catalog traits. at the cost of requiring a restart to update the palette.
#[derive(Debug, Clone, Copy, PartialEq, Eq)] (this is just a patch, not a fix)
pub struct Theme(pub uad_core::theme::Theme); */
pub static OS_COLOR_SCHEME: LazyLock<dark_light::Mode> =
LazyLock::new(|| dark_light::detect().unwrap_or(dark_light::Mode::Unspecified));
#[derive(Default, Debug, PartialEq, Eq, Copy, Clone)]
/// Color scheme
pub enum Theme {
#[default]
/// `Dark` or `Light`, according to `dark_light`
Auto,
/// `Dark`-ish and purple
Lupin,
/// white on black
Dark,
/// black on white
Light,
}
#[derive(Debug, Clone, Copy)]
pub struct BaseColors {
pub background: Color,
pub foreground: Color,
}
#[derive(Debug, Clone, Copy)]
pub struct NormalColors {
pub primary: Color,
#[allow(dead_code, reason = "Reserved for future palette updates")]
pub secondary: Color,
pub surface: Color,
pub error: Color,
}
#[derive(Debug, Clone, Copy)]
pub struct BrightColors {
pub primary: Color,
pub secondary: Color,
pub surface: Color,
pub error: Color,
}
#[derive(Debug, Clone, Copy)]
pub struct ColorPalette {
pub base: BaseColors,
pub normal: NormalColors,
pub bright: BrightColors,
}
#[allow(
non_upper_case_globals,
reason = "Keep variant-like names matching core Theme"
)]
impl Theme { impl Theme {
pub const Auto: Self = Self(uad_core::theme::Theme::Auto);
pub const Lupin: Self = Self(uad_core::theme::Theme::Lupin);
pub const Dark: Self = Self(uad_core::theme::Theme::Dark);
pub const Light: Self = Self(uad_core::theme::Theme::Light);
pub const ALL: [Self; 4] = [Self::Auto, Self::Lupin, Self::Dark, Self::Light]; pub const ALL: [Self; 4] = [Self::Auto, Self::Lupin, Self::Dark, Self::Light];
#[allow(
clippy::unreadable_literal,
reason = "https://github.com/Universal-Debloater-Alliance/universal-android-debloater-next-generation/pull/578#discussion_r1759653408"
)]
/// This `fn` _could_ be `const`,
/// but `deref`ing a lazy-`static` is non-`const`.
#[must_use] #[must_use]
pub fn palette(self) -> ColorPalette { pub fn palette(self) -> ColorPalette {
self.0.palette() const DARK: ColorPalette = ColorPalette {
base: BaseColors {
background: color!(0x111111),
foreground: color!(0x1C1C1C),
},
normal: NormalColors {
primary: color!(0x5E4266),
secondary: color!(0x386E50),
surface: color!(0x828282),
error: color!(0x992B2B),
},
bright: BrightColors {
primary: color!(0xBA84FC),
secondary: color!(0x49EB7A),
surface: color!(0xE0E0E0),
error: color!(0xC13047),
},
};
const LIGHT: ColorPalette = ColorPalette {
base: BaseColors {
background: color!(0xEEEEEE),
foreground: color!(0xE0E0E0),
},
normal: NormalColors {
primary: color!(0x818181),
secondary: color!(0xF9D659),
surface: color!(0x818181),
error: color!(0x992B2B),
},
bright: BrightColors {
primary: color!(0x673AB7),
secondary: color!(0x3797A4),
surface: color!(0x000000),
error: color!(0xC13047),
},
};
const LUPIN: ColorPalette = ColorPalette {
base: BaseColors {
background: color!(0x282A36),
foreground: color!(0x353746),
},
normal: NormalColors {
primary: color!(0x58406F),
secondary: color!(0x386E50),
surface: color!(0xA2A4A3),
error: color!(0xA13034),
},
bright: BrightColors {
primary: color!(0xBD94F9),
secondary: color!(0x49EB7A),
surface: color!(0xF4F8F3),
error: color!(0xE63E6D),
},
};
match self {
Self::Dark => DARK,
Self::Light => LIGHT,
Self::Lupin => LUPIN,
Self::Auto => match *OS_COLOR_SCHEME {
dark_light::Mode::Light => LIGHT,
dark_light::Mode::Dark | dark_light::Mode::Unspecified => DARK,
},
}
} }
} }
impl From<uad_core::theme::Theme> for Theme { impl std::fmt::Display for Theme {
fn from(value: uad_core::theme::Theme) -> Self { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Self(value) write!(
f,
"{}",
match self {
Self::Dark => "Dark",
Self::Light => "Light",
Self::Lupin => "Lupin",
Self::Auto => "Auto (follow system theme)",
} }
} )
impl From<Theme> for uad_core::theme::Theme {
fn from(value: Theme) -> Self {
value.0
} }
} }
/// Converts a string to the GUI's Theme type /// Converts a string to the GUI's Theme type
#[must_use] #[must_use]
pub fn string_to_theme(theme: &str) -> Theme { pub fn string_to_theme(theme: &str) -> Theme {
Theme(uad_core::theme::string_to_theme(theme)) match theme {
"Lupin" => Theme::Lupin,
"Dark" => Theme::Dark,
"Light" => Theme::Light,
_ => Theme::Auto,
}
} }
impl theme::Base for Theme { impl theme::Base for Theme {
fn default(preference: Mode) -> Self { fn default(preference: Mode) -> Self {
Self(<uad_core::theme::Theme as theme::Base>::default(preference)) match preference {
Mode::Light => Self::Light,
Mode::Dark => Self::Dark,
Mode::None => match *OS_COLOR_SCHEME {
dark_light::Mode::Light => Self::Light,
dark_light::Mode::Dark | dark_light::Mode::Unspecified => Self::Dark,
},
}
} }
fn mode(&self) -> Mode { fn mode(&self) -> Mode {
<uad_core::theme::Theme as theme::Base>::mode(&self.0) let resolved = match self {
Self::Auto => match *OS_COLOR_SCHEME {
dark_light::Mode::Light => Self::Light,
dark_light::Mode::Dark | dark_light::Mode::Unspecified => Self::Dark,
},
other => *other,
};
match resolved {
Self::Light => Mode::Light,
_ => Mode::Dark,
}
} }
fn base(&self) -> Style { fn base(&self) -> Style {
<uad_core::theme::Theme as theme::Base>::base(&self.0) let p = Self::palette(*self);
Style {
background_color: p.base.background,
text_color: p.bright.surface,
}
} }
fn palette(&self) -> Option<Palette> { fn palette(&self) -> Option<Palette> {
<uad_core::theme::Theme as theme::Base>::palette(&self.0) let p = Self::palette(*self);
Some(Palette {
background: p.base.background,
text: p.bright.surface,
primary: p.normal.primary,
success: p.bright.secondary,
warning: p.normal.surface,
danger: p.normal.error,
})
} }
fn name(&self) -> &str { fn name(&self) -> &str {
<uad_core::theme::Theme as theme::Base>::name(&self.0) match self {
} Self::Dark => "Dark",
} Self::Light => "Light",
Self::Lupin => "Lupin",
impl std::fmt::Display for Theme { Self::Auto => "Auto",
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { }
std::fmt::Display::fmt(&self.0, f)
} }
} }

6
flake.lock generated
View file

@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1765270179, "lastModified": 1776949667,
"narHash": "sha256-g2a4MhRKu4ymR4xwo+I+auTknXt/+j37Lnf0Mvfl1rE=", "narHash": "sha256-GMSVw35Q+294GlrTUKlx087E31z7KurReQ1YHSKp5iw=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "677fbe97984e7af3175b6c121f3c39ee5c8d62c9", "rev": "01fbdeef22b76df85ea168fbfe1bfd9e63681b30",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -27,10 +27,10 @@
with pkgs; with pkgs;
[ [
libglvnd libglvnd
xorg.libX11 libX11
xorg.libXcursor libXcursor
xorg.libXi libXi
xorg.libXrandr libXrandr
libxkbcommon libxkbcommon
wayland wayland
] ]