|
@@ -1,8 +1,8 @@
|
|
|
-// TODO: Key/auth system
|
|
|
|
|
-// TODO: Args or config for username, language, server, and refresh rate.
|
|
|
|
|
|
|
+// TODO: CLI args for save location and server address
|
|
|
|
|
|
|
|
mod actions;
|
|
mod actions;
|
|
|
mod message;
|
|
mod message;
|
|
|
|
|
+mod persistence;
|
|
|
mod ui;
|
|
mod ui;
|
|
|
|
|
|
|
|
use cursive::views::{
|
|
use cursive::views::{
|
|
@@ -13,7 +13,9 @@ use cursive::{event, Cursive};
|
|
|
use cursive::{traits::*, CursiveExt as _};
|
|
use cursive::{traits::*, CursiveExt as _};
|
|
|
use message::Message;
|
|
use message::Message;
|
|
|
use std::collections::HashMap;
|
|
use std::collections::HashMap;
|
|
|
|
|
+use std::io::{Read as _, Write as _};
|
|
|
use std::thread;
|
|
use std::thread;
|
|
|
|
|
+use utils::serialize::Serialize;
|
|
|
|
|
|
|
|
use ui::{
|
|
use ui::{
|
|
|
DIALOGUE_MIN_SIZE, INPUT_BUTTON_ID, INPUT_CLEAR_BUTTON_ID, INPUT_FIELD_ID, INPUT_PANEL_ID,
|
|
DIALOGUE_MIN_SIZE, INPUT_BUTTON_ID, INPUT_CLEAR_BUTTON_ID, INPUT_FIELD_ID, INPUT_PANEL_ID,
|
|
@@ -25,17 +27,20 @@ const MAX_MESSAGE_LENGTH: usize = 512;
|
|
|
const MAX_USERNAME_LENGTH: usize = 16;
|
|
const MAX_USERNAME_LENGTH: usize = 16;
|
|
|
const DEFAULT_USERNAME_PREFIX: &str = "Myst";
|
|
const DEFAULT_USERNAME_PREFIX: &str = "Myst";
|
|
|
|
|
|
|
|
|
|
+const SAVE_FILE: &str = "savedata.bin";
|
|
|
const REMOTE_REFRESH_RATE: u64 = 10;
|
|
const REMOTE_REFRESH_RATE: u64 = 10;
|
|
|
|
|
|
|
|
|
|
+// TODO: Add server refresh rate
|
|
|
#[derive(Clone)]
|
|
#[derive(Clone)]
|
|
|
pub struct Appdata {
|
|
pub struct Appdata {
|
|
|
- pub messages: HashMap<String, Message>,
|
|
|
|
|
pub username: String,
|
|
pub username: String,
|
|
|
pub language: ui::Language,
|
|
pub language: ui::Language,
|
|
|
- pub quick_close_window_count: usize,
|
|
|
|
|
- pub api_endpoint: String,
|
|
|
|
|
pub blocked_phrases: Vec<String>,
|
|
pub blocked_phrases: Vec<String>,
|
|
|
pub blocked_phrases_censor_char: char,
|
|
pub blocked_phrases_censor_char: char,
|
|
|
|
|
+
|
|
|
|
|
+ pub messages: HashMap<String, Message>,
|
|
|
|
|
+ pub quick_close_window_count: usize,
|
|
|
|
|
+ pub api_endpoint: String,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
impl Default for Appdata {
|
|
impl Default for Appdata {
|
|
@@ -67,12 +72,39 @@ pub fn get_appdata(siv: &mut Cursive) -> Appdata {
|
|
|
.expect("Failed to retrieve appdata.")
|
|
.expect("Failed to retrieve appdata.")
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+pub fn save_appdata(siv: &mut Cursive) {
|
|
|
|
|
+ let appdata = get_appdata(siv);
|
|
|
|
|
+
|
|
|
|
|
+ let savedata = persistence::Savedata::from(appdata);
|
|
|
|
|
+ let bytes = savedata.serialize_checked();
|
|
|
|
|
+
|
|
|
|
|
+ let mut file = std::fs::File::create(SAVE_FILE).expect("Failed to create savedata file.");
|
|
|
|
|
+ file.write_all(&bytes)
|
|
|
|
|
+ .expect("Failed to write savedata file.");
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+pub fn load_appdata(siv: &mut Cursive) -> std::io::Result<()> {
|
|
|
|
|
+ let mut file = std::fs::File::open(SAVE_FILE)?;
|
|
|
|
|
+
|
|
|
|
|
+ let mut bytes = Vec::new();
|
|
|
|
|
+ file.read_to_end(&mut bytes)?;
|
|
|
|
|
+
|
|
|
|
|
+ let savedata = persistence::Savedata::deserialize_checked(bytes).unwrap();
|
|
|
|
|
+ let appdata = Appdata::from(savedata);
|
|
|
|
|
+
|
|
|
|
|
+ siv.set_user_data(appdata);
|
|
|
|
|
+
|
|
|
|
|
+ Ok(())
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
fn main() {
|
|
fn main() {
|
|
|
utils::rng::shuffle_rng();
|
|
utils::rng::shuffle_rng();
|
|
|
|
|
|
|
|
let mut siv = Cursive::default();
|
|
let mut siv = Cursive::default();
|
|
|
siv.set_user_data(Appdata::new());
|
|
siv.set_user_data(Appdata::new());
|
|
|
|
|
|
|
|
|
|
+ load_appdata(&mut siv);
|
|
|
|
|
+
|
|
|
// Global hotkeys
|
|
// Global hotkeys
|
|
|
siv.add_global_callback(event::Key::Backspace, |siv| {
|
|
siv.add_global_callback(event::Key::Backspace, |siv| {
|
|
|
let _ = siv.focus_name(INPUT_FIELD_ID);
|
|
let _ = siv.focus_name(INPUT_FIELD_ID);
|
|
@@ -90,6 +122,8 @@ fn main() {
|
|
|
if timer % REMOTE_REFRESH_RATE == 0 {
|
|
if timer % REMOTE_REFRESH_RATE == 0 {
|
|
|
actions::load_messages(siv);
|
|
actions::load_messages(siv);
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ save_appdata(siv);
|
|
|
}))
|
|
}))
|
|
|
.expect("Failed to send callback from background thread.");
|
|
.expect("Failed to send callback from background thread.");
|
|
|
|
|
|
|
@@ -346,6 +380,5 @@ fn main() {
|
|
|
);
|
|
);
|
|
|
|
|
|
|
|
siv.add_fullscreen_layer(main_layout);
|
|
siv.add_fullscreen_layer(main_layout);
|
|
|
- ui::change_language(&mut siv, ui::Language::English);
|
|
|
|
|
siv.run();
|
|
siv.run();
|
|
|
}
|
|
}
|