Files
feresaria/shell/ferese-settings/src/connections/wifi_ui.rs
T

303 lines
11 KiB
Rust

use cosmic::Element;
use cosmic::iced::{Alignment, Length};
use cosmic::widget::{column, row, text_input};
use zeroize::{Zeroize, Zeroizing};
use super::ui::{Input, message};
use super::{Command, Security};
use crate::{App, Message, visuals};
impl App {
pub(super) fn wifi_view(
&self,
result: &Result<super::wifi::Wifi, String>,
) -> Element<'_, Message> {
let s = &self.connections;
let p = visuals::Palette::from_resolved(&self.resolved.presented);
let ready = s.busy.is_none();
let Ok(wifi) = result else {
return self.connection_card(
column([])
.spacing(8)
.push(self.label(ferese_config::tr!("Wi-Fi unavailable"), 14.))
.push(self.connection_note(result.as_ref().expect_err(
"the unavailable-services branch contains a connection error",
))),
);
};
let mut body = column([]).spacing(6);
let status = if wifi.radios.is_empty() {
"No Wi-Fi adapter"
} else if !wifi.hardware_enabled {
"Blocked by a hardware switch or airplane mode"
} else if wifi.enabled {
"On"
} else {
"Off"
};
body = body.push(
self.connection_card(
row([])
.spacing(8)
.align_y(Alignment::Center)
.push(
column([])
.spacing(2)
.width(Length::Fill)
.push(self.label(ferese_config::tr!("Wi-Fi"), 15.))
.push(self.connection_note(status)),
)
.push(
ferese_theme::controls::switch(wifi.enabled, p)
.name(ferese_config::tr!("Wi-Fi power"))
.on_press_maybe(
(ready
&& (wifi.hardware_enabled || wifi.enabled)
&& !wifi.radios.is_empty())
.then(|| message(Input::Run(Command::WifiPower(!wifi.enabled)))),
),
),
),
);
if !wifi.enabled || !wifi.hardware_enabled || wifi.radios.is_empty() {
return body.into();
}
body = body.push(
row([])
.align_y(Alignment::Center)
.push(
self.label(ferese_config::tr!("Networks"), 14.)
.width(Length::Fill),
)
.push(self.connection_button("Scan", Input::Run(Command::WifiScan), ready, false)),
);
if wifi.networks.is_empty() {
body = body
.push(self.connection_note("No networks found. Scan to look for nearby networks."));
}
for network in &wifi.networks {
let radio = wifi
.radios
.iter()
.find(|r| r.path == network.device)
.map(|r| r.name.as_str())
.unwrap_or("");
let state = if network.connected {
"Connected · "
} else if network.connecting {
"Connecting · "
} else if network.saved.is_some() {
"Saved · "
} else {
""
};
let state = ferese_config::locale::text(state);
let detail = format!(
"{state}{} · {}{}",
ferese_config::locale::text(network.security.label()),
ferese_config::locale::format(
"{percent}% signal",
&[("percent", network.strength.to_string())]
),
if wifi.radios.len() > 1 {
format!(" · {radio}")
} else {
String::new()
}
);
let mut controls = row([]).spacing(6);
if network.connected || network.connecting {
controls = controls.push(self.connection_button(
"Disconnect",
Input::Run(Command::WifiDisconnect(network.device.clone())),
ready,
false,
));
} else if network.saved.is_some()
|| !network.security.password() && network.security.can_create()
{
controls = controls.push(self.connection_button(
"Connect",
Input::Run(Command::WifiConnect(
network.clone(),
Zeroizing::new(String::new()),
)),
ready,
false,
));
} else {
controls = controls.push(self.connection_button(
"Connect…",
Input::Select(network.clone()),
ready,
false,
));
}
if network.saved.is_some() && network.security.password() {
controls = controls.push(self.connection_button(
"Password…",
Input::Select(network.clone()),
ready,
false,
));
}
body = body.push(
self.connection_card(
row([])
.spacing(8)
.align_y(Alignment::Center)
.push(visuals::action_icon(
super::super::schema::Page::Connections.icon(),
p.accent,
))
.push(
column([])
.spacing(2)
.width(Length::Fill)
.push(self.label(network.name.clone(), 13.))
.push(self.connection_note(&detail)),
)
.push(controls),
),
);
if s.selected.as_ref().is_some_and(|selected| {
selected.ssid == network.ssid
&& selected.device == network.device
&& selected.security == network.security
}) {
body = body.push(self.wifi_credentials());
}
}
body = body.push(self.connection_button(
"Join a hidden network…",
Input::Hidden(true),
ready,
false,
));
if s.hidden {
body = body.push(self.wifi_credentials());
}
if !wifi.saved.is_empty() {
body = body.push(self.label(ferese_config::tr!("Saved networks"), 14.));
for saved in &wifi.saved {
body = body.push(
self.connection_card(
row([])
.spacing(8)
.align_y(Alignment::Center)
.push(visuals::action_icon(
crate::schema::Page::Connections.icon(),
p.muted,
))
.push(
column([])
.spacing(2)
.width(Length::Fill)
.push(self.label(saved.name.clone(), 13.))
.push(self.connection_note(saved.security.label())),
)
.push(self.connection_button(
"Forget",
Input::Forget(Command::WifiForget(saved.path.clone())),
ready,
false,
)),
),
);
}
}
body.into()
}
pub(super) fn wifi_credentials(&self) -> Element<'_, Message> {
let s = &self.connections;
let p = visuals::Palette::from_resolved(&self.resolved.presented);
let target = self.wifi_target();
let mut body = column([]).spacing(6).push(self.ui_label(
if s.hidden {
ferese_config::locale::translate("Hidden network")
} else {
ferese_config::locale::format(
"Join {network}",
&[(
"network",
s.selected
.as_ref()
.map(|n| n.name.clone())
.unwrap_or_else(|| ferese_config::locale::translate("network")),
)],
)
},
16.,
));
if s.hidden {
body = body.push(
text_input(
ferese_config::tr!("Network name (SSID)"),
s.hidden_name.clone(),
)
.font(self.font)
.size(13)
.padding([5, 8])
.style(visuals::input_style(p))
.on_input(|name| message(Input::HiddenName(name))),
);
let mut choices = row([]).spacing(6);
for security in [
Security::Personal,
Security::Sae,
Security::Open,
Security::Owe,
] {
choices = choices.push(self.connection_button(
security.label(),
Input::HiddenSecurity(security),
true,
s.hidden_security == security,
));
}
body = body.push(choices);
}
let security = target
.as_ref()
.map(|n| n.security)
.unwrap_or(s.hidden_security);
if security.password() {
body = body.push(
text_input(ferese_config::tr!("Network password"), s.password.as_str())
.id(cosmic::widget::Id::new("wifi-password"))
.password()
.font(self.font)
.size(13)
.padding([5, 8])
.style(visuals::input_style(p))
.on_input(|value| message(Input::Password(Zeroizing::new(value))))
.on_submit(|mut value| {
value.zeroize();
message(Input::SubmitWifi)
}),
);
}
if !security.can_create() {
body = body.push(self.connection_note(
"Enterprise and legacy networks need a saved NetworkManager profile with their security settings.",
));
}
body = body.push(
row([])
.spacing(8)
.push(self.connection_button("Cancel", Input::CancelWifi, true, false))
.push(self.connection_button(
"Connect",
Input::SubmitWifi,
target.is_some()
&& security.can_create()
&& super::wifi::valid_password(security, &s.password)
&& s.busy.is_none(),
true,
)),
);
self.connection_card(body)
}
}