From e67c55d67d5f6f26dacd529f40d01b2f0eb512d6 Mon Sep 17 00:00:00 2001 From: Shadow Cat Date: Mon, 19 Jan 2026 21:26:59 -0500 Subject: [PATCH] update iris & get button working again --- iris | 2 +- src/bin/client/debug.rs | 5 +- src/bin/client/main.rs | 45 ++++++++---- src/bin/client/state.rs | 2 +- src/bin/client/ui/connect.rs | 28 ++++---- src/bin/client/ui/login.rs | 134 +++++++++++++++++++++++++++++++++++ src/bin/client/ui/main.rs | 6 +- src/bin/client/ui/misc.rs | 61 +++++++--------- 8 files changed, 213 insertions(+), 70 deletions(-) create mode 100644 src/bin/client/ui/login.rs diff --git a/iris b/iris index a9c76e4..7bafb04 160000 --- a/iris +++ b/iris @@ -1 +1 @@ -Subproject commit a9c76e4326c913592501fbe67cd3f2fc93040f4c +Subproject commit 7bafb04a34807eb54fc5b068e5058420ab85a431 diff --git a/src/bin/client/debug.rs b/src/bin/client/debug.rs index 1059582..b4d55d3 100644 --- a/src/bin/client/debug.rs +++ b/src/bin/client/debug.rs @@ -1,9 +1,10 @@ use crate::{Client, Rsc}; +use iris::core::UiRenderState; use openworm::net::NetServerMsg; impl Client { - pub fn debug(&mut self, rsc: &mut Rsc) { - rsc.ui.debug_layers(); + pub fn debug(&mut self, _rsc: &mut Rsc, render: &mut UiRenderState) { + render.debug_layers(); // let mut file = std::fs::OpenOptions::new() // .write(true) // .create(true) diff --git a/src/bin/client/main.rs b/src/bin/client/main.rs index 4d02682..868ec73 100644 --- a/src/bin/client/main.rs +++ b/src/bin/client/main.rs @@ -11,7 +11,10 @@ use openworm::{ net::{ClientMsg, ServerMsg, install_crypto_provider}, rsc::DataDir, }; -use winit::event::{ElementState, MouseButton, WindowEvent}; +use winit::{ + event::{ElementState, MouseButton, WindowEvent}, + window::WindowAttributes, +}; mod account; mod debug; @@ -31,8 +34,8 @@ pub struct Client { dir: DataDir, data: ClientData, state: ClientState, - main_ui: WidgetRef, - notif: WidgetRef, + main_ui: WeakWidget, + notif: WeakWidget, proxy: Proxy, } @@ -48,7 +51,7 @@ impl DefaultAppState for Client { type Event = ClientEvent; fn new( - ui_state: DefaultUiState, + mut ui_state: DefaultUiState, rsc: &mut DefaultRsc, proxy: Proxy, ) -> Self { @@ -67,9 +70,9 @@ impl DefaultAppState for Client { notif.pad(Padding::top(10)).align(Align::TOP_CENTER), ) .stack() - .set_root(rsc); + .set_root(rsc, &mut ui_state); - main_view(rsc).set_ptr(main_ui, rsc); + start_ui(rsc).set_ptr(main_ui, rsc); Self { ui_state, @@ -82,7 +85,12 @@ impl DefaultAppState for Client { } } - fn event(&mut self, event: Self::Event, rsc: &mut DefaultRsc) { + fn event( + &mut self, + event: Self::Event, + rsc: &mut DefaultRsc, + _render: &mut UiRenderState, + ) { match event { ClientEvent::Connect { send } => { let ClientState::Connect(connect) = self.state.take() else { @@ -103,7 +111,7 @@ impl DefaultAppState for Client { && let Some(msg_area) = state.channel { let msg = msg_widget(&msg.user, &msg.content).add_strong(rsc); - rsc.ui[msg_area].children.push(msg); + rsc[msg_area].children.push(msg); } } ServerMsg::LoadMsgs(msgs) => { @@ -113,7 +121,7 @@ impl DefaultAppState for Client { for msg in msgs { state.msgs.push(msg.clone()); let msg = msg_widget(&msg.user, &msg.content).add_strong(rsc); - rsc.ui[msg_area].children.push(msg); + rsc[msg_area].children.push(msg); } } } @@ -132,28 +140,37 @@ impl DefaultAppState for Client { } ServerMsg::Error(error) => { let msg = format!("{error:?}"); - rsc.ui[self.notif].inner = Some(werror(&msg, rsc)); + rsc[self.notif].inner = Some(werror(&msg, rsc)); } }, ClientEvent::Err(msg) => { - rsc.ui[self.notif].inner = Some(werror(&msg, rsc)); + rsc[self.notif].inner = Some(werror(&msg, rsc)); } } } - fn exit(&mut self, _: &mut DefaultRsc) { + fn exit(&mut self, _rsc: &mut DefaultRsc, _render: &mut UiRenderState) { self.state.exit(); self.dir.save(CLIENT_DATA, &self.data); } - fn window_event(&mut self, event: WindowEvent, rsc: &mut DefaultRsc) { + fn window_event( + &mut self, + event: WindowEvent, + rsc: &mut DefaultRsc, + render: &mut UiRenderState, + ) { if let WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Middle, .. } = event { - self.debug(rsc); + self.debug(rsc, render); } } + + fn window_attributes() -> WindowAttributes { + WindowAttributes::default().with_title("OPENWORM") + } } diff --git a/src/bin/client/state.rs b/src/bin/client/state.rs index 1f5415b..b0de0a4 100644 --- a/src/bin/client/state.rs +++ b/src/bin/client/state.rs @@ -15,7 +15,7 @@ pub struct Login { pub struct LoggedIn { pub network: NetHandle, pub msgs: Vec, - pub channel: Option>, + pub channel: Option>, pub username: String, } diff --git a/src/bin/client/ui/connect.rs b/src/bin/client/ui/connect.rs index 476d90a..bf73a77 100644 --- a/src/bin/client/ui/connect.rs +++ b/src/bin/client/ui/connect.rs @@ -1,6 +1,6 @@ use super::*; -pub fn start_ui(rsc: &mut Rsc) -> WidgetRef { +pub fn start_ui(rsc: &mut Rsc) -> WeakWidget { let mut accounts = Span::empty(Dir::DOWN); accounts.push( @@ -14,17 +14,15 @@ pub fn start_ui(rsc: &mut Rsc) -> WidgetRef { let connect = Button::submit("connect", rsc); let create = Button::submit("create", rsc); - connect.on(Submit, move |_, rsc| { - connect.disable(); - create.disable(); + rsc.events.register(connect.root(), Submit, move |_, rsc| { + connect.disable(rsc); + create.disable(rsc); }); - let connect_ = connect.clone(); - let create_ = create.clone(); - ui.on(create.view(), Submit, move |ctx| { - connect_.disable(); - create_.disable(); - create_ui(ctx.ui).set_ptr(&ctx.state.main_ui, ctx.ui); + rsc.events.register(create.root(), Submit, move |ctx, rsc| { + connect.disable(rsc); + create.disable(rsc); + create_ui(rsc).set_ptr(ctx.state.main_ui, rsc); }); ( @@ -35,14 +33,14 @@ pub fn start_ui(rsc: &mut Rsc) -> WidgetRef { .span(Dir::DOWN) .gap(30) .modal(400) - .add(ui) + .add(rsc) } -pub fn create_ui(ui: &mut Ui) -> WidgetRef { - wtext("hi").add(ui) +pub fn create_ui(rsc: &mut Rsc) -> WeakWidget { + wtext("hi").add(rsc) } -// pub fn connect_screen(client: &mut Client, ui: &mut Ui, state: &UiState) -> WidgetRef { +// pub fn connect_screen(client: &mut Client, ui: &mut Ui, state: &UiState) -> WeakWidget { // let Client { data, proxy, .. } = client; // let ip = field_widget(&data.ip, "ip", ui); // let ip_ = ip.clone(); @@ -84,7 +82,7 @@ pub fn create_ui(ui: &mut Ui) -> WidgetRef { // .add(ui) // } -// pub fn login_screen(client: &mut Client, ui: &mut Ui) -> WidgetRef { +// pub fn login_screen(client: &mut Client, ui: &mut Ui) -> WeakWidget { // let Client { data, .. } = client; // let username = field_widget(&data.username, "username", ui); // let password = field_widget(&data.password, "password", ui); diff --git a/src/bin/client/ui/login.rs b/src/bin/client/ui/login.rs new file mode 100644 index 0000000..ba4c8a7 --- /dev/null +++ b/src/bin/client/ui/login.rs @@ -0,0 +1,134 @@ +use iris::prelude::*; +use openworm::net::ClientMsg; + +use crate::{net::AppHandle, state::ClientState}; + +use super::*; + +pub fn start_screen(client: &mut Client, ui: &mut Ui) -> WidgetHandle { + let mut accounts = Span::empty(Dir::DOWN); + + accounts.push( + wtext("no accounts") + .size(20) + .center_text() + .color(Color::GRAY) + .height(60) + .add(ui) + .any(), + ); + + ( + wtext("Select Account").text_align(Align::CENTER).size(30), + accounts, + ( + submit_button("connect", |_, _| {}), + submit_button("create", |_, _| {}), + ) + .span(Dir::RIGHT) + .gap(10), + ) + .span(Dir::DOWN) + .gap(10) + .pad(15) + .background(rect(Color::BLACK.brighter(0.2)).radius(15)) + .width(400) + .align(Align::CENTER) + .add(ui) + .any() +} + +pub fn connect_screen(client: &mut Client, ui: &mut Ui, state: &UiState) -> WidgetHandle { + let Client { data, proxy, .. } = client; + let ip = field_widget(&data.ip, "ip", ui); + let handle = AppHandle { + proxy: proxy.clone(), + window: state.window.clone(), + }; + let submit = submit_button("connect", move |client, _ui| { + let ClientState::Connect(state) = &mut client.state else { + return; + }; + let ip = ip_.get().content(); + state.handle = Some(connect(handle.clone(), ConnectInfo { ip })); + }); + ( + wtext("connect to a server") + .text_align(Align::CENTER) + .size(30), + field_box( + // NOTE: should probably do this on submit + ip.on(Edited, |ctx| { + ctx.state.data.ip = ctx.widget.get().content(); + }) + .add(ui), + ui, + ), + submit, + ) + .span(Dir::DOWN) + .gap(10) + .pad(15) + .background(rect(Color::BLACK.brighter(0.2)).radius(15)) + .width(400) + .align(Align::CENTER) + .add(ui) + .any() +} + +pub fn login_screen(client: &mut Client, ui: &mut Ui) -> WidgetRef { + let Client { data, .. } = client; + let username = field_widget(&data.username, "username", ui); + let password = field_widget(&data.password, "password", ui); + let username_ = username.clone(); + let password_ = password.clone(); + let submit = submit_button("login", move |client, _ui| { + let ClientState::Login(state) = &mut client.state else { + return; + }; + let username = username_.get().content(); + let password = password_.get().content(); + state.handle.send(ClientMsg::Login { username, password }); + }); + let username_ = username.clone(); + let password_ = password.clone(); + let create_button = submit_button("create account", move |client, _ui| { + let ClientState::Login(state) = &mut client.state else { + return; + }; + let username = username_.get().content(); + let password = password_.get().content(); + state + .handle + .send(ClientMsg::CreateAccount { username, password }); + }); + ( + wtext("login to server").text_align(Align::CENTER).size(30), + field_box( + username + .on(Edited, |ctx| { + ctx.state.data.username = ctx.widget.get().content(); + }) + .add(ui), + ui, + ), + field_box( + password + .on(Edited, |ctx| { + ctx.state.data.password = ctx.widget.get().content(); + }) + .add(ui), + ui, + ), + submit, + create_button, + ) + .span(Dir::DOWN) + .gap(10) + .pad(15) + .background(rect(Color::BLACK.brighter(0.2)).radius(15)) + .width(400) + .align(Align::CENTER) + .add(ui) + .any() +} diff --git a/src/bin/client/ui/main.rs b/src/bin/client/ui/main.rs index 50d89dd..d421c3b 100644 --- a/src/bin/client/ui/main.rs +++ b/src/bin/client/ui/main.rs @@ -4,7 +4,7 @@ use super::*; pub const SIZE: u32 = 20; -pub fn main_view(rsc: &mut Rsc) -> WidgetRef { +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); @@ -33,7 +33,7 @@ pub fn msg_widget(username: &str, content: &str) -> impl WidgetIdFn { .to_any() } -pub fn msg_panel(rsc: &mut Rsc) -> WidgetRef { +pub fn msg_panel(rsc: &mut Rsc) -> WeakWidget { let msg_area = Span::empty(Dir::DOWN).gap(15); let send_text = wtext("") @@ -54,7 +54,7 @@ pub fn msg_panel(rsc: &mut Rsc) -> WidgetRef { .on(Submit, move |ctx, rsc| { let content = ctx.widget.edit(rsc).take(); let msg = msg_widget("ur mothe:", &content).add_strong(rsc); - rsc.ui[msg_area].children.push(msg); + rsc[msg_area].children.push(msg); }) .pad(15) .attr::(send_text) diff --git a/src/bin/client/ui/misc.rs b/src/bin/client/ui/misc.rs index bb673b2..ab87886 100644 --- a/src/bin/client/ui/misc.rs +++ b/src/bin/client/ui/misc.rs @@ -1,6 +1,6 @@ use super::*; -pub fn werror(msg: &str, rsc: &mut Rsc) -> WidgetHandle { +pub fn werror(msg: &str, rsc: &mut Rsc) -> StrongWidget { wtext(msg) .size(20) .pad(10) @@ -12,7 +12,7 @@ pub fn hint(msg: impl Into) -> TextBuilder { wtext(msg).size(20).color(Color::GRAY) } -pub fn field_widget(name: &str, hint_text: &str, rsc: &mut Rsc) -> WidgetRef { +pub fn field_widget(name: &str, hint_text: &str, rsc: &mut Rsc) -> WeakWidget { wtext(name) .editable(EditMode::SingleLine) .size(20) @@ -20,7 +20,7 @@ pub fn field_widget(name: &str, hint_text: &str, rsc: &mut Rsc) -> WidgetRef, rsc: &mut Rsc) -> WidgetRef { +pub fn field_box(field: WeakWidget, rsc: &mut Rsc) -> WeakWidget { field .pad(10) .background(rect(Color::BLACK.brighter(0.1)).radius(15)) @@ -31,55 +31,48 @@ pub fn field_box(field: WidgetRef, rsc: &mut Rsc) -> WidgetRef { #[derive(Clone, Copy, WidgetView)] pub struct Button { #[root] - root: WidgetRef, - rect: WidgetRef, - enabled: Handle, + root: WeakWidget, + rect: WeakWidget, + color: UiColor, + enabled: WeakState, } -// impl WidgetView for Button { -// fn view(&self) -> &WidgetRef { -// &self.root -// } -// } - impl Button { pub fn new(text: &str, color: UiColor, rsc: &mut Rsc) -> Self { let rect = rect(color).radius(15).add(rsc); - // let enabled = Handle::from(true); - // let enabled_ = enabled.clone(); - // let enabled__ = enabled.clone(); + let enabled = rsc.create_state(rect, true); let root = rect .on( CursorSense::HoverStart | CursorSense::unclick(), move |ctx, rsc: &mut Rsc| { - // if !*enabled_.get() { - // return; - // } - rsc.ui[ctx.widget].color = color.brighter(0.1); + if !rsc[enabled] { + return; + } + rsc[ctx.widget].color = color.brighter(0.1); }, ) .on(CursorSense::HoverEnd, move |ctx, rsc| { - // if !*enabled__.get() { - // return; - // } - rsc.ui[ctx.widget].color = color; + if !rsc[enabled] { + return; + } + rsc[ctx.widget].color = color; }) .height(60) .foreground(wtext(text).size(25).text_align(Align::CENTER)) .add(rsc); - // let enabled_ = enabled.clone(); rect.on(CursorSense::click(), move |ctx, rsc: &mut Rsc| { - // if !*enabled_.get() { - // return; - // } - rsc.ui[ctx.widget].color = color.darker(0.2); + if !rsc[enabled] { + return; + } + rsc[ctx.widget].color = color.darker(0.2); rsc.run_event::(root, (), ctx.state); }) .add(rsc); Self { root, rect, - // enabled, + color, + enabled, } } @@ -88,21 +81,21 @@ impl Button { } pub fn disable(&self, rsc: &mut Rsc) { - *self.enabled.get_mut() = false; - self.rect.get_mut().color = self.color.darker(0.8); + rsc[self.enabled] = false; + rsc[self.rect].color = self.color.darker(0.8); } } widget_trait! { - pub trait Stuff; + pub trait Stuff; fn modal(self, width: impl UiNum) -> impl WidgetIdFn { - |ui| { + |rsc| { self .pad(15) .background(rect(color::MODAL_BG).radius(15)) .width(width) .align(Align::CENTER) - .add(ui) + .add(rsc) } } }