feat: use cosmic-config to remember active page

This commit is contained in:
Michael Aaron Murphy 2023-05-30 21:56:01 +02:00
parent 18527db707
commit 14a4a23bc9
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
4 changed files with 30 additions and 233 deletions

View file

@ -28,7 +28,7 @@ use cosmic::{
};
use crate::{
config::{self, Config},
config::Config,
pages::{
desktop::{self, panel},
sound, system, time,
@ -43,7 +43,6 @@ use std::process;
pub struct SettingsApp {
pub active_page: page::Entity,
pub config: Config,
pub config_path: config::PathManager,
pub debug: bool,
pub is_condensed: bool,
pub nav_bar_toggled_condensed: bool,
@ -87,13 +86,10 @@ impl Application for SettingsApp {
type Theme = Theme;
fn new(_: Self::Flags) -> (Self, Command<Self::Message>) {
let mut config_path = config::PathManager::new();
let mut app = SettingsApp {
sharp_corners: false,
active_page: page::Entity::default(),
config: config_path.config("main", Config::deserialize),
config_path,
config: Config::new(),
debug: false,
is_condensed: false,
nav_bar: segmented_button::Model::default(),
@ -389,8 +385,8 @@ impl SettingsApp {
if current_page != page {
self.config.active_page = Box::from(&*self.pages.info[page].id);
self.config_path
.config("main", |path| self.config.serialize(path));
self.config
.set_active_page(Box::from(&*self.pages.info[page].id));
}
self.search_clear();

View file

@ -1,99 +1,55 @@
// Copyright 2023 System76 <info@system76.com>
// SPDX-License-Identifier: GPL-3.0-only
mod path {
use std::path::Path;
use cosmic::cosmic_config::{self, ConfigGet, ConfigSet};
#[must_use]
const NAME: &str = "com.system76.CosmicSettings";
pub struct Manager {
base: String,
}
impl Manager {
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
let mut base = dirs::config_dir()
.expect("XDG config directory missing")
.join("cosmic-settings")
.into_os_string()
.into_string()
.expect("XDG config path is not UTF-8");
base.push('/');
if !Path::new(&base).exists() {
let _res = std::fs::create_dir_all(&base);
}
Self { base }
}
pub fn config<T>(&mut self, page: &str, with: impl Fn(&Path) -> T) -> T {
let truncate_length = self.base.len();
self.base.push_str(page);
self.base.push_str(".config");
let output = with(Path::new(&self.base));
self.base.truncate(truncate_length);
output
}
}
}
pub use path::Manager as PathManager;
use bytecheck::CheckBytes;
use rkyv::{ser::Serializer, Archive, Deserialize, Serialize};
use std::{io::Read, path::Path};
const ACTIVE_PAGE: &str = "active-page";
#[must_use]
#[repr(C)]
#[derive(Archive, Debug, Deserialize, Serialize)]
#[archive_attr(derive(CheckBytes, Debug))]
#[derive(Debug)]
pub struct Config {
pub cosmic_config: Option<cosmic_config::Config>,
pub active_page: Box<str>,
}
impl Config {
pub fn deserialize(path: &Path) -> Self {
let Ok(mut file) = std::fs::File::open(path) else {
return Self::default();
pub fn new() -> Self {
let mut config = Self::default();
let context = match cosmic_config::Config::new(NAME, 1) {
Ok(context) => context,
Err(why) => {
tracing::warn!(?why, "failed to get config");
return Self::default();
}
};
let mut buffer = Vec::with_capacity(128);
if file.read_to_end(&mut buffer).is_err() {
return Self::default();
if let Ok(page) = context.get::<Box<str>>(ACTIVE_PAGE) {
config.active_page = page;
}
buffer.shrink_to_fit();
config.cosmic_config = Some(context);
let Ok(archived) = rkyv::check_archived_root::<Self>(buffer.as_slice()) else {
return Self::default();
};
archived
.deserialize(&mut rkyv::Infallible)
.unwrap_or_default()
config
}
pub fn serialize(&self, path: &Path) {
let mut serializer = rkyv::ser::serializers::AllocSerializer::<0>::default();
pub fn set_active_page(&mut self, page: Box<str>) {
if let Some(context) = self.cosmic_config.as_ref() {
if let Err(why) = context.set::<Box<str>>(ACTIVE_PAGE, page.clone()) {
tracing::error!(?why, "failed to store active page ID");
}
}
if serializer.serialize_value(self).is_err() {
return;
};
let bytes = serializer.into_serializer().into_inner();
let _res = std::fs::write(path, &bytes);
self.active_page = page;
}
}
impl Default for Config {
fn default() -> Self {
Self {
cosmic_config: None,
active_page: Box::from("desktop"),
}
}