From f92ced1241447214fce8461d72cf3a1b44eac8fd Mon Sep 17 00:00:00 2001 From: shockrah Date: Fri, 9 Apr 2021 22:10:08 -0700 Subject: [PATCH] + Websocket setup is almost proper but it completely hangs after we start listening for connections Of course this is an issue because we can no longer get data from the user A full rearchitecting may be in order here however its not impossible to modify the current architecture so far The main issue here is that the cache is doing too much I think If the termion(main input) task does its thing, and a socket task, waits around waiting to build a sub task(socket) then we may be able to pass messages to the socket task to open up sockets when request This allows us to have shared state via message passing and a main task can take care of updating the cache. The renderer can then request data from the cache when it needs to render stuff --- tui/src/api_types.rs | 16 +++++++++- tui/src/cache.rs | 73 ++++++++++++++++++++++++++++++++++---------- tui/src/main.rs | 2 +- 3 files changed, 73 insertions(+), 18 deletions(-) diff --git a/tui/src/api_types.rs b/tui/src/api_types.rs index f38e26c..3d5c5cd 100644 --- a/tui/src/api_types.rs +++ b/tui/src/api_types.rs @@ -5,7 +5,7 @@ const VOICE_CHANNEL: i32 = 1; pub const TEXT_CHANNEL: i32 = 2; // Network Types -#[allow(dead_code)] +#[derive(Debug)] pub struct Message { pub id: u64, pub time: i64, @@ -16,6 +16,20 @@ pub struct Message { pub username: String, } +impl Message { + pub fn bogus(s: String) -> Message { + Message { + id: 1, + time: 1, + content: s, + content_type: "text/plain".into(), + channel_id: 1, + userid: 1, + username: "yes".into() + } + } +} + #[derive(Deserialize, Clone)] pub struct Channel { diff --git a/tui/src/cache.rs b/tui/src/cache.rs index 879cea9..ef00dfe 100644 --- a/tui/src/cache.rs +++ b/tui/src/cache.rs @@ -12,18 +12,23 @@ * */ -use crate::api_types::{Channel, Message}; +use crate::api_types::Channel; use crate::net; use crate::command::Command; use crate::config::{ConfigFile, ServerConfig}; - +use tokio_tungstenite::connect_async; +use futures::StreamExt; use std::collections::HashMap; +use crate::api_types as api; type ChannelMeta = Channel; +async fn nop() { +} + struct ChannelCache { pub meta: ChannelMeta, - pub messages: Vec + pub messages: Vec } struct ServerCache { @@ -37,7 +42,7 @@ pub struct Cache { // url -> Cache servers: HashMap, active_server: Option, - active_text: Option + active_text: Option, } impl ServerCache { @@ -58,18 +63,25 @@ impl Cache { Cache { servers, active_server: None, - active_text: None + active_text: None, } } -} -impl Cache { + pub fn find_serv(&self, portion: String) -> Option<(String, u64)> { + let item = self.servers.iter() + .find(|(url, _)| url.contains(portion.as_str())); + + if let Some((url, cache)) = item { + Some((url.clone(), cache.meta.user.id)) + } else { + None + } + } pub async fn switch_channel(&mut self, id: u64) -> Command { if let None = self.active_server { return Command::Failure("No active server set!".into()) } - // find the channel meta data let mut msg = String::new(); for (_url, cache) in &self.servers { if let Some(channel_cache) = cache.channels.get(&id) { @@ -86,22 +98,51 @@ impl Cache { } } - pub async fn switch_server(&mut self, host: &str) -> Command { - // TODO: implement some better fuzzy finding for better ergonomics - // Reallt though the ux is still pretty bad here - // Also it greedily matches so if two servers are behind one domain we're kinda fucked + + fn new_message(&mut self, msg: api::Message, url: String, chan_id: u64) { + self.servers.get_mut(&url).unwrap() + .channels.get_mut(&chan_id).unwrap() + .messages.push(msg); + } + + pub async fn setup_websocket(&mut self, url: String, chan_id: u64) { + use crate::log; + // Ignore inactive server state & NoneType + if let None = self.active_server { return; } + + match connect_async(url.clone()).await { + Ok((ws, _)) => { + let (_tx, rx) = ws.split(); + let reader = rx.for_each(move |message| { + let msg = message.unwrap().into_text().unwrap(); + let msg = api::Message::bogus(msg); + log::file(&msg); + self.new_message(msg, url.clone(), chan_id); + + nop() + }); + //tokio::spawn(reader); + }, + Err(e) => { + log::plain(format!("{}: {}\n", e, url)) + } + }; + } + + pub async fn switch_server(&mut self, host: &str) -> (Command, Option) { + // TODO: clean this func to be less ugly/easier to read let mut found = false; let mut err_msg = String::from("Nothing found"); + let mut fresh_token: Option = None; for (url, meta) in self.servers.iter_mut() { if url.contains(host) { let id = meta.meta.user.id; let secret = &meta.meta.user.secret; found = match net::login(url, id, secret).await { Ok(jwt) => { + fresh_token = Some(jwt.clone()); meta.meta.user.jwt = Some(jwt); self.active_server = Some(meta.meta.clone()); - // TODO: Setup websocket to server or something idk - net::setup_websocket("adsf").await; self.active_text = None; true }, @@ -120,9 +161,9 @@ impl Cache { } if found { - Command::Text(format!("logged in - /lc to list to list channels")) + (Command::Text(format!("logged in - /lc to list to list channels")), fresh_token) } else { - Command::Failure(err_msg) + (Command::Failure(err_msg), None) } } diff --git a/tui/src/main.rs b/tui/src/main.rs index cdd4c3c..385f2b9 100644 --- a/tui/src/main.rs +++ b/tui/src/main.rs @@ -231,7 +231,7 @@ async fn main() -> Result<(), Box> { if let Some((url, id)) = app.cache.find_serv(url_portion) { let (cmd, jwt) = app.cache.switch_server(url.as_str()).await; let url = net::ws_url(url.as_str(), jwt); - app.cache = app.cache.setup_websocket(url, id).await; + app.cache.setup_websocket(url, id).await; cmd } else { Command::Failure("No server found".into())