chore: update dependencies

This commit is contained in:
Michael Aaron Murphy 2024-09-20 20:37:14 +02:00
parent c6cd78ec9c
commit 0472c00096
No known key found for this signature in database
GPG key ID: B2732D4240C9212C
27 changed files with 262 additions and 237 deletions

324
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -8,7 +8,7 @@ rust-version = "1.80.0"
[workspace.dependencies]
cosmic-randr = { git = "https://github.com/pop-os/cosmic-randr" }
tokio = { version = "1.39.3", features = ["macros"] }
tokio = { version = "1.40.0", features = ["macros"] }
[workspace.dependencies.libcosmic]
git = "https://github.com/pop-os/libcosmic"

View file

@ -10,7 +10,7 @@ as-result = "0.2.1"
ashpd = { version = "0.9", default-features = false, features = ["tokio"] }
async-channel = "2.3.1"
chrono = "0.4.38"
clap = { version = "4.5.16", features = ["derive"] }
clap = { version = "4.5.17", features = ["derive"] }
color-eyre = "0.6.3"
cosmic-bg-config.workspace = true
cosmic-comp-config.workspace = true
@ -28,13 +28,13 @@ derive_setters = "0.1.6"
dirs = "5.0.1"
downcast-rs = "1.2.1"
eyre = "0.6.12"
freedesktop-desktop-entry = "0.7.3"
freedesktop-desktop-entry = "0.7.5"
futures = "0.3.30"
hostname-validator = "1.1.1"
hostname1-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings" }
i18n-embed-fl = "0.9.1"
image = "0.25"
indexmap = "2.4.0"
indexmap = "2.5.0"
itertools = "0.13.0"
itoa = "1.0.11"
libcosmic.workspace = true
@ -44,12 +44,12 @@ regex = "1.10.6"
ron = "0.8"
rust-embed = "8.5.0"
secure-string = "0.3.0"
serde = { version = "1.0.208", features = ["derive"] }
serde = { version = "1.0.210", features = ["derive"] }
slab = "0.4.9"
slotmap = "1.0.7"
static_init = "1.0.3"
sunrise = "1.0.1"
tachyonix = "0.3.0"
tachyonix = "0.3.1"
timedate-zbus = { git = "https://github.com/pop-os/dbus-settings-bindings" }
tokio.workspace = true
tracing = "0.1.40"

View file

@ -379,7 +379,7 @@ impl Page {
let theme = theme.cosmic();
cosmic::iced::widget::column![
// Export theme choice
settings::view_section("").add(
settings::section().add(
settings::item::builder(fl!("enable-export"))
.description(fl!("enable-export", "desc"))
.toggler(self.tk.apply_theme_global, Message::ApplyThemeGlobal)
@ -1360,12 +1360,13 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
.theme_builder
.accent
.map_or(palette.accent_blue, Srgba::from);
let mut section = settings::view_section(&section.title)
let mut section = settings::section()
.title(&section.title)
.add(
container(
cosmic::iced::widget::row![
cosmic::iced::widget::column![
button(
button::custom(
icon(dark_mode_illustration.clone())
.width(Length::Fill)
.height(Length::Fixed(100.0))
@ -1380,7 +1381,7 @@ pub fn mode_and_colors() -> Section<crate::pages::Message> {
.width(Length::FillPortion(1))
.align_items(cosmic::iced_core::Alignment::Center),
cosmic::iced::widget::column![
button(
button::custom(
icon(light_mode_illustration.clone(),)
.width(Length::Fill)
.height(Length::Fixed(100.0))
@ -1609,12 +1610,13 @@ pub fn style() -> Section<crate::pages::Message> {
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(
container(
cosmic::iced::widget::row![
cosmic::iced::widget::column![
button(
button::custom(
icon(
if page.theme_mode.is_dark {
&dark_round_style
@ -1636,7 +1638,7 @@ pub fn style() -> Section<crate::pages::Message> {
.width(Length::FillPortion(1))
.align_items(cosmic::iced_core::Alignment::Center),
cosmic::iced::widget::column![
button(
button::custom(
icon(
if page.theme_mode.is_dark {
&dark_slightly_round_style
@ -1658,7 +1660,7 @@ pub fn style() -> Section<crate::pages::Message> {
.width(Length::FillPortion(1))
.align_items(cosmic::iced_core::Alignment::Center),
cosmic::iced::widget::column![
button(
button::custom(
icon(
if page.theme_mode.is_dark {
&dark_square_style
@ -1706,7 +1708,8 @@ pub fn window_management() -> Section<crate::pages::Message> {
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::item::builder(&descriptions[active_hint]).control(
cosmic::widget::spin_button(
page.theme_builder.active_hint.to_string(),
@ -1739,13 +1742,13 @@ pub fn experimental() -> Section<crate::pages::Message> {
icon::from_name("go-next-symbolic").size(16).into(),
]);
settings::view_section("")
settings::section()
.add(
settings::item::builder(&descriptions[experimental_label])
.control(control)
.apply(container)
.style(cosmic::theme::Container::List)
.apply(button)
.apply(button::custom)
.style(cosmic::theme::Button::Transparent)
.on_press(Message::ExperimentalContextDrawer),
)
@ -1784,7 +1787,7 @@ pub fn color_button<'a, Message: 'a + Clone>(
width: u16,
height: u16,
) -> Element<'a, Message> {
button(color_image(
button::custom(color_image(
wallpaper::Color::Single([color.r, color.g, color.b]),
width,
height,

View file

@ -164,7 +164,8 @@ pub(crate) fn enable() -> Section<crate::pages::Message> {
let Some(container_config) = page.inner.container_config.as_ref() else {
return Element::from(text::body(fl!("unknown")));
};
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::item(
&descriptions[dock],
toggler(

View file

@ -269,7 +269,7 @@ impl Page {
.spacing(spacing.space_xxxs)
.width(Length::Fill)
.into(),
button(text::body(fl!("add")))
button::standard(fl!("add"))
.style(button::Style::Custom {
active: Box::new(|focused, theme| {
let mut style = theme.active(focused, false, &button::Style::Text);
@ -294,7 +294,6 @@ impl Page {
style
}),
})
.padding(8.0)
.on_press(msg_map(Message::AddApplet(info.clone())))
.into(),
])

View file

@ -114,7 +114,8 @@ pub(crate) fn behavior_and_position<
let Some(panel_config) = page.panel_config.as_ref() else {
return Element::from(text::body(fl!("unknown")));
};
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::item(
&descriptions[autohide_label],
toggler(None, panel_config.autohide.is_some(), |value| {
@ -170,7 +171,8 @@ pub(crate) fn style<
let Some(panel_config) = inner.panel_config.as_ref() else {
return Element::from(text::body(fl!("unknown")));
};
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::item(
&descriptions[gap_label],
toggler(None, panel_config.anchor_gap, |value| {
@ -264,7 +266,7 @@ pub(crate) fn configuration<P: page::Page<crate::pages::Message> + PanelPage>(
.title(fl!("panel-applets"))
.descriptions(descriptions)
.view::<P>(move |binder, page, section| {
let mut settings = settings::view_section(&section.title);
let mut settings = settings::section().title(&section.title);
let descriptions = &section.descriptions;
settings = if let Some((panel_applets_entity, _panel_applets_info)) = binder
.info
@ -282,7 +284,7 @@ pub(crate) fn configuration<P: page::Page<crate::pages::Message> + PanelPage>(
.spacing(16)
.apply(container)
.style(theme::Container::List)
.apply(button)
.apply(button::custom)
.style(theme::Button::Transparent)
.on_press(crate::pages::Message::Page(panel_applets_entity)),
)

View file

@ -175,7 +175,8 @@ pub fn super_key_action() -> Section<crate::pages::Message> {
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(
settings::item::builder(&descriptions[super_key]).control(widget::dropdown(
&page.super_key_selections,
@ -203,7 +204,8 @@ pub fn window_controls() -> Section<crate::pages::Message> {
.expect("desktop page not found");
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::item(
&descriptions[maximize],
toggler(
@ -239,7 +241,8 @@ pub fn focus_navigation() -> Section<crate::pages::Message> {
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::item(
&descriptions[focus_follows_cursor],
toggler(

View file

@ -134,7 +134,8 @@ fn multi_behavior() -> Section<crate::pages::Message> {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::item_row(vec![radio(
text::body(&descriptions[span]),
WorkspaceMode::Global,
@ -167,7 +168,8 @@ fn workspace_orientation() -> Section<crate::pages::Message> {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::item_row(vec![radio(
text::body(&descriptions[vertical]),
WorkspaceLayout::Vertical,

View file

@ -1155,7 +1155,8 @@ pub fn legacy_applications() -> Section<crate::pages::Message> {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
widget::settings::view_section(&section.title)
widget::settings::section()
.title(&section.title)
.add(widget::settings::item_row(vec![widget::radio(
widget::column()
.push(text::body(&descriptions[system]))

View file

@ -149,7 +149,7 @@ fn popover_menu_row(
..container::StyleSheet::appearance(theme, &cosmic::theme::Container::List)
}
}))
.apply(button)
.apply(button::custom)
.on_press(())
.style(theme::Button::Transparent)
.apply(Element::from)
@ -611,7 +611,7 @@ fn input_sources() -> Section<crate::pages::Message> {
.title(fl!("keyboard-sources"))
.view::<Page>(move |_binder, page, section| {
// TODO Need something more custom, with drag and drop
let mut section = settings::view_section(&section.title);
let mut section = settings::section().title(&section.title);
for id in &page.active_layouts {
if let Some((_locale, _variant, description, _source)) =
@ -650,7 +650,8 @@ fn special_character_entry() -> Section<crate::pages::Message> {
.view::<Page>(move |_binder, _page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(crate::widget::go_next_item(
&*descriptions[alternate],
Message::OpenSpecialCharacterContext(SpecialKey::AlternateCharacters),
@ -675,7 +676,7 @@ fn keyboard_shortcuts() -> Section<crate::pages::Message> {
.view::<Page>(move |binder, _page, section| {
let descriptions = &section.descriptions;
let mut section = settings::view_section(&section.title);
let mut section = settings::section().title(&section.title);
if let Some((shortcuts_entity, _)) = binder
.info
.iter()
@ -707,7 +708,8 @@ fn keyboard_typing_assist() -> Section<crate::pages::Message> {
let descriptions = &section.descriptions;
let theme = cosmic::theme::active();
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::flex_item(&descriptions[repeat_delay], {
// Delay
let delay_slider = cosmic::widget::slider(

View file

@ -588,7 +588,7 @@ fn shortcut_item(custom: bool, id: usize, data: &ShortcutModel) -> Element<Short
.spacing(16)
.apply(widget::container)
.style(theme::Container::List)
.apply(widget::button)
.apply(widget::button::custom)
.style(theme::Button::Transparent)
.on_press(LocalMessage::Show)
.apply(Element::from)

View file

@ -413,7 +413,7 @@ fn shortcuts() -> Section<crate::pages::Message> {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, _section| {
let content = if page.model.shortcut_models.is_empty() {
widget::settings::view_section("")
widget::settings::section()
.add(widget::settings::item_row(vec![widget::text::body(fl!(
"custom-shortcuts",
"none"

View file

@ -374,7 +374,7 @@ fn shortcuts() -> Section<crate::pages::Message> {
// If the search input is not empty, show the category view, else the search results.
let content = if page.search.input.is_empty() {
settings::view_section("")
settings::section()
.add(category_item(
Category::ManageWindow,
&descriptions[manage_window_label],
@ -437,7 +437,7 @@ fn category_item(category: Category, name: &str, modified: u16) -> Element<Messa
.spacing(16)
.apply(widget::container)
.style(theme::Container::List)
.apply(widget::button)
.apply(widget::button::custom)
.style(theme::Button::Transparent)
.on_press(Message::Category(category))
.into()

View file

@ -53,7 +53,8 @@ fn mouse() -> Section<crate::pages::Message> {
let input = binder.page::<super::Page>().expect("input page not found");
let theme = cosmic::theme::active();
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::flex_item(
&descriptions[primary_button],
cosmic::widget::segmented_control::horizontal(&input.primary_button)
@ -117,7 +118,8 @@ fn scrolling() -> Section<crate::pages::Message> {
let input = binder.page::<super::Page>().expect("input page not found");
let theme = cosmic::theme::active();
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::flex_item(&descriptions[scroll_speed], {
let value = input
.input_default

View file

@ -71,7 +71,8 @@ fn touchpad() -> Section<crate::pages::Message> {
let input = binder.page::<super::Page>().expect("input page not found");
let theme = cosmic::theme::active();
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(
settings::item::builder(&descriptions[primary_button])
.description(&descriptions[primary_button_desc])
@ -148,7 +149,8 @@ fn click_behavior() -> Section<crate::pages::Message> {
.page::<super::Page>()
.expect("input devices page not found");
settings::view_section(&*section.title)
settings::section()
.title(&*section.title)
// Secondary click via two fingers, and middle-click via three fingers
.add(settings::item_row(vec![widget::radio(
text::body(&descriptions[click_finger]),
@ -200,7 +202,8 @@ fn scrolling() -> Section<crate::pages::Message> {
.expect("input devices page not found");
let theme = cosmic::theme::active();
settings::view_section(&section.title)
settings::section()
.title(&section.title)
// Two-finger scrolling toggle
.add(settings::item_row(vec![widget::radio(
text::body(&descriptions[two_finger]),
@ -291,7 +294,8 @@ fn gestures() -> Section<crate::pages::Message> {
.view::<Page>(move |_binder, page, section| {
let descriptions = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
// .add(
// settings::item::builder(&descriptions[three_finger_any])
// .flex_control(text::body(&descriptions[switch_between_windows])),

View file

@ -621,7 +621,7 @@ fn devices_view() -> Section<crate::pages::Message> {
let mut view = widget::column::with_capacity(4);
let vpn_connections =
widget::settings::view_section(&section.descriptions[vpn_conns_txt]);
widget::settings::section().title(&section.descriptions[vpn_conns_txt]);
if page.known_connections.is_empty() {
view = view.push(vpn_connections.add(widget::settings::item_row(vec![
@ -725,7 +725,7 @@ fn devices_view() -> Section<crate::pages::Message> {
fn popup_button<'a>(message: Message, text: &'a str) -> Element<'a, Message> {
widget::text::body(text)
.vertical_alignment(alignment::Vertical::Center)
.apply(widget::button)
.apply(widget::button::custom)
.padding([4, 16])
.width(Length::Fill)
.style(cosmic::theme::Button::MenuItem)

View file

@ -567,8 +567,10 @@ fn devices_view() -> Section<crate::pages::Message> {
// Create separate sections for known and visible networks.
let (known_networks, visible_networks) = state.wireless_access_points.iter().fold(
(
widget::settings::view_section(&section.descriptions[known_networks_txt]),
widget::settings::view_section(&section.descriptions[visible_networks_txt]),
widget::settings::section()
.title(&section.descriptions[known_networks_txt]),
widget::settings::section()
.title(&section.descriptions[visible_networks_txt]),
),
|(mut known_networks, mut visible_networks), network| {
let is_connected = is_connected(state, network);
@ -715,7 +717,7 @@ fn is_connected(state: &NetworkManagerState, network: &AccessPoint) -> bool {
fn popup_button<'a>(message: Message, text: &'a str) -> Element<'a, Message> {
widget::text::body(text)
.vertical_alignment(alignment::Vertical::Center)
.apply(widget::button)
.apply(widget::button::custom)
.padding([4, 16])
.width(Length::Fill)
.style(cosmic::theme::Button::MenuItem)

View file

@ -455,7 +455,7 @@ impl Page {
.available_connections
.iter()
.fold(
widget::settings::view_section(header_txt),
widget::settings::section().title(header_txt),
|networks, connection| {
let is_connected = nm_state.active_conns.iter().any(|conn| match conn {
ActiveConnectionInfo::Wired { name, .. } => {
@ -598,7 +598,7 @@ fn devices_view() -> Section<crate::pages::Message> {
fn popup_button<'a>(message: Message, text: &'a str) -> Element<'a, Message> {
widget::text::body(text)
.vertical_alignment(alignment::Vertical::Center)
.apply(widget::button)
.apply(widget::button::custom)
.padding([4, 16])
.width(Length::Fill)
.style(cosmic::theme::Button::MenuItem)

View file

@ -199,7 +199,7 @@ fn profiles() -> Section<crate::pages::Message> {
.title(fl!("power-mode"))
.descriptions(descriptions)
.view::<Page>(move |_binder, _page, section| {
let mut section = settings::view_section(&section.title);
let mut section = settings::section().title(&section.title);
let runtime = tokio::runtime::Runtime::new().unwrap();

View file

@ -631,7 +631,8 @@ fn input() -> Section<crate::pages::Message> {
Message::SourceChanged,
);
let mut controls = settings::view_section(&section.title)
let mut controls = settings::section()
.title(&section.title)
.add(settings::flex_item(
&*section.descriptions[volume],
volume_control,
@ -688,7 +689,8 @@ fn output() -> Section<crate::pages::Message> {
Message::SinkChanged,
);
let mut controls = settings::view_section(&section.title)
let mut controls = settings::section()
.title(&section.title)
.add(settings::flex_item(
&*section.descriptions[volume],
volume_control,
@ -718,7 +720,7 @@ fn output() -> Section<crate::pages::Message> {
// .title(fl!("sound-alerts"))
// .descriptions(descriptions)
// .view::<Page>(move |_binder, _page, section| {
// settings::view_section(&section.title)
// settings::section().title(&section.title)
// .add(settings::item(&section.descriptions[volume], text::body("TODO")))
// .add(settings::item(&section.descriptions[sound], text::body("TODO")))
// .into()
@ -734,7 +736,7 @@ fn output() -> Section<crate::pages::Message> {
// .title(fl!("sound-applications"))
// .descriptions(descriptions)
// .view::<Page>(move |_binder, _page, section| {
// settings::view_section(&section.title)
// settings::section().title(&section.title)
// .add(settings::item(
// &*section.descriptions[applications],
// text::body("TODO"),

View file

@ -150,7 +150,8 @@ fn hardware() -> Section<crate::pages::Message> {
.view::<Page>(move |_binder, page, section| {
let desc = &section.descriptions;
let sections = settings::view_section(&section.title)
let sections = settings::section()
.title(&section.title)
.add(settings::flex_item(
&*desc[model],
text::body(&page.info.hardware_model),
@ -194,7 +195,8 @@ fn os() -> Section<crate::pages::Message> {
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
let desc = &section.descriptions;
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(settings::flex_item(
&*desc[os],
text::body(&page.info.operating_system),
@ -221,7 +223,7 @@ fn os() -> Section<crate::pages::Message> {
// .title(fl!("about-related"))
// .descriptions(vec![fl!("about-related", "support").into()])
// .view::<Page>(move |_binder, _page, section| {
// settings::view_section(&section.title)
// settings::section().title(&section.title)
// .add(settings::item(&*section.descriptions[0], text::body("TODO")))
// .into()
// })

View file

@ -330,7 +330,7 @@ impl Page {
}
fn timezone_context_item<'a>(&self, id: usize, timezone: &'a str) -> Element<'a, Message> {
widget::button(widget::settings::item_row(vec![
widget::button::custom(widget::settings::item_row(vec![
widget::text::body(timezone).wrap(Wrap::Word).into(),
widget::horizontal_space(Length::Fill).into(),
]))
@ -376,7 +376,8 @@ fn date() -> Section<crate::pages::Message> {
.title(fl!("time-date"))
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
settings::view_section(&section.title)
settings::section()
.title(&section.title)
.add(
settings::item::builder(&*section.descriptions[title])
.description(fl!("time-date", "auto-ntp"))
@ -399,7 +400,8 @@ fn format() -> Section<crate::pages::Message> {
.title(fl!("time-format"))
.descriptions(descriptions)
.view::<Page>(move |_binder, page, section| {
settings::view_section(&section.title)
settings::section()
.title(&section.title)
// 24-hour toggle
.add(
settings::item::builder(&section.descriptions[military])
@ -462,11 +464,12 @@ fn timezone() -> Section<crate::pages::Message> {
.push(widget::icon::from_name("go-next-symbolic").size(16).icon())
.apply(widget::container)
.style(cosmic::theme::Container::List)
.apply(widget::button)
.apply(widget::button::custom)
.style(cosmic::theme::Button::Transparent)
.on_press(Message::TimezoneContext);
settings::view_section(&section.title)
settings::section()
.title(&section.title)
// Time zone select
.add(
settings::item::builder(&*section.descriptions[time_zone])

View file

@ -96,7 +96,7 @@ pub fn page_title<Message: 'static>(page: &page::Info) -> Element<Message> {
#[must_use]
pub fn unimplemented_page<Message: 'static>() -> Element<'static, Message> {
settings::view_section("")
settings::section().title("")
.add(text::body("We haven't created that panel yet, and/or it is using a similar idea as current Pop! designs."))
.into()
}
@ -146,7 +146,7 @@ pub fn page_list_item<'a, Message: 'static + Clone>(
.padding([space_s, space_m])
.align_x(alignment::Horizontal::Center)
.style(theme::Container::List)
.apply(button)
.apply(button::custom)
.padding(0)
.style(theme::Button::Transparent)
.on_press(message)
@ -185,7 +185,7 @@ pub fn go_next_item<Msg: Clone + 'static>(description: &str, msg: Msg) -> cosmic
])
.apply(widget::container)
.style(cosmic::theme::Container::List)
.apply(button)
.apply(button::custom)
.style(theme::Button::Transparent)
.on_press(msg)
.into()

View file

@ -121,6 +121,5 @@ pub fn unimplemented<'a, Message: 'static>(
_page: &'a dyn Page<Message>,
_section: &'a Section<Message>,
) -> cosmic::Element<'a, Message> {
cosmic::widget::settings::view_column(vec![cosmic::widget::settings::view_section("").into()])
.into()
cosmic::widget::settings::view_column(vec![cosmic::widget::settings::section().into()]).into()
}

View file

@ -8,9 +8,9 @@ license = "GPL-3.0-only"
[dependencies]
byte-unit = "5.1.4"
const_format = "0.2.32"
const_format = "0.2.33"
concat-in-place = "1.1.0"
sysinfo = "0.31.2"
sysinfo = "0.31.4"
memchr = "2.7.4"
[dependencies.bumpalo]

View file

@ -15,5 +15,5 @@ futures-lite = "2.3.0"
futures-util = "0.3.30"
image = "0.25.2"
infer = "0.16.0"
tokio = { version = "1.39.3", features = ["sync"] }
tokio = { version = "1.40.0", features = ["sync"] }
tracing = "0.1.40"