add client data cache for ip and username
This commit is contained in:
24
Cargo.lock
generated
24
Cargo.lock
generated
@@ -298,6 +298,9 @@ name = "bitflags"
|
|||||||
version = "2.10.0"
|
version = "2.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitstream-io"
|
name = "bitstream-io"
|
||||||
@@ -1949,6 +1952,7 @@ dependencies = [
|
|||||||
"pollster",
|
"pollster",
|
||||||
"quinn",
|
"quinn",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
|
"ron",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tracing",
|
"tracing",
|
||||||
"wgpu",
|
"wgpu",
|
||||||
@@ -2557,6 +2561,20 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"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]]
|
[[package]]
|
||||||
name = "roxmltree"
|
name = "roxmltree"
|
||||||
version = "0.20.0"
|
version = "0.20.0"
|
||||||
@@ -3262,6 +3280,12 @@ dependencies = [
|
|||||||
"core_maths",
|
"core_maths",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typeid"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-bidi"
|
name = "unicode-bidi"
|
||||||
version = "0.3.18"
|
version = "0.3.18"
|
||||||
|
|||||||
@@ -18,3 +18,4 @@ wgpu = "27.0.1"
|
|||||||
winit = "0.30.12"
|
winit = "0.30.12"
|
||||||
bincode = "2.0.1"
|
bincode = "2.0.1"
|
||||||
zstd = "0.13.3"
|
zstd = "0.13.3"
|
||||||
|
ron = "0.12.0"
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ impl ApplicationHandler<ClientEvent> for App {
|
|||||||
let client = self.client.as_mut().unwrap();
|
let client = self.client.as_mut().unwrap();
|
||||||
client.event(event, event_loop);
|
client.event(event, event_loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn exiting(&mut self, _: &ActiveEventLoop) {
|
||||||
|
let client = self.client.as_mut().unwrap();
|
||||||
|
client.exit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppHandle {
|
impl AppHandle {
|
||||||
|
|||||||
@@ -6,8 +6,9 @@ use render::Renderer;
|
|||||||
use winit::{event::WindowEvent, event_loop::ActiveEventLoop};
|
use winit::{event::WindowEvent, event_loop::ActiveEventLoop};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::ui::{Submit, main_view, msg_widget},
|
client::ui::{Edited, Submit, main_view, msg_widget},
|
||||||
net::{ClientMsg, ServerMsg, client::NetSender},
|
net::{ClientMsg, ServerMsg, client::NetSender},
|
||||||
|
rsc::{CLIENT_DATA, ClientData, DataDir},
|
||||||
};
|
};
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
@@ -30,23 +31,30 @@ pub struct Client {
|
|||||||
channel: Option<WidgetId<Span>>,
|
channel: Option<WidgetId<Span>>,
|
||||||
username: String,
|
username: String,
|
||||||
clipboard: Clipboard,
|
clipboard: Clipboard,
|
||||||
|
dir: DataDir,
|
||||||
|
data: ClientData,
|
||||||
|
handle: AppHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Client {
|
impl Client {
|
||||||
pub fn new(handle: AppHandle) -> Self {
|
pub fn new(handle: AppHandle) -> Self {
|
||||||
let renderer = Renderer::new(handle.window.clone());
|
let renderer = Renderer::new(handle.window.clone());
|
||||||
|
let dir = DataDir::default();
|
||||||
|
|
||||||
let ui = ui::ui(handle);
|
let mut s = Self {
|
||||||
|
handle,
|
||||||
Self {
|
|
||||||
renderer,
|
renderer,
|
||||||
input: Input::default(),
|
input: Input::default(),
|
||||||
ui,
|
ui: Ui::new(),
|
||||||
|
data: dir.load(CLIENT_DATA),
|
||||||
|
dir,
|
||||||
channel: None,
|
channel: None,
|
||||||
focus: None,
|
focus: None,
|
||||||
username: "<unknown>".to_string(),
|
username: "<unknown>".to_string(),
|
||||||
clipboard: Clipboard::new().unwrap(),
|
clipboard: Clipboard::new().unwrap(),
|
||||||
}
|
};
|
||||||
|
ui::init(&mut s);
|
||||||
|
s
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event(&mut self, event: ClientEvent, _: &ActiveEventLoop) {
|
pub fn event(&mut self, event: ClientEvent, _: &ActiveEventLoop) {
|
||||||
@@ -104,20 +112,25 @@ impl Client {
|
|||||||
if let Some(sel) = &self.focus
|
if let Some(sel) = &self.focus
|
||||||
&& event.state.is_pressed()
|
&& event.state.is_pressed()
|
||||||
{
|
{
|
||||||
|
let sel = &sel.clone();
|
||||||
let mut text = self.ui.text(sel);
|
let mut text = self.ui.text(sel);
|
||||||
match text.apply_event(&event, &self.input.modifiers) {
|
match text.apply_event(&event, &self.input.modifiers) {
|
||||||
TextInputResult::Unfocus => {
|
TextInputResult::Unfocus => {
|
||||||
self.focus = None;
|
self.focus = None;
|
||||||
}
|
}
|
||||||
TextInputResult::Submit => {
|
TextInputResult::Submit => {
|
||||||
self.run_event(&sel.clone(), Submit, ());
|
self.run_event(sel, Submit, ());
|
||||||
}
|
}
|
||||||
TextInputResult::Paste => {
|
TextInputResult::Paste => {
|
||||||
if let Ok(t) = self.clipboard.get_text() {
|
if let Ok(t) = self.clipboard.get_text() {
|
||||||
text.insert(&t);
|
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();
|
self.input.end_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn exit(&mut self) {
|
||||||
|
self.dir.save(CLIENT_DATA, &self.data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UiCtx for Client {
|
impl UiCtx for Client {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use iris::prelude::*;
|
|||||||
use len_fns::*;
|
use len_fns::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
client::{Client, app::AppHandle},
|
client::Client,
|
||||||
net::{
|
net::{
|
||||||
ClientMsg, Msg,
|
ClientMsg, Msg,
|
||||||
client::{ConnectInfo, NetSender, connect},
|
client::{ConnectInfo, NetSender, connect},
|
||||||
@@ -12,14 +12,19 @@ use crate::{
|
|||||||
#[derive(Eq, PartialEq, Hash, Clone)]
|
#[derive(Eq, PartialEq, Hash, Clone)]
|
||||||
pub struct Submit;
|
pub struct Submit;
|
||||||
|
|
||||||
|
#[derive(Eq, PartialEq, Hash, Clone)]
|
||||||
|
pub struct Edited;
|
||||||
|
|
||||||
impl DefaultEvent for Submit {
|
impl DefaultEvent for Submit {
|
||||||
type Data = ();
|
type Data = ();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ui(handle: AppHandle) -> Ui {
|
impl DefaultEvent for Edited {
|
||||||
let mut ui = Ui::new();
|
type Data = ();
|
||||||
login_screen(&mut ui, handle).set_root(&mut ui);
|
}
|
||||||
ui
|
|
||||||
|
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> {
|
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()
|
.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 mut field = |name| text(name).editable().size(20).add(ui);
|
||||||
let ip = field("localhost:16839");
|
let ip = field(&data.ip);
|
||||||
let username = field("username");
|
let username = field(&data.username);
|
||||||
// let password = field("password");
|
// let password = field("password");
|
||||||
|
|
||||||
let fbx = |field: WidgetId<TextEdit>| {
|
let fbx = |field: WidgetId<TextEdit>| {
|
||||||
@@ -46,6 +55,8 @@ fn login_screen(ui: &mut Ui, handle: AppHandle) -> WidgetId<AnyWidget> {
|
|||||||
.on(CursorSense::click(), focus(field))
|
.on(CursorSense::click(), focus(field))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// I LAV NOT HAVING ERGONOMIC CLONES
|
||||||
|
let handle = handle.clone();
|
||||||
let ip_ = ip.clone();
|
let ip_ = ip.clone();
|
||||||
let username_ = username.clone();
|
let username_ = username.clone();
|
||||||
let color = Color::GREEN;
|
let color = Color::GREEN;
|
||||||
@@ -60,8 +71,16 @@ fn login_screen(ui: &mut Ui, handle: AppHandle) -> WidgetId<AnyWidget> {
|
|||||||
.height(40);
|
.height(40);
|
||||||
(
|
(
|
||||||
text("login").size(30),
|
text("login").size(30),
|
||||||
fbx(ip),
|
fbx(ip
|
||||||
fbx(username),
|
.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),
|
// fbx(password),
|
||||||
submit,
|
submit,
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod net;
|
pub mod net;
|
||||||
pub mod server;
|
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::{
|
use crate::{
|
||||||
ClientMsg, Msg, ServerMsg,
|
net::{
|
||||||
server::{ClientSender, ConAccepter, listen},
|
ClientMsg, Msg, ServerMsg,
|
||||||
transfer::RecvHandler,
|
server::{ClientSender, ConAccepter, listen},
|
||||||
|
transfer::RecvHandler,
|
||||||
|
},
|
||||||
|
rsc::DataDir,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
@@ -14,8 +17,8 @@ use tokio::sync::RwLock;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
pub async fn run_server() {
|
pub async fn run_server() {
|
||||||
let dirs = directories_next::ProjectDirs::from("", "", "openworm").unwrap();
|
let dir = DataDir::default();
|
||||||
let path = dirs.data_local_dir();
|
let path = dir.get();
|
||||||
let handler = ServerListener {
|
let handler = ServerListener {
|
||||||
msgs: Default::default(),
|
msgs: Default::default(),
|
||||||
senders: Default::default(),
|
senders: Default::default(),
|
||||||
|
|||||||
Reference in New Issue
Block a user