mirror of
https://github.com/MeexReay/bRAC.git
synced 2025-05-06 05:28:02 +03:00
gui as default and more ui
This commit is contained in:
parent
904ac31a97
commit
a85442f57d
149
Cargo.lock
generated
149
Cargo.lock
generated
@ -11,6 +11,21 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "android-tzdata"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
|
||||
|
||||
[[package]]
|
||||
name = "android_system_properties"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.18"
|
||||
@ -78,6 +93,7 @@ name = "bRAC"
|
||||
version = "0.1.2+2.0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"chrono",
|
||||
"clap",
|
||||
"colored",
|
||||
"crossterm",
|
||||
@ -97,6 +113,12 @@ version = "2.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.5.0"
|
||||
@ -157,6 +179,20 @@ version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.36"
|
||||
@ -688,6 +724,30 @@ dependencies = [
|
||||
"windows",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.63"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
"iana-time-zone-haiku",
|
||||
"js-sys",
|
||||
"log",
|
||||
"wasm-bindgen",
|
||||
"windows-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone-haiku"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.7.1"
|
||||
@ -710,6 +770,16 @@ version = "1.0.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
@ -822,6 +892,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.20.3"
|
||||
@ -1077,6 +1156,12 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustversion"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.19"
|
||||
@ -1357,6 +1442,64 @@ dependencies = [
|
||||
"wit-bindgen-rt",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
"rustversion",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.100"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "1.1.0"
|
||||
@ -1429,6 +1572,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
|
@ -14,12 +14,14 @@ serde_yml = "0.0.12"
|
||||
crossterm = { version = "0.29.0", optional = true }
|
||||
homedir = { version = "0.3.4", optional = true }
|
||||
native-tls = { version = "0.2.14", optional = true }
|
||||
gtk4 = { version = "0.9.6", optional = true }
|
||||
gtk4 = { version = "0.9.6", optional = true, features = [ "v4_10" ] }
|
||||
cfg-if = "1.0.0"
|
||||
chrono = { version = "0.4.40", optional = true }
|
||||
|
||||
[features]
|
||||
default = ["ssl", "homedir", "gtk_gui"]
|
||||
tui = ["ssl", "homedir", "pretty_tui"]
|
||||
ssl = ["dep:native-tls"]
|
||||
pretty_tui = ["dep:crossterm"]
|
||||
gtk_gui = ["dep:gtk4"]
|
||||
gtk_gui = ["dep:gtk4", "dep:chrono"]
|
||||
homedir = ["dep:homedir"]
|
||||
|
22
README.md
22
README.md
@ -9,6 +9,7 @@ better RAC client
|
||||
|
||||
## features
|
||||
|
||||
- gtk4 GUI
|
||||
- cheat commands (type /help)
|
||||
- no ip and date visible
|
||||
- uses TOR proxy server by default (meex.lol:11234)
|
||||
@ -19,7 +20,7 @@ better RAC client
|
||||
- RACS compatible (--enable-ssl or in --configure enable SSL)
|
||||
- chunked reading messages
|
||||
|
||||

|
||||

|
||||
|
||||
## how to run
|
||||
|
||||
@ -43,18 +44,19 @@ cargo build -r # build release (target/release/bRAC)
|
||||
cargo run -r # run (builds and runs bRAC itself)
|
||||
```
|
||||
|
||||
TUI version:
|
||||
|
||||
```bash
|
||||
cargo build -r --no-default-features -F tui
|
||||
cargo run -r --no-default-features -F tui
|
||||
```
|
||||
|
||||
Minimal version:
|
||||
|
||||
```bash
|
||||
cargo build -r --no-default-features
|
||||
cargo run -r --no-default-features
|
||||
```
|
||||
GTK version:
|
||||
|
||||
```bash
|
||||
cargo build -rF gtk_gui
|
||||
cargo run -rF gtk_gui
|
||||
```
|
||||
|
||||
### nix package
|
||||
|
||||
@ -72,11 +74,11 @@ nix build github:MeexReay/bRAC#bRAC-minimal
|
||||
nix run github:MeexReay/bRAC#bRAC-minimal
|
||||
```
|
||||
|
||||
GTK version:
|
||||
TUI version:
|
||||
|
||||
```bash
|
||||
nix build github:MeexReay/bRAC#bRAC-gtk
|
||||
nix run github:MeexReay/bRAC#bRAC-gtk
|
||||
nix build github:MeexReay/bRAC#bRAC-tui
|
||||
nix run github:MeexReay/bRAC#bRAC-tui
|
||||
```
|
||||
|
||||
## default config
|
||||
|
BIN
brac_logo.png
BIN
brac_logo.png
Binary file not shown.
Before Width: | Height: | Size: 95 KiB |
15
flake.nix
15
flake.nix
@ -55,15 +55,20 @@
|
||||
devShells.default = self'.devShells.stable;
|
||||
|
||||
packages.bRAC = (rustPackage {
|
||||
version = "-gtk";
|
||||
features = "ssl homedir gtk_gui";
|
||||
deps = with pkgs; [
|
||||
pkg-config
|
||||
openssl
|
||||
gtk4
|
||||
pango
|
||||
];
|
||||
});
|
||||
packages.bRAC-tui = (rustPackage {
|
||||
version = "";
|
||||
features = "default";
|
||||
deps = with pkgs; [ pkg-config openssl ];
|
||||
});
|
||||
packages.bRAC-gtk = (rustPackage {
|
||||
version = "-gtk";
|
||||
features = "ssl homedir gtk_gui";
|
||||
deps = with pkgs; [ pkg-config openssl gtk4 pango ];
|
||||
});
|
||||
packages.bRAC-minimal = (rustPackage {
|
||||
version = "-minimal";
|
||||
features = "";
|
||||
|
BIN
konata.png
Normal file
BIN
konata.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 24 KiB |
18
shell.nix
18
shell.nix
@ -1,18 +0,0 @@
|
||||
{ pkgs ? import <nixpkgs> {} }:
|
||||
let
|
||||
devDeps = with pkgs; [
|
||||
pkg-config
|
||||
openssl
|
||||
gtk4
|
||||
pango
|
||||
];
|
||||
in pkgs.mkShell {
|
||||
shellHook = ''
|
||||
export RUST_SRC_PATH=${pkgs.rustPlatform.rustLibSrc}
|
||||
'';
|
||||
buildInputs = devDeps;
|
||||
nativeBuildInputs = with pkgs; [
|
||||
rustc
|
||||
cargo
|
||||
] ++ devDeps;
|
||||
}
|
@ -32,12 +32,12 @@ lazy_static! {
|
||||
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "gtk_gui")] {
|
||||
mod gtk_gui;
|
||||
pub use gtk_gui::*;
|
||||
} else if #[cfg(feature = "pretty_tui")] {
|
||||
if #[cfg(feature = "pretty_tui")] {
|
||||
mod pretty_tui;
|
||||
pub use pretty_tui::*;
|
||||
} else if #[cfg(feature = "gtk_gui")] {
|
||||
mod gtk_gui;
|
||||
pub use gtk_gui::*;
|
||||
} else {
|
||||
mod minimal_tui;
|
||||
pub use minimal_tui::*;
|
||||
|
@ -1,20 +1,26 @@
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use std::time::Duration;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use chrono::Local;
|
||||
use colored::{Color, Colorize};
|
||||
use gtk4::gdk::{Cursor, Display};
|
||||
use gtk4::gdk_pixbuf::PixbufLoader;
|
||||
use gtk4::gio::MenuModel;
|
||||
use gtk4::gdk::{Cursor, Display, Texture};
|
||||
use gtk4::gdk_pixbuf::{Pixbuf, PixbufAnimation, PixbufLoader};
|
||||
use gtk4::gio::{ActionEntry, ApplicationFlags, MemoryInputStream, Menu, MenuItem, MenuModel};
|
||||
use gtk4::glib::clone::Downgrade;
|
||||
use gtk4::{gio, Image, Justification, ListBox, pango::WrapMode};
|
||||
use gtk4::glib::timeout_add_local;
|
||||
use gtk4::glib::{idle_add_local, idle_add_local_once, ControlFlow, source::timeout_add_local_once};
|
||||
use gtk4::{glib, glib::clone, Align, Box as GtkBox, Label, ScrolledWindow};
|
||||
use gtk4::{CssProvider, Entry, Orientation, Overlay, Picture, PopoverMenuBar};
|
||||
use gtk4::{AboutDialog, AlertDialog, ButtonsType, Calendar, CssProvider, Entry, Fixed, License, MessageDialog, MessageType, Orientation, Overlay, Picture, PopoverMenuBar, SelectionMode, Window};
|
||||
use gtk4::prelude::*;
|
||||
use gtk4::{Application, ApplicationWindow, Button};
|
||||
use rand::Rng;
|
||||
use std::sync::mpsc::{channel, Sender, Receiver};
|
||||
use std::error::Error;
|
||||
use std::thread;
|
||||
use std::cell::RefCell;
|
||||
use std::io::Bytes;
|
||||
|
||||
use crate::config::Context;
|
||||
use crate::proto::{connect, read_messages};
|
||||
@ -85,15 +91,217 @@ pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_ui(ctx: Arc<Context>, app: &Application) {
|
||||
fn load_pixbuf(data: &[u8]) -> Pixbuf {
|
||||
let loader = PixbufLoader::new();
|
||||
loader.write(data).unwrap();
|
||||
loader.close().unwrap();
|
||||
loader.pixbuf().unwrap()
|
||||
}
|
||||
|
||||
fn build_menu(ctx: Arc<Context>, app: &Application) {
|
||||
let menu = Menu::new();
|
||||
|
||||
let file_menu = Menu::new();
|
||||
file_menu.append(Some("New File"), Some("app.file_new"));
|
||||
file_menu.append(Some("Make a bottleflip"), Some("app.make_bottleflip"));
|
||||
file_menu.append(Some("Export brain to jpeg"), Some("unavailable"));
|
||||
file_menu.append(Some("About"), Some("app.about"));
|
||||
|
||||
let edit_menu = Menu::new();
|
||||
edit_menu.append(Some("Edit File"), Some("app.file_edit"));
|
||||
edit_menu.append(Some("Create a new parallel reality"), Some("app.parallel_reality_create"));
|
||||
|
||||
menu.append_submenu(Some("File"), &file_menu);
|
||||
menu.append_submenu(Some("Edit"), &edit_menu);
|
||||
|
||||
app.set_menubar(Some((&menu).into()));
|
||||
|
||||
// GtkAlertDialog::builder()
|
||||
// .title("Successful editioning")
|
||||
// .text("your file was edited")
|
||||
// .buttons(ButtonsType::Ok)
|
||||
// .application(&app)
|
||||
// .message_type(MessageType::Info)
|
||||
// .build()
|
||||
// .present();
|
||||
// AlertDialog::builder()
|
||||
// .message("Successful editioning")
|
||||
// .detail("your file was edited")
|
||||
// .buttons(["okey"])
|
||||
// .build()
|
||||
// .present(None);
|
||||
|
||||
app.add_action_entries([
|
||||
ActionEntry::builder("file_new")
|
||||
.activate(move |a: &Application, _, _| {
|
||||
AlertDialog::builder()
|
||||
.message("Successful creatin")
|
||||
.detail("your file was created")
|
||||
.buttons(["ok", "cancel", "confirm", "click"])
|
||||
.build()
|
||||
.show(Some(&a.windows()[0]));
|
||||
}
|
||||
)
|
||||
.build(),
|
||||
ActionEntry::builder("make_bottleflip")
|
||||
.activate(move |a: &Application, _, _| {
|
||||
AlertDialog::builder()
|
||||
.message("Sorry")
|
||||
.detail("bottleflip gone wrong :(")
|
||||
.buttons(["yes", "no"])
|
||||
.build()
|
||||
.show(Some(&a.windows()[0]));
|
||||
}
|
||||
)
|
||||
.build(),
|
||||
ActionEntry::builder("parallel_reality_create")
|
||||
.activate(move |a: &Application, _, _| {
|
||||
AlertDialog::builder()
|
||||
.message("Your new parallel reality has been created")
|
||||
.detail(format!("Your parallel reality code: {}", rand::rng().random_range(1..100)))
|
||||
.buttons(["chocolate"])
|
||||
.build()
|
||||
.show(Some(&a.windows()[0]));
|
||||
}
|
||||
)
|
||||
.build(),
|
||||
ActionEntry::builder("file_edit")
|
||||
.activate(move |a: &Application, _, _| {
|
||||
AlertDialog::builder()
|
||||
.message("Successful editioning")
|
||||
.detail("your file was edited")
|
||||
.buttons(["okey"])
|
||||
.build()
|
||||
.show(Some(&a.windows()[0]));
|
||||
}
|
||||
)
|
||||
.build(),
|
||||
ActionEntry::builder("about")
|
||||
.activate(clone!(
|
||||
#[weak] app,
|
||||
move |_, _, _| {
|
||||
AboutDialog::builder()
|
||||
.application(&app)
|
||||
.authors(["TheMixRay", "MeexReay"])
|
||||
.license(" DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.")
|
||||
.comments("better RAC client")
|
||||
.website("https://github.com/MeexReay/bRAC")
|
||||
.website_label("source code")
|
||||
.logo(&Texture::for_pixbuf(&load_pixbuf(include_bytes!("../../icon.png"))))
|
||||
.build()
|
||||
.present();
|
||||
}
|
||||
))
|
||||
.build()
|
||||
]);
|
||||
}
|
||||
|
||||
fn build_ui(ctx: Arc<Context>, app: &Application) -> UiModel {
|
||||
let main_box = GtkBox::new(Orientation::Vertical, 5);
|
||||
|
||||
let widget_box_overlay = Overlay::new();
|
||||
|
||||
let widget_box = GtkBox::new(Orientation::Horizontal, 5);
|
||||
|
||||
widget_box.set_css_classes(&["widget_box"]);
|
||||
|
||||
widget_box.append(&Calendar::builder()
|
||||
.css_classes(["calendar"])
|
||||
.show_heading(false)
|
||||
.can_target(false)
|
||||
.build());
|
||||
|
||||
let server_list_vbox = GtkBox::new(Orientation::Vertical, 5);
|
||||
|
||||
let server_list = ListBox::new();
|
||||
|
||||
server_list.append(&Label::builder().label("meex.lol:42666").halign(Align::Start).selectable(true).build());
|
||||
server_list.append(&Label::builder().label("meex.lol:11234").halign(Align::Start).selectable(true).build());
|
||||
server_list.append(&Label::builder().label("91.192.22.20:42666").halign(Align::Start).selectable(true).build());
|
||||
|
||||
server_list_vbox.append(&Label::builder().label("Server List:").build());
|
||||
|
||||
server_list_vbox.append(&server_list);
|
||||
|
||||
widget_box.append(&server_list_vbox);
|
||||
|
||||
let fixed = Fixed::new();
|
||||
fixed.set_can_target(false);
|
||||
|
||||
let konata = Picture::for_pixbuf(&load_pixbuf(include_bytes!("../../konata.png")));
|
||||
konata.set_size_request(174, 127);
|
||||
|
||||
fixed.put(&konata, 325.0, 4.0);
|
||||
|
||||
let logo = Picture::for_pixbuf(&load_pixbuf(include_bytes!("../../logo.gif")));
|
||||
logo.set_size_request(152, 64);
|
||||
|
||||
let logo_anim = PixbufAnimation::from_stream(
|
||||
&MemoryInputStream::from_bytes(
|
||||
&glib::Bytes::from(include_bytes!("../../logo.gif"))
|
||||
),
|
||||
None::<&gio::Cancellable>
|
||||
).unwrap().iter(Some(SystemTime::now()));
|
||||
|
||||
timeout_add_local(Duration::from_millis(30), {
|
||||
let logo = logo.clone();
|
||||
let logo_anim = logo_anim.clone();
|
||||
|
||||
move || {
|
||||
logo.set_pixbuf(Some(&logo_anim.pixbuf()));
|
||||
logo_anim.advance(SystemTime::now());
|
||||
|
||||
ControlFlow::Continue
|
||||
}
|
||||
});
|
||||
|
||||
fixed.put(&logo, 262.0, 4.0);
|
||||
|
||||
let time = Label::builder()
|
||||
.label(&Local::now().format("%H:%M").to_string())
|
||||
.justify(Justification::Right)
|
||||
.css_classes(["time"])
|
||||
.build();
|
||||
|
||||
timeout_add_local(Duration::from_secs(1), {
|
||||
let time = time.clone();
|
||||
|
||||
move || {
|
||||
time.set_label(&Local::now().format("%H:%M").to_string());
|
||||
|
||||
ControlFlow::Continue
|
||||
}
|
||||
});
|
||||
|
||||
fixed.put(&time, 432.0, 4.0);
|
||||
|
||||
widget_box_overlay.add_overlay(&fixed);
|
||||
|
||||
widget_box_overlay.set_child(Some(&widget_box));
|
||||
|
||||
main_box.append(&widget_box_overlay);
|
||||
|
||||
let chat_box = GtkBox::new(Orientation::Vertical, 2);
|
||||
|
||||
let chat_scrolled = ScrolledWindow::builder()
|
||||
.child(&chat_box)
|
||||
.vexpand(true)
|
||||
.hexpand(true)
|
||||
.margin_bottom(5)
|
||||
.margin_end(5)
|
||||
.margin_start(5)
|
||||
.propagate_natural_height(true)
|
||||
.build();
|
||||
|
||||
@ -101,8 +309,13 @@ fn build_ui(ctx: Arc<Context>, app: &Application) {
|
||||
|
||||
let send_box = GtkBox::new(Orientation::Horizontal, 5);
|
||||
|
||||
send_box.set_margin_bottom(5);
|
||||
send_box.set_margin_end(5);
|
||||
send_box.set_margin_start(5);
|
||||
|
||||
let text_entry = Entry::builder()
|
||||
.placeholder_text("Message")
|
||||
.css_classes(["send-button"])
|
||||
.hexpand(true)
|
||||
.build();
|
||||
|
||||
@ -110,6 +323,7 @@ fn build_ui(ctx: Arc<Context>, app: &Application) {
|
||||
|
||||
let send_btn = Button::builder()
|
||||
.label("Send")
|
||||
.css_classes(["send-text"])
|
||||
.cursor(&Cursor::from_name("pointer", None).unwrap())
|
||||
.build();
|
||||
|
||||
@ -168,25 +382,14 @@ fn build_ui(ctx: Arc<Context>, app: &Application) {
|
||||
}
|
||||
});
|
||||
|
||||
let overlay = Overlay::new();
|
||||
// let logo = Picture::for_pixbuf(&load_pixbuf(include_bytes!("../../brac_logo.png")));
|
||||
// logo.set_size_request(500, 189);
|
||||
// logo.set_can_target(false);
|
||||
// logo.set_can_focus(false);
|
||||
// logo.set_halign(Align::End);
|
||||
// logo.set_valign(Align::Start);
|
||||
// overlay.add_overlay(&logo);
|
||||
|
||||
overlay.set_child(Some(&main_box));
|
||||
|
||||
let bytes = include_bytes!("../../brac_logo.png");
|
||||
let loader = PixbufLoader::new();
|
||||
loader.write(bytes).unwrap();
|
||||
loader.close().unwrap();
|
||||
let pixbuf = loader.pixbuf().unwrap();
|
||||
|
||||
let logo = Picture::for_pixbuf(&pixbuf);
|
||||
logo.set_size_request(500, 189);
|
||||
logo.set_can_target(false);
|
||||
logo.set_can_focus(false);
|
||||
logo.set_halign(Align::End);
|
||||
logo.set_valign(Align::Start);
|
||||
|
||||
overlay.add_overlay(&logo);
|
||||
|
||||
let window = ApplicationWindow::builder()
|
||||
.application(app)
|
||||
.title(format!("bRAC - Connected to {} as {}", &ctx.host, &ctx.name))
|
||||
@ -195,7 +398,7 @@ fn build_ui(ctx: Arc<Context>, app: &Application) {
|
||||
.resizable(false)
|
||||
.decorated(true)
|
||||
.show_menubar(true)
|
||||
.child(&overlay)
|
||||
.child(&main_box)
|
||||
.build();
|
||||
|
||||
window.connect_default_width_notify({
|
||||
@ -212,15 +415,12 @@ fn build_ui(ctx: Arc<Context>, app: &Application) {
|
||||
}
|
||||
});
|
||||
|
||||
window.show();
|
||||
window.present();
|
||||
|
||||
let ui = UiModel {
|
||||
UiModel {
|
||||
chat_scrolled,
|
||||
chat_box
|
||||
};
|
||||
|
||||
setup(ctx.clone(), ui);
|
||||
load_css();
|
||||
}
|
||||
}
|
||||
|
||||
fn setup(ctx: Arc<Context>, ui: UiModel) {
|
||||
@ -273,91 +473,42 @@ fn setup(ctx: Arc<Context>, ui: UiModel) {
|
||||
fn load_css() {
|
||||
let provider = CssProvider::new();
|
||||
provider.load_from_data("
|
||||
|
||||
* {
|
||||
border-radius: 0;
|
||||
.send-button, .send-text { border-radius: 0; }
|
||||
.calendar {
|
||||
transform: scale(0.6);
|
||||
margin: -35px;
|
||||
}
|
||||
|
||||
.message-content {
|
||||
color: #000000;
|
||||
.widget_box {
|
||||
box-shadow: 0 10px 10px rgba(0, 0, 0, 0.20);
|
||||
border-bottom: 2px solid rgba(0, 0, 0, 0.20);
|
||||
}
|
||||
|
||||
.message-date {
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.message-ip {
|
||||
color: #777777;
|
||||
}
|
||||
|
||||
.message-name {
|
||||
.time {
|
||||
font-size: 20px;
|
||||
font-family: monospace;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.message-name-black {
|
||||
color: #2E2E2E; /* Темный черный */
|
||||
}
|
||||
|
||||
.message-name-red {
|
||||
color: #8B0000; /* Темный красный */
|
||||
}
|
||||
|
||||
.message-name-green {
|
||||
color: #006400; /* Темный зеленый */
|
||||
}
|
||||
|
||||
.message-name-yellow {
|
||||
color: #8B8B00; /* Темный желтый */
|
||||
}
|
||||
|
||||
.message-name-blue {
|
||||
color: #00008B; /* Темный синий */
|
||||
}
|
||||
|
||||
.message-name-magenta {
|
||||
color: #8B008B; /* Темный пурпурный */
|
||||
}
|
||||
|
||||
.message-name-cyan {
|
||||
color: #008B8B; /* Темный бирюзовый */
|
||||
}
|
||||
|
||||
.message-name-white {
|
||||
color: #A9A9A9; /* Темный белый */
|
||||
}
|
||||
|
||||
.message-name-bright-black {
|
||||
color: #555555; /* Яркий черный */
|
||||
}
|
||||
|
||||
.message-name-bright-red {
|
||||
color: #FF0000; /* Яркий красный */
|
||||
}
|
||||
|
||||
.message-name-bright-green {
|
||||
color: #00FF00; /* Яркий зеленый */
|
||||
}
|
||||
|
||||
.message-name-bright-yellow {
|
||||
color: #FFFF00; /* Яркий желтый */
|
||||
}
|
||||
|
||||
.message-name-bright-blue {
|
||||
color: #0000FF; /* Яркий синий */
|
||||
}
|
||||
|
||||
.message-name-bright-magenta {
|
||||
color: #FF00FF; /* Яркий пурпурный */
|
||||
}
|
||||
|
||||
.message-name-bright-cyan {
|
||||
color: #00FFFF; /* Яркий бирюзовый */
|
||||
}
|
||||
|
||||
.message-name-bright-white {
|
||||
color: #FFFFFF; /* Яркий белый */
|
||||
}
|
||||
.message-content { color:rgb(255, 255, 255); }
|
||||
.message-date { color:rgb(146, 146, 146); }
|
||||
.message-ip { color:rgb(73, 73, 73); }
|
||||
.message-name { font-weight: bold; }
|
||||
|
||||
.message-name-black { color: #2E2E2E; }
|
||||
.message-name-bright-black { color: #555555; }
|
||||
.message-name-red { color: #8B0000; }
|
||||
.message-name-bright-red { color: #FF0000; }
|
||||
.message-name-green { color: #006400; }
|
||||
.message-name-bright-green { color: #00FF00; }
|
||||
.message-name-yellow { color: #8B8B00; }
|
||||
.message-name-bright-yellow { color: #FFFF00; }
|
||||
.message-name-blue { color: #00008B; }
|
||||
.message-name-bright-blue { color: #0000FF; }
|
||||
.message-name-bright-magenta { color: #FF00FF; }
|
||||
.message-name-magenta { color: #8B008B; }
|
||||
.message-name-cyan { color: #008B8B; }
|
||||
.message-name-bright-cyan { color: #00FFFF; }
|
||||
.message-name-white { color: #A9A9A9; }
|
||||
.message-name-bright-white { color: #FFFFFF; }
|
||||
");
|
||||
|
||||
gtk4::style_context_add_provider_for_display(
|
||||
@ -382,6 +533,9 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String) {
|
||||
.margin_end(10)
|
||||
.halign(Align::Start)
|
||||
.css_classes(["message-ip"])
|
||||
.selectable(true)
|
||||
.wrap(true)
|
||||
.wrap_mode(WrapMode::Char)
|
||||
.build();
|
||||
|
||||
hbox.append(&ip);
|
||||
@ -392,6 +546,9 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String) {
|
||||
.label(format!("[{date}]"))
|
||||
.halign(Align::Start)
|
||||
.css_classes(["message-date"])
|
||||
.selectable(true)
|
||||
.wrap(true)
|
||||
.wrap_mode(WrapMode::Char)
|
||||
.build();
|
||||
|
||||
hbox.append(&date);
|
||||
@ -421,6 +578,9 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String) {
|
||||
.label(format!("<{name}>"))
|
||||
.halign(Align::Start)
|
||||
.css_classes(["message-name", &format!("message-name-{}", color)])
|
||||
.selectable(true)
|
||||
.wrap(true)
|
||||
.wrap_mode(WrapMode::Char)
|
||||
.build();
|
||||
|
||||
hbox.append(&name);
|
||||
@ -430,6 +590,9 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String) {
|
||||
.label(content)
|
||||
.halign(Align::Start)
|
||||
.css_classes(["message-content"])
|
||||
.selectable(true)
|
||||
.wrap(true)
|
||||
.wrap_mode(WrapMode::Char)
|
||||
.build();
|
||||
|
||||
hbox.append(&content);
|
||||
@ -438,6 +601,9 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String) {
|
||||
.label(message)
|
||||
.halign(Align::Start)
|
||||
.css_classes(["message-content"])
|
||||
.selectable(true)
|
||||
.wrap(true)
|
||||
.wrap_mode(WrapMode::Char)
|
||||
.build();
|
||||
|
||||
hbox.append(&content);
|
||||
@ -445,28 +611,40 @@ fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String) {
|
||||
|
||||
ui.chat_box.append(&hbox);
|
||||
|
||||
timeout_add_local_once(Duration::from_millis(100), move || {
|
||||
timeout_add_local_once(Duration::from_millis(1000), move || {
|
||||
GLOBAL.with(|global| {
|
||||
if let Some((ui, _)) = &*global.borrow() {
|
||||
let o = &ui.chat_scrolled;
|
||||
o.vadjustment().set_value(o.vadjustment().upper() - o.vadjustment().page_size());
|
||||
}
|
||||
});
|
||||
println!("12s3");
|
||||
});
|
||||
}
|
||||
|
||||
pub fn run_main_loop(ctx: Arc<Context>) {
|
||||
let application = Application::builder()
|
||||
.application_id("ru.themixray.bRAC")
|
||||
.flags(ApplicationFlags::empty())
|
||||
.build();
|
||||
|
||||
application.connect_activate({
|
||||
let ctx = ctx.clone();
|
||||
|
||||
move |app| {
|
||||
build_ui(ctx.clone(), app);
|
||||
let ui = build_ui(ctx.clone(), app);
|
||||
setup(ctx.clone(), ui);
|
||||
load_css();
|
||||
}
|
||||
});
|
||||
|
||||
application.run();
|
||||
application.connect_startup({
|
||||
let ctx = ctx.clone();
|
||||
|
||||
move |app| {
|
||||
build_menu(ctx.clone(), app);
|
||||
}
|
||||
});
|
||||
|
||||
application.run_with_args::<&str>(&[]);
|
||||
}
|
Loading…
Reference in New Issue
Block a user