From b3c833c667c0ad5b3be9aa5b26135638844f5a5a Mon Sep 17 00:00:00 2001 From: shadow cat Date: Mon, 17 Nov 2025 17:57:41 -0500 Subject: [PATCH] add client data cache for ip and username --- Cargo.lock | 24 +++++++++++++++++++ Cargo.toml | 1 + src/client/app.rs | 5 ++++ src/client/mod.rs | 33 +++++++++++++++++++------- src/client/ui.rs | 39 +++++++++++++++++++++++-------- src/lib.rs | 1 + src/rsc.rs | 59 +++++++++++++++++++++++++++++++++++++++++++++++ src/server/mod.rs | 15 +++++++----- 8 files changed, 153 insertions(+), 24 deletions(-) create mode 100644 src/rsc.rs diff --git a/Cargo.lock b/Cargo.lock index acddbfe..a6a841a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -298,6 +298,9 @@ name = "bitflags" version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +dependencies = [ + "serde_core", +] [[package]] name = "bitstream-io" @@ -1949,6 +1952,7 @@ dependencies = [ "pollster", "quinn", "rcgen", + "ron", "tokio", "tracing", "wgpu", @@ -2557,6 +2561,20 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ron" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32" +dependencies = [ + "bitflags 2.10.0", + "once_cell", + "serde", + "serde_derive", + "typeid", + "unicode-ident", +] + [[package]] name = "roxmltree" version = "0.20.0" @@ -3262,6 +3280,12 @@ dependencies = [ "core_maths", ] +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "unicode-bidi" version = "0.3.18" diff --git a/Cargo.toml b/Cargo.toml index ed0d116..b1c211e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,4 @@ wgpu = "27.0.1" winit = "0.30.12" bincode = "2.0.1" zstd = "0.13.3" +ron = "0.12.0" diff --git a/src/client/app.rs b/src/client/app.rs index 2a5f8b5..df984b8 100644 --- a/src/client/app.rs +++ b/src/client/app.rs @@ -58,6 +58,11 @@ impl ApplicationHandler for App { let client = self.client.as_mut().unwrap(); client.event(event, event_loop); } + + fn exiting(&mut self, _: &ActiveEventLoop) { + let client = self.client.as_mut().unwrap(); + client.exit(); + } } impl AppHandle { diff --git a/src/client/mod.rs b/src/client/mod.rs index 9490eda..207e5f3 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -6,8 +6,9 @@ use render::Renderer; use winit::{event::WindowEvent, event_loop::ActiveEventLoop}; use crate::{ - client::ui::{Submit, main_view, msg_widget}, + client::ui::{Edited, Submit, main_view, msg_widget}, net::{ClientMsg, ServerMsg, client::NetSender}, + rsc::{CLIENT_DATA, ClientData, DataDir}, }; mod app; @@ -30,23 +31,30 @@ pub struct Client { channel: Option>, username: String, clipboard: Clipboard, + dir: DataDir, + data: ClientData, + handle: AppHandle, } impl Client { pub fn new(handle: AppHandle) -> Self { let renderer = Renderer::new(handle.window.clone()); + let dir = DataDir::default(); - let ui = ui::ui(handle); - - Self { + let mut s = Self { + handle, renderer, input: Input::default(), - ui, + ui: Ui::new(), + data: dir.load(CLIENT_DATA), + dir, channel: None, focus: None, username: "".to_string(), clipboard: Clipboard::new().unwrap(), - } + }; + ui::init(&mut s); + s } pub fn event(&mut self, event: ClientEvent, _: &ActiveEventLoop) { @@ -104,20 +112,25 @@ impl Client { if let Some(sel) = &self.focus && event.state.is_pressed() { + let sel = &sel.clone(); let mut text = self.ui.text(sel); match text.apply_event(&event, &self.input.modifiers) { TextInputResult::Unfocus => { self.focus = None; } TextInputResult::Submit => { - self.run_event(&sel.clone(), Submit, ()); + self.run_event(sel, Submit, ()); } TextInputResult::Paste => { if let Ok(t) = self.clipboard.get_text() { text.insert(&t); } + self.run_event(sel, Edited, ()); } - TextInputResult::Unused | TextInputResult::Used => (), + TextInputResult::Used => { + self.run_event(sel, Edited, ()); + } + TextInputResult::Unused => (), } } } @@ -128,6 +141,10 @@ impl Client { } self.input.end_frame(); } + + pub fn exit(&mut self) { + self.dir.save(CLIENT_DATA, &self.data); + } } impl UiCtx for Client { diff --git a/src/client/ui.rs b/src/client/ui.rs index 8aaa7b7..266e552 100644 --- a/src/client/ui.rs +++ b/src/client/ui.rs @@ -2,7 +2,7 @@ use iris::prelude::*; use len_fns::*; use crate::{ - client::{Client, app::AppHandle}, + client::Client, net::{ ClientMsg, Msg, client::{ConnectInfo, NetSender, connect}, @@ -12,14 +12,19 @@ use crate::{ #[derive(Eq, PartialEq, Hash, Clone)] pub struct Submit; +#[derive(Eq, PartialEq, Hash, Clone)] +pub struct Edited; + impl DefaultEvent for Submit { type Data = (); } -pub fn ui(handle: AppHandle) -> Ui { - let mut ui = Ui::new(); - login_screen(&mut ui, handle).set_root(&mut ui); - ui +impl DefaultEvent for Edited { + type Data = (); +} + +pub fn init(client: &mut Client) { + login_screen(client).set_root(&mut client.ui); } pub fn main_view(client: &mut Client, network: NetSender) -> WidgetId { @@ -32,10 +37,14 @@ pub fn main_view(client: &mut Client, network: NetSender) -> WidgetId .any() } -fn login_screen(ui: &mut Ui, handle: AppHandle) -> WidgetId { +fn login_screen(client: &mut Client) -> WidgetId { + let Client { + ui, handle, data, .. + } = client; + let mut field = |name| text(name).editable().size(20).add(ui); - let ip = field("localhost:16839"); - let username = field("username"); + let ip = field(&data.ip); + let username = field(&data.username); // let password = field("password"); let fbx = |field: WidgetId| { @@ -46,6 +55,8 @@ fn login_screen(ui: &mut Ui, handle: AppHandle) -> WidgetId { .on(CursorSense::click(), focus(field)) }; + // I LAV NOT HAVING ERGONOMIC CLONES + let handle = handle.clone(); let ip_ = ip.clone(); let username_ = username.clone(); let color = Color::GREEN; @@ -60,8 +71,16 @@ fn login_screen(ui: &mut Ui, handle: AppHandle) -> WidgetId { .height(40); ( text("login").size(30), - fbx(ip), - fbx(username), + fbx(ip + .id_on(Edited, |id, client: &mut Client, _| { + client.data.ip = client.ui[id].content(); + }) + .add(ui)), + fbx(username + .id_on(Edited, |id, client: &mut Client, _| { + client.data.username = client.ui[id].content(); + }) + .add(ui)), // fbx(password), submit, ) diff --git a/src/lib.rs b/src/lib.rs index 7564016..15700d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ pub mod client; pub mod net; pub mod server; +pub mod rsc; diff --git a/src/rsc.rs b/src/rsc.rs new file mode 100644 index 0000000..6dce7ab --- /dev/null +++ b/src/rsc.rs @@ -0,0 +1,59 @@ +use std::{ + fs::{self, File}, + path::Path, +}; + +use directories_next::ProjectDirs; + +use crate::net::BINCODE_CONFIG; + +pub const CLIENT_DATA: &str = "client_data"; + +pub struct DataDir { + dirs: ProjectDirs, +} + +impl Default for DataDir { + fn default() -> Self { + Self { + dirs: ProjectDirs::from("", "", "openworm").unwrap(), + } + } +} + +impl DataDir { + pub fn get(&self) -> &Path { + self.dirs.data_local_dir() + } + + pub fn load + Default>(&self, path: &str) -> T { + let path = self.get().join(path); + match fs::read(path) { + Ok(bytes) => match bincode::decode_from_slice(&bytes, BINCODE_CONFIG) { + Ok((data, _)) => data, + Err(_) => todo!(), + }, + Err(_) => T::default(), + } + } + + pub fn save(&self, path: &str, data: &T) { + let mut file = File::create(self.get().join(path)).unwrap(); + bincode::encode_into_std_write(data, &mut file, BINCODE_CONFIG).unwrap(); + } +} + +#[derive(bincode::Encode, bincode::Decode)] +pub struct ClientData { + pub ip: String, + pub username: String, +} + +impl Default for ClientData { + fn default() -> Self { + Self { + ip: "localhost:39420".to_string(), + username: "your [NOVEMBER]".to_string(), + } + } +} diff --git a/src/server/mod.rs b/src/server/mod.rs index f01873e..4b031c4 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1,7 +1,10 @@ -use crate::net::{ - ClientMsg, Msg, ServerMsg, - server::{ClientSender, ConAccepter, listen}, - transfer::RecvHandler, +use crate::{ + net::{ + ClientMsg, Msg, ServerMsg, + server::{ClientSender, ConAccepter, listen}, + transfer::RecvHandler, + }, + rsc::DataDir, }; use std::{ collections::HashMap, @@ -14,8 +17,8 @@ use tokio::sync::RwLock; #[tokio::main] pub async fn run_server() { - let dirs = directories_next::ProjectDirs::from("", "", "openworm").unwrap(); - let path = dirs.data_local_dir(); + let dir = DataDir::default(); + let path = dir.get(); let handler = ServerListener { msgs: Default::default(), senders: Default::default(),