Cosmic advanced text (#103)
* wip: update to use cosmic-advanced-text * use cosmic-advanced-text branch of iced * fix: line height and spacing for segmented button and update to get svg fix * fix: spin button styling & spacing * update iced to fix segmented button border radius * feat: example improvements * feat: helper for loading fonts * feat: add focus style to button * fix: slider height and iced fixed * feat: hash icon width and height * cleanup * update ci * refactor: always use lazy feature of iced * update iced * update iced * cleanup & update iced * update iced: new slider & tiny-skia quad updates * update iced: fixes for tiny-skia quad rendering with edge case border radius * re-export iced_runtime & iced_widget * merge master * udpate iced * update iced * update iced * update iced * fix: make rectangle_tracker subscription only return update if there is some * feat: derive macro for loading a cosmic-config * feat (cosmic-config): iced subscription * fix (example): update to rectangle tracker subscription * fix (cosmic-config) * refactor(cosmic-config-derive): add support for types with generic parameters * fix (cosmic-config): feature gate updates for subscription helpers * feat: support for custom & system themes + move cosmic-theme to libcosmic * feat: sorta hacky way of creating header bars for libcosmic + update iced to get support for resizable windows in iced-sctk * update iced * update and reexport sctk * fix: applet border radius * feat (cosmic-theme): add id and name methods * fix(cosmic-theme): reexport palette from cosmic-theme * fix(cosmic-config-derive): allow use with reexported cosmic-config * feat: update iced with fix and refactor applet env vars * update iced
This commit is contained in:
parent
a173794bed
commit
e056e8c830
65 changed files with 3431 additions and 405 deletions
|
|
@ -1,12 +1,21 @@
|
|||
use notify::Watcher;
|
||||
#[cfg(feature = "subscription")]
|
||||
use iced_futures::futures::channel::mpsc;
|
||||
#[cfg(feature = "subscription")]
|
||||
use iced_futures::subscription;
|
||||
use notify::{RecommendedWatcher, Watcher};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
fs,
|
||||
hash::Hash,
|
||||
io::Write,
|
||||
path::{Path, PathBuf},
|
||||
sync::Mutex,
|
||||
};
|
||||
|
||||
#[cfg(feature = "macro")]
|
||||
pub use cosmic_config_derive;
|
||||
|
||||
#[cfg(feature = "calloop")]
|
||||
pub mod calloop;
|
||||
|
||||
|
|
@ -251,3 +260,123 @@ impl<'a> ConfigSet for ConfigTransaction<'a> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "subscription")]
|
||||
pub enum ConfigState<T> {
|
||||
Init(Cow<'static, str>, u64),
|
||||
Waiting(T, RecommendedWatcher, mpsc::Receiver<()>, Config),
|
||||
Failed,
|
||||
}
|
||||
|
||||
#[cfg(feature = "subscription")]
|
||||
pub enum ConfigUpdate<T> {
|
||||
Update(T),
|
||||
UpdateError(T, Vec<crate::Error>),
|
||||
Failed,
|
||||
}
|
||||
|
||||
pub trait CosmicConfigEntry
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
fn write_entry(&self, config: &Config) -> Result<(), crate::Error>;
|
||||
fn get_entry(config: &Config) -> Result<Self, (Vec<crate::Error>, Self)>;
|
||||
}
|
||||
|
||||
#[cfg(feature = "subscription")]
|
||||
pub fn config_subscription<
|
||||
I: 'static + Copy + Send + Sync + Hash,
|
||||
T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry,
|
||||
>(
|
||||
id: I,
|
||||
config_id: Cow<'static, str>,
|
||||
config_version: u64,
|
||||
) -> iced_futures::Subscription<(I, Result<T, (Vec<crate::Error>, T)>)> {
|
||||
subscription::unfold(
|
||||
id,
|
||||
ConfigState::Init(config_id, config_version),
|
||||
move |state| start_listening_loop(id, state),
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(feature = "subscription")]
|
||||
async fn start_listening<
|
||||
I: Copy,
|
||||
T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry,
|
||||
>(
|
||||
id: I,
|
||||
state: ConfigState<T>,
|
||||
) -> (
|
||||
Option<(I, Result<T, (Vec<crate::Error>, T)>)>,
|
||||
ConfigState<T>,
|
||||
) {
|
||||
use iced_futures::futures::{future::pending, StreamExt};
|
||||
|
||||
match state {
|
||||
ConfigState::Init(config_id, version) => {
|
||||
let (tx, rx) = mpsc::channel(100);
|
||||
let config = match Config::new(&config_id, version) {
|
||||
Ok(c) => c,
|
||||
Err(_) => return (None, ConfigState::Failed),
|
||||
};
|
||||
let watcher = match config.watch(move |_helper, _keys| {
|
||||
let mut tx = tx.clone();
|
||||
let _ = tx.try_send(());
|
||||
}) {
|
||||
Ok(w) => w,
|
||||
Err(_) => return (None, ConfigState::Failed),
|
||||
};
|
||||
|
||||
match T::get_entry(&config) {
|
||||
Ok(t) => (
|
||||
Some((id, Ok(t.clone()))),
|
||||
ConfigState::Waiting(t, watcher, rx, config),
|
||||
),
|
||||
Err((errors, t)) => (
|
||||
Some((id, Err((errors, t.clone())))),
|
||||
ConfigState::Waiting(t, watcher, rx, config),
|
||||
),
|
||||
}
|
||||
}
|
||||
ConfigState::Waiting(old, watcher, mut rx, config) => match rx.next().await {
|
||||
Some(_) => match T::get_entry(&config) {
|
||||
Ok(t) => (
|
||||
if t != old {
|
||||
Some((id, Ok(t.clone())))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
ConfigState::Waiting(t, watcher, rx, config),
|
||||
),
|
||||
Err((errors, t)) => (
|
||||
if t != old {
|
||||
Some((id, Err((errors, t.clone()))))
|
||||
} else {
|
||||
None
|
||||
},
|
||||
ConfigState::Waiting(t, watcher, rx, config),
|
||||
),
|
||||
},
|
||||
|
||||
None => (None, ConfigState::Failed),
|
||||
},
|
||||
ConfigState::Failed => pending().await,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "subscription")]
|
||||
async fn start_listening_loop<
|
||||
I: Copy,
|
||||
T: 'static + Send + Sync + PartialEq + Clone + CosmicConfigEntry,
|
||||
>(
|
||||
id: I,
|
||||
mut state: ConfigState<T>,
|
||||
) -> ((I, Result<T, (Vec<crate::Error>, T)>), ConfigState<T>) {
|
||||
loop {
|
||||
let (update, new_state) = start_listening(id, state).await;
|
||||
state = new_state;
|
||||
if let Some(update) = update {
|
||||
return (update, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue