freechat/tui/src/main.rs

100 lines
3.0 KiB
Rust

extern crate serde;
extern crate clap;
extern crate cursive;
extern crate tokio;
extern crate reqwest;
use std::{fs, env};
use std::path::PathBuf;
use clap::{Arg, App};
use cursive::Cursive;
use cursive::menu::MenuTree;
use cursive::event::Key;
use serde_json;
mod types;
mod http;
#[tokio::main]
async fn main() {
let args = App::new("Freechat TUI")
.version("69.420")
.author("godrah")
.about("oh you know")
.arg(Arg::with_name("config")
.short("c")
.long("config")
.value_name("CONFIG")
.help("Specify path of config to use")
.takes_value(true))
.arg(Arg::with_name("theme")
.short("t")
.long("theme")
.value_name("THEME_FILE")
.help("Specify theme file on startup")
.takes_value(true)).get_matches();
let config: types::Config = if args.args.len() == 0 {
let home = env::var("HOME").unwrap();
match fs::read_to_string(format!("{}/.config/freechat/config.json", home)) {
Ok(data) => serde_json::from_str(&data).unwrap(),
Err(e) => panic!("Bro: {}", e)
}
} else{
let path = args.value_of("config").unwrap();
match fs::read_to_string(path) {
Ok(data) => serde_json::from_str(&data).unwrap(),
Err(e) => panic!("Bro: {}", e)
}
};
// only load a theme if requested
let theme = if let Some(theme) = args.value_of("theme") {
Some(PathBuf::from(theme))
} else {
None
};
let mut app = cursive::default();
// optionally load optional theme
if let Some(theme) = theme { let _ = app.load_theme_file(theme); }
app.add_global_callback('q', Cursive::quit);
app.add_global_callback(Key::Esc, |s| s.select_menubar());
app.set_autohide_menu(false); // don't hide the menubar all the time
// menu bar at the top lets us pick between different servers in the config
for server in config.servers.iter() {
let name = match &server.name {
Some(name) => name.to_string(),
//None => String::from(&format!("{}", server.ip))
None => String::from("None")
};
app.menubar().add_subtree(&name, MenuTree::new()); // add server name
// on action:
// open up search able list of channels
// choose from that list of channels which one you want to see
// NOTE: not passing the domain as the IP is resolved on server join
if let Some(channels) = http::fetch_channels(&server.ip, server.port).await {
// add a bunch of actionable leafs to our sub tree
for channel in channels {
app.menubar().find_subtree(name.as_ref()).unwrap().add_leaf(channel.name.clone(), move |s| {
let (ip, name) = channel.parts();
http::sync::open_channel(ip, name, s);
});
}
}
}
app.run();
}