diff --git a/src/gui/ratatui_interface.rs b/src/gui/ratatui_interface.rs index 7e10936..31a7050 100644 --- a/src/gui/ratatui_interface.rs +++ b/src/gui/ratatui_interface.rs @@ -1,31 +1,32 @@ use color_eyre::Result; +use color_eyre::eyre::Error; use crossterm::event::{self, Event}; +use ratatui::layout::{Constraint, Direction, Layout}; +use ratatui::widgets::{Block, Paragraph}; use ratatui::{DefaultTerminal, Frame}; -use ratatui::widgets::{Block, Paragraph,}; -use ratatui::layout::{Constraint, Layout, Direction}; use sys_info; +use tokio::task; use crate::omikron::omikron_connection::OmikronConnection; pub fn launch(connection_status: bool) -> Result<()> { color_eyre::install()?; - let terminal = ratatui::init(); - let result = run(terminal, connection_status); + task::spawn(run(connection_status)); ratatui::restore(); - result + Ok(()) } -fn run(mut terminal: DefaultTerminal, connection_status: bool) -> Result<()> { +async fn run(connection_status: bool) -> Result<()> { loop { - terminal.draw(|frame| render(frame, connection_status))?; - if matches!(event::read()?, Event::Key(_)) { - break Ok(()); - } + ratatui::init().draw(|frame| render(frame, connection_status))?; } } fn render(frame: &mut Frame, connection_status: bool) { - let main_layout = Layout::default().direction(Direction::Horizontal).margin(1).constraints([Constraint::Percentage((100))].as_ref()); + let main_layout = Layout::default() + .direction(Direction::Horizontal) + .margin(1) + .constraints([Constraint::Percentage((100))].as_ref()); let main_block = Block::bordered().title("Tensamin - Iota"); let main_chunks = main_layout.split(frame.area()); @@ -39,14 +40,18 @@ fn render(frame: &mut Frame, connection_status: bool) { let mut operating_system: String; match sys_info::os_type() { Ok(os) => operating_system = os, - Err(error) => operating_system = error.to_string(), + Err(error) => operating_system = error.to_string(), } - let mut text_content: String = String::from(""); + let mut text_content: String = String::from(""); text_content.push_str("Operating System: "); text_content.push_str(operating_system.as_str()); text_content.push_str("\nConnection: "); - text_content.push_str(if connection_status {"Connected"} else {"Disconnected"}); + text_content.push_str(if connection_status { + "Connected" + } else { + "Disconnected" + }); let paragraph_systeminfo = Paragraph::new(text_content).block(block_systeminfo); @@ -54,4 +59,4 @@ fn render(frame: &mut Frame, connection_status: bool) { frame.render_widget(Block::bordered().title("Logs"), left); frame.render_widget(paragraph_systeminfo, top_right); frame.render_widget(Block::bordered().title("Ping"), bottom_right); -} \ No newline at end of file +} diff --git a/src/langu/language_manager.rs b/src/langu/language_manager.rs index 41076fa..bf6a0f6 100644 --- a/src/langu/language_manager.rs +++ b/src/langu/language_manager.rs @@ -6,7 +6,7 @@ use std::sync::Mutex; #[derive(Clone)] pub struct LanguagePack { - languages: HashMap, + language: HashMap, } // Language packs need to have formatting @@ -19,10 +19,42 @@ pub fn get_language() -> LanguagePack { LANGUAGE_PACK.lock().unwrap().clone() } +pub fn get_languages() -> Vec { + file_util::get_children("languages") +} + +pub fn set_language(language: &str) { + LANGUAGE_PACK.lock().unwrap().language.clear(); + LANGUAGE_PACK.lock().unwrap().load_language(language); +} + +pub fn from_key(key: &str) -> String { + LANGUAGE_PACK + .lock() + .unwrap() + .language + .get(key) + .unwrap_or(&String::new()) + .to_string() +} + +pub fn format(key: &str, args: &[&str]) -> String { + let message = from_key(key); + let mut formatted = String::new(); + let mut parts = message.split("{}"); + for (i, part) in parts.enumerate() { + formatted.push_str(part); + if i < args.len() { + formatted.push_str(args[i]); + } + } + formatted +} + impl LanguagePack { pub fn new(language: &str) -> Self { let mut pack = LanguagePack { - languages: HashMap::new(), + language: HashMap::new(), }; pack.load_language(language); pack @@ -34,33 +66,33 @@ impl LanguagePack { let frontend_messages = file_util::load_file(&path, "frontend.json"); let frontend_messages = parse(&frontend_messages).unwrap(); for (key, value) in frontend_messages.entries() { - self.languages + self.language .insert(key.to_string(), value.as_str().unwrap().to_string()); } let omikron_messages = file_util::load_file(&path, "omikron.json"); let omikron_messages = parse(&omikron_messages).unwrap(); for (key, value) in omikron_messages.entries() { - self.languages + self.language .insert(key.to_string(), value.as_str().unwrap().to_string()); } let button_texts = file_util::load_file(&path, "buttons.json"); let button_texts = parse(&button_texts).unwrap(); for (key, value) in button_texts.entries() { - self.languages + self.language .insert(key.to_string(), value.as_str().unwrap().to_string()); } let debug_messages = file_util::load_file(&path, "debug.json"); let debug_messages = parse(&debug_messages).unwrap(); for (key, value) in debug_messages.entries() { - self.languages + self.language .insert(key.to_string(), value.as_str().unwrap().to_string()); } } pub fn get_translation(&self, key: &str) -> &String { - self.languages.get(key).unwrap() + self.language.get(key).unwrap() } } diff --git a/src/main.rs b/src/main.rs index 2f363d7..4bb5431 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,9 @@ async fn main() { // return; //} + // UI + gui::ratatui_interface::launch(false); + // LANGUAGE PACK language_creator::create_languages(); @@ -62,7 +65,10 @@ async fn main() { for up in UserManager::get_users() { sb = sb + "," + &up.user_id.to_string().as_str(); } - sb.remove(0); + + if !sb.is_empty() { + sb.remove(0); + } println!( "IOTA ID: {}-####-####-####-############", CONFIG diff --git a/src/omikron/omikron_connection.rs b/src/omikron/omikron_connection.rs index 12c7ffb..b52ebbf 100644 --- a/src/omikron/omikron_connection.rs +++ b/src/omikron/omikron_connection.rs @@ -116,6 +116,7 @@ impl OmikronConnection { if cv.is_type(CommunicationType::MessageOtherIota) { let sender_id = &cv.get_sender(); let receiver_id = &cv.get_receiver(); + ChatFiles::add_message( cv.get_data(DataTypes::SendTime) .unwrap() @@ -128,6 +129,9 @@ impl OmikronConnection { .unwrap() .as_str() .unwrap(), + false, + false, + 0, ); let response = CommunicationValue::new(CommunicationType::MessageLive) .with_id(cv.get_id()) @@ -153,6 +157,24 @@ impl OmikronConnection { } if cv.is_type(CommunicationType::Message) { + /* + "user": { + "avatar": true, + "display": true, + "timestamp": true + }, + "body": { + "tint": "", + "content": "", + "files": [ + { + "name": "", + "id": "", + "type": "[ image | image_top_right | file ]" + } + ] + } + */ let my_id = cv.get_sender(); ChatFiles::add_message( SystemTime::now() @@ -166,6 +188,9 @@ impl OmikronConnection { ) .unwrap(), &*cv.get_data(DataTypes::MessageContent).unwrap().to_string(), + false, + false, + 0, ); // ack let ack = CommunicationValue::ack_message(cv.get_id(), my_id); diff --git a/src/util/chat_files.rs b/src/util/chat_files.rs index 903148e..1a67e8a 100644 --- a/src/util/chat_files.rs +++ b/src/util/chat_files.rs @@ -1,5 +1,5 @@ - -use json::{self, array, object, JsonValue}; +use json::{self, JsonValue, array, object}; +use sha2::digest::typenum::Add1; use std::fs::{self, File}; use std::io::{Read, Write}; use std::path::Path; @@ -43,13 +43,15 @@ impl ChatFiles { let mut file = File::create(path)?; file.write_all(content.as_bytes()) } - pub fn add_message( send_time: i64, storage_owner_is_sender: bool, storage_owner: Uuid, external_user: Uuid, message: &str, + avatar: bool, + timestamp: bool, + tint: i64, ) -> std::io::Result<()> { let user_dir = format!("users/{}/chats/{}", storage_owner, external_user); @@ -82,7 +84,11 @@ impl ChatFiles { }; message_chunk.push(json_obj).unwrap(); - Self::save_file(&user_dir, &format!("msgs_{}.json", chunk_index), &message_chunk.dump()) + Self::save_file( + &user_dir, + &format!("msgs_{}.json", chunk_index), + &message_chunk.dump(), + ) } pub fn change_message_state( @@ -198,14 +204,3 @@ impl ChatFiles { messages } } - -fn main() { - let owner = Uuid::new_v4(); - let external = Uuid::new_v4(); - - ChatFiles::add_message(1234567890, true, owner, external, "Hello!").unwrap(); - ChatFiles::change_message_state(owner, external, 1234567890, MessageState::Read).unwrap(); - let msgs = ChatFiles::get_messages(owner, external, 0, 10); - - println!("Messages: {}", msgs.dump()); -} diff --git a/src/util/file_util.rs b/src/util/file_util.rs index ac3d822..76e873f 100644 --- a/src/util/file_util.rs +++ b/src/util/file_util.rs @@ -91,6 +91,19 @@ pub fn save_file(path: &str, name: &str, value: &str) { } } +pub fn get_children(path: &str) -> Vec { + let dir = Path::new(&get_directory()).join(path); + let mut children = Vec::new(); + if let Ok(entries) = fs::read_dir(&dir) { + for entry in entries { + if let Ok(entry) = entry { + children.push(entry.file_name().to_string_lossy().to_string()); + } + } + } + children +} + pub fn get_directory() -> String { let exe = std::env::current_exe().unwrap_or_else(|_| PathBuf::from(".")); exe.parent()