feat: use cosmic-config to remember active page
This commit is contained in:
parent
18527db707
commit
14a4a23bc9
4 changed files with 30 additions and 233 deletions
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue