add client data cache for ip and username
This commit is contained in:
@@ -58,6 +58,11 @@ impl ApplicationHandler<ClientEvent> 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 {
|
||||
|
||||
@@ -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<WidgetId<Span>>,
|
||||
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: "<unknown>".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 {
|
||||
|
||||
@@ -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<AnyWidget> {
|
||||
@@ -32,10 +37,14 @@ pub fn main_view(client: &mut Client, network: NetSender) -> WidgetId<AnyWidget>
|
||||
.any()
|
||||
}
|
||||
|
||||
fn login_screen(ui: &mut Ui, handle: AppHandle) -> WidgetId<AnyWidget> {
|
||||
fn login_screen(client: &mut Client) -> WidgetId<AnyWidget> {
|
||||
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<TextEdit>| {
|
||||
@@ -46,6 +55,8 @@ fn login_screen(ui: &mut Ui, handle: AppHandle) -> WidgetId<AnyWidget> {
|
||||
.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<AnyWidget> {
|
||||
.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,
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
pub mod client;
|
||||
pub mod net;
|
||||
pub mod server;
|
||||
pub mod rsc;
|
||||
|
||||
59
src/rsc.rs
Normal file
59
src/rsc.rs
Normal file
@@ -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<T: bincode::Decode<()> + 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<T: bincode::Encode>(&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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user