Implement design items

This commit is contained in:
Jeremy Soller 2023-10-06 13:07:53 -06:00
parent bec5cb5b7d
commit 7cb1c89474
No known key found for this signature in database
GPG key ID: DCFCA852D3906975
4 changed files with 221 additions and 42 deletions

55
Cargo.lock generated
View file

@ -94,6 +94,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3aa2999eb46af81abb65c2d30d446778d7e613b60bbf4e174a027e80f90a3c14"
[[package]]
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_system_properties"
version = "0.1.5"
@ -575,6 +581,20 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
[[package]]
name = "chrono"
version = "0.4.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
dependencies = [
"android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-targets 0.48.5",
]
[[package]]
name = "clang-sys"
version = "1.6.1"
@ -729,6 +749,7 @@ dependencies = [
name = "cosmic-greeter"
version = "0.1.0"
dependencies = [
"chrono",
"env_logger 0.10.0",
"freedesktop_entry_parser",
"greetd_ipc",
@ -1546,7 +1567,7 @@ dependencies = [
"log",
"thiserror",
"winapi",
"windows",
"windows 0.44.0",
]
[[package]]
@ -1682,6 +1703,29 @@ version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "iana-time-zone"
version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"wasm-bindgen",
"windows 0.48.0",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "iced"
version = "0.10.0"
@ -4443,6 +4487,15 @@ dependencies = [
"windows-targets 0.42.2",
]
[[package]]
name = "windows"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.42.0"

View file

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
chrono = "0.4"
env_logger = "0.10"
freedesktop_entry_parser = "1"
log = "0.4"

View file

@ -439,7 +439,7 @@ impl cosmic::Application for App {
widget::cosmic_container::container(column)
.layer(cosmic::cosmic_theme::Layer::Primary)
.padding(16)
.style(cosmic::theme::Container::Primary),
.style(cosmic::theme::Container::Card),
)
.on_press(Message::Username(socket.clone(), user.name.clone())),
);

View file

@ -5,7 +5,7 @@ use cosmic::app::{message, Command, Core, Settings};
use cosmic::{
executor,
iced::{
self,
self, alignment,
event::wayland::{Event as WaylandEvent, OutputEvent},
futures::{self, SinkExt},
subscription,
@ -15,16 +15,17 @@ use cosmic::{
destroy_layer_surface, get_layer_surface, Anchor, KeyboardInteractivity, Layer,
},
},
Subscription,
Length, Subscription,
},
iced_runtime::core::window::Id as SurfaceId,
widget, Element,
style, widget, Element,
};
use std::{
collections::HashMap,
ffi::{CStr, CString},
fs,
path::Path,
process,
};
use tokio::{sync::mpsc, task, time};
use wayland_client::{protocol::wl_output::WlOutput, Proxy};
@ -145,6 +146,7 @@ pub struct Flags {
/// Messages that are used specifically by our [`App`].
#[derive(Clone, Debug)]
pub enum Message {
None,
OutputEvent(OutputEvent, WlOutput),
Channel(mpsc::Sender<String>),
Prompt(String, bool, String),
@ -216,22 +218,17 @@ impl cosmic::Application for App {
/// Handle application events here.
fn update(&mut self, message: Self::Message) -> Command<Self::Message> {
match message {
Message::None => {}
Message::OutputEvent(output_event, output) => match output_event {
OutputEvent::Created(_output_info_opt) => {
log::info!("output {}: created", output.id());
//TODO: COVER ALL OUTPUTS AFTER FIXING FOCUS BUG
if !self.surface_ids.is_empty() {
log::error!("COVER ALL OUTPUTS AFTER FIXING FOCUS BUG");
return Command::none();
}
let surface_id = self.next_surface_id;
self.next_surface_id.0 += 1;
match self.surface_ids.insert(output.clone(), surface_id) {
Some(old_surface_id) => {
//TODO: remove old surface
//TODO: remove old surface?
log::warn!(
"output {}: already had surface ID {}",
output.id(),
@ -244,7 +241,7 @@ impl cosmic::Application for App {
return Command::batch([
get_layer_surface(SctkLayerSurfaceSettings {
id: surface_id,
layer: Layer::Top,
layer: Layer::Overlay,
keyboard_interactivity: KeyboardInteractivity::Exclusive,
pointer_interactivity: true,
anchor: Anchor::TOP | Anchor::BOTTOM | Anchor::LEFT | Anchor::RIGHT,
@ -258,10 +255,7 @@ impl cosmic::Application for App {
right: 0,
},
exclusive_zone: 0,
size_limits: iced::Limits::NONE
.min_width(1.0)
.min_height(1.0)
.max_width(600.0),
size_limits: iced::Limits::NONE.min_width(1.0).min_height(1.0),
}),
widget::text_input::focus(self.text_input_id.clone()),
]);
@ -309,7 +303,14 @@ impl cosmic::Application for App {
}
Message::Exit => {
self.exited = true;
return iced::window::close();
let mut commands = Vec::new();
for (_output, surface_id) in self.surface_ids.drain() {
commands.push(destroy_layer_surface(surface_id));
}
//TODO: cleaner method to exit?
commands.push(Command::perform(async { process::exit(0) }, |x| x));
return Command::batch(commands);
}
}
Command::none()
@ -321,40 +322,164 @@ impl cosmic::Application for App {
}
/// Creates a view after each update.
fn view_window(&self, id: SurfaceId) -> Element<Self::Message> {
let mut column = widget::column::with_capacity(3)
.max_width(280.0)
fn view_window(&self, _id: SurfaceId) -> Element<Self::Message> {
let left_element = {
let date_time_column = {
let mut column = widget::column::with_capacity(2).padding(16.0).spacing(12.0);
let dt = chrono::Local::now();
//TODO: localized format
let date = dt.format("%A, %B %-d");
column = column
.push(widget::text::title2(format!("{}", date)).style(style::Text::Accent));
//TODO: localized format
let time = dt.format("%R");
column = column.push(
widget::text(format!("{}", time))
.size(112.0)
.style(style::Text::Accent),
);
column
};
//TODO: get actual status
let status_row = iced::widget::row![
widget::icon::from_name("network-wireless-signal-ok-symbolic",),
iced::widget::row![
widget::icon::from_name("battery-level-50-symbolic"),
widget::text("50%"),
]
]
.padding(16.0)
.spacing(12.0);
match &self.prompt_opt {
Some((prompt, secret, value)) => {
let mut text_input = widget::text_input(&prompt, &value)
.id(self.text_input_id.clone())
.on_input(|value| Message::Prompt(prompt.clone(), *secret, value))
.on_submit(Message::Submit);
//TODO: implement these buttons
let button_row = iced::widget::row![
widget::button(widget::icon::from_name(
"applications-accessibility-symbolic"
))
.padding(12.0)
.on_press(Message::None),
widget::button(widget::icon::from_name("input-keyboard-symbolic"))
.padding(12.0)
.on_press(Message::None),
widget::button(widget::icon::from_name("system-users-symbolic"))
.padding(12.0)
.on_press(Message::None),
widget::button(widget::icon::from_name("system-suspend-symbolic"))
.padding(12.0)
.on_press(Message::None),
]
.padding([16.0, 0.0, 0.0, 0.0])
.spacing(8.0);
if *secret {
text_input = text_input.password()
widget::container(iced::widget::column![
date_time_column,
widget::divider::horizontal::default(),
status_row,
widget::divider::horizontal::default(),
button_row,
])
.width(Length::Fill)
.align_x(alignment::Horizontal::Left)
};
let right_element = {
let mut column = widget::column::with_capacity(2)
.spacing(12.0)
.max_width(280.0);
match &self.flags.icon_opt {
Some(icon) => {
column = column.push(
widget::container(
widget::Image::new(icon.clone())
.width(Length::Fixed(78.0))
.height(Length::Fixed(78.0)),
)
.width(Length::Fill)
.align_x(alignment::Horizontal::Center),
)
}
column = column.push(text_input);
None => {}
}
match &self.flags.current_user.gecos {
Some(gecos) => {
column = column.push(
widget::container(widget::text::title4(gecos))
.width(Length::Fill)
.align_x(alignment::Horizontal::Center),
);
}
None => {}
}
None => {}
}
if let Some(error) = &self.error_opt {
column = column.push(widget::text(error));
}
match &self.prompt_opt {
Some((prompt, secret, value)) => {
let mut text_input = widget::text_input(&prompt, &value)
.id(self.text_input_id.clone())
.leading_icon(widget::icon::from_name("system-lock-screen-symbolic").into())
.trailing_icon(
widget::icon::from_name("document-properties-symbolic").into(),
)
.on_input(|value| Message::Prompt(prompt.clone(), *secret, value))
.on_submit(Message::Submit);
let centered = widget::container(column)
.width(iced::Length::Fill)
.height(iced::Length::Fill)
.align_x(iced::alignment::Horizontal::Center)
.align_y(iced::alignment::Vertical::Center);
if *secret {
text_input = text_input.password()
}
Element::from(centered)
column = column.push(text_input);
}
None => {}
}
if let Some(error) = &self.error_opt {
column = column.push(widget::text(error));
}
widget::container(column)
.align_x(alignment::Horizontal::Center)
.width(Length::Fill)
};
widget::container(
widget::cosmic_container::container(
iced::widget::row![left_element, right_element]
.align_items(alignment::Alignment::Center),
)
.layer(cosmic::cosmic_theme::Layer::Background)
.padding(16)
.style(cosmic::theme::Container::Custom(Box::new(
|theme: &cosmic::Theme| {
// Use background appearance as the base
let mut appearance = widget::container::StyleSheet::appearance(
theme,
&cosmic::theme::Container::Background,
);
appearance.border_radius = 16.0.into();
appearance
},
)))
.width(Length::Fixed(800.0)),
)
.padding([32.0, 0.0, 0.0, 0.0])
.width(Length::Fill)
.height(Length::Fill)
.align_x(alignment::Horizontal::Center)
.align_y(alignment::Vertical::Top)
.style(cosmic::theme::Container::Custom(Box::new(|_| {
let mut appearance = widget::container::Appearance::default();
appearance.background = Some(iced::Background::Color(iced::Color::BLACK));
appearance
})))
.into()
}
//TODO: subscription for date/time
fn subscription(&self) -> Subscription<Self::Message> {
if self.exited {
return Subscription::none();