#![windows_subsystem = "windows"] use crate::{ net::{NetHandle, NetSender}, rsc::{CLIENT_DATA, ClientData}, state::{ClientState, LoggedIn, Login}, ui::*, }; use iris::{prelude::*, winit::*}; use openworm::{ net::{ClientMsg, ServerMsg, install_crypto_provider}, rsc::DataDir, }; use winit::{ event::{ElementState, MouseButton, WindowEvent}, window::WindowAttributes, }; mod debug; mod net; mod rsc; mod state; mod ui; fn main() { install_crypto_provider(); UiApp::::run(); } pub struct Client { dir: DataDir, data: ClientData, state: ClientState, main_ui: WidgetId, notif: WidgetId, ui: DefaultUi, proxy: Proxy, } pub enum ClientEvent { Connect { send: NetSender }, ServerMsg(ServerMsg), Err(String), } impl DefaultUiState for Client { type Event = ClientEvent; fn ui(&mut self) -> &mut DefaultUi { &mut self.ui } fn window_attrs() -> WindowAttributes { WindowAttributes::default().with_title("OPENWORM") } fn new(mut ui: DefaultUi, proxy: Proxy) -> Self { let dir = DataDir::default(); let notif = WidgetPtr::default().add(&mut ui); let main_ui = WidgetPtr::default().add(&mut ui); ( notif.clone().pad(Padding::top(10)).align(Align::TOP_CENTER), main_ui.clone(), ) .stack() .set_root(&mut ui); let mut s = Self { data: dir.load(CLIENT_DATA), state: Default::default(), dir, main_ui: main_ui.clone(), notif, ui, proxy, }; connect_screen(&mut s).set_ptr(&s.main_ui, &mut s.ui); s } fn event(&mut self, event: ClientEvent) { match event { ClientEvent::Connect { send } => { let ClientState::Connect(connect) = self.state.take() else { panic!("invalid state"); }; let th = connect.handle.unwrap(); self.state = ClientState::Login(Login { handle: NetHandle { send: send.clone(), thread: th, }, }); login_screen(self).set_ptr(&self.main_ui, &mut self.ui); } ClientEvent::ServerMsg(msg) => match msg { ServerMsg::SendMsg(msg) => { if let ClientState::LoggedIn(state) = &mut self.state && let Some(msg_area) = &state.channel { let msg = msg_widget(&msg.user, &msg.content).add(&mut self.ui); self.ui[msg_area].children.push(msg.any()); } } ServerMsg::LoadMsgs(msgs) => { if let ClientState::LoggedIn(state) = &mut self.state && let Some(msg_area) = &state.channel { for msg in msgs { state.msgs.push(msg.clone()); let msg = msg_widget(&msg.user, &msg.content).add(&mut self.ui); self.ui[msg_area].children.push(msg.any()); } } } ServerMsg::Login { username } => { let ClientState::Login(state) = self.state.take() else { panic!("invalid state"); }; state.handle.send(ClientMsg::RequestMsgs); self.state = ClientState::LoggedIn(LoggedIn { network: state.handle, channel: None, msgs: Vec::new(), username, }); main_view(self).set_ptr(&self.main_ui, &mut self.ui); } ServerMsg::Error(error) => { let msg = format!("{error:?}"); self.ui[&self.notif].inner = Some(werror(&mut self.ui, &msg)); } }, ClientEvent::Err(msg) => { self.ui[&self.notif].inner = Some(werror(&mut self.ui, &msg)); } } } fn exit(&mut self) { self.state.exit(); self.dir.save(CLIENT_DATA, &self.data); } fn window_event(&mut self, event: WindowEvent) { if let WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Middle, .. } = event { debug::debug(self); } } }