diff --git a/src/bin/client/ui/channel.rs b/src/bin/client/ui/channel.rs new file mode 100644 index 0000000..64154e6 --- /dev/null +++ b/src/bin/client/ui/channel.rs @@ -0,0 +1,67 @@ +use super::*; + +pub fn view(rsc: &mut Rsc) -> StrongWidget { + let msg_panel = msg_panel(rsc); + let side_bar = rect(Color::BLACK.alpha(150)).width(260); + + (side_bar, msg_panel).span(Dir::RIGHT).add_strong(rsc) +} + +pub fn msg_widget(username: &str, content: &str) -> impl WidgetIdFn { + let content = wtext(content) + .editable(EditMode::MultiLine) + .size(SIZE) + .wrap(true) + .attr::(()); + let header = wtext(username).size(SIZE); + ( + image(include_bytes!("../assets/sungals.png")) + .sized((70, 70)) + .align(Align::TOP), + (header, content) + .span(Dir::DOWN) + .gap(10) + .width(rest(1)) + .align(Align::TOP), + ) + .span(Dir::RIGHT) + .gap(10) + .to_any() +} + +pub fn msg_panel(rsc: &mut Rsc) -> WeakWidget { + let msg_area = Span::empty(Dir::DOWN).gap(15); + + let send_text = wtext("") + .editable(EditMode::MultiLine) + .size(SIZE) + .wrap(true) + .hint(hint_text("send message")) + .add(rsc); + + let msg_area = msg_area.add(rsc); + + ( + msg_area + .scrollable() + .pad(Padding::x(15).with_top(15)) + .height(rest(1)), + send_text + .on(Submit, move |ctx, rsc| { + let content = ctx.widget.edit(rsc).take(); + let msg = msg_widget("ur mothe:", &content).add_strong(rsc); + rsc[msg_area].children.push(msg); + }) + .pad(15) + .attr::(send_text) + .scrollable() + .masked() + .background(rect(Color::BLACK.brighter(0.05)).radius(15)) + .pad(15) + .max_height(rel(0.5)) + .layer_offset(1), + ) + .span(Dir::DOWN) + .width(rest(1)) + .add(rsc) +} diff --git a/src/bin/client/ui/main.rs b/src/bin/client/ui/main.rs index be016df..503bbd8 100644 --- a/src/bin/client/ui/main.rs +++ b/src/bin/client/ui/main.rs @@ -1,71 +1,32 @@ +use std::hash::Hash; + use crate::Rsc; use super::*; pub const SIZE: u32 = 20; +#[derive(PartialEq, Eq, Hash, Clone, Copy)] +pub enum MainView { + Channel, + Server, +} + pub fn main_view(rsc: &mut Rsc) -> WeakWidget { - let msg_panel = msg_panel(rsc); - let side_bar = rect(Color::BLACK.brighter(0.05)).width(80); - - (side_bar, msg_panel).span(Dir::RIGHT).add(rsc) + let mut view = WidgetSelector::new(MainView::Channel, channel::view(rsc)); + view.set(MainView::Server, server::view(rsc)); + let view = view.add(rsc); + (top_bar(rsc, view), view).span(Dir::DOWN).add(rsc) } -pub fn msg_widget(username: &str, content: &str) -> impl WidgetIdFn { - let content = wtext(content) - .editable(EditMode::MultiLine) - .size(SIZE) - .wrap(true) - .attr::(()); - let header = wtext(username).size(SIZE); - ( - image(include_bytes!("../assets/sungals.png")) - .sized((70, 70)) - .align(Align::TOP), - (header, content) - .span(Dir::DOWN) - .gap(10) - .width(rest(1)) - .align(Align::TOP), - ) - .span(Dir::RIGHT) - .gap(10) - .to_any() -} - -pub fn msg_panel(rsc: &mut Rsc) -> WeakWidget { - let msg_area = Span::empty(Dir::DOWN).gap(15); - - let send_text = wtext("") - .editable(EditMode::MultiLine) - .size(SIZE) - .wrap(true) - .hint(hint_text("send message")) - .add(rsc); - - let msg_area = msg_area.add(rsc); - - ( - msg_area - .scrollable() - .pad(Padding::x(15).with_top(15)) - .height(rest(1)), - send_text - .on(Submit, move |ctx, rsc| { - let content = ctx.widget.edit(rsc).take(); - let msg = msg_widget("ur mothe:", &content).add_strong(rsc); - rsc[msg_area].children.push(msg); - }) - .pad(15) - .attr::(send_text) - .scrollable() - .masked() - .background(rect(Color::BLACK.brighter(0.05)).radius(15)) - .pad(15) - .max_height(rel(0.5)) - .layer_offset(1), - ) - .span(Dir::DOWN) - .width(rest(1)) +pub fn top_bar(rsc: &mut Rsc, view: WeakWidget>) -> WeakWidget { + let [channel, server] = tabs( + rsc, + view, + [("channel", MainView::Channel), ("server", MainView::Server)], + ); + rect(Color::BLACK.alpha(150)) + .height(50) + .foreground((channel, server).span(Dir::RIGHT)) .add(rsc) } diff --git a/src/bin/client/ui/misc.rs b/src/bin/client/ui/misc.rs index 6dbae08..8bdafa5 100644 --- a/src/bin/client/ui/misc.rs +++ b/src/bin/client/ui/misc.rs @@ -112,3 +112,17 @@ widget_trait! { } } } + +pub fn tabs( + rsc: &mut Rsc, + view: WeakWidget>, + list: [(&'static str, T); N], +) -> [WeakWidget; N] { + list.map(|(name, sel)| { + Button::new(name, color::DARK, rsc) + .on(Submit, move |_, rsc: &mut Rsc| { + rsc[view].select(sel); + }) + .add(rsc) + }) +} diff --git a/src/bin/client/ui/mod.rs b/src/bin/client/ui/mod.rs index ee7d85c..e360207 100644 --- a/src/bin/client/ui/mod.rs +++ b/src/bin/client/ui/mod.rs @@ -1,10 +1,12 @@ use crate::Rsc; use iris::prelude::*; +mod channel; pub mod color; mod connect; mod main; mod misc; +mod server; pub use connect::*; pub use main::*; diff --git a/src/bin/client/ui/server.rs b/src/bin/client/ui/server.rs new file mode 100644 index 0000000..8a9ab21 --- /dev/null +++ b/src/bin/client/ui/server.rs @@ -0,0 +1,28 @@ +use super::*; + +#[derive(PartialEq, Eq, Hash, Clone, Copy)] +enum View { + Info, + User, +} + +pub fn view(rsc: &mut Rsc) -> StrongWidget { + let mut view = WidgetSelector::new(View::Info, info(rsc)); + view.set(View::User, users(rsc)); + let view = view.add(rsc); + let [info, server] = tabs(rsc, view, [("info", View::Info), ("users", View::User)]); + + let side_bar = rect(Color::BLACK.alpha(150)) + .foreground((info, server).span(Dir::DOWN)) + .width(260); + + (side_bar, view).span(Dir::RIGHT).add_strong(rsc) +} + +fn info(rsc: &mut Rsc) -> StrongWidget { + wtext("server info").center_text().add_strong(rsc) +} + +fn users(rsc: &mut Rsc) -> StrongWidget { + wtext("users").center_text().add_strong(rsc) +} diff --git a/src/bin/server/main.rs b/src/bin/server/main.rs index d677168..3c8373f 100644 --- a/src/bin/server/main.rs +++ b/src/bin/server/main.rs @@ -228,7 +228,6 @@ impl RecvHandler for ClientHandler { let _ = replier.send(LoginResp::InvalidPassword).await; return; } - println!("login: \"{username}\""); *self.state.write().await = ClientState::Authed(id); let _ = replier.send(LoginResp::Ok { id }).await; } diff --git a/src/rsc.rs b/src/rsc.rs index 26ecc2e..bf0bec2 100644 --- a/src/rsc.rs +++ b/src/rsc.rs @@ -94,7 +94,7 @@ impl Drop for DataGuard { let dir = self.path.parent().unwrap(); fs::create_dir_all(dir).unwrap(); let mut file = File::create(dir.join(T::path())).unwrap(); - let ron = ron::to_string(&self.val).unwrap(); + let ron = ron::ser::to_string_pretty(&self.val, ron::ser::PrettyConfig::new()).unwrap(); let data = format!("// v{}\n{}\n", T::version(), ron); if let Err(e) = file.write_all(data.as_bytes()) { println!("Failed to write config @ {:?}: {e}", self.path);