From 48c493c4f5a091a99e824dacd7ffbfe1fb68222b Mon Sep 17 00:00:00 2001 From: CanadianBaconBoi Date: Fri, 8 May 2026 23:30:01 +0200 Subject: [PATCH] Update Pexels and fix binding loops --- Cargo.toml | 7 ++--- src/callbacks.rs | 45 +++++++++++++++++----------- ui/data.slint | 2 ++ ui/window.slint | 77 ++++++++++++++++++++++-------------------------- 4 files changed, 68 insertions(+), 63 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 115e9f5..bbc450a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ build = "build.rs" edition = "2024" [dependencies] -#slint = { version = "1.16.1", default-features = false, features = [ slint = { git = "https://github.com/slint-ui/slint", branch = "master", default-features = false, features = [ "std", "compat-1-2", @@ -20,7 +19,7 @@ greetd_ipc = { version = "0.10.3", features = [ "tokio-codec", ] } i-slint-core = { git = "https://github.com/slint-ui/slint", branch = "master" } -toml = { version = "1.1.2+spec-1.1.0", features = ["serde"] } +toml = { version = "1.1.2", features = ["serde"] } serde = { version = "1.0.228", features = ["derive"] } serde-aux = "4.7.0" zbus = { version = "5.15.0", features = ["blocking"] } @@ -29,11 +28,11 @@ tokio-stream = {version = "0.1.18", features = ["fs"]} greetd-stub = "0.3.0" chrono = "0.4.44" -pexels-api = "0.0.5" +pexels-api = { git = "https://github.com/houseme/pexels", rev = "b0b692a" } reqwest = { version = "0.13.3", features = ["json", "default-tls"] } magick_rust = "2.0.0" +rand = "0.9.4" [build-dependencies] -#slint-build = "1.16.1" slint-build = { git = "https://github.com/slint-ui/slint", branch = "master" } diff --git a/src/callbacks.rs b/src/callbacks.rs index e707c21..b1152a3 100644 --- a/src/callbacks.rs +++ b/src/callbacks.rs @@ -8,7 +8,8 @@ use greetd_ipc::codec::TokioCodec; use i_slint_core::api::{ComponentHandle, Global, Image, Rgba8Pixel, SharedPixelBuffer, Weak}; use i_slint_core::model::{Model, VecModel}; use magick_rust::MagickWand; -use pexels_api::{Pexels, SearchBuilder}; +use pexels_api::{PexelsClient, SearchParams}; +use rand::seq::SliceRandom; use tokio::fs::File; use tokio::io::{AsyncBufReadExt, BufReader, Lines}; use tokio::net::UnixStream; @@ -273,7 +274,6 @@ pub fn register_wallpaper_callback(data: &GreeterData, display_weak: Weak { if photos.total_results > 0 { @@ -399,7 +396,7 @@ pub fn register_wallpaper_callback(data: &GreeterData, display_weak: Weak false, - }); + }).collect::>().await; + + photos.shuffle(&mut rand::rng()); + + let mut photos = tokio_stream::iter(photos); while let Some(photo) = photos.next().await { match photo { @@ -552,6 +553,13 @@ pub fn register_clean_inactive_wallpaper_callback(data: &GreeterData, display_we } }) } +pub fn register_get_default_font_size(data: &GreeterData, display_weak: Weak) { + data.on_get_default_font_size(move || { + let display = display_weak.unwrap(); + let size = display.window().size(); + ((size.width as f32).min(size.height as f32)) * 0.01 + }); +} pub fn register_callbacks( display: &GreeterDisplay, @@ -568,4 +576,5 @@ pub fn register_callbacks( register_lock_state_callback(data, data_weak.clone()); register_wallpaper_callback(data, display_weak.clone(), data_weak.clone(), cache_dir, config); register_clean_inactive_wallpaper_callback(data, display_weak.clone(), data_weak.clone()); + register_get_default_font_size(data, display_weak.clone()); } \ No newline at end of file diff --git a/ui/data.slint b/ui/data.slint index aa8871d..65e8f39 100644 --- a/ui/data.slint +++ b/ui/data.slint @@ -5,6 +5,8 @@ export global Data { in-out property error_count; + pure callback get-default-font-size() -> length; + callback login(username: string, password: string); callback loginctl(command: string); callback check-lock-states(); diff --git a/ui/window.slint b/ui/window.slint index 63314fd..4c048f5 100644 --- a/ui/window.slint +++ b/ui/window.slint @@ -1,4 +1,4 @@ -import { ScrollView, Button } from "std-widgets.slint"; +import { ScrollView, Button, TabWidget } from "std-widgets.slint"; import { Data, LoginOptionTileData } from "data.slint"; import { LoginOptionTile } from "envtile.slint"; @@ -9,7 +9,19 @@ import { IconButton } from "iconbutton.slint"; export { Data as GreeterData } from "data.slint"; export component GreeterDisplay inherits Window { - default-font-size: root.width < root.height ? root.width * 0.01 : root.height * 0.01; + changed width => { + self.default-font-size = Data.get-default-font-size(); + login_manager_underlay.width = max(self.width * 0.33, 640px); + login_manager_underlay.height = self.height; + } + + changed height => { + self.default-font-size = Data.get-default-font-size(); + login_manager_underlay.width = max(self.width * 0.33, 640px); + login_manager_underlay.height = self.height; + } + + default-font-size: Data.get-default-font-size(); in-out property selected_index <=> Data.selected_index; @@ -39,6 +51,8 @@ export component GreeterDisplay inherits Window { } full-screen: true; + preferred-width: 1920px; + preferred-height: 1080px; min-width: 640px; min-height: 480px; @@ -62,9 +76,6 @@ export component GreeterDisplay inherits Window { source: Data.wallpaper-image; image-fit: ImageFit.cover; - width: parent.width; - height: parent.height; - opacity: background-toggle && self.source.width > 0 ? 1.0 : 0.0; background_timer := Timer { interval: Data.wallpaper-cooldown * 1s; @@ -95,9 +106,6 @@ export component GreeterDisplay inherits Window { source: Data.wallpaper-image-1; image-fit: ImageFit.cover; - width: parent.width; - height: parent.height; - opacity: !background-toggle && self.source.width > 0 ? 1.0 : 0.0; } @@ -112,7 +120,7 @@ export component GreeterDisplay inherits Window { x: 1rem; y: root.height - 7.5rem; height: 6.5rem; - width: parent.width * 0.33; + width: 33%; private property show_extended; VerticalLayout { @@ -174,8 +182,6 @@ export component GreeterDisplay inherits Window { } TouchArea { - height: parent.height; - width: parent.width; clicked => { show_extended = !show_extended } @@ -185,19 +191,21 @@ export component GreeterDisplay inherits Window { login_manager_underlay := Rectangle { background: rgba(0, 0, 0, 0.5); drop-shadow-blur: 4rem; - height: parent.height; + height: 0px; + width: 0px; + + animate width { + duration: 500ms; + easing: ease-in-sine; + } + z: -1; - width: max(parent.width * 0.33, 640px); VerticalLayout { - height: parent.height; - width: parent.width; - clock := VerticalLayout { alignment: center; - height: parent.height * 0.15; + height: 15%; HorizontalLayout { - width: parent.width; alignment: center; Rectangle { y: 10rem; @@ -243,8 +251,7 @@ export component GreeterDisplay inherits Window { } login_model := VerticalLayout { alignment: center; - height: parent.height * 0.70; - width: parent.width; + height: 70%; spacing: 1rem; @@ -262,8 +269,7 @@ export component GreeterDisplay inherits Window { } environment_selector := FocusScope { - height: max(parent.width * 0.2, parent.height * 0.2); - width: parent.width; + height: 25%; key-pressed(event) => { if (event.text == Key.LeftArrow || event.text == "a" || event.text == "A") { if (Data.selected_index == 0) { @@ -284,22 +290,17 @@ export component GreeterDisplay inherits Window { } scroll_view := ScrollView { - height: parent.height; width: min(((self.height + 1rem) * tiles.length) - 1rem, parent.width); animate viewport-x { duration: 250ms; } viewport-width: ((self.height + 1rem) * tiles.length) - 1rem; -// viewport-x: -(Data.selected_index * self.height) + (self.height / 2); viewport-x: (self.viewport-width - self.height) / 2 - (Data.selected_index * (self.height)); - //x: self.viewport-width < self.width ? ((self.width - self.viewport-width) / 2) : 0; - scroll_layout := HorizontalLayout { height: parent.height; for tile[i] in tiles: LoginOptionTile { width: parent.height; - height: parent.height; icon: tile.image; label: tile.name; index: i; @@ -313,13 +314,12 @@ export component GreeterDisplay inherits Window { } // Username field HorizontalLayout { - width: parent.width; height: 2.5rem; alignment: center; username_box := LineEdit { font-size: 2rem; font-family: "monospace"; - width: parent.width * 0.45; + width: 45%; placeholder-text: "Username"; text: default_username; border-color: rgba(185, 15, 220, 0.85); @@ -338,13 +338,12 @@ export component GreeterDisplay inherits Window { } // Password field HorizontalLayout { - width: parent.width; height: 2.5rem; alignment: center; password_box := LineEdit { font-size: 2rem; font-family: "monospace"; - width: parent.width * 0.45; + width: username_box.width; placeholder-text: "Password"; input-type: password; border-color: rgba(185, 15, 220, 0.85); @@ -362,11 +361,10 @@ export component GreeterDisplay inherits Window { } // Submit button HorizontalLayout { - width: parent.width; height: 2.5rem; alignment: center; IconButton { - width: parent.width * 0.45; //min(parent.width * 0.85, 32rem); + width: username_box.width; icon: @image-url("icons/right_arrow.svg"); icon-width: 4rem; icon-height: self.icon-width/3; @@ -380,8 +378,7 @@ export component GreeterDisplay inherits Window { } } power_model := VerticalLayout { - height: parent.height * 0.15; - width: parent.width; + height: 15%; confirm_prompt := Text { horizontal-alignment: center; @@ -401,7 +398,6 @@ export component GreeterDisplay inherits Window { } HorizontalLayout { - width: parent.width; alignment: center; Rectangle { @@ -416,7 +412,6 @@ export component GreeterDisplay inherits Window { private property lastaction; padding-top: 0.4rem; - width: parent.width; alignment: center; spacing: 0.5rem; @@ -477,8 +472,8 @@ export component GreeterDisplay inherits Window { error_popup := Rectangle { background: rgba(220, 50, 50, 0.85); - width: min(parent.width * 0.5, 64rem); - height: max(parent.height * 0.125, 6rem); + width: 25%; + height: 12.5%; y: (parent.height * 0.025); opacity: 0.0; @@ -489,8 +484,8 @@ export component GreeterDisplay inherits Window { Text { color: rgba(240, 240, 240, 1); - width: parent.width * 0.85; - height: parent.height * 0.85; + width: 85%; + height: 85%; vertical-alignment: center; horizontal-alignment: center;