mirror of
https://github.com/MeexReay/bRAC.git
synced 2025-07-01 22:13:00 +03:00
feat: new ui prototype
This commit is contained in:
parent
56f66232eb
commit
47342294e8
878
Cargo.lock
generated
878
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -21,6 +21,7 @@ notify-rust = { version = "4.11.7", optional = true }
|
||||
gdk-pixbuf = { version = "0.3.0", optional = true } # DO NOT UPDATE
|
||||
winapi = { version = "0.3.9", optional = true, features = ["wincon", "winuser"] }
|
||||
tungstenite = "0.27.0"
|
||||
reqwest = "0.12.20"
|
||||
|
||||
[build-dependencies]
|
||||
winresource = { version = "0.1.20", optional = true }
|
||||
|
@ -59,6 +59,8 @@ pub struct Config {
|
||||
pub proxy: Option<String>,
|
||||
#[serde(default = "default_true")]
|
||||
pub notifications_enabled: bool,
|
||||
#[serde(default = "default_true")]
|
||||
pub new_ui_enabled: bool,
|
||||
#[serde(default)]
|
||||
pub debug_logs: bool,
|
||||
}
|
||||
@ -148,6 +150,8 @@ pub struct Args {
|
||||
#[arg(long)]
|
||||
pub notifications_enabled: Option<bool>,
|
||||
#[arg(long)]
|
||||
pub new_ui_enabled: Option<bool>,
|
||||
#[arg(long)]
|
||||
pub proxy: Option<String>,
|
||||
#[arg(long)]
|
||||
pub debug_logs: bool,
|
||||
@ -200,6 +204,9 @@ impl Args {
|
||||
if let Some(v) = self.notifications_enabled {
|
||||
config.notifications_enabled = v
|
||||
}
|
||||
if let Some(v) = self.new_ui_enabled {
|
||||
config.new_ui_enabled = v
|
||||
}
|
||||
if self.debug_logs {
|
||||
config.debug_logs = true
|
||||
}
|
||||
|
169
src/chat/gui.rs
169
src/chat/gui.rs
@ -1,4 +1,5 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::error::Error;
|
||||
use std::sync::{atomic::Ordering, mpsc::channel, Arc, RwLock};
|
||||
use std::thread;
|
||||
@ -6,7 +7,8 @@ use std::time::{Duration, SystemTime};
|
||||
|
||||
use chrono::Local;
|
||||
|
||||
use gtk4::{self as gtk};
|
||||
use gtk4::ffi::GtkGrid;
|
||||
use gtk4 as gtk;
|
||||
|
||||
use gtk::gdk::{Cursor, Display, Texture};
|
||||
use gtk::gdk_pixbuf::{Pixbuf, PixbufAnimation, PixbufLoader};
|
||||
@ -43,6 +45,8 @@ struct UiModel {
|
||||
notifications: Arc<RwLock<Vec<libnotify::Notification>>>,
|
||||
#[cfg(all(not(feature = "libnotify"), not(feature = "notify-rust")))]
|
||||
notifications: Arc<RwLock<Vec<String>>>,
|
||||
default_avatar: Pixbuf,
|
||||
avatars: Arc<RwLock<HashMap<u64, Pixbuf>>>,
|
||||
}
|
||||
|
||||
thread_local!(
|
||||
@ -203,6 +207,7 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
||||
gui_usize_entry_setting!("Konata Size", konata_size, ctx, settings_vbox);
|
||||
let remove_gui_shit_entry =
|
||||
gui_checkbox_setting!("Remove Gui Shit", remove_gui_shit, ctx, settings_vbox);
|
||||
let new_ui_enabled_entry = gui_checkbox_setting!("New UI", new_ui_enabled, ctx, settings_vbox);
|
||||
|
||||
let scrollable = ScrolledWindow::builder()
|
||||
.child(&settings_vbox)
|
||||
@ -251,6 +256,8 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
||||
konata_size_entry,
|
||||
#[weak]
|
||||
remove_gui_shit_entry,
|
||||
#[weak]
|
||||
new_ui_enabled_entry,
|
||||
move |_| {
|
||||
let config = Config {
|
||||
host: host_entry.text().to_string(),
|
||||
@ -315,6 +322,7 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
||||
formatting_enabled: formatting_enabled_entry.is_active(),
|
||||
commands_enabled: commands_enabled_entry.is_active(),
|
||||
notifications_enabled: notifications_enabled_entry.is_active(),
|
||||
new_ui_enabled: new_ui_enabled_entry.is_active(),
|
||||
debug_logs: debug_logs_entry.is_active(),
|
||||
proxy: {
|
||||
let proxy = proxy_entry.text().to_string();
|
||||
@ -371,6 +379,8 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
||||
konata_size_entry,
|
||||
#[weak]
|
||||
remove_gui_shit_entry,
|
||||
#[weak]
|
||||
new_ui_enabled_entry,
|
||||
move |_| {
|
||||
let config = Config::default();
|
||||
ctx.set_config(&config);
|
||||
@ -391,6 +401,7 @@ fn open_settings(ctx: Arc<Context>, app: &Application) {
|
||||
oof_update_time_entry.set_text(&config.oof_update_time.to_string());
|
||||
konata_size_entry.set_text(&config.konata_size.to_string());
|
||||
remove_gui_shit_entry.set_active(config.remove_gui_shit);
|
||||
new_ui_enabled_entry.set_active(config.new_ui_enabled);
|
||||
}
|
||||
));
|
||||
let window = Window::builder()
|
||||
@ -779,6 +790,8 @@ fn build_ui(ctx: Arc<Context>, app: &Application) -> UiModel {
|
||||
notifications: Arc::new(RwLock::new(Vec::<libnotify::Notification>::new())),
|
||||
#[cfg(all(not(feature = "libnotify"), not(feature = "notify-rust")))]
|
||||
notifications: Arc::new(RwLock::new(Vec::<String>::new())),
|
||||
default_avatar: load_pixbuf(include_bytes!("images/avatar.png")).unwrap(),
|
||||
avatars: Arc::new(RwLock::new(HashMap::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@ -929,23 +942,13 @@ fn send_notification(_: Arc<Context>, ui: &UiModel, title: &str, message: &str)
|
||||
ui.notifications.write().unwrap().push(id);
|
||||
}
|
||||
|
||||
fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String, notify: bool) {
|
||||
let notify = notify && ctx.config(|c| c.notifications_enabled);
|
||||
|
||||
let formatting_enabled = ctx.config(|c| c.formatting_enabled);
|
||||
|
||||
let Some(sanitized) = (if formatting_enabled {
|
||||
sanitize_message(message.clone())
|
||||
} else {
|
||||
Some(message.clone())
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if sanitized.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
fn get_message_box(
|
||||
ctx: Arc<Context>,
|
||||
ui: &UiModel,
|
||||
message: String,
|
||||
notify: bool,
|
||||
formatting_enabled: bool,
|
||||
) -> GtkBox {
|
||||
// TODO: softcode these colors
|
||||
|
||||
let (ip_color, date_color, text_color) = if ui.is_dark_theme {
|
||||
@ -956,7 +959,7 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String, notify: bool
|
||||
|
||||
let mut label = String::new();
|
||||
|
||||
if let (true, Some((date, ip, content, nick, avatar))) =
|
||||
if let (true, Some((date, ip, content, nick, _))) =
|
||||
(formatting_enabled, parse_message(message.clone()))
|
||||
{
|
||||
if let Some(ip) = ip {
|
||||
@ -1031,7 +1034,133 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String, notify: bool
|
||||
|
||||
hbox.set_hexpand(true);
|
||||
|
||||
ui.chat_box.append(&hbox);
|
||||
hbox
|
||||
}
|
||||
|
||||
fn load_avatar(ui: &UiModel, url: &str) -> Option<Pixbuf> {
|
||||
Some(ui.default_avatar.clone())
|
||||
}
|
||||
|
||||
fn get_new_message_box(
|
||||
ctx: Arc<Context>,
|
||||
ui: &UiModel,
|
||||
message: String,
|
||||
notify: bool,
|
||||
formatting_enabled: bool,
|
||||
) -> GtkBox {
|
||||
// TODO: softcode these colors
|
||||
|
||||
let (ip_color, date_color, text_color) = if ui.is_dark_theme {
|
||||
("#494949", "#929292", "#FFFFFF")
|
||||
} else {
|
||||
("#585858", "#292929", "#000000")
|
||||
};
|
||||
|
||||
let (date, ip, content, name, color, avatar) =
|
||||
if let (true, Some((date, ip, content, nick, avatar))) =
|
||||
(formatting_enabled, parse_message(message.clone()))
|
||||
{
|
||||
(
|
||||
date,
|
||||
ip,
|
||||
content,
|
||||
nick.as_ref()
|
||||
.map(|o| o.0.to_string())
|
||||
.unwrap_or("System".to_string()),
|
||||
nick.as_ref()
|
||||
.map(|o| o.1.to_string())
|
||||
.unwrap_or("#DDDDDD".to_string()),
|
||||
avatar
|
||||
.and_then(|o| load_avatar(ui, &o))
|
||||
.unwrap_or(ui.default_avatar.clone()),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
Local::now().format("%d.%m.%Y %H:%M").to_string(),
|
||||
None,
|
||||
message,
|
||||
"System".to_string(),
|
||||
"#DDDDDD".to_string(),
|
||||
ui.default_avatar.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
let hbox = GtkBox::new(Orientation::Horizontal, 2);
|
||||
|
||||
let avatar_picture = Picture::for_pixbuf(&avatar);
|
||||
avatar_picture.set_css_classes(&["message-avatar"]);
|
||||
avatar_picture.set_size_request(32, 32);
|
||||
avatar_picture.set_vexpand(false);
|
||||
avatar_picture.set_hexpand(false);
|
||||
avatar_picture.set_valign(Align::Start);
|
||||
avatar_picture.set_halign(Align::Start);
|
||||
|
||||
hbox.append(&avatar_picture);
|
||||
|
||||
let vbox = GtkBox::new(Orientation::Vertical, 2);
|
||||
|
||||
vbox.append(&Label::builder()
|
||||
.label(format!(
|
||||
"<span color=\"{color}\">{}</span> <span color=\"{date_color}\">{}</span> <span color=\"{ip_color}\">{}</span>",
|
||||
glib::markup_escape_text(&name),
|
||||
glib::markup_escape_text(&date),
|
||||
glib::markup_escape_text(&ip.unwrap_or_default()),
|
||||
))
|
||||
.halign(Align::Start)
|
||||
.valign(Align::Start)
|
||||
.selectable(true)
|
||||
.wrap(true)
|
||||
.wrap_mode(WrapMode::WordChar)
|
||||
.use_markup(true)
|
||||
.vexpand(true)
|
||||
.build());
|
||||
|
||||
vbox.append(&Label::builder()
|
||||
.label(format!(
|
||||
"<span color=\"{text_color}\">{}</span>",
|
||||
glib::markup_escape_text(&content)
|
||||
))
|
||||
.halign(Align::Start)
|
||||
.valign(Align::Start)
|
||||
.selectable(true)
|
||||
.wrap(true)
|
||||
.wrap_mode(WrapMode::WordChar)
|
||||
.use_markup(true)
|
||||
.vexpand(true)
|
||||
.build());
|
||||
|
||||
vbox.set_valign(Align::Fill);
|
||||
vbox.set_halign(Align::Fill);
|
||||
vbox.set_vexpand(true);
|
||||
vbox.set_hexpand(true);
|
||||
|
||||
hbox.append(&vbox);
|
||||
|
||||
hbox
|
||||
}
|
||||
|
||||
fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String, notify: bool) {
|
||||
let notify = notify && ctx.config(|c| c.notifications_enabled);
|
||||
|
||||
let formatting_enabled = ctx.config(|c| c.formatting_enabled);
|
||||
|
||||
let Some(sanitized) = (if formatting_enabled {
|
||||
sanitize_message(message.clone())
|
||||
} else {
|
||||
Some(message.clone())
|
||||
}) else {
|
||||
return;
|
||||
};
|
||||
|
||||
if sanitized.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
if ctx.config(|o| o.new_ui_enabled) {
|
||||
ui.chat_box.append(&get_new_message_box(ctx.clone(), ui, message, notify, formatting_enabled));
|
||||
} else {
|
||||
ui.chat_box.append(&get_message_box(ctx.clone(), ui, message, notify, formatting_enabled));
|
||||
}
|
||||
|
||||
timeout_add_local_once(Duration::from_millis(1000), move || {
|
||||
GLOBAL.with(|global| {
|
||||
|
BIN
src/chat/images/avatar.png
Normal file
BIN
src/chat/images/avatar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
@ -1,6 +1,6 @@
|
||||
|
||||
/* Now made with GTK Pango Markup */
|
||||
|
||||
/* .message-content { color:rgb(255, 255, 255); }
|
||||
.message-content { color:rgb(255, 255, 255); }
|
||||
.message-date { color:rgb(146, 146, 146); }
|
||||
.message-ip { color:rgb(73, 73, 73); } */
|
||||
.message-ip { color:rgb(73, 73, 73); }
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
/* Now made with GTK Pango Markup */
|
||||
|
||||
/* .message-content { color:rgb(0, 0, 0); }
|
||||
.message-content { color:rgb(0, 0, 0); }
|
||||
.message-date { color:rgb(41, 41, 41); }
|
||||
.message-ip { color:rgb(88, 88, 88); } */
|
||||
.message-ip { color:rgb(88, 88, 88); }
|
@ -14,11 +14,15 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.message-avatar {
|
||||
border-radius: 64px;
|
||||
}
|
||||
|
||||
/* Now made with GTK Pango Markup */
|
||||
|
||||
/* .message-name { font-weight: bold; }
|
||||
.message-name { font-weight: bold; }
|
||||
|
||||
.message-name-green { color: #70fa7a; }
|
||||
/* .message-name-green { color: #70fa7a; }
|
||||
.message-name-red { color: #fa7070; }
|
||||
.message-name-magenta { color: #da70fa; }
|
||||
.message-name-cyan { color: #70fadc; } */
|
Loading…
x
Reference in New Issue
Block a user