UI-Loading Messages with more (Optional) Data

This commit is contained in:
Alex Emmet 2025-09-26 17:37:40 +02:00
commit a5ade7dd03
6 changed files with 114 additions and 38 deletions

View file

@ -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);
}
}

View file

@ -6,7 +6,7 @@ use std::sync::Mutex;
#[derive(Clone)]
pub struct LanguagePack {
languages: HashMap<String, String>,
language: HashMap<String, String>,
}
// 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<String> {
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()
}
}

View file

@ -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

View file

@ -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": "<hex color>",
"content": "<markdown (encrypted)>",
"files": [
{
"name": "<cool name>",
"id": "<uuid>",
"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);

View file

@ -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());
}

View file

@ -91,6 +91,19 @@ pub fn save_file(path: &str, name: &str, value: &str) {
}
}
pub fn get_children(path: &str) -> Vec<String> {
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()