582 lines
19 KiB
Rust
582 lines
19 KiB
Rust
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();
|
||
}
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
});
|
||
} |