feat: refactor the settings page architecture

This commit is contained in:
Michael Aaron Murphy 2023-04-25 00:30:50 +02:00
parent efdd934e62
commit c015ad9948
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
55 changed files with 2212 additions and 1635 deletions

279
pages/system/Cargo.lock generated
View file

@ -1,279 +0,0 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bumpalo"
version = "3.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
[[package]]
name = "byte-unit"
version = "4.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3348673602e04848647fffaa8e9a861e7b5d5cae6570727b41bde0f722514484"
dependencies = [
"utf8-width",
]
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "concat-in-place"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5b80dba65d26e0c4b692ad0312b837f1177e8175031af57fd1de4f3bc36b430"
[[package]]
name = "const_format"
version = "0.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7309d9b4d3d2c0641e018d449232f2e28f1b22933c137f157d3dbc14228b8c0e"
dependencies = [
"const_format_proc_macros",
]
[[package]]
name = "const_format_proc_macros"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f47bf7270cf70d370f8f98c1abb6d2d4cf60a6845d30e05bfb90c6568650"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cosmic-settings-system"
version = "0.1.0"
dependencies = [
"bumpalo",
"byte-unit",
"concat-in-place",
"const_format",
"memchr",
"sysinfo",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"scopeguard",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
dependencies = [
"cfg-if",
]
[[package]]
name = "either"
version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
[[package]]
name = "hermit-abi"
version = "0.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
dependencies = [
"libc",
]
[[package]]
name = "libc"
version = "0.2.139"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memoffset"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
dependencies = [
"autocfg",
]
[[package]]
name = "ntapi"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc51db7b362b205941f71232e56c625156eb9a929f8cf74a428fd5bc094a4afc"
dependencies = [
"winapi",
]
[[package]]
name = "num_cpus"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "once_cell"
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
[[package]]
name = "proc-macro2"
version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rayon"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "356a0625f1954f730c0201cdab48611198dc6ce21f4acff55089b5a78e6e835b"
dependencies = [
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-utils",
"num_cpus",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "sysinfo"
version = "0.27.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "975fe381e0ecba475d4acff52466906d95b153a40324956552e027b2a9eaa89e"
dependencies = [
"cfg-if",
"core-foundation-sys",
"libc",
"ntapi",
"once_cell",
"rayon",
"winapi",
]
[[package]]
name = "unicode-ident"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
[[package]]
name = "unicode-xid"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
[[package]]
name = "utf8-width"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View file

@ -2,7 +2,7 @@
name = "cosmic-settings-system"
version = "0.1.0"
edition = "2021"
license = "MPL-2.0"
license = "GPL-3.0-only"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -10,9 +10,9 @@ license = "MPL-2.0"
byte-unit = { version = "4.0.18", default-features = false }
const_format = "0.2.30"
concat-in-place = "1.1.0"
sysinfo = "0.27.7"
sysinfo = "0.28.4"
memchr = "2.5.0"
[dependencies.bumpalo]
version = "3.12.0"
version = "3.12.1"
features = ["collections"]

210
pages/system/src/about.rs Normal file
View file

@ -0,0 +1,210 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use bumpalo::Bump;
use std::{ffi::OsStr, io::Read};
use sysinfo::{DiskExt, SystemExt};
use concat_in_place::strcat;
use const_format::concatcp;
const DMI_DIR: &str = "/sys/devices/virtual/dmi/id/";
const BOARD_NAME: &str = concatcp!(DMI_DIR, "board_name");
const BOARD_VERSION: &str = concatcp!(DMI_DIR, "board_version");
const SYS_VENDOR: &str = concatcp!(DMI_DIR, "sys_vendor");
const VERSION_IGNORING_PRODUCTS: &[&str] = &["Dev One"];
#[must_use]
#[derive(Clone, Debug, Default)]
pub struct Info {
pub desktop_environment: String,
pub device_name: String,
pub disk_capacity: String,
pub graphics: Vec<String>,
pub hardware_model: String,
pub memory: String,
pub operating_system: String,
pub os_architecture: String,
pub processor: String,
pub windowing_system: String,
}
impl Info {
pub fn load() -> Info {
let mut info = Info::default();
let mut bump = Bump::with_capacity(8 * 1024);
architecture(&bump, &mut info.os_architecture);
bump.reset();
hardware_model(&bump, &mut info.hardware_model);
bump.reset();
operating_system(&bump, &mut info.operating_system);
bump.reset();
processor_name(&bump, &mut info.processor);
bump.reset();
let mut sys = sysinfo::System::new();
sys.refresh_disks_list();
sys.refresh_disks();
sys.refresh_memory();
let mut total_capacity = 0;
for disk in sys.disks() {
total_capacity += disk.total_space();
}
info.disk_capacity = format_size(total_capacity);
if let Some(name) = sys.host_name() {
info.device_name = name;
}
info.memory = format_size(sys.total_memory());
if let Ok(mut session) = std::env::var("XDG_SESSION_TYPE") {
if let Some(first) = session.get_mut(0..1) {
first.make_ascii_uppercase();
}
info.windowing_system = session;
}
if let Ok(mut session) = std::env::var("DESKTOP_SESSION") {
if let Some(first) = session.get_mut(0..1) {
first.make_ascii_uppercase();
}
info.desktop_environment = session;
}
if let Ok(output) = std::process::Command::new("lspci").output() {
if let Ok(stdout) = std::str::from_utf8(&output.stdout) {
for line in stdout.lines() {
if let Some(pos) = memchr::memmem::find(line.as_bytes(), b"VGA") {
let line = &line[pos + 3..];
if let Some(pos) = memchr::memmem::find(line.as_bytes(), b": ") {
info.graphics.push(String::from(&line[pos + 2..]));
}
}
}
}
}
info
}
}
pub fn architecture(bump: &Bump, arch: &mut String) {
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(value) = read_to_string("/proc/sys/kernel/arch", buffer) {
arch.push_str(value.trim());
}
}
pub fn hardware_model(bump: &Bump, hardware_model: &mut String) {
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut sys_vendor) = read_to_string(SYS_VENDOR, buffer) {
sys_vendor = sys_vendor.trim();
hardware_model.push_str(sys_vendor);
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut name) = read_to_string(BOARD_NAME, buffer) {
name = name.trim();
if !name.is_empty() && name != sys_vendor {
// Ensure that the name does not contain the vendor.
name = match name.strip_prefix(sys_vendor) {
Some(stripped) => stripped.trim(),
None => name,
};
strcat!(&mut *hardware_model, " " name);
}
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut version) = read_to_string(BOARD_VERSION, buffer) {
version = version.trim();
if !version.is_empty() && !VERSION_IGNORING_PRODUCTS.contains(&name) {
strcat!(hardware_model, " (" version.trim() ")");
}
}
}
}
}
pub fn operating_system(bump: &Bump, operating_system: &mut String) {
let mut buffer = bumpalo::collections::Vec::new_in(bump);
let Some(os_release) = read_to_string("/etc/os-release", &mut buffer) else {
return;
};
for line in os_release.lines() {
if let Some(mut value) = line.strip_prefix("PRETTY_NAME=") {
if let Some(v) = value.strip_prefix('"') {
value = v;
}
if let Some(v) = value.strip_suffix('"') {
value = v;
}
operating_system.push_str(value.trim());
break;
}
}
}
pub fn processor_name(bump: &Bump, name: &mut String) {
if let Some(cpuinfo) = read_to_string(
"/proc/cpuinfo",
&mut bumpalo::collections::Vec::new_in(bump),
) {
for line in cpuinfo.lines() {
if let Some(info) = line.strip_prefix("model name") {
if let Some(info) = info.trim_start().strip_prefix(':') {
name.push_str(info.trim());
}
break;
}
}
}
}
pub fn read_to_string<'a, P: AsRef<OsStr>>(
path: P,
buffer: &'a mut bumpalo::collections::Vec<u8>,
) -> Option<&'a str> {
let mut file = std::fs::File::open(path.as_ref()).ok()?;
if let Ok(metadata) = file.metadata() {
if let Ok(len) = usize::try_from(metadata.len()) {
buffer.reserve_exact(len);
}
}
let mut buf = [0; 16 * 1024];
loop {
match file.read(&mut buf) {
Ok(0) => break,
Ok(read) => buffer.extend_from_slice(&buf[..read]),
Err(_) => return None,
}
}
std::str::from_utf8(buffer.as_slice()).ok()
}
fn format_size(size: u64) -> String {
byte_unit::Byte::from_bytes(size)
.get_appropriate_unit(true)
.to_string()
}

View file

@ -1,208 +1,4 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: MPL-2.0
// SPDX-License-Identifier: GPL-3.0-only
use bumpalo::Bump;
use std::{ffi::OsStr, io::Read};
use sysinfo::{DiskExt, SystemExt};
use concat_in_place::strcat;
use const_format::concatcp;
const DMI_DIR: &str = "/sys/devices/virtual/dmi/id/";
const BOARD_NAME: &str = concatcp!(DMI_DIR, "board_name");
const BOARD_VERSION: &str = concatcp!(DMI_DIR, "board_version");
const SYS_VENDOR: &str = concatcp!(DMI_DIR, "sys_vendor");
#[derive(Clone, Debug, Default)]
pub struct Info {
pub desktop_environment: String,
pub device_name: String,
pub disk_capacity: String,
pub graphics: Vec<String>,
pub hardware_model: String,
pub memory: String,
pub operating_system: String,
pub os_architecture: String,
pub processor: String,
pub windowing_system: String,
}
impl Info {
pub fn load() -> Info {
let mut info = Info::default();
let mut bump = Bump::with_capacity(8 * 1024);
architecture(&bump, &mut info.os_architecture);
bump.reset();
hardware_model(&bump, &mut info.hardware_model);
bump.reset();
operating_system(&bump, &mut info.operating_system);
bump.reset();
processor_name(&bump, &mut info.processor);
bump.reset();
let mut sys = sysinfo::System::new();
sys.refresh_disks_list();
sys.refresh_disks();
sys.refresh_memory();
let mut total_capacity = 0;
for disk in sys.disks() {
total_capacity += disk.total_space();
}
info.disk_capacity = format_size(total_capacity);
if let Some(name) = sys.host_name() {
info.device_name = name;
}
info.memory = format_size(sys.total_memory());
if let Ok(mut session) = std::env::var("XDG_SESSION_TYPE") {
if let Some(first) = session.get_mut(0..1) {
first.make_ascii_uppercase();
}
info.windowing_system = session;
}
if let Ok(mut session) = std::env::var("DESKTOP_SESSION") {
if let Some(first) = session.get_mut(0..1) {
first.make_ascii_uppercase();
}
info.desktop_environment = session;
}
if let Ok(output) = std::process::Command::new("lspci").output() {
if let Ok(stdout) = std::str::from_utf8(&output.stdout) {
for line in stdout.lines() {
if let Some(pos) = memchr::memmem::find(line.as_bytes(), b"VGA") {
let line = &line[pos + 3..];
if let Some(pos) = memchr::memmem::find(line.as_bytes(), b": ") {
info.graphics.push(String::from(&line[pos + 2..]));
}
}
}
}
}
info
}
}
pub fn architecture(bump: &Bump, arch: &mut String) {
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(value) = read_to_string("/proc/sys/kernel/arch", buffer) {
arch.push_str(value.trim());
}
}
pub fn hardware_model(bump: &Bump, hardware_model: &mut String) {
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut sys_vendor) = read_to_string(SYS_VENDOR, buffer) {
sys_vendor = sys_vendor.trim();
hardware_model.push_str(sys_vendor);
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut name) = read_to_string(BOARD_NAME, buffer) {
name = name.trim();
if !name.is_empty() && name != sys_vendor {
// Ensure that the name does not contain the vendor.
name = match name.strip_prefix(sys_vendor) {
Some(stripped) => stripped.trim(),
None => name,
};
strcat!(&mut *hardware_model, " " name);
}
let buffer = &mut bumpalo::collections::Vec::new_in(bump);
if let Some(mut version) = read_to_string(BOARD_VERSION, buffer) {
version = version.trim();
// These have bogus values for their version.
const IGNORE_PRODUCTS: &[&str] = &["Dev One"];
if !version.is_empty() && !IGNORE_PRODUCTS.contains(&name) {
strcat!(hardware_model, " (" version.trim() ")");
}
}
}
}
}
pub fn operating_system(bump: &Bump, operating_system: &mut String) {
let mut buffer = bumpalo::collections::Vec::new_in(bump);
let Some(os_release) = read_to_string("/etc/os-release", &mut buffer) else {
return;
};
for line in os_release.lines() {
if let Some(mut value) = line.strip_prefix("PRETTY_NAME=") {
if let Some(v) = value.strip_prefix('"') {
value = v;
}
if let Some(v) = value.strip_suffix('"') {
value = v;
}
operating_system.push_str(value.trim());
break;
}
}
}
pub fn processor_name(bump: &Bump, name: &mut String) {
if let Some(cpuinfo) = read_to_string(
"/proc/cpuinfo",
&mut bumpalo::collections::Vec::new_in(bump),
) {
for line in cpuinfo.lines() {
if let Some(info) = line.strip_prefix("model name") {
if let Some(info) = info.trim_start().strip_prefix(":") {
name.push_str(info.trim());
}
break;
}
}
}
}
pub fn read_to_string<'a, P: AsRef<OsStr>>(
path: P,
buffer: &'a mut bumpalo::collections::Vec<u8>,
) -> Option<&'a str> {
let mut file = std::fs::File::open(path.as_ref()).ok()?;
if let Ok(metadata) = file.metadata() {
buffer.reserve_exact(metadata.len() as usize);
}
let mut buf = [0; 16 * 1024];
loop {
match file.read(&mut buf) {
Ok(0) => break,
Ok(read) => buffer.extend_from_slice(&buf[..read]),
Err(_) => return None,
}
}
std::str::from_utf8(buffer.as_slice()).ok()
}
fn format_size(size: u64) -> String {
byte_unit::Byte::from_bytes(size)
.get_appropriate_unit(true)
.to_string()
}
pub mod about;

14
pages/time/Cargo.toml Normal file
View file

@ -0,0 +1,14 @@
[package]
name = "cosmic-settings-time"
version = "0.1.0"
edition = "2021"
[dependencies]
icu_calendar = "1.2.0"
icu_timezone = "1.2.0"
timedate-zbus = "0.1.0"
[dependencies.zbus]
version = "3.12.0"
default-features = false
features = ["tokio"]

48
pages/time/src/lib.rs Normal file
View file

@ -0,0 +1,48 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
use std::time::SystemTime;
use icu_calendar::{types::IsoSecond, DateTime, Iso};
use icu_timezone::CustomTimeZone;
use timedate_zbus::TimeDateProxy;
pub struct Info {
pub can_ntp: bool,
pub timezone: CustomTimeZone,
pub local_time: DateTime<Iso>,
}
impl Info {
pub async fn load(proxy: &TimeDateProxy<'_>) -> Option<Info> {
let can_ntp = proxy.can_ntp().await.unwrap_or_default();
let Ok(timezone) = proxy.timezone()
.await
.unwrap_or_default()
.parse::<CustomTimeZone>() else {
return None;
};
let Ok(duration) = SystemTime::now().duration_since(SystemTime::UNIX_EPOCH) else {
return None;
};
let seconds = duration.as_secs();
let Ok(iso_seconds) = IsoSecond::try_from((seconds % 60) as u8) else {
return None;
};
#[allow(clippy::cast_possible_truncation)]
let mut local_time = DateTime::from_minutes_since_local_unix_epoch((seconds / 60) as i32);
local_time.time.second = iso_seconds;
Some(Info {
can_ntp,
timezone,
local_time,
})
}
}