mirror of
https://github.com/MeexReay/bRAC.git
synced 2025-05-06 13:38:04 +03:00
gtk gui
This commit is contained in:
parent
b99311bd7c
commit
440d6c72d8
617
Cargo.lock
generated
617
Cargo.lock
generated
@ -2,6 +2,21 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "addr2line"
|
||||||
|
version = "0.24.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||||
|
dependencies = [
|
||||||
|
"gimli",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "adler2"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aho-corasick"
|
name = "aho-corasick"
|
||||||
version = "1.1.3"
|
version = "1.1.3"
|
||||||
@ -77,9 +92,11 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
|
|||||||
name = "bRAC"
|
name = "bRAC"
|
||||||
version = "0.1.2+2.0"
|
version = "0.1.2+2.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
"clap",
|
"clap",
|
||||||
"colored",
|
"colored",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
|
"gtk4",
|
||||||
"homedir",
|
"homedir",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"native-tls",
|
"native-tls",
|
||||||
@ -87,6 +104,22 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_yml",
|
"serde_yml",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "backtrace"
|
||||||
|
version = "0.3.74"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
|
||||||
|
dependencies = [
|
||||||
|
"addr2line",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"miniz_oxide",
|
||||||
|
"object",
|
||||||
|
"rustc-demangle",
|
||||||
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -101,6 +134,35 @@ version = "1.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytes"
|
||||||
|
version = "1.10.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cairo-rs"
|
||||||
|
version = "0.20.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ae50b5510d86cf96ac2370e66d8dc960882f3df179d6a5a1e52bd94a1416c0f7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cairo-sys-rs",
|
||||||
|
"glib",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cairo-sys-rs"
|
||||||
|
version = "0.20.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f18b6bb8e43c7eb0f2aac7976afe0c61b6f5fc2ab7bc4c139537ea56c92290df"
|
||||||
|
dependencies = [
|
||||||
|
"glib-sys",
|
||||||
|
"libc",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.13"
|
version = "1.2.13"
|
||||||
@ -110,6 +172,16 @@ dependencies = [
|
|||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-expr"
|
||||||
|
version = "0.17.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d4ba6e40bd1184518716a6e1a781bf9160e286d219ccdb8ab2612e74cfe4789"
|
||||||
|
dependencies = [
|
||||||
|
"smallvec",
|
||||||
|
"target-lexicon",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -281,6 +353,16 @@ version = "2.3.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "field-offset"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f"
|
||||||
|
dependencies = [
|
||||||
|
"memoffset",
|
||||||
|
"rustc_version",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foreign-types"
|
name = "foreign-types"
|
||||||
version = "0.3.2"
|
version = "0.3.2"
|
||||||
@ -296,6 +378,126 @@ version = "0.1.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-executor"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-task",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gdk-pixbuf"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7563afd6ff0a221edfbb70a78add5075b8d9cb48e637a40a24c3ece3fea414d0"
|
||||||
|
dependencies = [
|
||||||
|
"gdk-pixbuf-sys",
|
||||||
|
"gio",
|
||||||
|
"glib",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gdk-pixbuf-sys"
|
||||||
|
version = "0.20.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "67f2587c9202bf997476bbba6aaed4f78a11538a2567df002a5f57f5331d0b5c"
|
||||||
|
dependencies = [
|
||||||
|
"gio-sys",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"libc",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gdk4"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4850c9d9c1aecd1a3eb14fadc1cdb0ac0a2298037e116264c7473e1740a32d60"
|
||||||
|
dependencies = [
|
||||||
|
"cairo-rs",
|
||||||
|
"gdk-pixbuf",
|
||||||
|
"gdk4-sys",
|
||||||
|
"gio",
|
||||||
|
"glib",
|
||||||
|
"libc",
|
||||||
|
"pango",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gdk4-sys"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f6eb95798e2b46f279cf59005daf297d5b69555428f185650d71974a910473a"
|
||||||
|
dependencies = [
|
||||||
|
"cairo-sys-rs",
|
||||||
|
"gdk-pixbuf-sys",
|
||||||
|
"gio-sys",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"libc",
|
||||||
|
"pango-sys",
|
||||||
|
"pkg-config",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
@ -308,6 +510,203 @@ dependencies = [
|
|||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gimli"
|
||||||
|
version = "0.31.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gio"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4f00c70f8029d84ea7572dd0e1aaa79e5329667b4c17f329d79ffb1e6277487"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-util",
|
||||||
|
"gio-sys",
|
||||||
|
"glib",
|
||||||
|
"libc",
|
||||||
|
"pin-project-lite",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gio-sys"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "160eb5250a26998c3e1b54e6a3d4ea15c6c7762a6062a19a7b63eff6e2b33f9e"
|
||||||
|
dependencies = [
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"libc",
|
||||||
|
"system-deps",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glib"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "707b819af8059ee5395a2de9f2317d87a53dbad8846a2f089f0bb44703f37686"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
"gio-sys",
|
||||||
|
"glib-macros",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"libc",
|
||||||
|
"memchr",
|
||||||
|
"smallvec",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glib-macros"
|
||||||
|
version = "0.20.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "715601f8f02e71baef9c1f94a657a9a77c192aea6097cf9ae7e5e177cd8cde68"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "glib-sys"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a8928869a44cfdd1fccb17d6746e4ff82c8f82e41ce705aa026a52ca8dc3aefb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gobject-sys"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c773a3cb38a419ad9c26c81d177d96b4b08980e8bdbbf32dace883e96e96e7e3"
|
||||||
|
dependencies = [
|
||||||
|
"glib-sys",
|
||||||
|
"libc",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "graphene-rs"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3cbc5911bfb32d68dcfa92c9510c462696c2f715548fcd7f3f1be424c739de19"
|
||||||
|
dependencies = [
|
||||||
|
"glib",
|
||||||
|
"graphene-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "graphene-sys"
|
||||||
|
version = "0.20.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "11a68d39515bf340e879b72cecd4a25c1332557757ada6e8aba8654b4b81d23a"
|
||||||
|
dependencies = [
|
||||||
|
"glib-sys",
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gsk4"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61f5e72f931c8c9f65fbfc89fe0ddc7746f147f822f127a53a9854666ac1f855"
|
||||||
|
dependencies = [
|
||||||
|
"cairo-rs",
|
||||||
|
"gdk4",
|
||||||
|
"glib",
|
||||||
|
"graphene-rs",
|
||||||
|
"gsk4-sys",
|
||||||
|
"libc",
|
||||||
|
"pango",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gsk4-sys"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "755059de55fa6f85a46bde8caf03e2184c96bfda1f6206163c72fb0ea12436dc"
|
||||||
|
dependencies = [
|
||||||
|
"cairo-sys-rs",
|
||||||
|
"gdk4-sys",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"graphene-sys",
|
||||||
|
"libc",
|
||||||
|
"pango-sys",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gtk4"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af1c491051f030994fd0cde6f3c44f3f5640210308cff1298c7673c47408091d"
|
||||||
|
dependencies = [
|
||||||
|
"cairo-rs",
|
||||||
|
"field-offset",
|
||||||
|
"futures-channel",
|
||||||
|
"gdk-pixbuf",
|
||||||
|
"gdk4",
|
||||||
|
"gio",
|
||||||
|
"glib",
|
||||||
|
"graphene-rs",
|
||||||
|
"gsk4",
|
||||||
|
"gtk4-macros",
|
||||||
|
"gtk4-sys",
|
||||||
|
"libc",
|
||||||
|
"pango",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gtk4-macros"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ed1786c4703dd196baf7e103525ce0cf579b3a63a0570fe653b7ee6bac33999"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gtk4-sys"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "41e03b01e54d77c310e1d98647d73f996d04b2f29b9121fe493ea525a7ec03d6"
|
||||||
|
dependencies = [
|
||||||
|
"cairo-sys-rs",
|
||||||
|
"gdk-pixbuf-sys",
|
||||||
|
"gdk4-sys",
|
||||||
|
"gio-sys",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"graphene-sys",
|
||||||
|
"gsk4-sys",
|
||||||
|
"libc",
|
||||||
|
"pango-sys",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.2"
|
version = "0.15.2"
|
||||||
@ -416,6 +815,24 @@ version = "2.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.8.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||||
|
dependencies = [
|
||||||
|
"adler2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.0.3"
|
version = "1.0.3"
|
||||||
@ -457,6 +874,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "object"
|
||||||
|
version = "0.36.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.20.3"
|
version = "1.20.3"
|
||||||
@ -507,6 +933,30 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pango"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b1f5dc1b8cf9bc08bfc0843a04ee0fa2e78f1e1fa4b126844a383af4f25f0ec"
|
||||||
|
dependencies = [
|
||||||
|
"gio",
|
||||||
|
"glib",
|
||||||
|
"libc",
|
||||||
|
"pango-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pango-sys"
|
||||||
|
version = "0.20.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dbb9b751673bd8fe49eb78620547973a1e719ed431372122b20abd12445bab5"
|
||||||
|
dependencies = [
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"libc",
|
||||||
|
"system-deps",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -530,6 +980,18 @@ dependencies = [
|
|||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-project-lite"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pkg-config"
|
name = "pkg-config"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
@ -545,6 +1007,15 @@ dependencies = [
|
|||||||
"zerocopy 0.7.35",
|
"zerocopy 0.7.35",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-crate"
|
||||||
|
version = "3.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
|
||||||
|
dependencies = [
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.93"
|
version = "1.0.93"
|
||||||
@ -632,6 +1103,21 @@ version = "0.8.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-demangle"
|
||||||
|
version = "0.1.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_version"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
|
||||||
|
dependencies = [
|
||||||
|
"semver",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.44"
|
version = "0.38.44"
|
||||||
@ -702,6 +1188,12 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "semver"
|
||||||
|
version = "1.0.26"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.219"
|
version = "1.0.219"
|
||||||
@ -722,6 +1214,15 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_spanned"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_yml"
|
name = "serde_yml"
|
||||||
version = "0.0.12"
|
version = "0.0.12"
|
||||||
@ -773,12 +1274,31 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.2"
|
version = "1.13.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "socket2"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "strsim"
|
name = "strsim"
|
||||||
version = "0.11.1"
|
version = "0.11.1"
|
||||||
@ -796,6 +1316,25 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "system-deps"
|
||||||
|
version = "7.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "66d23aaf9f331227789a99e8de4c91bf46703add012bdfd45fdecdfb2975a005"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-expr",
|
||||||
|
"heck",
|
||||||
|
"pkg-config",
|
||||||
|
"toml",
|
||||||
|
"version-compare",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "target-lexicon"
|
||||||
|
version = "0.12.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.16.0"
|
version = "3.16.0"
|
||||||
@ -810,6 +1349,69 @@ dependencies = [
|
|||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio"
|
||||||
|
version = "1.44.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
|
||||||
|
dependencies = [
|
||||||
|
"backtrace",
|
||||||
|
"bytes",
|
||||||
|
"libc",
|
||||||
|
"mio",
|
||||||
|
"parking_lot",
|
||||||
|
"pin-project-lite",
|
||||||
|
"signal-hook-registry",
|
||||||
|
"socket2",
|
||||||
|
"tokio-macros",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-macros"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.8.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_datetime"
|
||||||
|
version = "0.6.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.22.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap",
|
||||||
|
"serde",
|
||||||
|
"serde_spanned",
|
||||||
|
"toml_datetime",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.16"
|
version = "1.0.16"
|
||||||
@ -834,6 +1436,12 @@ version = "0.2.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "version-compare"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
@ -1018,6 +1626,15 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winnow"
|
||||||
|
version = "0.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen-rt"
|
name = "wit-bindgen-rt"
|
||||||
version = "0.33.0"
|
version = "0.33.0"
|
||||||
|
10
Cargo.toml
10
Cargo.toml
@ -14,9 +14,13 @@ serde_yml = "0.0.12"
|
|||||||
crossterm = { version = "0.29.0", optional = true }
|
crossterm = { version = "0.29.0", optional = true }
|
||||||
homedir = { version = "0.3.4", optional = true }
|
homedir = { version = "0.3.4", optional = true }
|
||||||
native-tls = { version = "0.2.14", optional = true }
|
native-tls = { version = "0.2.14", optional = true }
|
||||||
|
gtk4 = { version = "0.9.6", optional = true }
|
||||||
|
cfg-if = "1.0.0"
|
||||||
|
tokio = { version = "1.44.2", optional = true, features = [ "full" ] }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["ssl", "pretty", "homedir"]
|
default = ["ssl", "homedir", "gtk_gui"]
|
||||||
ssl = ["dep:native-tls"]
|
ssl = ["dep:native-tls"]
|
||||||
pretty = ["dep:crossterm"]
|
pretty_tui = ["dep:crossterm"]
|
||||||
homedir = ["dep:homedir"]
|
gtk_gui = ["dep:gtk4"]
|
||||||
|
homedir = ["dep:homedir", "dep:tokio"]
|
||||||
|
BIN
brac_logo.png
Normal file
BIN
brac_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 95 KiB |
@ -59,6 +59,11 @@
|
|||||||
features = "default";
|
features = "default";
|
||||||
deps = with pkgs; [ pkg-config openssl ];
|
deps = with pkgs; [ pkg-config openssl ];
|
||||||
});
|
});
|
||||||
|
packages.bRAC-gtk = (rustPackage {
|
||||||
|
version = "-gtk";
|
||||||
|
features = "default gtk_gui";
|
||||||
|
deps = with pkgs; [ pkg-config openssl gtk4 pango ];
|
||||||
|
});
|
||||||
packages.bRAC-minimal = (rustPackage {
|
packages.bRAC-minimal = (rustPackage {
|
||||||
version = "-minimal";
|
version = "-minimal";
|
||||||
features = "";
|
features = "";
|
||||||
|
120
src/chat.rs
120
src/chat.rs
@ -16,6 +16,7 @@ use super::{
|
|||||||
|
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
|
use cfg_if::cfg_if;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref DATE_REGEX: Regex = Regex::new(r"\[(.*?)\] (.*)").unwrap();
|
pub static ref DATE_REGEX: Regex = Regex::new(r"\[(.*?)\] (.*)").unwrap();
|
||||||
@ -29,15 +30,19 @@ lazy_static! {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "pretty"))]
|
|
||||||
pub mod minimal_tui;
|
|
||||||
#[cfg(not(feature = "pretty"))]
|
|
||||||
pub use minimal_tui::{run_main_loop, update_console};
|
|
||||||
|
|
||||||
#[cfg(feature = "pretty")]
|
cfg_if! {
|
||||||
pub mod pretty_tui;
|
if #[cfg(feature = "gtk_gui")] {
|
||||||
#[cfg(feature = "pretty")]
|
mod gtk_gui;
|
||||||
pub use pretty_tui::{run_main_loop, update_console};
|
pub use gtk_gui::*;
|
||||||
|
} else if #[cfg(feature = "pretty_tui")] {
|
||||||
|
mod pretty_tui;
|
||||||
|
pub use pretty_tui::*;
|
||||||
|
} else {
|
||||||
|
mod minimal_tui;
|
||||||
|
pub use minimal_tui::*;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct ChatStorage {
|
pub struct ChatStorage {
|
||||||
@ -94,11 +99,11 @@ const HELP_MESSAGE: &str = "Help message:
|
|||||||
|
|
||||||
|
|
||||||
pub fn add_message(ctx: Arc<Context>, message: &str) -> Result<(), Box<dyn Error>> {
|
pub fn add_message(ctx: Arc<Context>, message: &str) -> Result<(), Box<dyn Error>> {
|
||||||
ctx.messages.append(
|
for i in message.split("\n")
|
||||||
ctx.max_messages,
|
.map(|o| o.to_string()) {
|
||||||
message.split("\n").map(|o| o.to_string()).collect::<Vec<String>>()
|
print_message(ctx.clone(), i)?;
|
||||||
);
|
}
|
||||||
update_console(ctx)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>> {
|
pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>> {
|
||||||
@ -130,7 +135,7 @@ pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>
|
|||||||
match register_user(&mut connect(&ctx.host, ctx.enable_ssl)?, &ctx.name, pass) {
|
match register_user(&mut connect(&ctx.host, ctx.enable_ssl)?, &ctx.name, pass) {
|
||||||
Ok(true) => {
|
Ok(true) => {
|
||||||
add_message(ctx.clone(), "you was registered successfully bro")?;
|
add_message(ctx.clone(), "you was registered successfully bro")?;
|
||||||
*ctx.registered.write().unwrap() = Some(pass.to_string());
|
*ctx.chat().registered.write().unwrap() = Some(pass.to_string());
|
||||||
},
|
},
|
||||||
Ok(false) => add_message(ctx.clone(), "user with this account already exists bruh")?,
|
Ok(false) => add_message(ctx.clone(), "user with this account already exists bruh")?,
|
||||||
Err(e) => add_message(ctx.clone(), &format!("ERROR while registrationing: {}", e))?
|
Err(e) => add_message(ctx.clone(), &format!("ERROR while registrationing: {}", e))?
|
||||||
@ -142,9 +147,9 @@ pub fn on_command(ctx: Arc<Context>, command: &str) -> Result<(), Box<dyn Error>
|
|||||||
};
|
};
|
||||||
|
|
||||||
add_message(ctx.clone(), "ye bro you was logged in")?;
|
add_message(ctx.clone(), "ye bro you was logged in")?;
|
||||||
*ctx.registered.write().unwrap() = Some(pass.to_string());
|
*ctx.chat().registered.write().unwrap() = Some(pass.to_string());
|
||||||
} else if command == "ping" {
|
} else if command == "ping" {
|
||||||
let mut before = ctx.messages.packet_size();
|
let mut before = ctx.chat().messages.packet_size();
|
||||||
let message = format!("Checking ping... {:X}", SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis());
|
let message = format!("Checking ping... {:X}", SystemTime::now().duration_since(UNIX_EPOCH)?.as_millis());
|
||||||
|
|
||||||
send_message(&mut connect(&ctx.host, ctx.enable_ssl)?, &message)?;
|
send_message(&mut connect(&ctx.host, ctx.enable_ssl)?, &message)?;
|
||||||
@ -218,7 +223,7 @@ pub fn on_send_message(ctx: Arc<Context>, message: &str) -> Result<(), Box<dyn E
|
|||||||
.replace("{text}", &message)
|
.replace("{text}", &message)
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(password) = ctx.registered.read().unwrap().clone() {
|
if let Some(password) = ctx.chat().registered.read().unwrap().clone() {
|
||||||
send_message_auth(&mut connect(&ctx.host, ctx.enable_ssl)?, &ctx.name, &password, &message)?;
|
send_message_auth(&mut connect(&ctx.host, ctx.enable_ssl)?, &ctx.name, &password, &message)?;
|
||||||
} else if ctx.enable_auth {
|
} else if ctx.enable_auth {
|
||||||
send_message_spoof_auth(&mut connect(&ctx.host, ctx.enable_ssl)?, &message)?;
|
send_message_spoof_auth(&mut connect(&ctx.host, ctx.enable_ssl)?, &message)?;
|
||||||
@ -230,16 +235,21 @@ pub fn on_send_message(ctx: Arc<Context>, message: &str) -> Result<(), Box<dyn E
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn format_message(enable_ip_viewing: bool, message: String) -> Option<String> {
|
/// message -> (date, ip, text)
|
||||||
if message.is_empty() {
|
pub fn parse_message(message: String) -> Option<(String, Option<String>, String, Option<(String, Color)>)> {
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(
|
|
||||||
{
|
|
||||||
let message = message.clone();
|
|
||||||
move || -> Option<String> {
|
|
||||||
let message = sanitize_text(&message);
|
let message = sanitize_text(&message);
|
||||||
|
|
||||||
|
let message = message
|
||||||
|
.trim_start_matches("(UNREGISTERED)")
|
||||||
|
.trim_start_matches("(UNAUTHORIZED)")
|
||||||
|
.trim_start_matches("(UNAUTHENTICATED)")
|
||||||
|
.trim()
|
||||||
|
.to_string()+" ";
|
||||||
|
|
||||||
|
if message.is_empty() {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
|
||||||
let date = DATE_REGEX.captures(&message)?;
|
let date = DATE_REGEX.captures(&message)?;
|
||||||
let (date, message) = (
|
let (date, message) = (
|
||||||
date.get(1)?.as_str().to_string(),
|
date.get(1)?.as_str().to_string(),
|
||||||
@ -252,14 +262,19 @@ pub fn format_message(enable_ip_viewing: bool, message: String) -> Option<String
|
|||||||
(None, message)
|
(None, message)
|
||||||
};
|
};
|
||||||
|
|
||||||
let message = message
|
let (message, nick) = match find_username_color(&message) {
|
||||||
.trim_start_matches("(UNREGISTERED)")
|
Some((name, content, color)) => (content, Some((name, color))),
|
||||||
.trim_start_matches("(UNAUTHORIZED)")
|
None => (message, None),
|
||||||
.trim_start_matches("(UNAUTHENTICATED)")
|
};
|
||||||
.trim()
|
|
||||||
.to_string()+" ";
|
|
||||||
|
|
||||||
let prefix = if enable_ip_viewing {
|
Some((date, ip, message, nick))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn format_message(enable_ip_viewing: bool, message: String) -> Option<String> {
|
||||||
|
if let Some((date, ip, content, nick)) = parse_message(message.clone()) {
|
||||||
|
Some(format!(
|
||||||
|
"{} {}{}",
|
||||||
|
if enable_ip_viewing {
|
||||||
if let Some(ip) = ip {
|
if let Some(ip) = ip {
|
||||||
format!("{}{} [{}]", ip, " ".repeat(if 15 >= ip.chars().count() {15-ip.chars().count()} else {0}), date)
|
format!("{}{} [{}]", ip, " ".repeat(if 15 >= ip.chars().count() {15-ip.chars().count()} else {0}), date)
|
||||||
} else {
|
} else {
|
||||||
@ -267,36 +282,23 @@ pub fn format_message(enable_ip_viewing: bool, message: String) -> Option<String
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
format!("[{}]", date)
|
format!("[{}]", date)
|
||||||
};
|
}.white().dimmed(),
|
||||||
|
nick.map(|(name, color)|
|
||||||
Some(if let Some(captures) = find_username_color(&message) {
|
format!("<{}> ", name)
|
||||||
let nick = captures.0;
|
.color(color)
|
||||||
let content = captures.1;
|
.bold()
|
||||||
let color = captures.2;
|
.to_string()
|
||||||
|
).unwrap_or_default(),
|
||||||
format!(
|
|
||||||
"{} {} {}",
|
|
||||||
prefix.white().dimmed(),
|
|
||||||
format!("<{}>", nick).color(color).bold(),
|
|
||||||
content.white().blink()
|
content.white().blink()
|
||||||
)
|
))
|
||||||
|
} else if !message.is_empty() {
|
||||||
|
Some(message.bright_white().to_string())
|
||||||
} else {
|
} else {
|
||||||
format!(
|
None
|
||||||
"{} {}",
|
|
||||||
prefix.white().dimmed(),
|
|
||||||
message.white().blink()
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}()
|
|
||||||
}.unwrap_or_else(|| {
|
|
||||||
format!(
|
|
||||||
"{}",
|
|
||||||
message.bright_white()
|
|
||||||
)
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// message -> (nick, content, color)
|
||||||
pub fn find_username_color(message: &str) -> Option<(String, String, Color)> {
|
pub fn find_username_color(message: &str) -> Option<(String, String, Color)> {
|
||||||
for (re, color) in COLORED_USERNAMES.iter() {
|
for (re, color) in COLORED_USERNAMES.iter() {
|
||||||
if let Some(captures) = re.captures(message) {
|
if let Some(captures) = re.captures(message) {
|
||||||
@ -305,3 +307,7 @@ pub fn find_username_color(message: &str) -> Option<(String, String, Color)> {
|
|||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_chat(ctx: Arc<Context>, chat: ChatContext) {
|
||||||
|
*ctx.chat.write().unwrap() = Some(Arc::new(chat));
|
||||||
|
}
|
467
src/chat/gtk_gui.rs
Normal file
467
src/chat/gtk_gui.rs
Normal file
@ -0,0 +1,467 @@
|
|||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use colored::{Color, Colorize};
|
||||||
|
use gtk4::gdk::Display;
|
||||||
|
use gtk4::gdk_pixbuf::PixbufLoader;
|
||||||
|
use gtk4::glib::clone::Downgrade;
|
||||||
|
use gtk4::glib::{idle_add_local, idle_add_local_once, ControlFlow, source::timeout_add_once};
|
||||||
|
use gtk4::{glib, glib::clone, Align, Box as GtkBox, Label, ScrolledWindow};
|
||||||
|
use gtk4::{CssProvider, Entry, Orientation, Overlay, Picture};
|
||||||
|
use gtk4::prelude::*;
|
||||||
|
use gtk4::{Application, ApplicationWindow, Button};
|
||||||
|
use std::sync::mpsc::{channel, Sender, Receiver};
|
||||||
|
use std::error::Error;
|
||||||
|
use std::thread;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
|
||||||
|
use crate::config::Context;
|
||||||
|
use crate::proto::{connect, read_messages};
|
||||||
|
|
||||||
|
use super::{format_message, on_send_message, parse_message, set_chat, ChatStorage};
|
||||||
|
|
||||||
|
|
||||||
|
pub struct ChatContext {
|
||||||
|
pub messages: Arc<ChatStorage>,
|
||||||
|
pub registered: Arc<RwLock<Option<String>>>,
|
||||||
|
pub sender: Sender<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UiModel {
|
||||||
|
chat_box: GtkBox,
|
||||||
|
chat_scrolled: ScrolledWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_chat_message(ctx: Arc<Context>, message: String) {
|
||||||
|
let _ = ctx.chat().sender.send(message);
|
||||||
|
// MainContext::default().invoke_local(move || {
|
||||||
|
// ctx.chat().chat_box.upgrade().unwrap().append(&Label::new(Some(message.as_str())));
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_message(ctx: Arc<Context>, message: String) -> Result<(), Box<dyn Error>> {
|
||||||
|
ctx.chat().messages.append(ctx.max_messages, vec![message.clone()]);
|
||||||
|
add_chat_message(ctx.clone(), message);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
||||||
|
match read_messages(
|
||||||
|
&mut connect(&ctx.host, ctx.enable_ssl)?,
|
||||||
|
ctx.max_messages,
|
||||||
|
ctx.chat().messages.packet_size(),
|
||||||
|
!ctx.enable_ssl,
|
||||||
|
ctx.enable_chunked
|
||||||
|
) {
|
||||||
|
Ok(Some((messages, size))) => {
|
||||||
|
let messages: Vec<String> = if ctx.disable_formatting {
|
||||||
|
messages
|
||||||
|
} else {
|
||||||
|
messages.into_iter().flat_map(|o| format_message(ctx.enable_ip_viewing, o)).collect()
|
||||||
|
};
|
||||||
|
|
||||||
|
if ctx.enable_chunked {
|
||||||
|
ctx.chat().messages.append_and_store(ctx.max_messages, messages.clone(), size);
|
||||||
|
for msg in messages {
|
||||||
|
add_chat_message(ctx.clone(), msg.clone());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx.chat().messages.update(ctx.max_messages, messages.clone(), size);
|
||||||
|
for msg in messages {
|
||||||
|
add_chat_message(ctx.clone(), msg.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
let msg = format!("Read messages error: {}", e.to_string()).bright_red().to_string();
|
||||||
|
ctx.chat().messages.append(ctx.max_messages, vec![msg.clone()]);
|
||||||
|
add_chat_message(ctx.clone(), msg.clone());
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
thread::sleep(Duration::from_millis(ctx.update_time as u64));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_ui(ctx: Arc<Context>, app: &Application) {
|
||||||
|
let main_box = GtkBox::new(Orientation::Vertical, 5);
|
||||||
|
|
||||||
|
main_box.set_margin_bottom(5);
|
||||||
|
main_box.set_margin_end(5);
|
||||||
|
main_box.set_margin_start(5);
|
||||||
|
main_box.set_margin_top(5);
|
||||||
|
|
||||||
|
let chat_box = GtkBox::new(Orientation::Vertical, 2);
|
||||||
|
|
||||||
|
let chat_scrolled = ScrolledWindow::builder()
|
||||||
|
.child(&chat_box)
|
||||||
|
.vexpand(true)
|
||||||
|
.hexpand(true)
|
||||||
|
.propagate_natural_height(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
main_box.append(&chat_scrolled);
|
||||||
|
|
||||||
|
let send_box = GtkBox::new(Orientation::Horizontal, 5);
|
||||||
|
|
||||||
|
let text_entry = Entry::builder()
|
||||||
|
.placeholder_text("Message")
|
||||||
|
.hexpand(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
send_box.append(&text_entry);
|
||||||
|
|
||||||
|
let send_btn = Button::builder()
|
||||||
|
.label("Send")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
send_btn.connect_clicked(clone!(
|
||||||
|
#[weak] text_entry,
|
||||||
|
#[weak] ctx,
|
||||||
|
move |_| {
|
||||||
|
idle_add_local_once(clone!(
|
||||||
|
#[weak] text_entry,
|
||||||
|
move || {
|
||||||
|
text_entry.set_text("");
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
if let Err(e) = on_send_message(ctx.clone(), &text_entry.text()) {
|
||||||
|
let msg = format!("Send message error: {}", e.to_string()).bright_red().to_string();
|
||||||
|
add_chat_message(ctx.clone(), msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
text_entry.connect_activate(clone!(
|
||||||
|
#[weak] text_entry,
|
||||||
|
#[weak] ctx,
|
||||||
|
move |_| {
|
||||||
|
idle_add_local_once(clone!(
|
||||||
|
#[weak] text_entry,
|
||||||
|
move || {
|
||||||
|
text_entry.set_text("");
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
if let Err(e) = on_send_message(ctx.clone(), &text_entry.text()) {
|
||||||
|
let msg = format!("Send message error: {}", e.to_string()).bright_red().to_string();
|
||||||
|
add_chat_message(ctx.clone(), msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
send_box.append(&send_btn);
|
||||||
|
|
||||||
|
main_box.append(&send_box);
|
||||||
|
|
||||||
|
let scrolled_window_weak = Downgrade::downgrade(&chat_scrolled);
|
||||||
|
|
||||||
|
idle_add_local({
|
||||||
|
let scrolled_window_weak = scrolled_window_weak.clone();
|
||||||
|
|
||||||
|
move || {
|
||||||
|
if let Some(o) = scrolled_window_weak.upgrade() {
|
||||||
|
o.vadjustment().set_value(o.vadjustment().upper() - o.vadjustment().page_size());
|
||||||
|
}
|
||||||
|
ControlFlow::Break
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let overlay = Overlay::new();
|
||||||
|
|
||||||
|
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))
|
||||||
|
.default_width(500)
|
||||||
|
.default_height(500)
|
||||||
|
.resizable(false)
|
||||||
|
.decorated(true)
|
||||||
|
.child(&overlay)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
window.connect_default_width_notify({
|
||||||
|
let scrolled_window_weak = scrolled_window_weak.clone();
|
||||||
|
|
||||||
|
move |_| {
|
||||||
|
let scrolled_window_weak = scrolled_window_weak.clone();
|
||||||
|
idle_add_local(move || {
|
||||||
|
if let Some(o) = scrolled_window_weak.upgrade() {
|
||||||
|
o.vadjustment().set_value(o.vadjustment().upper() - o.vadjustment().page_size());
|
||||||
|
}
|
||||||
|
ControlFlow::Break
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
window.show();
|
||||||
|
|
||||||
|
let ui = UiModel {
|
||||||
|
chat_scrolled,
|
||||||
|
chat_box
|
||||||
|
};
|
||||||
|
|
||||||
|
setup(ctx.clone(), ui);
|
||||||
|
load_css();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup(ctx: Arc<Context>, ui: UiModel) {
|
||||||
|
let (sender, receiver) = channel();
|
||||||
|
|
||||||
|
set_chat(ctx.clone(), ChatContext {
|
||||||
|
messages: Arc::new(ChatStorage::new()),
|
||||||
|
registered: Arc::new(RwLock::new(None)),
|
||||||
|
sender
|
||||||
|
});
|
||||||
|
|
||||||
|
thread::spawn({
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
|
||||||
|
move || {
|
||||||
|
loop {
|
||||||
|
if let Err(e) = recv_tick(ctx.clone()) {
|
||||||
|
let _ = print_message(ctx.clone(), format!("Print messages error: {}", e.to_string()).bright_red().to_string());
|
||||||
|
thread::sleep(Duration::from_secs(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let (tx, rx) = channel();
|
||||||
|
|
||||||
|
GLOBAL.with(|global| {
|
||||||
|
*global.borrow_mut() = Some((ui, rx));
|
||||||
|
});
|
||||||
|
|
||||||
|
thread::spawn({
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
move || {
|
||||||
|
while let Ok(message) = receiver.recv() {
|
||||||
|
let _ = tx.send(message.clone());
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
glib::source::timeout_add_once(Duration::ZERO, move || {
|
||||||
|
GLOBAL.with(|global| {
|
||||||
|
if let Some((ui, rx)) = &*global.borrow() {
|
||||||
|
let message: String = rx.recv().unwrap();
|
||||||
|
on_add_message(ctx.clone(), &ui, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_css() {
|
||||||
|
let provider = CssProvider::new();
|
||||||
|
provider.load_from_data("
|
||||||
|
|
||||||
|
.message-content {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-date {
|
||||||
|
color: #AAAAAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-ip {
|
||||||
|
color: #AAAAAA;
|
||||||
|
}
|
||||||
|
|
||||||
|
.message-name {
|
||||||
|
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; /* Яркий белый */
|
||||||
|
}
|
||||||
|
|
||||||
|
");
|
||||||
|
|
||||||
|
gtk4::style_context_add_provider_for_display(
|
||||||
|
&Display::default().expect("Could not connect to a display."),
|
||||||
|
&provider,
|
||||||
|
gtk4::STYLE_PROVIDER_PRIORITY_APPLICATION,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_add_message(ctx: Arc<Context>, ui: &UiModel, message: String) {
|
||||||
|
if let Some((date, ip, content, nick)) = parse_message(message.clone()) {
|
||||||
|
let hbox = GtkBox::new(Orientation::Horizontal, 2);
|
||||||
|
|
||||||
|
if let Some(ip) = ip {
|
||||||
|
if ctx.enable_ip_viewing {
|
||||||
|
let ip = Label::builder()
|
||||||
|
.label(ip)
|
||||||
|
.margin_end(10)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.css_classes(["message-ip"])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
hbox.append(&ip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let date = Label::builder()
|
||||||
|
.label(format!("[{date}]"))
|
||||||
|
.halign(Align::Start)
|
||||||
|
.css_classes(["message-date"])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
hbox.append(&date);
|
||||||
|
|
||||||
|
if let Some((name, color)) = nick {
|
||||||
|
let color = match color {
|
||||||
|
Color::Black => "black",
|
||||||
|
Color::Red => "red",
|
||||||
|
Color::Green => "green",
|
||||||
|
Color::Yellow => "yellow",
|
||||||
|
Color::Blue => "blue",
|
||||||
|
Color::Magenta => "magenta",
|
||||||
|
Color::Cyan => "cyan",
|
||||||
|
Color::White => "white",
|
||||||
|
Color::BrightBlack => "bright-black",
|
||||||
|
Color::BrightRed => "bright-red",
|
||||||
|
Color::BrightGreen => "bright-green",
|
||||||
|
Color::BrightYellow => "bright-yellow",
|
||||||
|
Color::BrightBlue => "bright-blue",
|
||||||
|
Color::BrightMagenta => "bright-magenta",
|
||||||
|
Color::BrightCyan => "bright-cyan",
|
||||||
|
Color::BrightWhite => "bright-white",
|
||||||
|
_ => "unknown"
|
||||||
|
};
|
||||||
|
|
||||||
|
let name = Label::builder()
|
||||||
|
.label(format!("<{name}>"))
|
||||||
|
.halign(Align::Start)
|
||||||
|
.css_classes(["message-name", &format!("message-name-{}", color)])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
hbox.append(&name);
|
||||||
|
}
|
||||||
|
|
||||||
|
let content = Label::builder()
|
||||||
|
.label(content)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.css_classes(["message-content"])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
hbox.append(&content);
|
||||||
|
|
||||||
|
ui.chat_box.append(&hbox);
|
||||||
|
} else {
|
||||||
|
let content = Label::builder()
|
||||||
|
.label(message)
|
||||||
|
.halign(Align::Start)
|
||||||
|
.css_classes(["message-content"])
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ui.chat_box.append(&content);
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout_add_once(Duration::from_millis(10), 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());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run_main_loop(ctx: Arc<Context>) {
|
||||||
|
let application = Application::builder()
|
||||||
|
.application_id("ru.themixray.bRAC")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
application.connect_activate({
|
||||||
|
let ctx = ctx.clone();
|
||||||
|
|
||||||
|
move |app| {
|
||||||
|
build_ui(ctx.clone(), app);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
application.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
thread_local!(
|
||||||
|
static GLOBAL: RefCell<Option<(UiModel, Receiver<String>)>> = RefCell::new(None);
|
||||||
|
);
|
@ -13,7 +13,12 @@ use super::{
|
|||||||
}, format_message, on_send_message
|
}, format_message, on_send_message
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn update_console(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
pub struct ChatContext {
|
||||||
|
pub messages: Arc<ChatStorage>,
|
||||||
|
pub registered: Arc<RwLock<Option<String>>>
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_console(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
||||||
let messages = ctx.messages.messages();
|
let messages = ctx.messages.messages();
|
||||||
|
|
||||||
let mut out = stdout().lock();
|
let mut out = stdout().lock();
|
||||||
@ -33,7 +38,17 @@ pub fn update_console(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn print_message(ctx: Arc<Context>, message: String) -> Result<(), Box<dyn Error>> {
|
||||||
|
ctx.chat().messages.append(ctx.max_messages, vec![message]);
|
||||||
|
update_console(ctx.clone())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn run_main_loop(ctx: Arc<Context>) {
|
pub fn run_main_loop(ctx: Arc<Context>) {
|
||||||
|
set_chat(ctx.clone(), ChatContext {
|
||||||
|
messages: Arc::new(ChatStorage::new()),
|
||||||
|
registered: Arc::new(RwLock::new(None)),
|
||||||
|
});
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match connect(&ctx.host, ctx.enable_ssl) {
|
match connect(&ctx.host, ctx.enable_ssl) {
|
||||||
Ok(mut stream) => {
|
Ok(mut stream) => {
|
||||||
|
@ -10,7 +10,7 @@ use colored::Colorize;
|
|||||||
use std::{
|
use std::{
|
||||||
cmp::{max, min},
|
cmp::{max, min},
|
||||||
error::Error, io::{stdout, Write},
|
error::Error, io::{stdout, Write},
|
||||||
sync::{atomic::Ordering, Arc},
|
sync::{atomic::{AtomicUsize, Ordering}, Arc, RwLock},
|
||||||
thread,
|
thread,
|
||||||
time::Duration
|
time::Duration
|
||||||
};
|
};
|
||||||
@ -20,11 +20,11 @@ use super::{
|
|||||||
config::Context,
|
config::Context,
|
||||||
proto::{connect, read_messages},
|
proto::{connect, read_messages},
|
||||||
util::{char_index_to_byte_index, string_chunks}
|
util::{char_index_to_byte_index, string_chunks}
|
||||||
}, format_message, on_send_message
|
}, format_message, on_send_message, set_chat, ChatStorage
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
pub fn print_console(ctx: Arc<Context>, messages: Vec<String>, input: &str) -> Result<(), Box<dyn Error>> {
|
fn print_console(ctx: Arc<Context>, messages: Vec<String>, input: &str) -> Result<(), Box<dyn Error>> {
|
||||||
let (width, height) = terminal::size()?;
|
let (width, height) = terminal::size()?;
|
||||||
let (width, height) = (width as usize, height as usize);
|
let (width, height) = (width as usize, height as usize);
|
||||||
|
|
||||||
@ -43,7 +43,7 @@ pub fn print_console(ctx: Arc<Context>, messages: Vec<String>, input: &str) -> R
|
|||||||
0
|
0
|
||||||
};
|
};
|
||||||
|
|
||||||
let scroll = min(ctx.scroll.load(Ordering::SeqCst), messages_size);
|
let scroll = min(ctx.chat().scroll.load(Ordering::SeqCst), messages_size);
|
||||||
let scroll_f = ((1f64 - scroll as f64 / (messages_size+1) as f64) * (height-2) as f64).round() as usize+1;
|
let scroll_f = ((1f64 - scroll as f64 / (messages_size+1) as f64) * (height-2) as f64).round() as usize+1;
|
||||||
|
|
||||||
let messages = if height < messages.len() {
|
let messages = if height < messages.len() {
|
||||||
@ -143,8 +143,8 @@ fn poll_events(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
let mut history_cursor: usize = 0;
|
let mut history_cursor: usize = 0;
|
||||||
let mut cursor: usize = 0;
|
let mut cursor: usize = 0;
|
||||||
|
|
||||||
let input = ctx.input.clone();
|
let input = ctx.chat().input.clone();
|
||||||
let messages = ctx.messages.clone();
|
let messages = ctx.chat().messages.clone();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if !event::poll(Duration::from_millis(50)).unwrap_or(false) { continue }
|
if !event::poll(Duration::from_millis(50)).unwrap_or(false) { continue }
|
||||||
@ -171,8 +171,8 @@ fn poll_events(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
|
|
||||||
if let Err(e) = on_send_message(ctx.clone(), &message) {
|
if let Err(e) = on_send_message(ctx.clone(), &message) {
|
||||||
let msg = format!("Send message error: {}", e.to_string()).bright_red().to_string();
|
let msg = format!("Send message error: {}", e.to_string()).bright_red().to_string();
|
||||||
ctx.messages.append(ctx.max_messages, vec![msg]);
|
ctx.chat().messages.append(ctx.max_messages, vec![msg]);
|
||||||
print_console(ctx.clone(), ctx.messages.messages(), &ctx.input.read().unwrap())?;
|
print_console(ctx.clone(), ctx.chat().messages.messages(), &ctx.chat().input.read().unwrap())?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
print_console(
|
print_console(
|
||||||
@ -220,7 +220,11 @@ fn poll_events(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
KeyCode::PageUp => {
|
KeyCode::PageUp => {
|
||||||
let height = terminal::size().unwrap().1 as usize;
|
let height = terminal::size().unwrap().1 as usize;
|
||||||
ctx.scroll.store(min(ctx.scroll.load(Ordering::SeqCst)+height, ctx.messages.messages().len()), Ordering::SeqCst);
|
ctx.chat().scroll.store(min(
|
||||||
|
ctx.chat().scroll.load(Ordering::SeqCst)+height,
|
||||||
|
ctx.chat().messages.messages().len()
|
||||||
|
),
|
||||||
|
Ordering::SeqCst);
|
||||||
print_console(
|
print_console(
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
messages.messages(),
|
messages.messages(),
|
||||||
@ -229,7 +233,11 @@ fn poll_events(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
KeyCode::PageDown => {
|
KeyCode::PageDown => {
|
||||||
let height = terminal::size().unwrap().1 as usize;
|
let height = terminal::size().unwrap().1 as usize;
|
||||||
ctx.scroll.store(max(ctx.scroll.load(Ordering::SeqCst), height)-height, Ordering::SeqCst);
|
ctx.chat().scroll.store(max(
|
||||||
|
ctx.chat().scroll.load(Ordering::SeqCst),
|
||||||
|
height
|
||||||
|
)-height,
|
||||||
|
Ordering::SeqCst);
|
||||||
print_console(
|
print_console(
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
messages.messages(),
|
messages.messages(),
|
||||||
@ -289,7 +297,10 @@ fn poll_events(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
Event::Mouse(data) => {
|
Event::Mouse(data) => {
|
||||||
match data.kind {
|
match data.kind {
|
||||||
MouseEventKind::ScrollUp => {
|
MouseEventKind::ScrollUp => {
|
||||||
ctx.scroll.store(min(ctx.scroll.load(Ordering::SeqCst)+3, ctx.messages.messages().len()), Ordering::SeqCst);
|
ctx.chat().scroll.store(min(
|
||||||
|
ctx.chat().scroll.load(Ordering::SeqCst)+3,
|
||||||
|
ctx.chat().messages.messages().len()
|
||||||
|
), Ordering::SeqCst);
|
||||||
print_console(
|
print_console(
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
messages.messages(),
|
messages.messages(),
|
||||||
@ -297,7 +308,7 @@ fn poll_events(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
)?;
|
)?;
|
||||||
},
|
},
|
||||||
MouseEventKind::ScrollDown => {
|
MouseEventKind::ScrollDown => {
|
||||||
ctx.scroll.store(max(ctx.scroll.load(Ordering::SeqCst), 3)-3, Ordering::SeqCst);
|
ctx.chat().scroll.store(max(ctx.chat().scroll.load(Ordering::SeqCst), 3)-3, Ordering::SeqCst);
|
||||||
print_console(
|
print_console(
|
||||||
ctx.clone(),
|
ctx.clone(),
|
||||||
messages.messages(),
|
messages.messages(),
|
||||||
@ -314,11 +325,11 @@ fn poll_events(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
||||||
match read_messages(
|
match read_messages(
|
||||||
&mut connect(&ctx.host, ctx.enable_ssl)?,
|
&mut connect(&ctx.host, ctx.enable_ssl)?,
|
||||||
ctx.max_messages,
|
ctx.max_messages,
|
||||||
ctx.messages.packet_size(),
|
ctx.chat().messages.packet_size(),
|
||||||
!ctx.enable_ssl,
|
!ctx.enable_ssl,
|
||||||
ctx.enable_chunked
|
ctx.enable_chunked
|
||||||
) {
|
) {
|
||||||
@ -330,17 +341,17 @@ pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if ctx.enable_chunked {
|
if ctx.enable_chunked {
|
||||||
ctx.messages.append_and_store(ctx.max_messages, messages.clone(), size);
|
ctx.chat().messages.append_and_store(ctx.max_messages, messages.clone(), size);
|
||||||
print_console(ctx.clone(), ctx.messages.messages(), &ctx.input.read().unwrap())?;
|
print_console(ctx.clone(), ctx.chat().messages.messages(), &ctx.chat().input.read().unwrap())?;
|
||||||
} else {
|
} else {
|
||||||
ctx.messages.update(ctx.max_messages, messages.clone(), size);
|
ctx.chat().messages.update(ctx.max_messages, messages.clone(), size);
|
||||||
print_console(ctx.clone(), messages, &ctx.input.read().unwrap())?;
|
print_console(ctx.clone(), messages, &ctx.chat().input.read().unwrap())?;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let msg = format!("Read messages error: {}", e.to_string()).bright_red().to_string();
|
let msg = format!("Read messages error: {}", e.to_string()).bright_red().to_string();
|
||||||
ctx.messages.append(ctx.max_messages, vec![msg]);
|
ctx.chat().messages.append(ctx.max_messages, vec![msg]);
|
||||||
print_console(ctx.clone(), ctx.messages.messages(), &ctx.input.read().unwrap())?;
|
print_console(ctx.clone(), ctx.chat().messages.messages(), &ctx.chat().input.read().unwrap())?;
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -348,23 +359,39 @@ pub fn recv_tick(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_close() {
|
fn on_close() {
|
||||||
disable_raw_mode().unwrap();
|
disable_raw_mode().unwrap();
|
||||||
execute!(stdout(), event::DisableMouseCapture).unwrap();
|
execute!(stdout(), event::DisableMouseCapture).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_console(ctx: Arc<Context>) -> Result<(), Box<dyn Error>> {
|
|
||||||
print_console(ctx.clone(), ctx.messages.messages(), &ctx.input.read().unwrap())
|
pub struct ChatContext {
|
||||||
|
pub messages: Arc<ChatStorage>,
|
||||||
|
pub input: Arc<RwLock<String>>,
|
||||||
|
pub registered: Arc<RwLock<Option<String>>>,
|
||||||
|
pub scroll: Arc<AtomicUsize>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_message(ctx: Arc<Context>, message: String) -> Result<(), Box<dyn Error>> {
|
||||||
|
ctx.chat().messages.append(ctx.max_messages, vec![message]);
|
||||||
|
print_console(ctx.clone(), ctx.chat().messages.messages(), &ctx.chat().input.read().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_main_loop(ctx: Arc<Context>) {
|
pub fn run_main_loop(ctx: Arc<Context>) {
|
||||||
|
set_chat(ctx.clone(), ChatContext {
|
||||||
|
messages: Arc::new(ChatStorage::new()),
|
||||||
|
input: Arc::new(RwLock::new(String::new())),
|
||||||
|
registered: Arc::new(RwLock::new(None)),
|
||||||
|
scroll: Arc::new(AtomicUsize::new(0)),
|
||||||
|
});
|
||||||
|
|
||||||
enable_raw_mode().unwrap();
|
enable_raw_mode().unwrap();
|
||||||
execute!(stdout(), event::EnableMouseCapture).unwrap();
|
execute!(stdout(), event::EnableMouseCapture).unwrap();
|
||||||
|
|
||||||
if let Err(e) = print_console(ctx.clone(), Vec::new(), &ctx.input.read().unwrap()) {
|
if let Err(e) = print_console(ctx.clone(), Vec::new(), &ctx.chat().input.read().unwrap()) {
|
||||||
let msg = format!("Print messages error: {}", e.to_string()).bright_red().to_string();
|
let msg = format!("Print messages error: {}", e.to_string()).bright_red().to_string();
|
||||||
ctx.messages.append(ctx.max_messages, vec![msg]);
|
ctx.chat().messages.append(ctx.max_messages, vec![msg]);
|
||||||
let _ = print_console(ctx.clone(), ctx.messages.messages(), &ctx.input.read().unwrap());
|
let _ = print_console(ctx.clone(), ctx.chat().messages.messages(), &ctx.chat().input.read().unwrap());
|
||||||
}
|
}
|
||||||
|
|
||||||
thread::spawn({
|
thread::spawn({
|
||||||
@ -374,8 +401,8 @@ pub fn run_main_loop(ctx: Arc<Context>) {
|
|||||||
loop {
|
loop {
|
||||||
if let Err(e) = recv_tick(ctx.clone()) {
|
if let Err(e) = recv_tick(ctx.clone()) {
|
||||||
let msg = format!("Print messages error: {}", e.to_string()).bright_red().to_string();
|
let msg = format!("Print messages error: {}", e.to_string()).bright_red().to_string();
|
||||||
ctx.messages.append(ctx.max_messages, vec![msg]);
|
ctx.chat().messages.append(ctx.max_messages, vec![msg]);
|
||||||
let _ = print_console(ctx.clone(), ctx.messages.messages(), &ctx.input.read().unwrap());
|
let _ = print_console(ctx.clone(), ctx.chat().messages.messages(), &ctx.chat().input.read().unwrap());
|
||||||
thread::sleep(Duration::from_secs(1));
|
thread::sleep(Duration::from_secs(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -384,7 +411,7 @@ pub fn run_main_loop(ctx: Arc<Context>) {
|
|||||||
|
|
||||||
if let Err(e) = poll_events(ctx.clone()) {
|
if let Err(e) = poll_events(ctx.clone()) {
|
||||||
let msg = format!("Poll events error: {}", e.to_string()).bright_red().to_string();
|
let msg = format!("Poll events error: {}", e.to_string()).bright_red().to_string();
|
||||||
ctx.messages.append(ctx.max_messages, vec![msg]);
|
ctx.chat().messages.append(ctx.max_messages, vec![msg]);
|
||||||
let _ = print_console(ctx.clone(), ctx.messages.messages(), &ctx.input.read().unwrap());
|
let _ = print_console(ctx.clone(), ctx.chat().messages.messages(), &ctx.chat().input.read().unwrap());
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,4 +1,4 @@
|
|||||||
use std::{str::FromStr, sync::{atomic::AtomicUsize, Arc, RwLock}};
|
use std::{str::FromStr, sync::{Arc, RwLock}};
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use std::{env, fs, path::{Path, PathBuf}, thread, time::Duration};
|
use std::{env, fs, path::{Path, PathBuf}, thread, time::Duration};
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
@ -6,7 +6,7 @@ use rand::random;
|
|||||||
use serde_yml;
|
use serde_yml;
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
|
|
||||||
use crate::chat::ChatStorage;
|
use crate::chat::ChatContext;
|
||||||
|
|
||||||
use super::util::get_input;
|
use super::util::get_input;
|
||||||
|
|
||||||
@ -209,11 +209,9 @@ pub struct Args {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct Context {
|
pub struct Context {
|
||||||
pub messages: Arc<ChatStorage>,
|
pub chat: Arc<RwLock<Option<Arc<ChatContext>>>>,
|
||||||
pub input: Arc<RwLock<String>>,
|
|
||||||
pub host: String,
|
pub host: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub registered: Arc<RwLock<Option<String>>>,
|
|
||||||
pub disable_formatting: bool,
|
pub disable_formatting: bool,
|
||||||
pub disable_commands: bool,
|
pub disable_commands: bool,
|
||||||
pub disable_hiding_ip: bool,
|
pub disable_hiding_ip: bool,
|
||||||
@ -221,7 +219,6 @@ pub struct Context {
|
|||||||
pub update_time: usize,
|
pub update_time: usize,
|
||||||
pub max_messages: usize,
|
pub max_messages: usize,
|
||||||
pub enable_ip_viewing: bool,
|
pub enable_ip_viewing: bool,
|
||||||
pub scroll: Arc<AtomicUsize>,
|
|
||||||
pub enable_auth: bool,
|
pub enable_auth: bool,
|
||||||
pub enable_ssl: bool,
|
pub enable_ssl: bool,
|
||||||
pub enable_chunked: bool,
|
pub enable_chunked: bool,
|
||||||
@ -230,22 +227,23 @@ pub struct Context {
|
|||||||
impl Context {
|
impl Context {
|
||||||
pub fn new(config: &Config, args: &Args) -> Context {
|
pub fn new(config: &Config, args: &Args) -> Context {
|
||||||
Context {
|
Context {
|
||||||
messages: Arc::new(ChatStorage::new()),
|
chat: Arc::new(RwLock::new(None)),
|
||||||
input: Arc::new(RwLock::new(String::new())),
|
|
||||||
message_format: args.message_format.clone().unwrap_or(config.message_format.clone()),
|
message_format: args.message_format.clone().unwrap_or(config.message_format.clone()),
|
||||||
host: args.host.clone().unwrap_or(config.host.clone()),
|
host: args.host.clone().unwrap_or(config.host.clone()),
|
||||||
name: args.name.clone().or(config.name.clone()).unwrap_or_else(|| ask_string("Name", format!("Anon#{:X}", random::<u16>()))),
|
name: args.name.clone().or(config.name.clone()).unwrap_or_else(|| ask_string("Name", format!("Anon#{:X}", random::<u16>()))),
|
||||||
registered: Arc::new(RwLock::new(None)),
|
|
||||||
disable_formatting: args.disable_formatting,
|
disable_formatting: args.disable_formatting,
|
||||||
disable_commands: args.disable_commands,
|
disable_commands: args.disable_commands,
|
||||||
disable_hiding_ip: args.disable_ip_hiding,
|
disable_hiding_ip: args.disable_ip_hiding,
|
||||||
update_time: config.update_time,
|
update_time: config.update_time,
|
||||||
max_messages: config.max_messages,
|
max_messages: config.max_messages,
|
||||||
enable_ip_viewing: args.enable_users_ip_viewing || config.enable_ip_viewing,
|
enable_ip_viewing: args.enable_users_ip_viewing || config.enable_ip_viewing,
|
||||||
scroll: Arc::new(AtomicUsize::new(0)),
|
|
||||||
enable_auth: args.enable_auth || config.enable_auth,
|
enable_auth: args.enable_auth || config.enable_auth,
|
||||||
enable_ssl: args.enable_ssl || config.enable_ssl,
|
enable_ssl: args.enable_ssl || config.enable_ssl,
|
||||||
enable_chunked: args.enable_chunked || config.enable_chunked,
|
enable_chunked: args.enable_chunked || config.enable_chunked,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn chat(&self) -> Arc<ChatContext> {
|
||||||
|
self.chat.read().unwrap().clone().unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user