Merge pull request #397 from Revertron/feature/tray-icon

Added tray icon and ability to start ALFIS with hidden UI, shown by tray icon actions.
This commit is contained in:
Revertron
2025-10-29 16:41:39 +01:00
committed by GitHub
7 changed files with 378 additions and 15 deletions
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Install dependencies - name: Install dependencies
run: sudo apt update && sudo apt install libwebkit2gtk-4.1-dev libsoup-3.0-dev run: sudo apt update && sudo apt install libwebkit2gtk-4.1-dev libxdo-dev libsoup-3.0-dev
if: contains(matrix.os, 'ubuntu') if: contains(matrix.os, 'ubuntu')
- name: Update Rust - name: Update Rust
+2 -2
View File
@@ -67,7 +67,7 @@ jobs:
run: | run: |
sudo apt update sudo apt update
sudo apt upgrade sudo apt upgrade
sudo apt install libwebkit2gtk-4.1-dev libsoup-3.0-dev upx-ucl sudo apt install libwebkit2gtk-4.1-dev libxdo-dev libsoup-3.0-dev upx-ucl
cargo install cross cargo install cross
- name: Build and package deb packages - name: Build and package deb packages
@@ -99,7 +99,7 @@ jobs:
- name: install dependencies - name: install dependencies
if: contains(matrix.os, 'ubuntu') if: contains(matrix.os, 'ubuntu')
run: sudo apt update && sudo apt install --no-install-recommends libwebkit2gtk-4.1-dev libsoup-3.0-dev upx-ucl run: sudo apt update && sudo apt install --no-install-recommends libwebkit2gtk-4.1-dev libxdo-dev libsoup-3.0-dev upx-ucl
- name: Build release binaries - name: Build release binaries
run: cargo build --release run: cargo build --release
Generated
+276 -1
View File
@@ -56,6 +56,7 @@ dependencies = [
"ecies-ed25519-ng", "ecies-ed25519-ng",
"ed25519-dalek", "ed25519-dalek",
"getopts", "getopts",
"image",
"lazy_static", "lazy_static",
"log", "log",
"lru", "lru",
@@ -76,6 +77,7 @@ dependencies = [
"time", "time",
"tinyfiledialogs", "tinyfiledialogs",
"toml 0.9.8", "toml 0.9.8",
"tray-icon",
"ureq", "ureq",
"uuid", "uuid",
"winapi", "winapi",
@@ -172,6 +174,9 @@ name = "bitflags"
version = "2.10.0" version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
dependencies = [
"serde_core",
]
[[package]] [[package]]
name = "blake2" name = "blake2"
@@ -218,12 +223,24 @@ version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "bytemuck"
version = "1.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.5.0" 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 = "byteorder-lite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.10.1" version = "1.10.1"
@@ -742,6 +759,15 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
[[package]]
name = "fdeflate"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c"
dependencies = [
"simd-adler32",
]
[[package]] [[package]]
name = "fiat-crypto" name = "fiat-crypto"
version = "0.2.9" version = "0.2.9"
@@ -1427,6 +1453,19 @@ dependencies = [
"icu_properties", "icu_properties",
] ]
[[package]]
name = "image"
version = "0.25.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7"
dependencies = [
"bytemuck",
"byteorder-lite",
"moxcms",
"num-traits",
"png 0.18.0",
]
[[package]] [[package]]
name = "indexmap" name = "indexmap"
version = "2.12.0" version = "2.12.0"
@@ -1526,6 +1565,17 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "keyboard-types"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a"
dependencies = [
"bitflags 2.10.0",
"serde",
"unicode-segmentation",
]
[[package]] [[package]]
name = "kuchikiki" name = "kuchikiki"
version = "0.8.8-speedreader" version = "0.8.8-speedreader"
@@ -1544,12 +1594,46 @@ 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 = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]]
name = "libappindicator"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a"
dependencies = [
"glib",
"gtk",
"gtk-sys",
"libappindicator-sys",
"log",
]
[[package]]
name = "libappindicator-sys"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf"
dependencies = [
"gtk-sys",
"libloading",
"once_cell",
]
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.177" version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "libloading"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
dependencies = [
"cfg-if",
"winapi",
]
[[package]] [[package]]
name = "libredox" name = "libredox"
version = "0.1.10" version = "0.1.10"
@@ -1560,6 +1644,25 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "libxdo"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00333b8756a3d28e78def82067a377de7fa61b24909000aeaa2b446a948d14db"
dependencies = [
"libxdo-sys",
]
[[package]]
name = "libxdo-sys"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212"
dependencies = [
"libc",
"x11",
]
[[package]] [[package]]
name = "litemap" name = "litemap"
version = "0.8.0" version = "0.8.0"
@@ -1664,6 +1767,37 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "moxcms"
version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fbdd3d7436f8b5e892b8b7ea114271ff0fa00bc5acae845d53b07d498616ef6"
dependencies = [
"num-traits",
"pxfm",
]
[[package]]
name = "muda"
version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a"
dependencies = [
"crossbeam-channel",
"dpi",
"gtk",
"keyboard-types",
"libxdo",
"objc2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-foundation",
"once_cell",
"png 0.17.16",
"thiserror 2.0.17",
"windows-sys 0.60.2",
]
[[package]] [[package]]
name = "ndk" name = "ndk"
version = "0.9.0" version = "0.9.0"
@@ -1814,6 +1948,16 @@ dependencies = [
"objc2", "objc2",
] ]
[[package]]
name = "objc2-core-graphics"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807"
dependencies = [
"bitflags 2.10.0",
"objc2-core-foundation",
]
[[package]] [[package]]
name = "objc2-encode" name = "objc2-encode"
version = "4.1.0" version = "4.1.0"
@@ -1836,6 +1980,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
dependencies = [ dependencies = [
"bitflags 2.10.0", "bitflags 2.10.0",
"block2",
"objc2", "objc2",
"objc2-core-foundation", "objc2-core-foundation",
] ]
@@ -2103,6 +2248,32 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "png"
version = "0.17.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526"
dependencies = [
"bitflags 1.3.2",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]]
name = "png"
version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0"
dependencies = [
"bitflags 2.10.0",
"crc32fast",
"fdeflate",
"flate2",
"miniz_oxide",
]
[[package]] [[package]]
name = "poly1305" name = "poly1305"
version = "0.8.0" version = "0.8.0"
@@ -2224,6 +2395,15 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "pxfm"
version = "0.1.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84"
dependencies = [
"num-traits",
]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.41" version = "1.0.41"
@@ -3054,6 +3234,27 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2" checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
[[package]]
name = "tray-icon"
version = "0.21.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3d5572781bee8e3f994d7467084e1b1fd7a93ce66bd480f8156ba89dee55a2b"
dependencies = [
"crossbeam-channel",
"dirs",
"libappindicator",
"muda",
"objc2",
"objc2-app-kit",
"objc2-core-foundation",
"objc2-core-graphics",
"objc2-foundation",
"once_cell",
"png 0.17.16",
"thiserror 2.0.17",
"windows-sys 0.60.2",
]
[[package]] [[package]]
name = "typenum" name = "typenum"
version = "1.19.0" version = "1.19.0"
@@ -3569,6 +3770,15 @@ dependencies = [
"windows-targets 0.52.6", "windows-targets 0.52.6",
] ]
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets 0.53.5",
]
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.61.2" version = "0.61.2"
@@ -3602,13 +3812,30 @@ dependencies = [
"windows_aarch64_gnullvm 0.52.6", "windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.6", "windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.6", "windows_i686_gnu 0.52.6",
"windows_i686_gnullvm", "windows_i686_gnullvm 0.52.6",
"windows_i686_msvc 0.52.6", "windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.6", "windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.6", "windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.6", "windows_x86_64_msvc 0.52.6",
] ]
[[package]]
name = "windows-targets"
version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
"windows-link 0.2.1",
"windows_aarch64_gnullvm 0.53.1",
"windows_aarch64_msvc 0.53.1",
"windows_i686_gnu 0.53.1",
"windows_i686_gnullvm 0.53.1",
"windows_i686_msvc 0.53.1",
"windows_x86_64_gnu 0.53.1",
"windows_x86_64_gnullvm 0.53.1",
"windows_x86_64_msvc 0.53.1",
]
[[package]] [[package]]
name = "windows-threading" name = "windows-threading"
version = "0.1.0" version = "0.1.0"
@@ -3639,6 +3866,12 @@ 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 = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.42.2" version = "0.42.2"
@@ -3651,6 +3884,12 @@ 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 = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.42.2" version = "0.42.2"
@@ -3663,12 +3902,24 @@ 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 = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]]
name = "windows_i686_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
[[package]] [[package]]
name = "windows_i686_gnullvm" name = "windows_i686_gnullvm"
version = "0.52.6" 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 = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.42.2" version = "0.42.2"
@@ -3681,6 +3932,12 @@ 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 = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]]
name = "windows_i686_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.42.2" version = "0.42.2"
@@ -3693,6 +3950,12 @@ 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 = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.42.2" version = "0.42.2"
@@ -3705,6 +3968,12 @@ 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 = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.42.2" version = "0.42.2"
@@ -3717,6 +3986,12 @@ 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 = "windows_x86_64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.5.40" version = "0.5.40"
+5 -1
View File
@@ -44,9 +44,13 @@ thread-priority = "3.0.0"
# Optional dependencies regulated by features # Optional dependencies regulated by features
wry = { version = "0.53", optional = true } wry = { version = "0.53", optional = true }
tao = { version = "0.34", optional = true } tao = { version = "0.34", optional = true }
tray-icon = { version = "0.21.2", optional = true }
tinyfiledialogs = { version = "3.9.1", optional = true } tinyfiledialogs = { version = "3.9.1", optional = true }
open = { version = "5.3.0", optional = true } open = { version = "5.3.0", optional = true }
[target.'cfg(not(target_os = "windows"))'.dependencies]
image = { version = "0.25", default-features = false, features = ["png"] }
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["impl-default", "wincon", "shellscalingapi"] } winapi = { version = "0.3.9", features = ["impl-default", "wincon", "shellscalingapi"] }
windows-service = "0.8.0" windows-service = "0.8.0"
@@ -70,6 +74,6 @@ ProductName="ALFIS"
FileDescription="Alternative Free Identity System" FileDescription="Alternative Free Identity System"
[features] [features]
webgui = ["wry", "tao", "tinyfiledialogs", "open"] webgui = ["wry", "tao", "tray-icon", "tinyfiledialogs", "open"]
doh = ["ureq"] doh = ["ureq"]
default = ["webgui", "doh"] default = ["webgui", "doh"]
+2 -2
View File
@@ -58,8 +58,8 @@ cargo build
``` ```
### ![Linux Logo](/img/linux.svg) On Linux ### ![Linux Logo](/img/linux.svg) On Linux
If you are building on Linux, you must ensure that you have `libwebkitgtk` library installed. If you are building on Linux, you must ensure that you have `libwebkitgtk` and `libxdo` libraries installed (for UI and tray icon respectively).
You can do it by issuing this command: `sudo apt install libwebkit2gtk-4.1-dev` (on Debian/Ubuntu and derivatives). You can do it by issuing this command: `sudo apt install libwebkit2gtk-4.1-dev libxdo-dev` (on Debian/Ubuntu and derivatives).
#### ![Arch Linux Logo](/img/archlinux.svg) On Arch Linux #### ![Arch Linux Logo](/img/archlinux.svg) On Arch Linux
+2 -1
View File
@@ -59,6 +59,7 @@ fn main() {
opts.optflag("v", "version", "Print version and exit"); opts.optflag("v", "version", "Print version and exit");
opts.optflag("d", "debug", "Show debug messages, more than usual"); opts.optflag("d", "debug", "Show debug messages, more than usual");
opts.optflag("t", "trace", "Show trace messages, more than debug"); opts.optflag("t", "trace", "Show trace messages, more than debug");
opts.optflag("", "hide", "Hide UI, show only tray icon.");
opts.optflag("b", "blocks", "List blocks from DB and exit"); opts.optflag("b", "blocks", "List blocks from DB and exit");
opts.optflag("g", "generate", "Generate new config file. Generated config will be printed to console."); opts.optflag("g", "generate", "Generate new config file. Generated config will be printed to console.");
#[cfg(windows)] #[cfg(windows)]
@@ -251,7 +252,7 @@ fn main() {
}); });
} }
#[cfg(feature = "webgui")] #[cfg(feature = "webgui")]
web_ui::run_interface(Arc::clone(&context), miner); web_ui::run_interface(Arc::clone(&context), miner, opt_matches.opt_present("hide"));
} }
// Without explicitly detaching the console cmd won't redraw it's prompt. // Without explicitly detaching the console cmd won't redraw it's prompt.
+90 -7
View File
@@ -4,6 +4,7 @@ extern crate serde_json;
extern crate tinyfiledialogs as tfd; extern crate tinyfiledialogs as tfd;
use std::sync::{Arc, Mutex, MutexGuard}; use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
@@ -17,6 +18,7 @@ use alfis::eventbus::{post, register};
use alfis::miner::Miner; use alfis::miner::Miner;
use alfis::{keystore, Block, Bytes, Context, Keystore, Transaction}; use alfis::{keystore, Block, Bytes, Context, Keystore, Transaction};
use chrono::{Local, Utc}; use chrono::{Local, Utc};
use image::GenericImageView;
#[allow(unused_imports)] #[allow(unused_imports)]
use log::{debug, error, info, trace, warn, LevelFilter}; use log::{debug, error, info, trace, warn, LevelFilter};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -28,9 +30,11 @@ use tao::{
window::WindowBuilder, window::WindowBuilder,
}; };
use tao::dpi::PhysicalPosition; use tao::dpi::PhysicalPosition;
use tray_icon::menu::{Menu, MenuEvent, MenuItem};
use tray_icon::{TrayIconBuilder, TrayIconEvent};
use wry::WebViewBuilder; use wry::WebViewBuilder;
pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) { pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>, hide: bool) {
let file_content = include_str!("webview/index.html"); let file_content = include_str!("webview/index.html");
let mut styles = inline_style(include_str!("webview/bulma.css")); let mut styles = inline_style(include_str!("webview/bulma.css"));
styles.push_str(&inline_style(include_str!("webview/styles.css"))); styles.push_str(&inline_style(include_str!("webview/styles.css")));
@@ -42,7 +46,27 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
// Create event loop and window // Create event loop and window
let event_loop = EventLoopBuilder::<UserEvent>::with_user_event().build(); let event_loop = EventLoopBuilder::<UserEvent>::with_user_event().build();
let proxy = event_loop.create_proxy();
// Create tray menu
let tray_menu = Menu::new();
let show_item = MenuItem::new("Show Window", true, None);
let quit_item = MenuItem::new("Quit", true, None);
tray_menu.append(&show_item).unwrap();
tray_menu.append(&quit_item).unwrap();
#[cfg(windows)]
let icon = tray_icon::Icon::from_resource(1, None).unwrap();
// Create tray icon
#[cfg(not(target_os = "windows"))]
let icon = load_icon_from_png();
let tray_icon = TrayIconBuilder::new()
.with_menu(Box::new(tray_menu))
.with_tooltip(&title)
.with_icon(icon)
.with_menu_on_left_click(false)
.build()
.unwrap();
let window_size = tao::dpi::LogicalSize::new(1024, 720); let window_size = tao::dpi::LogicalSize::new(1024, 720);
// Get primary monitor and calculate center position // Get primary monitor and calculate center position
@@ -65,7 +89,7 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
.with_inner_size(window_size) .with_inner_size(window_size)
.with_min_inner_size(tao::dpi::LogicalSize::new(773, 350)) .with_min_inner_size(tao::dpi::LogicalSize::new(773, 350))
.with_resizable(true) .with_resizable(true)
.with_visible(true); .with_visible(!hide);
if let Some(position) = position { if let Some(position) = position {
builder = builder.with_position(position); builder = builder.with_position(position);
@@ -89,6 +113,7 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
// Clone for the IPC handler // Clone for the IPC handler
let context_ipc = Arc::clone(&context); let context_ipc = Arc::clone(&context);
let miner_ipc = Arc::clone(&miner); let miner_ipc = Arc::clone(&miner);
let proxy = event_loop.create_proxy();
let proxy_ipc = proxy.clone(); let proxy_ipc = proxy.clone();
// Create webview // Create webview
@@ -173,10 +198,13 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
_ => threads _ => threads
}; };
let status = Arc::new(Mutex::new(UiStatus::new(threads))); let status = Arc::new(Mutex::new(UiStatus::new(threads)));
let connected_nodes = Arc::new(AtomicUsize::new(0));
let nodes_copy = Arc::clone(&connected_nodes);
register(move |_uuid, e| { register(move |_uuid, e| {
let status = Arc::clone(&status); let status = Arc::clone(&status);
let proxy = proxy_events.clone(); let proxy = proxy_events.clone();
let nodes_copy = Arc::clone(&nodes_copy);
thread::Builder::new().name(String::from("webui")).spawn(move || { thread::Builder::new().name(String::from("webui")).spawn(move || {
let mut status = status.lock().unwrap(); let mut status = status.lock().unwrap();
@@ -267,6 +295,7 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
} }
} }
Event::NetworkStatus { blocks, domains, keys, nodes } => { Event::NetworkStatus { blocks, domains, keys, nodes } => {
nodes_copy.store(nodes, Ordering::SeqCst);
if status.mining || status.syncing || nodes < 3 { if status.mining || status.syncing || nodes < 3 {
format!("setStats({}, {}, {}, {});", blocks, domains, keys, nodes) format!("setStats({}, {}, {}, {});", blocks, domains, keys, nodes)
} else { } else {
@@ -289,6 +318,18 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
true true
}); });
let proxy = event_loop.create_proxy();
TrayIconEvent::set_event_handler(Some(move |event| {
let _ = proxy.send_event(UserEvent::TrayIconEvent(event));
}));
let proxy = event_loop.create_proxy();
MenuEvent::set_event_handler(Some(move |event| {
let _ = proxy.send_event(UserEvent::MenuEvent(event));
}));
let proxy = event_loop.create_proxy();
// Run event loop // Run event loop
event_loop.run(move |event, _, control_flow| { event_loop.run(move |event, _, control_flow| {
*control_flow = ControlFlow::Wait; *control_flow = ControlFlow::Wait;
@@ -298,10 +339,7 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
event: WindowEvent::CloseRequested, event: WindowEvent::CloseRequested,
.. ..
} => { } => {
info!("Interface closed, exiting"); window.set_visible(false);
post(Event::ActionQuit);
thread::sleep(Duration::from_millis(100));
*control_flow = ControlFlow::Exit;
} }
TaoEvent::UserEvent(user_event) => { TaoEvent::UserEvent(user_event) => {
let wv = webview_clone.lock().unwrap(); let wv = webview_clone.lock().unwrap();
@@ -324,6 +362,32 @@ pub fn run_interface(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>) {
UserEvent::ShowWarning(text) => { UserEvent::ShowWarning(text) => {
show_warning(&wv, &text); show_warning(&wv, &text);
} }
UserEvent::TrayIconEvent(event) => {
match event {
TrayIconEvent::DoubleClick { button, .. } => {
if button == tray_icon::MouseButton::Left {
window.set_visible(true);
window.set_focus();
}
}
TrayIconEvent::Enter { .. } => {
let nodes = connected_nodes.load(Ordering::SeqCst);
let title = format!("ALFIS {}\nConnected: {nodes}", env!("CARGO_PKG_VERSION"));
let _ = tray_icon.set_tooltip(Some(title));
}
_ => {}
}
}
UserEvent::MenuEvent(event) => {
if event.id == show_item.id() {
window.set_visible(true);
} else if event.id == quit_item.id() {
info!("Interface closed, exiting");
post(Event::ActionQuit);
thread::sleep(Duration::from_millis(100));
*control_flow = ControlFlow::Exit;
}
}
} }
} }
_ => {} _ => {}
@@ -338,6 +402,25 @@ enum UserEvent {
LoadDomains, LoadDomains,
SendKeysToUi, SendKeysToUi,
ShowWarning(String), ShowWarning(String),
TrayIconEvent(TrayIconEvent),
MenuEvent(MenuEvent)
}
/// Load icon from embedded in binary PNG file. Only needed in Linux/macOS builds.
#[cfg(not(target_os = "windows"))]
fn load_icon_from_png() -> tray_icon::Icon {
// Include PNG in binary
const ICON_BYTES: &[u8] = include_bytes!("../img/logo/alfis_icon32.png");
// decode image by crate `image`
let image = image::load_from_memory(ICON_BYTES)
.expect("Error loading image from png");
let rgba = image.to_rgba8();
let (width, height) = image.dimensions();
// Convert to format for tray_icon
tray_icon::Icon::from_rgba(rgba.into_vec(), width, height)
.expect("Error loading icon")
} }
fn check_record(data: &str) -> bool { fn check_record(data: &str) -> bool {