- Removing network control from the cache

From this point forward the cache should basically just be a data container.
Methods on the cache object are there for convenience and should only ever
return very simple data [booleans, integers, () etc.].
The cache should also have very litter/no concept of commands to decouple it
from the renderer process.
! list_channels is still implemented in the cache however it remaains a vestige
and will be moved to the net module

Also the client is getting some new packages for websocket connections and
while they work some additional work has to be put in to figure out where fug to
actually place the websocket so that it can update the cache+DOM in a seomewhat sensible fashion
This commit is contained in:
shockrah 2021-04-11 17:39:54 -07:00
parent 3708d2cd08
commit 42d6a77050
6 changed files with 56 additions and 184 deletions

View File

@ -259,14 +259,6 @@
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==",
"dev": true "dev": true
}, },
"bufferutil": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.3.tgz",
"integrity": "sha512-yEYTwGndELGvfXsImMBLop58eaGW+YdONi1fNjTINSY98tmMmFijBG6WXgdkfuLNt4imzQNtIE+eBp1PVpMCSw==",
"requires": {
"node-gyp-build": "^4.2.0"
}
},
"cacheable-lookup": { "cacheable-lookup": {
"version": "5.0.4", "version": "5.0.4",
"resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz",
@ -330,19 +322,11 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true "dev": true
}, },
"d": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
"requires": {
"es5-ext": "^0.10.50",
"type": "^1.0.1"
}
},
"debug": { "debug": {
"version": "2.6.9", "version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
"requires": { "requires": {
"ms": "2.0.0" "ms": "2.0.0"
}, },
@ -350,7 +334,8 @@
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
} }
} }
}, },
@ -445,16 +430,6 @@
"integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
"dev": true "dev": true
}, },
"es5-ext": {
"version": "0.10.53",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
"integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
"requires": {
"es6-iterator": "~2.0.3",
"es6-symbol": "~3.1.3",
"next-tick": "~1.0.0"
}
},
"es6-error": { "es6-error": {
"version": "4.1.1", "version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
@ -462,25 +437,6 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"es6-iterator": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
"requires": {
"d": "1",
"es5-ext": "^0.10.35",
"es6-symbol": "^3.1.1"
}
},
"es6-symbol": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
"integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
"requires": {
"d": "^1.0.1",
"ext": "^1.1.2"
}
},
"escape-string-regexp": { "escape-string-regexp": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@ -488,21 +444,6 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"ext": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
"integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
"requires": {
"type": "^2.0.0"
},
"dependencies": {
"type": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/type/-/type-2.5.0.tgz",
"integrity": "sha512-180WMDQaIMm3+7hGXWf12GtdniDEy7nYcyFMKJn/eZz/6tSLXrUN9V0wKSbMjej0I1WHWbpREDEKHtqPQa9NNw=="
}
}
},
"extract-zip": { "extract-zip": {
"version": "1.7.0", "version": "1.7.0",
"resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.7.0.tgz",
@ -645,11 +586,6 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
},
"isarray": { "isarray": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@ -826,16 +762,6 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
}, },
"next-tick": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
"integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
},
"node-gyp-build": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.3.tgz",
"integrity": "sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg=="
},
"normalize-url": { "normalize-url": {
"version": "4.5.0", "version": "4.5.0",
"resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz",
@ -1070,11 +996,6 @@
"dev": true, "dev": true,
"optional": true "optional": true
}, },
"type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
"integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"type-fest": { "type-fest": {
"version": "0.13.1", "version": "0.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz",
@ -1088,14 +1009,6 @@
"integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=",
"dev": true "dev": true
}, },
"typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"requires": {
"is-typedarray": "^1.0.0"
}
},
"typescript": { "typescript": {
"version": "4.2.3", "version": "4.2.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz",
@ -1116,42 +1029,21 @@
"prepend-http": "^2.0.0" "prepend-http": "^2.0.0"
} }
}, },
"utf-8-validate": {
"version": "5.0.4",
"resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.4.tgz",
"integrity": "sha512-MEF05cPSq3AwJ2C7B7sHAA6i53vONoZbMGX8My5auEVm6W+dJ2Jd/TZPyGJ5CH42V2XtbI5FD28HeHeqlPzZ3Q==",
"requires": {
"node-gyp-build": "^4.2.0"
}
},
"util-deprecate": { "util-deprecate": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=",
"dev": true "dev": true
}, },
"websocket": {
"version": "1.0.33",
"resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.33.tgz",
"integrity": "sha512-XwNqM2rN5eh3G2CUQE3OHZj+0xfdH42+OFK6LdC2yqiC0YU8e5UK0nYre220T0IyyN031V/XOvtHvXozvJYFWA==",
"requires": {
"bufferutil": "^4.0.1",
"debug": "^2.2.0",
"es5-ext": "^0.10.50",
"typedarray-to-buffer": "^3.1.5",
"utf-8-validate": "^5.0.2",
"yaeti": "^0.0.6"
}
},
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"yaeti": { "ws": {
"version": "0.0.6", "version": "7.4.4",
"resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.4.tgz",
"integrity": "sha1-8m9ITXJoTPQr7ft2lwqhYI+/lXc=" "integrity": "sha512-Qm8k8ojNQIMx7S+Zp8u/uHOx7Qazv3Yv4q68MiWWWOJhiwG5W3x7iqmRtJo8xxrciZUY4vRxUTJCKuRnF28ZZw=="
}, },
"yallist": { "yallist": {
"version": "4.0.0", "version": "4.0.0",

View File

@ -16,7 +16,7 @@
"jsonwebtoken": "^8.5.1", "jsonwebtoken": "^8.5.1",
"popper.js": "^1.16.1", "popper.js": "^1.16.1",
"typescript": "^4.2.3", "typescript": "^4.2.3",
"websocket": "^1.0.33" "ws": "^7.4.4"
}, },
"devDependencies": { "devDependencies": {
"electron": "^7.3.3" "electron": "^7.3.3"

View File

@ -16,16 +16,11 @@ use crate::api_types::Channel;
use crate::net; use crate::net;
use crate::command::Command; use crate::command::Command;
use crate::config::{ConfigFile, ServerConfig}; use crate::config::{ConfigFile, ServerConfig};
use tokio_tungstenite::connect_async;
use futures::StreamExt;
use std::collections::HashMap; use std::collections::HashMap;
use crate::api_types as api; use crate::api_types as api;
type ChannelMeta = Channel; type ChannelMeta = Channel;
async fn nop() {
}
struct ChannelCache { struct ChannelCache {
pub meta: ChannelMeta, pub meta: ChannelMeta,
pub messages: Vec<api::Message> pub messages: Vec<api::Message>
@ -67,17 +62,6 @@ 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 { pub async fn switch_channel(&mut self, id: u64) -> Command {
if let None = self.active_server { if let None = self.active_server {
return Command::Failure("No active server set!".into()) return Command::Failure("No active server set!".into())
@ -99,47 +83,28 @@ impl Cache {
} }
fn new_message(&mut self, msg: api::Message, url: String, chan_id: u64) { pub fn set_jwt(&mut self, url: &str, jwt: &str) -> bool {
let mut set = false;
for (surl, serv) in self.servers.iter_mut() {
if url == surl {
serv.meta.user.jwt = Some(jwt.into());
set = true;
}
};
return set;
}
fn _new_message(&mut self, msg: api::Message, url: String, chan_id: u64) {
self.servers.get_mut(&url).unwrap() self.servers.get_mut(&url).unwrap()
.channels.get_mut(&chan_id).unwrap() .channels.get_mut(&chan_id).unwrap()
.messages.push(msg); .messages.push(msg);
} }
pub async fn switch_server(&mut self, host: &str) -> (Command, Option<String>) { pub fn set_active(&mut self, url: &str) {
// TODO: clean this func to be less ugly/easier to read for (surl, serv) in self.servers.iter() {
let mut found = false; if url == surl {
let mut err_msg = String::from("Nothing found"); self.active_server = Some(serv.meta.clone());
let mut fresh_token: Option<String> = 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());
self.active_text = None;
true
},
Err(e) => {
err_msg = match e.is_status() {
true => format!("{:?}", e.status().unwrap()),
false => format!("Issue connecting to server")
};
meta.meta.user.jwt = None;
false
} }
};
meta.meta.user.jwt = Some(String::from("asdf"));
break
}
}
if found {
(Command::Text(format!("logged in - /lc to list to list channels")), fresh_token)
} else {
(Command::Failure(err_msg), None)
} }
} }
@ -156,7 +121,7 @@ impl Cache {
Err(_) => Command::Failure("Couldn't send text message".into()) Err(_) => Command::Failure("Couldn't send text message".into())
} }
} }
Command::Text("yes".into()) Command::Text("No active channel".into())
} }
pub fn list_hosts(&self) -> Command { pub fn list_hosts(&self) -> Command {

View File

@ -43,6 +43,16 @@ impl ConfigFile {
Ok(()) Ok(())
} }
pub fn find_login_data(&self, url_portion: &str) -> Option<(u64, String, String)> {
let mut found: Option<(u64, String, String)> = None;
for serv in self.servers.iter() {
if serv.server.url.contains(url_portion) {
found = Some((serv.user.id, serv.user.secret.clone(), serv.server.url.clone()))
}
}
return found;
}
} }

View File

@ -37,8 +37,7 @@ struct App {
/// Current input mode /// Current input mode
input_mode: InputMode, input_mode: InputMode,
/// History of recorded messages /// History of recorded messages
messages: Mutex<Vec<Command>>, messages: Vec<Command>,
cache: Cache
} }
impl App { impl App {
@ -54,8 +53,7 @@ impl App {
App { App {
input: String::new(), input: String::new(),
input_mode: InputMode::Normal, input_mode: InputMode::Normal,
messages: Mutex::new(init_commands), messages: init_commands,
cache
} }
} }
} }
@ -113,6 +111,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
// Create default app state // Create default app state
let mut app = App::new(&config); let mut app = App::new(&config);
let cache: Mutex<Cache> = Mutex::new(Cache::from(&config));
loop { loop {
// Draw UI // Draw UI
@ -157,7 +156,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
f.render_widget(input, chunks[1]); f.render_widget(input, chunks[1]);
let mut lines: Vec<Spans> = Vec::new(); let mut lines: Vec<Spans> = Vec::new();
let msgs = app.messages.lock().unwrap(); let msgs = &app.messages;
for cmd in msgs.iter().rev() { for cmd in msgs.iter().rev() {
&lines.push(cmd.styled()); &lines.push(cmd.styled());
} }
@ -219,27 +218,32 @@ async fn main() -> Result<(), Box<dyn Error>> {
let raw: String = app.input.drain(..).collect(); let raw: String = app.input.drain(..).collect();
let trimmed = raw.trim(); let trimmed = raw.trim();
// ensure that we don't bother with empty input // TODO: flattten me mommy
if trimmed.len() != 0 { if trimmed.len() != 0 {
let cmd = Command::from(trimmed); let cmd = Command::from(trimmed);
app.messages.lock().unwrap().push(match cmd { app.messages.push(match cmd {
// only for networked commands do we need to touch cache // only for networked commands do we need to touch cache
Command::Channel(id) => { Command::Channel(id) => {
app.cache.switch_channel(id).await cache.lock().unwrap().switch_channel(id).await
}, },
Command::Server(url_portion) => { Command::Server(url_portion) => {
if let Some((url, id)) = app.cache.find_serv(url_portion) { if let Some((id, secret, url)) = config.find_login_data(&url_portion) {
let (cmd, jwt) = app.cache.switch_server(url.as_str()).await; match net::login(&url, id, &secret).await {
let url = net::ws_url(url.as_str(), jwt); Ok(jwt) => if cache.lock().unwrap().set_jwt(&url, &jwt) {
// maybe hook some message passing listener here? cache.lock().unwrap().set_active(&url);
cmd Command::Text("[Tell shock to make this ux not suck btw] /lc to fetch/update channels".into())
} else {
Command::Failure("Token could not be set".into())
},
Err(_) => Command::Failure(format!("Unable to login to {}", url))
}
} else { } else {
Command::Failure("No server found".into()) Command::Failure("No server found".into())
} }
}, },
Command::Message(msg) => app.cache.send_message(&msg).await, Command::Message(msg) => cache.lock().unwrap().send_message(&msg).await,
Command::ListHost => app.cache.list_hosts(), Command::ListHost => cache.lock().unwrap().list_hosts(),
Command::ListChannel => app.cache.list_channels().await, Command::ListChannel => cache.lock().unwrap().list_channels().await,
_ => cmd _ => cmd
}); });
} }

View File

@ -61,3 +61,4 @@ pub fn ws_url(base: &str, jwt: Option<String>) -> String {
let _ = url.set_scheme("ws"); let _ = url.set_scheme("ws");
url.to_string() url.to_string()
} }