mirror of
https://github.com/vlinkz/nix-software-center.git
synced 2024-09-17 16:27:28 +03:00
Add rebuild output window
This commit is contained in:
parent
f355d40336
commit
0e9d1105f7
65
Cargo.lock
generated
65
Cargo.lock
generated
@ -198,9 +198,9 @@ checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck"
|
name = "bytemuck"
|
||||||
version = "1.12.1"
|
version = "1.12.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
|
checksum = "5aec14f5d4e6e3f927cd0c81f72e5710d95ee9019fbeb4b3021193867491bfd8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
@ -250,9 +250,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.73"
|
version = "1.0.74"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
checksum = "581f5dba903aac52ea3feb5ec4810848460ee833876f1f9b0fdeab1f19091574"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-expr"
|
name = "cfg-expr"
|
||||||
@ -1230,9 +1230,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
version = "0.14.20"
|
version = "0.14.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
|
checksum = "abfba89e19b959ca163c7752ba59d737c1ceea53a5d31a149c805446fc958064"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
@ -1617,7 +1617,7 @@ checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "nix-data"
|
name = "nix-data"
|
||||||
version = "0.0.2"
|
version = "0.0.2"
|
||||||
source = "git+https://github.com/snowflakelinux/nix-data?rev=a5168c768e8cf8bd3e1afe1772f8e05e5b03ed95#a5168c768e8cf8bd3e1afe1772f8e05e5b03ed95"
|
source = "git+https://github.com/snowflakelinux/nix-data#33479e595f14142f15fb6ec29cc585352c2c7703"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"csv",
|
"csv",
|
||||||
@ -1669,6 +1669,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_yaml",
|
"serde_yaml",
|
||||||
"sha256",
|
"sha256",
|
||||||
|
"sourceview5",
|
||||||
"spdx",
|
"spdx",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -1751,9 +1752,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.15.0"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
|
checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opaque-debug"
|
name = "opaque-debug"
|
||||||
@ -1967,14 +1968,14 @@ checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "png"
|
name = "png"
|
||||||
version = "0.17.6"
|
version = "0.17.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f0e7f4c94ec26ff209cee506314212639d6c91b80afb82984819fafce9df01c"
|
checksum = "5d708eaf860a19b19ce538740d2b4bdeeb8337fa53f7738455e706623ad5c638"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"flate2",
|
"flate2",
|
||||||
"miniz_oxide 0.5.4",
|
"miniz_oxide 0.6.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2500,6 +2501,42 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sourceview5"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "922cc28db6bec169868319262dd932f6403e5ce95dad0d2bb6fcc9ac03be7f10"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"gdk-pixbuf",
|
||||||
|
"gdk4",
|
||||||
|
"gio",
|
||||||
|
"glib",
|
||||||
|
"gtk4",
|
||||||
|
"libc",
|
||||||
|
"pango",
|
||||||
|
"sourceview5-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sourceview5-sys"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73277b2a53923aeecd212a89379dce7e6c687fe35fe6dd41d9b0d7b3d4c2eb0b"
|
||||||
|
dependencies = [
|
||||||
|
"gdk-pixbuf-sys",
|
||||||
|
"gdk4-sys",
|
||||||
|
"gio-sys",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"gtk4-sys",
|
||||||
|
"libc",
|
||||||
|
"pango-sys",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spdx"
|
name = "spdx"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -2777,9 +2814,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiff"
|
name = "tiff"
|
||||||
version = "0.7.3"
|
version = "0.7.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7259662e32d1e219321eb309d5f9d898b779769d81b76e762c07c8e5d38fcb65"
|
checksum = "9f71e422515e83e3ab8a03d4781d05ebf864fc61f4546e6ecffa58cbd34181a0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"flate2",
|
"flate2",
|
||||||
"jpeg-decoder",
|
"jpeg-decoder",
|
||||||
|
@ -9,6 +9,7 @@ relm4 = { version = "0.5.0-beta.4", features = ["all"] }
|
|||||||
relm4-components = { package = "relm4-components", version = "0.5.0-beta.4"}
|
relm4-components = { package = "relm4-components", version = "0.5.0-beta.4"}
|
||||||
adw = { package = "libadwaita", version = "0.2", features = ["v1_2", "gtk_v4_6"] }
|
adw = { package = "libadwaita", version = "0.2", features = ["v1_2", "gtk_v4_6"] }
|
||||||
gtk = { package = "gtk4", version = "0.5", features = ["v4_6"] }
|
gtk = { package = "gtk4", version = "0.5", features = ["v4_6"] }
|
||||||
|
sourceview5 = { version = "0.5", features = ["v5_4"] }
|
||||||
tokio = { version = "1.21", features = ["rt", "macros", "time", "rt-multi-thread", "sync", "process"] }
|
tokio = { version = "1.21", features = ["rt", "macros", "time", "rt-multi-thread", "sync", "process"] }
|
||||||
tracker = "0.1"
|
tracker = "0.1"
|
||||||
|
|
||||||
@ -17,7 +18,7 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
serde_yaml = "0.9"
|
serde_yaml = "0.9"
|
||||||
|
|
||||||
nix-editor = "0.3.0-beta.1"
|
nix-editor = "0.3.0-beta.1"
|
||||||
nix-data = { git = "https://github.com/snowflakelinux/nix-data", rev = "a5168c768e8cf8bd3e1afe1772f8e05e5b03ed95" }
|
nix-data = { git = "https://github.com/snowflakelinux/nix-data" }
|
||||||
|
|
||||||
sqlx = { version = "0.6", features = [ "runtime-tokio-native-tls" , "sqlite" ] }
|
sqlx = { version = "0.6", features = [ "runtime-tokio-native-tls" , "sqlite" ] }
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
pango
|
pango
|
||||||
pkg-config
|
pkg-config
|
||||||
polkit
|
polkit
|
||||||
|
sqlite
|
||||||
wrapGAppsHook4
|
wrapGAppsHook4
|
||||||
nixos-appstream-data
|
nixos-appstream-data
|
||||||
];
|
];
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
use super::pkgpage::{InstallType, PkgAction, PkgMsg, WorkPkg};
|
use super::pkgpage::{InstallType, PkgAction, PkgMsg, WorkPkg};
|
||||||
use super::window::{SystemPkgs, UserPkgs};
|
use super::rebuild::RebuildMsg;
|
||||||
|
use super::window::{SystemPkgs, UserPkgs, REBUILD_BROKER};
|
||||||
use log::*;
|
use log::*;
|
||||||
use nix_data::config::configfile::NixDataConfig;
|
use nix_data::config::configfile::NixDataConfig;
|
||||||
use relm4::*;
|
use relm4::*;
|
||||||
use std::error::Error;
|
use anyhow::{Result, anyhow};
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
use std::{fs, io};
|
use std::fs;
|
||||||
use tokio::io::{AsyncBufReadExt, AsyncWriteExt};
|
use tokio::io::{AsyncBufReadExt, AsyncWriteExt};
|
||||||
|
|
||||||
#[tracker::track]
|
#[tracker::track]
|
||||||
@ -265,6 +266,7 @@ impl Worker for InstallAsyncHandler {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
InstallType::System => {
|
InstallType::System => {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::Show);
|
||||||
if let Some(systemconfig) = systemconfig {
|
if let Some(systemconfig) = systemconfig {
|
||||||
match work.action {
|
match work.action {
|
||||||
PkgAction::Install => {
|
PkgAction::Install => {
|
||||||
@ -281,12 +283,15 @@ impl Worker for InstallAsyncHandler {
|
|||||||
{
|
{
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
if b {
|
if b {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::FinishSuccess);
|
||||||
sender.output(PkgMsg::FinishedProcess(work))
|
sender.output(PkgMsg::FinishedProcess(work))
|
||||||
} else {
|
} else {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::FinishError(None));
|
||||||
sender.output(PkgMsg::FailedProcess(work))
|
sender.output(PkgMsg::FailedProcess(work))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::FinishError(None));
|
||||||
sender.output(PkgMsg::FailedProcess(work));
|
sender.output(PkgMsg::FailedProcess(work));
|
||||||
warn!("Error installing system package: {}", e);
|
warn!("Error installing system package: {}", e);
|
||||||
}
|
}
|
||||||
@ -307,12 +312,15 @@ impl Worker for InstallAsyncHandler {
|
|||||||
{
|
{
|
||||||
Ok(b) => {
|
Ok(b) => {
|
||||||
if b {
|
if b {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::FinishSuccess);
|
||||||
sender.output(PkgMsg::FinishedProcess(work))
|
sender.output(PkgMsg::FinishedProcess(work))
|
||||||
} else {
|
} else {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::FinishError(None));
|
||||||
sender.output(PkgMsg::FailedProcess(work))
|
sender.output(PkgMsg::FailedProcess(work))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::FinishError(None));
|
||||||
sender.output(PkgMsg::FailedProcess(work));
|
sender.output(PkgMsg::FailedProcess(work));
|
||||||
warn!("Error removing system package: {}", e);
|
warn!("Error removing system package: {}", e);
|
||||||
}
|
}
|
||||||
@ -344,7 +352,7 @@ async fn installsys(
|
|||||||
systemconfig: String,
|
systemconfig: String,
|
||||||
flakeargs: Option<String>,
|
flakeargs: Option<String>,
|
||||||
_sender: ComponentSender<InstallAsyncHandler>,
|
_sender: ComponentSender<InstallAsyncHandler>,
|
||||||
) -> Result<bool, Box<dyn Error>> {
|
) -> Result<bool> {
|
||||||
let mut p = pkg;
|
let mut p = pkg;
|
||||||
let f = fs::read_to_string(&systemconfig)?;
|
let f = fs::read_to_string(&systemconfig)?;
|
||||||
if let Ok(s) = nix_editor::read::getwithvalue(&f, "environment.systemPackages") {
|
if let Ok(s) = nix_editor::read::getwithvalue(&f, "environment.systemPackages") {
|
||||||
@ -352,10 +360,7 @@ async fn installsys(
|
|||||||
p = format!("pkgs.{}", p);
|
p = format!("pkgs.{}", p);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(Box::new(io::Error::new(
|
return Err(anyhow!("Failed to write configuration.nix"));
|
||||||
io::ErrorKind::InvalidData,
|
|
||||||
"Failed to write configuration.nix",
|
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let out = match action {
|
let out = match action {
|
||||||
@ -363,10 +368,7 @@ async fn installsys(
|
|||||||
match nix_editor::write::addtoarr(&f, "environment.systemPackages", vec![p]) {
|
match nix_editor::write::addtoarr(&f, "environment.systemPackages", vec![p]) {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(Box::new(io::Error::new(
|
return Err(anyhow!("Failed to write configuration.nix"));
|
||||||
io::ErrorKind::InvalidData,
|
|
||||||
"Failed to write configuration.nix",
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,10 +376,7 @@ async fn installsys(
|
|||||||
match nix_editor::write::rmarr(&f, "environment.systemPackages", vec![p]) {
|
match nix_editor::write::rmarr(&f, "environment.systemPackages", vec![p]) {
|
||||||
Ok(x) => x,
|
Ok(x) => x,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
return Err(Box::new(io::Error::new(
|
return Err(anyhow!("Failed to write configuration.nix"));
|
||||||
io::ErrorKind::InvalidData,
|
|
||||||
"Failed to write configuration.nix",
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -419,13 +418,12 @@ async fn installsys(
|
|||||||
.arg(&systemconfig)
|
.arg(&systemconfig)
|
||||||
.arg("--")
|
.arg("--")
|
||||||
.arg("switch")
|
.arg("switch")
|
||||||
|
.arg("--impure")
|
||||||
.args(&rebuildargs)
|
.args(&rebuildargs)
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
|
|
||||||
// sender.input(InstallAsyncHandlerMsg::SetPid(cmd.id()));
|
|
||||||
|
|
||||||
cmd.stdin.take().unwrap().write_all(out.as_bytes()).await?;
|
cmd.stdin.take().unwrap().write_all(out.as_bytes()).await?;
|
||||||
let stderr = cmd.stderr.take().unwrap();
|
let stderr = cmd.stderr.take().unwrap();
|
||||||
let reader = tokio::io::BufReader::new(stderr);
|
let reader = tokio::io::BufReader::new(stderr);
|
||||||
@ -433,6 +431,7 @@ async fn installsys(
|
|||||||
let mut lines = reader.lines();
|
let mut lines = reader.lines();
|
||||||
while let Ok(Some(line)) = lines.next_line().await {
|
while let Ok(Some(line)) = lines.next_line().await {
|
||||||
trace!("CAUGHT LINE: {}", line);
|
trace!("CAUGHT LINE: {}", line);
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::UpdateText(line));
|
||||||
}
|
}
|
||||||
if cmd.wait().await?.success() {
|
if cmd.wait().await?.success() {
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
pub mod window;
|
|
||||||
pub mod windowloading;
|
|
||||||
pub mod pkgtile;
|
|
||||||
pub mod categories;
|
|
||||||
pub mod pkgpage;
|
|
||||||
pub mod screenshotfactory;
|
|
||||||
pub mod installworker;
|
|
||||||
pub mod searchpage;
|
|
||||||
pub mod installedpage;
|
|
||||||
pub mod updatepage;
|
|
||||||
pub mod updatedialog;
|
|
||||||
pub mod updateworker;
|
|
||||||
pub mod about;
|
pub mod about;
|
||||||
pub mod preferencespage;
|
pub mod categories;
|
||||||
pub mod categorypage;
|
pub mod categorypage;
|
||||||
pub mod categorytile;
|
pub mod categorytile;
|
||||||
|
pub mod installedpage;
|
||||||
|
pub mod installworker;
|
||||||
|
pub mod pkgpage;
|
||||||
|
pub mod pkgtile;
|
||||||
|
pub mod preferencespage;
|
||||||
|
pub mod rebuild;
|
||||||
|
pub mod screenshotfactory;
|
||||||
|
pub mod searchpage;
|
||||||
|
pub mod updatepage;
|
||||||
|
pub mod updateworker;
|
||||||
pub mod welcome;
|
pub mod welcome;
|
||||||
|
pub mod window;
|
||||||
|
pub mod windowloading;
|
||||||
|
244
src/ui/rebuild.rs
Normal file
244
src/ui/rebuild.rs
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
use super::window::AppMsg;
|
||||||
|
use adw::prelude::*;
|
||||||
|
use log::{info, trace};
|
||||||
|
use relm4::*;
|
||||||
|
use sourceview5::prelude::*;
|
||||||
|
|
||||||
|
#[tracker::track]
|
||||||
|
pub struct RebuildModel {
|
||||||
|
hidden: bool,
|
||||||
|
text: String,
|
||||||
|
status: RebuildStatus,
|
||||||
|
config: String,
|
||||||
|
path: String,
|
||||||
|
flake: Option<String>,
|
||||||
|
scheme: Option<sourceview5::StyleScheme>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum RebuildMsg {
|
||||||
|
Show,
|
||||||
|
FinishSuccess,
|
||||||
|
FinishError(Option<String>),
|
||||||
|
UpdateText(String),
|
||||||
|
Close,
|
||||||
|
SetScheme(String),
|
||||||
|
Quit,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum RebuildStatus {
|
||||||
|
Building,
|
||||||
|
Success,
|
||||||
|
Error,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[relm4::component(pub)]
|
||||||
|
impl SimpleComponent for RebuildModel {
|
||||||
|
type Init = gtk::Window;
|
||||||
|
type Input = RebuildMsg;
|
||||||
|
type Output = AppMsg;
|
||||||
|
type Widgets = RebuildWidgets;
|
||||||
|
|
||||||
|
view! {
|
||||||
|
dialog = adw::Window {
|
||||||
|
set_transient_for: Some(&parent_window),
|
||||||
|
set_modal: true,
|
||||||
|
#[track(model.changed(RebuildModel::hidden()))]
|
||||||
|
set_default_width: 500,
|
||||||
|
#[track(model.changed(RebuildModel::hidden()))]
|
||||||
|
set_default_height: 200,//295),
|
||||||
|
set_resizable: true,
|
||||||
|
#[watch]
|
||||||
|
set_visible: !model.hidden,
|
||||||
|
add_css_class: "dialog",
|
||||||
|
add_css_class: "message",
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
#[name(statusstack)]
|
||||||
|
gtk::Stack {
|
||||||
|
set_margin_top: 20,
|
||||||
|
set_transition_type: gtk::StackTransitionType::Crossfade,
|
||||||
|
set_vhomogeneous: false,
|
||||||
|
#[name(building)]
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_spacing: 10,
|
||||||
|
gtk::Spinner {
|
||||||
|
#[watch]
|
||||||
|
set_spinning: true,
|
||||||
|
set_height_request: 60,
|
||||||
|
},
|
||||||
|
gtk::Label {
|
||||||
|
set_label: "Building...",
|
||||||
|
add_css_class: "title-1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
#[name(success)]
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_spacing: 10,
|
||||||
|
gtk::Image {
|
||||||
|
add_css_class: "success",
|
||||||
|
set_icon_name: Some("object-select-symbolic"),
|
||||||
|
set_pixel_size: 128,
|
||||||
|
},
|
||||||
|
gtk::Label {
|
||||||
|
set_label: "Done!",
|
||||||
|
add_css_class: "title-1",
|
||||||
|
},
|
||||||
|
gtk::Label {
|
||||||
|
set_label: "Rebuild successful!",
|
||||||
|
add_css_class: "dim-label",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
#[name(error)]
|
||||||
|
gtk::Box {
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
set_spacing: 10,
|
||||||
|
gtk::Image {
|
||||||
|
add_css_class: "error",
|
||||||
|
set_icon_name: Some("dialog-error-symbolic"),
|
||||||
|
set_pixel_size: 128,
|
||||||
|
},
|
||||||
|
gtk::Label {
|
||||||
|
set_label: "Error!",
|
||||||
|
add_css_class: "title-1",
|
||||||
|
},
|
||||||
|
gtk::Label {
|
||||||
|
set_label: "Rebuild failed! See below for error message.",
|
||||||
|
add_css_class: "dim-label",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
gtk::Frame {
|
||||||
|
set_margin_all: 20,
|
||||||
|
#[name(scrollwindow)]
|
||||||
|
gtk::ScrolledWindow {
|
||||||
|
set_max_content_height: 500,
|
||||||
|
set_min_content_height: 100,
|
||||||
|
#[name(outview)]
|
||||||
|
sourceview5::View {
|
||||||
|
set_editable: false,
|
||||||
|
set_cursor_visible: false,
|
||||||
|
set_monospace: true,
|
||||||
|
set_top_margin: 5,
|
||||||
|
set_bottom_margin: 5,
|
||||||
|
set_left_margin: 5,
|
||||||
|
set_vexpand: true,
|
||||||
|
set_hexpand: true,
|
||||||
|
set_vscroll_policy: gtk::ScrollablePolicy::Minimum,
|
||||||
|
#[wrap(Some)]
|
||||||
|
set_buffer: outbuf = &sourceview5::Buffer {
|
||||||
|
#[track(model.changed(RebuildModel::scheme()))]
|
||||||
|
set_style_scheme: model.scheme.as_ref(),
|
||||||
|
#[track(model.changed(RebuildModel::text()))]
|
||||||
|
set_text: &model.text,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
gtk::Box {
|
||||||
|
add_css_class: "dialog-action-area",
|
||||||
|
set_orientation: gtk::Orientation::Horizontal,
|
||||||
|
set_homogeneous: true,
|
||||||
|
#[track(model.changed(RebuildModel::status()))]
|
||||||
|
set_visible: model.status != RebuildStatus::Building,
|
||||||
|
gtk::Button {
|
||||||
|
set_label: "Close",
|
||||||
|
#[track(model.changed(RebuildModel::status()))]
|
||||||
|
set_visible: model.status != RebuildStatus::Building,
|
||||||
|
connect_clicked[sender] => move |_| {
|
||||||
|
sender.input(RebuildMsg::Close)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pre_view() {
|
||||||
|
match model.status {
|
||||||
|
RebuildStatus::Building => {
|
||||||
|
statusstack.set_visible_child(building);
|
||||||
|
}
|
||||||
|
RebuildStatus::Success => statusstack.set_visible_child(success),
|
||||||
|
RebuildStatus::Error => statusstack.set_visible_child(error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn post_view() {
|
||||||
|
let adj = scrollwindow.vadjustment();
|
||||||
|
if model.status == RebuildStatus::Building {
|
||||||
|
adj.set_upper(adj.upper() + 20.0);
|
||||||
|
}
|
||||||
|
adj.set_value(adj.upper());
|
||||||
|
if model.status != RebuildStatus::Building {
|
||||||
|
outview.scroll_to_mark(&outview.buffer().get_insert(), 0.0, true, 0.0, 0.0);
|
||||||
|
scrollwindow.hadjustment().set_value(0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init(
|
||||||
|
parent_window: Self::Init,
|
||||||
|
root: &Self::Root,
|
||||||
|
sender: ComponentSender<Self>,
|
||||||
|
) -> ComponentParts<Self> {
|
||||||
|
|
||||||
|
let model = RebuildModel {
|
||||||
|
hidden: true,
|
||||||
|
text: String::new(),
|
||||||
|
status: RebuildStatus::Building,
|
||||||
|
config: String::new(),
|
||||||
|
path: String::new(),
|
||||||
|
flake: None,
|
||||||
|
scheme: None,
|
||||||
|
tracker: 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
let widgets = view_output!();
|
||||||
|
|
||||||
|
ComponentParts { model, widgets }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update(&mut self, msg: Self::Input, sender: ComponentSender<Self>) {
|
||||||
|
self.reset();
|
||||||
|
match msg {
|
||||||
|
RebuildMsg::Show => {
|
||||||
|
self.update_hidden(|x| *x = false);
|
||||||
|
self.update_text(|x| x.clear());
|
||||||
|
self.set_status(RebuildStatus::Building);
|
||||||
|
}
|
||||||
|
RebuildMsg::UpdateText(s) => {
|
||||||
|
info!("RebuildMsg::UpdateText({})", s);
|
||||||
|
let newtext = if self.text.is_empty() {
|
||||||
|
s
|
||||||
|
} else {
|
||||||
|
format!("{}\n{}", self.text, s)
|
||||||
|
};
|
||||||
|
self.set_text(newtext);
|
||||||
|
trace!("NEWTEXT: {}", self.text);
|
||||||
|
}
|
||||||
|
RebuildMsg::FinishSuccess => {
|
||||||
|
self.set_status(RebuildStatus::Success);
|
||||||
|
}
|
||||||
|
RebuildMsg::FinishError(msg) => {
|
||||||
|
if let Some(s) = msg {
|
||||||
|
self.set_text(s)
|
||||||
|
}
|
||||||
|
self.update_hidden(|x| *x = false);
|
||||||
|
self.set_status(RebuildStatus::Error);
|
||||||
|
}
|
||||||
|
RebuildMsg::Close => {
|
||||||
|
self.update_hidden(|x| *x = true);
|
||||||
|
self.update_text(|x| x.clear());
|
||||||
|
}
|
||||||
|
RebuildMsg::SetScheme(scheme) => {
|
||||||
|
self.set_scheme(sourceview5::StyleSchemeManager::default().scheme(&scheme));
|
||||||
|
}
|
||||||
|
RebuildMsg::Quit => {
|
||||||
|
sender.output(AppMsg::Close);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,137 +0,0 @@
|
|||||||
use adw::prelude::*;
|
|
||||||
use relm4::*;
|
|
||||||
|
|
||||||
use super::updatepage::UpdatePageMsg;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct UpdateDialogModel {
|
|
||||||
hidden: bool,
|
|
||||||
message: String,
|
|
||||||
done: bool,
|
|
||||||
failed: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum UpdateDialogMsg {
|
|
||||||
Show(String),
|
|
||||||
Close,
|
|
||||||
Done,
|
|
||||||
Failed,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[relm4::component(pub)]
|
|
||||||
impl SimpleComponent for UpdateDialogModel {
|
|
||||||
type Init = gtk::Window;
|
|
||||||
type Input = UpdateDialogMsg;
|
|
||||||
type Output = UpdatePageMsg;
|
|
||||||
type Widgets = UpdateDialogWidgets;
|
|
||||||
|
|
||||||
view! {
|
|
||||||
dialog = adw::Window {
|
|
||||||
#[watch]
|
|
||||||
set_visible: !model.hidden,
|
|
||||||
set_transient_for: Some(&parent_window),
|
|
||||||
set_modal: true,
|
|
||||||
set_resizable: false,
|
|
||||||
set_default_width: 500,
|
|
||||||
set_default_height: 200,
|
|
||||||
add_css_class: "dialog",
|
|
||||||
add_css_class: "message",
|
|
||||||
gtk::Box {
|
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
|
||||||
set_halign: gtk::Align::Fill,
|
|
||||||
set_valign: gtk::Align::Fill,
|
|
||||||
set_hexpand: true,
|
|
||||||
set_vexpand: true,
|
|
||||||
gtk::Box {
|
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
|
||||||
set_halign: gtk::Align::Center,
|
|
||||||
set_valign: gtk::Align::Center,
|
|
||||||
set_hexpand: true,
|
|
||||||
set_vexpand: true,
|
|
||||||
set_margin_all: 15,
|
|
||||||
set_spacing: 10,
|
|
||||||
gtk::Label {
|
|
||||||
#[watch]
|
|
||||||
set_visible: !model.message.is_empty(),
|
|
||||||
add_css_class: "title-1",
|
|
||||||
#[watch]
|
|
||||||
set_label: &model.message,
|
|
||||||
},
|
|
||||||
if model.done {
|
|
||||||
gtk::Image {
|
|
||||||
add_css_class: "success",
|
|
||||||
set_icon_name: Some("emblem-ok-symbolic"),
|
|
||||||
set_pixel_size: 128,
|
|
||||||
}
|
|
||||||
} else if model.failed {
|
|
||||||
gtk::Image {
|
|
||||||
add_css_class: "error",
|
|
||||||
set_icon_name: Some("dialog-error-symbolic"),
|
|
||||||
set_pixel_size: 128,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
gtk::Spinner {
|
|
||||||
#[watch]
|
|
||||||
set_visible: !model.done,
|
|
||||||
#[watch]
|
|
||||||
set_spinning: !model.done,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
gtk::Box {
|
|
||||||
#[watch]
|
|
||||||
set_visible: model.done || model.failed,
|
|
||||||
add_css_class: "dialog-action-area",
|
|
||||||
set_valign: gtk::Align::End,
|
|
||||||
set_vexpand: true,
|
|
||||||
set_orientation: gtk::Orientation::Horizontal,
|
|
||||||
set_homogeneous: true,
|
|
||||||
gtk::Button {
|
|
||||||
set_label: "Close",
|
|
||||||
connect_clicked[sender] => move |_| {
|
|
||||||
sender.input(UpdateDialogMsg::Close);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn init(
|
|
||||||
parent_window: Self::Init,
|
|
||||||
root: &Self::Root,
|
|
||||||
sender: ComponentSender<Self>,
|
|
||||||
) -> ComponentParts<Self> {
|
|
||||||
let model = UpdateDialogModel {
|
|
||||||
hidden: true,
|
|
||||||
done: false,
|
|
||||||
failed: false,
|
|
||||||
message: String::default(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let widgets = view_output!();
|
|
||||||
|
|
||||||
ComponentParts { model, widgets }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, msg: Self::Input, _sender: ComponentSender<Self>) {
|
|
||||||
match msg {
|
|
||||||
UpdateDialogMsg::Show(desc) => {
|
|
||||||
self.message = desc;
|
|
||||||
self.hidden = false;
|
|
||||||
self.done = false;
|
|
||||||
self.failed = false;
|
|
||||||
}
|
|
||||||
UpdateDialogMsg::Close => {
|
|
||||||
self.hidden = true;
|
|
||||||
}
|
|
||||||
UpdateDialogMsg::Done => {
|
|
||||||
self.done = true;
|
|
||||||
}
|
|
||||||
UpdateDialogMsg::Failed => {
|
|
||||||
self.failed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
use crate::APPINFO;
|
use crate::APPINFO;
|
||||||
|
|
||||||
use super::{pkgpage::InstallType, window::*, updatedialog::{UpdateDialogModel, UpdateDialogMsg}, updateworker::{UpdateAsyncHandler, UpdateAsyncHandlerMsg, UpdateAsyncHandlerInit}};
|
use super::{pkgpage::InstallType, window::*, updateworker::{UpdateAsyncHandler, UpdateAsyncHandlerMsg, UpdateAsyncHandlerInit}, rebuild::RebuildMsg};
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use nix_data::config::configfile::NixDataConfig;
|
use nix_data::config::configfile::NixDataConfig;
|
||||||
use relm4::{factory::*, gtk::pango, *};
|
use relm4::{factory::*, gtk::pango, *};
|
||||||
@ -16,8 +16,6 @@ pub struct UpdatePageModel {
|
|||||||
updatesystemlist: FactoryVecDeque<UpdateItemModel>,
|
updatesystemlist: FactoryVecDeque<UpdateItemModel>,
|
||||||
channelupdate: Option<(String, String)>,
|
channelupdate: Option<(String, String)>,
|
||||||
#[tracker::no_eq]
|
#[tracker::no_eq]
|
||||||
updatedialog: Controller<UpdateDialogModel>,
|
|
||||||
#[tracker::no_eq]
|
|
||||||
updateworker: WorkerController<UpdateAsyncHandler>,
|
updateworker: WorkerController<UpdateAsyncHandler>,
|
||||||
config: NixDataConfig,
|
config: NixDataConfig,
|
||||||
systype: SystemPkgs,
|
systype: SystemPkgs,
|
||||||
@ -34,11 +32,10 @@ pub enum UpdatePageMsg {
|
|||||||
UpdateSystem,
|
UpdateSystem,
|
||||||
UpdateAllUser,
|
UpdateAllUser,
|
||||||
UpdateUser(String),
|
UpdateUser(String),
|
||||||
UpdateChannels,
|
// UpdateChannels,
|
||||||
UpdateSystemAndChannels,
|
// UpdateSystemAndChannels,
|
||||||
UpdateAll,
|
UpdateAll,
|
||||||
DoneWorking,
|
DoneWorking,
|
||||||
DoneLoading,
|
|
||||||
FailedWorking,
|
FailedWorking,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,101 +84,101 @@ impl SimpleComponent for UpdatePageModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
gtk::Box {
|
// gtk::Box {
|
||||||
set_orientation: gtk::Orientation::Horizontal,
|
// set_orientation: gtk::Orientation::Horizontal,
|
||||||
set_hexpand: true,
|
// set_hexpand: true,
|
||||||
#[watch]
|
// #[watch]
|
||||||
set_visible: model.channelupdate.is_some(),
|
// set_visible: model.channelupdate.is_some(),
|
||||||
gtk::Label {
|
// gtk::Label {
|
||||||
set_halign: gtk::Align::Start,
|
// set_halign: gtk::Align::Start,
|
||||||
add_css_class: "title-4",
|
// add_css_class: "title-4",
|
||||||
set_label: "Channels",
|
// set_label: "Channels",
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
gtk::ListBox {
|
// gtk::ListBox {
|
||||||
set_valign: gtk::Align::Start,
|
// set_valign: gtk::Align::Start,
|
||||||
add_css_class: "boxed-list",
|
// add_css_class: "boxed-list",
|
||||||
set_selection_mode: gtk::SelectionMode::None,
|
// set_selection_mode: gtk::SelectionMode::None,
|
||||||
#[watch]
|
// #[watch]
|
||||||
set_visible: model.channelupdate.is_some(),
|
// set_visible: model.channelupdate.is_some(),
|
||||||
adw::PreferencesRow {
|
// adw::PreferencesRow {
|
||||||
set_activatable: false,
|
// set_activatable: false,
|
||||||
set_can_focus: false,
|
// set_can_focus: false,
|
||||||
#[wrap(Some)]
|
// #[wrap(Some)]
|
||||||
set_child = >k::Box {
|
// set_child = >k::Box {
|
||||||
set_orientation: gtk::Orientation::Horizontal,
|
// set_orientation: gtk::Orientation::Horizontal,
|
||||||
set_hexpand: true,
|
// set_hexpand: true,
|
||||||
set_spacing: 10,
|
// set_spacing: 10,
|
||||||
set_margin_all: 10,
|
// set_margin_all: 10,
|
||||||
adw::Bin {
|
// adw::Bin {
|
||||||
set_valign: gtk::Align::Center,
|
// set_valign: gtk::Align::Center,
|
||||||
gtk::Image {
|
// gtk::Image {
|
||||||
add_css_class: "icon-dropshadow",
|
// add_css_class: "icon-dropshadow",
|
||||||
set_halign: gtk::Align::Start,
|
// set_halign: gtk::Align::Start,
|
||||||
set_icon_name: Some("application-x-addon"),
|
// set_icon_name: Some("application-x-addon"),
|
||||||
set_pixel_size: 64,
|
// set_pixel_size: 64,
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
gtk::Box {
|
// gtk::Box {
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
// set_orientation: gtk::Orientation::Vertical,
|
||||||
set_halign: gtk::Align::Fill,
|
// set_halign: gtk::Align::Fill,
|
||||||
set_valign: gtk::Align::Center,
|
// set_valign: gtk::Align::Center,
|
||||||
set_hexpand: true,
|
// set_hexpand: true,
|
||||||
set_spacing: 2,
|
// set_spacing: 2,
|
||||||
gtk::Label {
|
// gtk::Label {
|
||||||
set_halign: gtk::Align::Start,
|
// set_halign: gtk::Align::Start,
|
||||||
set_label: "nixos",
|
// set_label: "nixos",
|
||||||
set_ellipsize: pango::EllipsizeMode::End,
|
// set_ellipsize: pango::EllipsizeMode::End,
|
||||||
set_lines: 1,
|
// set_lines: 1,
|
||||||
set_wrap: true,
|
// set_wrap: true,
|
||||||
set_max_width_chars: 0,
|
// set_max_width_chars: 0,
|
||||||
},
|
// },
|
||||||
gtk::Label {
|
// gtk::Label {
|
||||||
set_halign: gtk::Align::Start,
|
// set_halign: gtk::Align::Start,
|
||||||
add_css_class: "dim-label",
|
// add_css_class: "dim-label",
|
||||||
add_css_class: "caption",
|
// add_css_class: "caption",
|
||||||
set_label: {
|
// set_label: {
|
||||||
&(if let Some((old, new)) = &model.channelupdate {
|
// &(if let Some((old, new)) = &model.channelupdate {
|
||||||
format!("{} → {}", old, new)
|
// format!("{} → {}", old, new)
|
||||||
} else {
|
// } else {
|
||||||
String::default()
|
// String::default()
|
||||||
})
|
// })
|
||||||
},
|
// },
|
||||||
set_visible: model.channelupdate.is_some(),
|
// set_visible: model.channelupdate.is_some(),
|
||||||
set_ellipsize: pango::EllipsizeMode::End,
|
// set_ellipsize: pango::EllipsizeMode::End,
|
||||||
set_lines: 1,
|
// set_lines: 1,
|
||||||
set_wrap: true,
|
// set_wrap: true,
|
||||||
set_max_width_chars: 0,
|
// set_max_width_chars: 0,
|
||||||
},
|
// },
|
||||||
},
|
// },
|
||||||
gtk::Box {
|
// gtk::Box {
|
||||||
set_orientation: gtk::Orientation::Vertical,
|
// set_orientation: gtk::Orientation::Vertical,
|
||||||
set_spacing: 5,
|
// set_spacing: 5,
|
||||||
set_halign: gtk::Align::End,
|
// set_halign: gtk::Align::End,
|
||||||
set_valign: gtk::Align::Center,
|
// set_valign: gtk::Align::Center,
|
||||||
gtk::Button {
|
// gtk::Button {
|
||||||
add_css_class: "suggested-action",
|
// add_css_class: "suggested-action",
|
||||||
set_valign: gtk::Align::Center,
|
// set_valign: gtk::Align::Center,
|
||||||
set_halign: gtk::Align::End,
|
// set_halign: gtk::Align::End,
|
||||||
set_label: "Update channel and system",
|
// set_label: "Update channel and system",
|
||||||
set_can_focus: false,
|
// set_can_focus: false,
|
||||||
connect_clicked[sender] => move |_| {
|
// connect_clicked[sender] => move |_| {
|
||||||
sender.input(UpdatePageMsg::UpdateSystemAndChannels);
|
// sender.input(UpdatePageMsg::UpdateSystemAndChannels);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
gtk::Button {
|
// gtk::Button {
|
||||||
set_valign: gtk::Align::Center,
|
// set_valign: gtk::Align::Center,
|
||||||
set_halign: gtk::Align::End,
|
// set_halign: gtk::Align::End,
|
||||||
set_label: "Update channel only",
|
// set_label: "Update channel only",
|
||||||
set_can_focus: false,
|
// set_can_focus: false,
|
||||||
connect_clicked[sender] => move |_| {
|
// connect_clicked[sender] => move |_| {
|
||||||
sender.input(UpdatePageMsg::UpdateChannels);
|
// sender.input(UpdatePageMsg::UpdateChannels);
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
},
|
// },
|
||||||
gtk::Box {
|
gtk::Box {
|
||||||
set_orientation: gtk::Orientation::Horizontal,
|
set_orientation: gtk::Orientation::Horizontal,
|
||||||
set_hexpand: true,
|
set_hexpand: true,
|
||||||
@ -234,7 +231,7 @@ impl SimpleComponent for UpdatePageModel {
|
|||||||
set_halign: gtk::Align::End,
|
set_halign: gtk::Align::End,
|
||||||
set_hexpand: true,
|
set_hexpand: true,
|
||||||
set_valign: gtk::Align::Center,
|
set_valign: gtk::Align::Center,
|
||||||
set_label: "Update All",
|
set_label: "Update",
|
||||||
connect_clicked[sender] => move |_|{
|
connect_clicked[sender] => move |_|{
|
||||||
sender.input(UpdatePageMsg::UpdateSystem);
|
sender.input(UpdatePageMsg::UpdateSystem);
|
||||||
},
|
},
|
||||||
@ -282,9 +279,6 @@ impl SimpleComponent for UpdatePageModel {
|
|||||||
root: &Self::Root,
|
root: &Self::Root,
|
||||||
sender: ComponentSender<Self>,
|
sender: ComponentSender<Self>,
|
||||||
) -> ComponentParts<Self> {
|
) -> ComponentParts<Self> {
|
||||||
let updatedialog = UpdateDialogModel::builder()
|
|
||||||
.launch(initparams.window.upcast())
|
|
||||||
.forward(sender.input_sender(), identity);
|
|
||||||
let updateworker = UpdateAsyncHandler::builder()
|
let updateworker = UpdateAsyncHandler::builder()
|
||||||
.detach_worker(UpdateAsyncHandlerInit { syspkgs: initparams.systype.clone(), userpkgs: initparams.usertype.clone() })
|
.detach_worker(UpdateAsyncHandlerInit { syspkgs: initparams.systype.clone(), userpkgs: initparams.usertype.clone() })
|
||||||
.forward(sender.input_sender(), identity);
|
.forward(sender.input_sender(), identity);
|
||||||
@ -297,7 +291,6 @@ impl SimpleComponent for UpdatePageModel {
|
|||||||
updatesystemlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
|
updatesystemlist: FactoryVecDeque::new(gtk::ListBox::new(), sender.input_sender()),
|
||||||
channelupdate: None,
|
channelupdate: None,
|
||||||
updatetracker: 0,
|
updatetracker: 0,
|
||||||
updatedialog,
|
|
||||||
updateworker,
|
updateworker,
|
||||||
config,
|
config,
|
||||||
systype: initparams.systype,
|
systype: initparams.systype,
|
||||||
@ -329,13 +322,13 @@ impl SimpleComponent for UpdatePageModel {
|
|||||||
info!("UpdatePageMsg::Update");
|
info!("UpdatePageMsg::Update");
|
||||||
debug!("UPDATEUSERLIST: {:?}", updateuserlist);
|
debug!("UPDATEUSERLIST: {:?}", updateuserlist);
|
||||||
debug!("UPDATESYSTEMLIST: {:?}", updatesystemlist);
|
debug!("UPDATESYSTEMLIST: {:?}", updatesystemlist);
|
||||||
self.channelupdate = match nix_data::cache::channel::uptodate() {
|
// self.channelupdate = match nix_data::cache::channel::uptodate() {
|
||||||
Ok(x) => {
|
// Ok(x) => {
|
||||||
x
|
// x
|
||||||
},
|
// },
|
||||||
Err(_) => None,
|
// Err(_) => None,
|
||||||
};
|
// };
|
||||||
debug!("CHANNELUPDATE: {:?}", self.channelupdate);
|
// debug!("CHANNELUPDATE: {:?}", self.channelupdate);
|
||||||
self.update_updatetracker(|_| ());
|
self.update_updatetracker(|_| ());
|
||||||
let mut updateuserlist_guard = self.updateuserlist.guard();
|
let mut updateuserlist_guard = self.updateuserlist.guard();
|
||||||
updateuserlist_guard.clear();
|
updateuserlist_guard.clear();
|
||||||
@ -347,6 +340,16 @@ impl SimpleComponent for UpdatePageModel {
|
|||||||
for updatesystem in updatesystemlist {
|
for updatesystem in updatesystemlist {
|
||||||
updatesystemlist_guard.push_back(updatesystem);
|
updatesystemlist_guard.push_back(updatesystem);
|
||||||
}
|
}
|
||||||
|
updatesystemlist_guard.push_back(UpdateItem {
|
||||||
|
pkg: None,
|
||||||
|
name: "NixOS".to_string(),
|
||||||
|
pname: "nixos".to_string(),
|
||||||
|
summary: None,
|
||||||
|
icon: None,
|
||||||
|
pkgtype: InstallType::System,
|
||||||
|
verfrom: None,
|
||||||
|
verto: None,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
UpdatePageMsg::OpenRow(row, pkgtype) => match pkgtype {
|
UpdatePageMsg::OpenRow(row, pkgtype) => match pkgtype {
|
||||||
InstallType::User => {
|
InstallType::User => {
|
||||||
@ -366,38 +369,36 @@ impl SimpleComponent for UpdatePageModel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
UpdatePageMsg::UpdateChannels => {
|
// UpdatePageMsg::UpdateChannels => {
|
||||||
self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating channels...")));
|
// self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating channels...")));
|
||||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateChannels);
|
// self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateChannels);
|
||||||
}
|
// }
|
||||||
UpdatePageMsg::UpdateSystemAndChannels => {
|
// UpdatePageMsg::UpdateSystemAndChannels => {
|
||||||
self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating system and channels...")));
|
// self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating system and channels...")));
|
||||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateChannelsAndSystem);
|
// self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateChannelsAndSystem);
|
||||||
}
|
// }
|
||||||
UpdatePageMsg::UpdateSystem => {
|
UpdatePageMsg::UpdateSystem => {
|
||||||
self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating system...")));
|
REBUILD_BROKER.send(RebuildMsg::Show);
|
||||||
self.updateworker.emit(UpdateAsyncHandlerMsg::RebuildSystem);
|
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateSystem);
|
||||||
}
|
}
|
||||||
UpdatePageMsg::UpdateUser(pkg) => {
|
UpdatePageMsg::UpdateUser(pkg) => {
|
||||||
info!("UPDATE USER PKG: {}", pkg);
|
info!("UPDATE USER PKG: {}", pkg);
|
||||||
warn!("unimplemented");
|
warn!("unimplemented");
|
||||||
}
|
}
|
||||||
UpdatePageMsg::UpdateAllUser => {
|
UpdatePageMsg::UpdateAllUser => {
|
||||||
self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating all user packages...")));
|
REBUILD_BROKER.send(RebuildMsg::Show);
|
||||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateUserPkgs);
|
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateUserPkgs);
|
||||||
}
|
}
|
||||||
UpdatePageMsg::UpdateAll => {
|
UpdatePageMsg::UpdateAll => {
|
||||||
self.updatedialog.emit(UpdateDialogMsg::Show(String::from("Updating everything...")));
|
REBUILD_BROKER.send(RebuildMsg::Show);
|
||||||
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateAll);
|
self.updateworker.emit(UpdateAsyncHandlerMsg::UpdateAll);
|
||||||
}
|
}
|
||||||
UpdatePageMsg::DoneWorking => {
|
UpdatePageMsg::DoneWorking => {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::FinishSuccess);
|
||||||
sender.output(AppMsg::UpdateInstalledPkgs);
|
sender.output(AppMsg::UpdateInstalledPkgs);
|
||||||
}
|
}
|
||||||
UpdatePageMsg::DoneLoading => {
|
|
||||||
self.updatedialog.emit(UpdateDialogMsg::Done);
|
|
||||||
}
|
|
||||||
UpdatePageMsg::FailedWorking => {
|
UpdatePageMsg::FailedWorking => {
|
||||||
self.updatedialog.emit(UpdateDialogMsg::Failed);
|
REBUILD_BROKER.send(RebuildMsg::FinishError(None));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use nix_data::config::configfile::NixDataConfig;
|
use nix_data::config::configfile::NixDataConfig;
|
||||||
use relm4::*;
|
use relm4::*;
|
||||||
use std::{error::Error, path::Path, process::Stdio};
|
use std::{path::Path, process::Stdio};
|
||||||
use tokio::io::AsyncBufReadExt;
|
use tokio::io::AsyncBufReadExt;
|
||||||
|
use anyhow::Result;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
|
||||||
|
use crate::ui::{rebuild::RebuildMsg, window::REBUILD_BROKER};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
updatepage::UpdatePageMsg,
|
updatepage::UpdatePageMsg,
|
||||||
window::{SystemPkgs, UserPkgs},
|
window::{SystemPkgs, UserPkgs},
|
||||||
@ -25,8 +28,10 @@ pub enum UpdateAsyncHandlerMsg {
|
|||||||
UpdateConfig(NixDataConfig),
|
UpdateConfig(NixDataConfig),
|
||||||
UpdatePkgTypes(SystemPkgs, UserPkgs),
|
UpdatePkgTypes(SystemPkgs, UserPkgs),
|
||||||
|
|
||||||
UpdateChannels,
|
// UpdateChannels,
|
||||||
UpdateChannelsAndSystem,
|
// UpdateChannelsAndSystem,
|
||||||
|
|
||||||
|
UpdateSystem,
|
||||||
|
|
||||||
RebuildSystem,
|
RebuildSystem,
|
||||||
UpdateUserPkgs,
|
UpdateUserPkgs,
|
||||||
@ -79,35 +84,52 @@ impl Worker for UpdateAsyncHandler {
|
|||||||
self.syspkgs = syspkgs;
|
self.syspkgs = syspkgs;
|
||||||
self.userpkgs = userpkgs;
|
self.userpkgs = userpkgs;
|
||||||
}
|
}
|
||||||
UpdateAsyncHandlerMsg::UpdateChannels => {
|
// UpdateAsyncHandlerMsg::UpdateChannels => {
|
||||||
|
// let systemconfig = self.systemconfig.clone();
|
||||||
|
// let flakeargs = self.flakeargs.clone();
|
||||||
|
// let syspkgs = self.syspkgs.clone();
|
||||||
|
// relm4::spawn(async move {
|
||||||
|
// let result = runcmd(NscCmd::Channel, systemconfig, flakeargs, syspkgs).await;
|
||||||
|
// match result {
|
||||||
|
// Ok(true) => {
|
||||||
|
// sender.output(UpdatePageMsg::DoneWorking);
|
||||||
|
// }
|
||||||
|
// _ => {
|
||||||
|
// warn!("UPDATE CHANNEL FAILED");
|
||||||
|
// sender.output(UpdatePageMsg::FailedWorking);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// UpdateAsyncHandlerMsg::UpdateChannelsAndSystem => {
|
||||||
|
// let systenconfig = self.systemconfig.clone();
|
||||||
|
// let flakeargs = self.flakeargs.clone();
|
||||||
|
// let syspkgs = self.syspkgs.clone();
|
||||||
|
// relm4::spawn(async move {
|
||||||
|
// let result = runcmd(NscCmd::All, systenconfig, flakeargs, syspkgs).await;
|
||||||
|
// match result {
|
||||||
|
// Ok(true) => {
|
||||||
|
// sender.output(UpdatePageMsg::DoneWorking);
|
||||||
|
// }
|
||||||
|
// _ => {
|
||||||
|
// warn!("UPDATE CHANNEL AND SYSTEM FAILED");
|
||||||
|
// sender.output(UpdatePageMsg::FailedWorking);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
UpdateAsyncHandlerMsg::UpdateSystem => {
|
||||||
let systemconfig = self.systemconfig.clone();
|
let systemconfig = self.systemconfig.clone();
|
||||||
let flakeargs = self.flakeargs.clone();
|
let flakeargs = self.flakeargs.clone();
|
||||||
let syspkgs = self.syspkgs.clone();
|
let syspkgs = self.syspkgs.clone();
|
||||||
relm4::spawn(async move {
|
relm4::spawn(async move {
|
||||||
let result = runcmd(NscCmd::Channel, systemconfig, flakeargs, syspkgs).await;
|
let result = runcmd(NscCmd::All, systemconfig, flakeargs, syspkgs).await;
|
||||||
match result {
|
match result {
|
||||||
Ok(true) => {
|
Ok(true) => {
|
||||||
sender.output(UpdatePageMsg::DoneWorking);
|
sender.output(UpdatePageMsg::DoneWorking);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
warn!("UPDATE CHANNEL FAILED");
|
warn!("UPDATE SYSTEM FAILED");
|
||||||
sender.output(UpdatePageMsg::FailedWorking);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
UpdateAsyncHandlerMsg::UpdateChannelsAndSystem => {
|
|
||||||
let systenconfig = self.systemconfig.clone();
|
|
||||||
let flakeargs = self.flakeargs.clone();
|
|
||||||
let syspkgs = self.syspkgs.clone();
|
|
||||||
relm4::spawn(async move {
|
|
||||||
let result = runcmd(NscCmd::All, systenconfig, flakeargs, syspkgs).await;
|
|
||||||
match result {
|
|
||||||
Ok(true) => {
|
|
||||||
sender.output(UpdatePageMsg::DoneWorking);
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
warn!("UPDATE CHANNEL AND SYSTEM FAILED");
|
|
||||||
sender.output(UpdatePageMsg::FailedWorking);
|
sender.output(UpdatePageMsg::FailedWorking);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,7 +212,7 @@ async fn runcmd(
|
|||||||
_systemconfig: Option<String>,
|
_systemconfig: Option<String>,
|
||||||
flakeargs: Option<String>,
|
flakeargs: Option<String>,
|
||||||
syspkgs: SystemPkgs,
|
syspkgs: SystemPkgs,
|
||||||
) -> Result<bool, Box<dyn Error + Send + Sync>> {
|
) -> Result<bool> {
|
||||||
let exe = match std::env::current_exe() {
|
let exe = match std::env::current_exe() {
|
||||||
Ok(mut e) => {
|
Ok(mut e) => {
|
||||||
e.pop(); // root/bin
|
e.pop(); // root/bin
|
||||||
@ -255,6 +277,7 @@ async fn runcmd(
|
|||||||
.arg(flakepath)
|
.arg(flakepath)
|
||||||
.arg("--")
|
.arg("--")
|
||||||
.arg("switch")
|
.arg("switch")
|
||||||
|
.arg("--impure")
|
||||||
.args(&rebuildargs)
|
.args(&rebuildargs)
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.spawn()?,
|
.spawn()?,
|
||||||
@ -267,6 +290,7 @@ async fn runcmd(
|
|||||||
|
|
||||||
let mut lines = reader.lines();
|
let mut lines = reader.lines();
|
||||||
while let Ok(Some(line)) = lines.next_line().await {
|
while let Ok(Some(line)) = lines.next_line().await {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::UpdateText(line.to_string()));
|
||||||
trace!("CAUGHT REBUILD LINE: {}", line);
|
trace!("CAUGHT REBUILD LINE: {}", line);
|
||||||
}
|
}
|
||||||
if cmd.wait().await?.success() {
|
if cmd.wait().await?.success() {
|
||||||
@ -276,7 +300,7 @@ async fn runcmd(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn updateenv() -> Result<bool, Box<dyn Error + Send + Sync>> {
|
async fn updateenv() -> Result<bool> {
|
||||||
let mut cmd = tokio::process::Command::new("nix-env")
|
let mut cmd = tokio::process::Command::new("nix-env")
|
||||||
.arg("-u")
|
.arg("-u")
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
@ -287,6 +311,7 @@ async fn updateenv() -> Result<bool, Box<dyn Error + Send + Sync>> {
|
|||||||
|
|
||||||
let mut lines = reader.lines();
|
let mut lines = reader.lines();
|
||||||
while let Ok(Some(line)) = lines.next_line().await {
|
while let Ok(Some(line)) = lines.next_line().await {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::UpdateText(line.to_string()));
|
||||||
trace!("CAUGHT NIXENV LINE: {}", line);
|
trace!("CAUGHT NIXENV LINE: {}", line);
|
||||||
}
|
}
|
||||||
if cmd.wait().await?.success() {
|
if cmd.wait().await?.success() {
|
||||||
@ -296,7 +321,7 @@ async fn updateenv() -> Result<bool, Box<dyn Error + Send + Sync>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn updateprofile() -> Result<bool, Box<dyn Error + Send + Sync>> {
|
async fn updateprofile() -> Result<bool> {
|
||||||
let mut cmd = tokio::process::Command::new("nix")
|
let mut cmd = tokio::process::Command::new("nix")
|
||||||
.arg("profile")
|
.arg("profile")
|
||||||
.arg("upgrade")
|
.arg("upgrade")
|
||||||
@ -311,6 +336,7 @@ async fn updateprofile() -> Result<bool, Box<dyn Error + Send + Sync>> {
|
|||||||
|
|
||||||
let mut lines = reader.lines();
|
let mut lines = reader.lines();
|
||||||
while let Ok(Some(line)) = lines.next_line().await {
|
while let Ok(Some(line)) = lines.next_line().await {
|
||||||
|
REBUILD_BROKER.send(RebuildMsg::UpdateText(line.to_string()));
|
||||||
trace!("CAUGHT NIX PROFILE LINE: {}", line);
|
trace!("CAUGHT NIX PROFILE LINE: {}", line);
|
||||||
}
|
}
|
||||||
if cmd.wait().await?.success() {
|
if cmd.wait().await?.success() {
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
config::{editconfig, getconfig},
|
config::{editconfig, getconfig},
|
||||||
packages::{AppData, LicenseEnum, PkgMaintainer, Platform},
|
packages::{AppData, LicenseEnum, PkgMaintainer, Platform},
|
||||||
},
|
},
|
||||||
ui::{installedpage::InstalledItem, pkgpage::PkgPageInit, welcome::WelcomeMsg},
|
ui::{installedpage::InstalledItem, pkgpage::PkgPageInit, welcome::WelcomeMsg, rebuild::RebuildMsg},
|
||||||
APPINFO,
|
APPINFO,
|
||||||
};
|
};
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
@ -32,9 +32,11 @@ use super::{
|
|||||||
searchpage::{SearchItem, SearchPageModel, SearchPageMsg},
|
searchpage::{SearchItem, SearchPageModel, SearchPageMsg},
|
||||||
updatepage::{UpdateItem, UpdatePageInit, UpdatePageModel, UpdatePageMsg},
|
updatepage::{UpdateItem, UpdatePageInit, UpdatePageModel, UpdatePageMsg},
|
||||||
welcome::WelcomeModel,
|
welcome::WelcomeModel,
|
||||||
windowloading::{LoadErrorModel, LoadErrorMsg, WindowAsyncHandler, WindowAsyncHandlerMsg},
|
windowloading::{LoadErrorModel, LoadErrorMsg, WindowAsyncHandler, WindowAsyncHandlerMsg}, rebuild::RebuildModel,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub static REBUILD_BROKER: MessageBroker<RebuildModel> = MessageBroker::new();
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
enum Page {
|
enum Page {
|
||||||
FrontPage,
|
FrontPage,
|
||||||
@ -109,6 +111,8 @@ pub struct AppModel {
|
|||||||
updatepage: Controller<UpdatePageModel>,
|
updatepage: Controller<UpdatePageModel>,
|
||||||
viewstack: adw::ViewStack,
|
viewstack: adw::ViewStack,
|
||||||
installedpagebusy: Vec<(String, InstallType)>,
|
installedpagebusy: Vec<(String, InstallType)>,
|
||||||
|
#[tracker::no_eq]
|
||||||
|
rebuild: Controller<RebuildModel>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -146,8 +150,8 @@ pub enum AppMsg {
|
|||||||
RemoveInstalledBusy(WorkPkg),
|
RemoveInstalledBusy(WorkPkg),
|
||||||
OpenCategoryPage(PkgCategory),
|
OpenCategoryPage(PkgCategory),
|
||||||
LoadCategory(PkgCategory),
|
LoadCategory(PkgCategory),
|
||||||
|
|
||||||
UpdateRecPkgs(Vec<String>),
|
UpdateRecPkgs(Vec<String>),
|
||||||
|
SetDarkMode(bool),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
@ -490,6 +494,9 @@ impl Component for AppModel {
|
|||||||
config: config.clone(),
|
config: config.clone(),
|
||||||
})
|
})
|
||||||
.forward(sender.input_sender(), identity);
|
.forward(sender.input_sender(), identity);
|
||||||
|
let rebuild = RebuildModel::builder()
|
||||||
|
.launch_with_broker(root.clone().upcast(), &REBUILD_BROKER)
|
||||||
|
.forward(sender.input_sender(), identity);
|
||||||
let viewstack = adw::ViewStack::new();
|
let viewstack = adw::ViewStack::new();
|
||||||
|
|
||||||
let model = AppModel {
|
let model = AppModel {
|
||||||
@ -523,9 +530,18 @@ impl Component for AppModel {
|
|||||||
updatepage,
|
updatepage,
|
||||||
viewstack,
|
viewstack,
|
||||||
installedpagebusy: vec![],
|
installedpagebusy: vec![],
|
||||||
|
rebuild,
|
||||||
tracker: 0,
|
tracker: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
let sender = sender.clone();
|
||||||
|
adw::StyleManager::default()
|
||||||
|
.connect_dark_notify(move |x| sender.input(AppMsg::SetDarkMode(x.is_dark())));
|
||||||
|
}
|
||||||
|
|
||||||
|
sender.input(AppMsg::SetDarkMode(adw::StyleManager::default().is_dark()));
|
||||||
|
|
||||||
if welcome {
|
if welcome {
|
||||||
let welcomepage = WelcomeModel::builder()
|
let welcomepage = WelcomeModel::builder()
|
||||||
.launch(root.clone().upcast())
|
.launch(root.clone().upcast())
|
||||||
@ -582,6 +598,7 @@ impl Component for AppModel {
|
|||||||
frontvs.set_icon_name(Some("nsc-home-symbolic"));
|
frontvs.set_icon_name(Some("nsc-home-symbolic"));
|
||||||
installedvs.set_icon_name(Some("nsc-installed-symbolic"));
|
installedvs.set_icon_name(Some("nsc-installed-symbolic"));
|
||||||
updatesvs.set_icon_name(Some("nsc-update-symbolic"));
|
updatesvs.set_icon_name(Some("nsc-update-symbolic"));
|
||||||
|
|
||||||
ComponentParts { model, widgets }
|
ComponentParts { model, widgets }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1803,6 +1820,11 @@ FROM pkgs JOIN meta ON (pkgs.attribute = meta.attribute) WHERE pkgs.attribute =
|
|||||||
AppAsyncMsg::LoadCategory(category, catrec, catall)
|
AppAsyncMsg::LoadCategory(category, catrec, catall)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
AppMsg::SetDarkMode(dark) => {
|
||||||
|
info!("AppMsg::SetDarkMode({})", dark);
|
||||||
|
let scheme = if dark { "Adwaita-dark" } else { "Adwaita" };
|
||||||
|
self.rebuild.emit(RebuildMsg::SetScheme(scheme.to_string()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user