Implement design items
This commit is contained in:
parent
bec5cb5b7d
commit
7cb1c89474
4 changed files with 221 additions and 42 deletions
55
Cargo.lock
generated
55
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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())),
|
||||
);
|
||||
|
|
|
|||
205
src/locker.rs
205
src/locker.rs
|
|
@ -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();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue