Files
realm-chat/client/src/ui/gui.rs
2024-10-15 22:25:34 -04:00

582 lines
19 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
use chrono::Utc;
use egui::{Context, SelectableLabel};
use tarpc::context;
use tarpc::tokio_serde::formats::Json;
use realm_auth::types::RealmAuthClient;
use realm_shared::types::ErrorCode::RPCError;
use regex::Regex;
use tracing::log::*;
use realm_server::types::{Message, MessageData, Room, User};
use realm_shared::stoken;
use crate::app::RealmApp;
use crate::types::CServer;
pub fn top_panel(app: &mut RealmApp, ctx: &Context) {
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| {
egui::menu::bar(ui, |ui| {
if app.current_user.is_none() && ui.button("Sign Up").clicked() {
app.signup_window_open = true;
}
if app.current_user.is_none() && ui.button("Login").clicked() {
app.login_window_open = true;
}
if app.current_user.is_some() && ui.button("Logout").clicked() {
let address = app.current_user.clone().unwrap().auth_address;
let username = app.current_user.clone().unwrap().username;
let token = app.current_user.clone().unwrap().token;
let _handle = tokio::spawn(async move {
let mut transport = tarpc::serde_transport::tcp::connect(&address, Json::default);
transport.config_mut().max_frame_length(usize::MAX);
let result = transport.await;
let connection = match result {
Ok(connection) => connection,
Err(e) => {
tracing::error!("Failed to connect to server: {}", e);
return;
}
};
let client = RealmAuthClient::new(tarpc::client::Config::default(), connection).spawn();
let result = client.sign_out(context::current(), username, token).await;
match result {
Ok(_) => info!("Signed out!"), // TODO: properly handle this
Err(e) => error!("Error signing out: {:?}", e),
}
});
app.current_user = None;
app.saved_username = None;
app.saved_token = None;
app.saved_auth_address = None;
app.active_servers = None;
app.selected_roomid.clear();
app.selected_serverid.clear();
}
if ui.button("Quit").clicked() {
ctx.send_viewport_cmd(egui::ViewportCommand::Close);
}
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
egui::widgets::global_theme_preference_buttons(ui);
if ui.button("").clicked() {
app.info_window_open = true;
}
if app.current_user.is_some() && ui.button("Delete Account").clicked() {
let address = app.current_user.clone().unwrap().auth_address;
let username = app.current_user.clone().unwrap().username;
let token = app.current_user.clone().unwrap().token;
let _handle = tokio::spawn(async move {
let mut transport = tarpc::serde_transport::tcp::connect(address, Json::default);
transport.config_mut().max_frame_length(usize::MAX);
let result = transport.await;
let connection = match result {
Ok(connection) => connection,
Err(e) => {
tracing::error!("Failed to connect to server: {}", e);
return;
}
};
let client = RealmAuthClient::new(tarpc::client::Config::default(), connection).spawn();
let result = client.delete_account(context::current(), username, token).await;
match result {
Ok(_) => info!("Account deleted successfully!"),
Err(e) => error!("Error deleting account: {:?}", e),
}
});
app.current_user = None;
app.saved_username = None;
app.saved_token = None;
app.saved_auth_address = None;
app.active_servers = None;
app.selected_roomid.clear();
app.selected_serverid.clear();
}
});
});
});
}
pub fn servers(app: &mut RealmApp, ctx: &Context) {
egui::SidePanel::left("servers").show(ctx, |ui| {
ui.horizontal(|ui| {
ui.heading("Servers");
if app.current_user.is_some() && ui.button("+").clicked() {
app.server_window_open = true;
}
if !app.selected_serverid.is_empty() && ui.button("-").clicked() {
let server = app.active_servers.clone().unwrap().into_iter().find(|s| s.server_id.eq(&app.selected_serverid)).unwrap();
let token = app.current_user.as_ref().unwrap().token.clone();
let userid = app.current_user.as_ref().unwrap().username.clone();
let send_channel = app.leave_server_channel.0.clone();
let _handle = tokio::spawn(async move {
let result = server.tarpc_conn.leave_server(
context::current(),
stoken(&token, &server.server_id, &server.domain, server.port),
userid
).await;
match result {
Ok(r) => {
match r {
Ok(_) => send_channel.send(Ok((server.server_id.clone(), server.domain.clone(), server.port))).unwrap(),
Err(e) => send_channel.send(Err(e)).unwrap()
}
},
Err(_) => send_channel.send(Err(RPCError)).unwrap(),
}
});
}
});
ui.separator();
if let Some(active_servers) = &mut app.active_servers {
for server in active_servers {
if ui.add(SelectableLabel::new(server.server_id.eq(&app.selected_serverid), server.server_id.clone())).clicked() {
if app.selected_serverid.eq(&server.server_id) {
app.selected_serverid.clear();
} else {
app.selected_serverid = server.server_id.clone();
}
app.selected_roomid.clear();
}
}
}
});
}
pub fn rooms(app: &mut RealmApp, ctx: &Context) {
egui::SidePanel::left("rooms").show(ctx, |ui| {
let mut current_server: Option<CServer> = None;
if let Some(servers) = app.active_servers.clone() {
for server in servers {
if server.server_id.eq(&app.selected_serverid) {
current_server = Some(server);
}
}
}
ui.horizontal(|ui| {
ui.heading("Rooms");
if let Some(server) = current_server.clone() {
if server.is_admin && ui.button("+").clicked() {
app.room_window_open = true;
}
if server.is_admin && !app.selected_roomid.is_empty() && ui.button("-").clicked() {
let token = app.current_user.as_ref().unwrap().token.clone();
let roomid = app.selected_roomid.clone();
let userid = app.current_user.as_ref().unwrap().username.clone();
let send_channel = app.delete_room_channel.0.clone();
let _handle = tokio::spawn(async move {
let result = server.tarpc_conn.delete_room(
context::current(),
stoken(&token, &server.server_id, &server.domain, server.port),
userid,
roomid
).await;
match result {
Ok(r) => {
match r {
Ok(_) => send_channel.send(Ok(server)).unwrap(),
Err(e) => send_channel.send(Err(e)).unwrap()
}
},
Err(_) => send_channel.send(Err(RPCError)).unwrap(),
}
});
}
}
});
ui.separator();
if let Some(server) = current_server {
for room in &server.rooms {
if ui.add(SelectableLabel::new(room.roomid.eq(&app.selected_roomid), room.roomid.clone())).clicked() {
if app.selected_roomid.eq(&room.roomid) {
app.selected_roomid.clear();
} else {
app.selected_roomid = room.roomid.clone();
}
}
}
}
});
}
pub fn messages(app: &mut RealmApp, ctx: &Context) {
egui::CentralPanel::default().show(ctx, |ui| {
ui.with_layout(egui::Layout::bottom_up(egui::Align::TOP), |ui| {
ui.with_layout(egui::Layout::right_to_left(egui::Align::TOP), |ui| {
if ui.button("").on_hover_text("Send a message").clicked() {
if let Some(active_servers) = &app.active_servers {
for server in active_servers.clone() {
if server.server_id.eq(&app.selected_serverid) {
let username = app.current_user.as_ref().unwrap().username.clone();
let token = app.current_user.as_ref().unwrap().token.clone();
let room = server.rooms.iter().find(|r| r.roomid.eq(&app.selected_roomid)).unwrap().clone();
let text_message = app.text_message_input.clone();
let _handle = tokio::spawn(async move {
let result = server.tarpc_conn.send_message(
context::current(),
stoken(&token, &server.server_id, &server.domain, server.port),
Message {
id: 0,
timestamp: Utc::now(),
user: server.tarpc_conn.get_user(context::current(), username.clone()).await.unwrap().unwrap(),
room,
data: MessageData::Text(text_message),
}
).await;
});
app.text_message_input.clear();
}
}
}
}
ui.add(
egui::TextEdit::multiline(&mut app.text_message_input)
.desired_rows(1)
.desired_width(ui.available_width())
.hint_text("Send a message...")
);
});
ui.with_layout(egui::Layout::top_down_justified(egui::Align::Min), |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
if let Some(active_servers) = &app.active_servers {
for server in active_servers {
let messages_to_display = server.messages
.iter()
.filter(|m| m.room.roomid.eq(&app.selected_roomid))
.collect::<Vec<&Message>>();
for message in messages_to_display {
match message.clone().data {
MessageData::Text(text) => {
ui.label(format!("{} - {}: {}",
message.timestamp.format("%Y-%m-%d %H:%M:%S"),
message.user.userid.split(':').collect::<Vec<&str>>()[0],
text));
}
MessageData::Attachment(_) => {}
MessageData::Reply(_) => {}
MessageData::Edit(_) => {}
MessageData::Reaction(_) => {}
MessageData::Redaction(_) => {}
}
}
}
}
});
});
});
});
}
pub fn modals(app: &mut RealmApp, ctx: &Context) {
egui::Window::new("Info")
.open(&mut app.info_window_open)
.min_size((500.0, 200.0))
.show(ctx, |ui| {
egui::ScrollArea::vertical().show(ui, |ui| {
ui.label(format!("Saved username: {:?}", app.saved_username));
ui.label(format!("Saved token: {:?}", app.saved_token));
ui.label(format!("Saved auth address: {:?}", app.saved_auth_address));
ui.separator();
if let Some(servers) = &app.active_servers {
for server in servers {
ui.heading(&server.server_id);
ui.label(format!("{:?}", server));
}
}
ui.separator();
ui.label(format!("Current user: {:?}", app.current_user));
});
});
egui::Window::new("Signup")
.open(&mut app.signup_window_open)
.min_size((500.0, 200.0))
.show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label("Domain: ");
ui.text_edit_singleline(&mut app.login_window_server_domain);
ui.label("Port: ");
if ui.text_edit_singleline(&mut app.login_window_server_port).changed() {
let re = Regex::new(r"[^0-9]+").unwrap();
app.login_window_server_port = re.replace_all(&app.login_window_server_port, "").to_string();
}
});
ui.horizontal(|ui| {
ui.label("Username: ");
ui.text_edit_singleline(&mut app.login_window_username);
});
ui.horizontal(|ui| {
ui.label("Email: ");
ui.text_edit_singleline(&mut app.login_window_email);
});
if ui.button("Create Account").clicked() {
let login_window_server_address = format!("{}:{}", app.login_window_server_domain, app.login_window_server_port);
let login_window_username = format!("@{}:{}", app.login_window_username, app.login_window_server_domain);
let login_window_email = app.login_window_email.clone();
let send_channel = app.login_start_channel.0.clone();
let _handle = tokio::spawn(async move {
let mut transport = tarpc::serde_transport::tcp::connect(login_window_server_address, Json::default);
transport.config_mut().max_frame_length(usize::MAX);
let result = transport.await;
let connection = match result {
Ok(connection) => connection,
Err(e) => {
tracing::error!("Failed to connect to server: {}", e);
return;
}
};
let client = RealmAuthClient::new(tarpc::client::Config::default(), connection).spawn();
let result = client.create_account_flow(context::current(), login_window_username, login_window_email).await;
match result {
Ok(r) => send_channel.send(r).unwrap(),
Err(_) => send_channel.send(Err(RPCError)).unwrap(),
};
});
//ui.close_menu()
}
});
egui::Window::new("Login")
.open(&mut app.login_window_open)
.min_size((500.0, 200.0))
.show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label("Domain: ");
ui.text_edit_singleline(&mut app.login_window_server_domain);
ui.label("Port: ");
if ui.text_edit_singleline(&mut app.login_window_server_port).changed() {
let re = Regex::new(r"[^0-9]+").unwrap();
app.login_window_server_port = re.replace_all(&app.login_window_server_port, "").to_string();
}
});
ui.horizontal(|ui| {
ui.label("Username: ");
ui.text_edit_singleline(&mut app.login_window_username);
});
if ui.button("Send Login Code").clicked() {
let login_window_server_address = format!("{}:{}", app.login_window_server_domain, app.login_window_server_port);
let login_window_username = format!("@{}:{}", app.login_window_username, app.login_window_server_domain);
let send_channel = app.login_start_channel.0.clone();
let _handle = tokio::spawn(async move {
let mut transport = tarpc::serde_transport::tcp::connect(login_window_server_address, Json::default);
transport.config_mut().max_frame_length(usize::MAX);
let result = transport.await;
let connection = match result {
Ok(connection) => connection,
Err(e) => {
tracing::error!("Failed to connect to server: {}", e);
return;
}
};
let client = RealmAuthClient::new(tarpc::client::Config::default(), connection).spawn();
let result = client.create_login_flow(context::current(), Some(login_window_username), None).await;
match result {
Ok(r) => send_channel.send(r).unwrap(),
Err(_) => send_channel.send(Err(RPCError)).unwrap(),
};
});
//ui.close_menu()
}
});
egui::Window::new("Auth Code")
.open(&mut app.login_ready_for_code_input)
.min_size((500.0, 200.0))
.show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label("Code: ");
if ui.text_edit_singleline(&mut app.login_window_code).changed() {
let re = Regex::new(r"[^0-9]+").unwrap();
app.login_window_code = re.replace_all(&app.login_window_code, "").to_string();
}
});
if ui.button("Login").clicked() {
let login_window_server_address = format!("{}:{}", app.login_window_server_domain, app.login_window_server_port);
let login_window_code = app.login_window_code.clone();
let login_window_username = format!("@{}:{}", app.login_window_username, app.login_window_server_domain);
let send_channel = app.login_ending_channel.0.clone();
let _handle = tokio::spawn(async move {
let mut transport = tarpc::serde_transport::tcp::connect(login_window_server_address, Json::default);
transport.config_mut().max_frame_length(usize::MAX);
let result = transport.await;
let connection = match result {
Ok(connection) => connection,
Err(e) => {
tracing::error!("Failed to connect to server: {}", e);
return;
}
};
let client = RealmAuthClient::new(tarpc::client::Config::default(), connection).spawn();
let result = client.finish_login_flow(context::current(), login_window_username, login_window_code.parse::<u32>().unwrap()).await;
match result {
Ok(r) => {
send_channel.send(r).unwrap();
}
Err(e) => {
send_channel.send(Err(RPCError)).unwrap();
}
}
});
//ui.close_menu()
}
});
egui::Window::new("Add Server")
.open(&mut app.server_window_open)
.min_size((500.0, 200.0))
.show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label("Domain: ");
ui.text_edit_singleline(&mut app.server_window_domain);
});
ui.horizontal(|ui| {
ui.label("Port: ");
if ui.text_edit_singleline(&mut app.server_window_port).changed() {
let re = Regex::new(r"[^0-9]+").unwrap();
app.login_window_code = re.replace_all(&app.server_window_port, "").to_string();
}
});
if app.current_user.is_some() && ui.button("Add Server").clicked() {
let domain = app.server_window_domain.clone();
let port = app.server_window_port.clone();
let auth_address = app.current_user.clone().unwrap().auth_address;
let auth_username = app.current_user.clone().unwrap().username;
let auth_token = app.current_user.clone().unwrap().token;
let send_channel = app.add_server_channel.0.clone();
let _handle = tokio::spawn(async move {
let mut transport = tarpc::serde_transport::tcp::connect(auth_address, Json::default);
transport.config_mut().max_frame_length(usize::MAX);
let result = transport.await;
let connection = match result {
Ok(connection) => connection,
Err(e) => {
tracing::error!("Failed to connect to server: {}", e);
return;
}
};
let client = RealmAuthClient::new(tarpc::client::Config::default(), connection).spawn();
let result = client.add_server(
context::current(), auth_username, auth_token, domain.clone(), port.parse::<u16>().unwrap()).await;
match result {
Ok(r) => {
match r {
Ok(_) => {
info!("Server added successfully!");
send_channel.send(Ok(format!("{}:{}", domain, port))).unwrap();
},
Err(e) => error!("Error adding server: {:?}", e),
}
},
Err(_) => { send_channel.send(Err(RPCError)).unwrap(); },
};
});
}
});
egui::Window::new("Add Room")
.open(&mut app.room_window_open)
.min_size((500.0, 200.0))
.show(ctx, |ui| {
ui.horizontal(|ui| {
ui.label("Name: ");
ui.text_edit_singleline(&mut app.room_window_name);
});
ui.checkbox(&mut app.room_window_admin_only_send, "Only admins can send");
ui.checkbox(&mut app.room_window_admin_only_view, "Only admins can view");
if ui.button("Add Room").clicked() {
for server in app.active_servers.clone().unwrap() {
if server.server_id.eq(&app.selected_serverid) {
let token = app.current_user.as_ref().unwrap().token.clone();
let roomid = app.room_window_name.clone();
let admin_only_send = app.room_window_admin_only_send;
let admin_only_view = app.room_window_admin_only_view;
let userid = app.current_user.as_ref().unwrap().username.clone();
let send_channel = app.add_room_channel.0.clone();
let _handle = tokio::spawn(async move {
let result = server.tarpc_conn.create_room(
context::current(),
stoken(&token, &server.server_id, &server.domain, server.port),
userid,
Room {
id: 0,
roomid,
admin_only_send,
admin_only_view,
}
).await;
match result {
Ok(r) => {
match r {
Ok(_) => { send_channel.send(Ok(server)).unwrap(); }
Err(e) => { send_channel.send(Err(e)).unwrap(); }
}
}
Err(_) => {
send_channel.send(Err(RPCError)).unwrap();
}
}
});
}
}
}
});
}