Compare commits
10 commits
9e829d3663
...
e270cde5da
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e270cde5da | ||
|
|
4b262fce9e | ||
|
|
b8d2b09fa5 | ||
|
|
250d6dd5d3 | ||
|
|
8097330bf4 | ||
|
|
2e23a4f5ce | ||
|
|
1d583b58af | ||
|
|
691d458a70 | ||
|
|
d152af02f6 | ||
|
|
65274d0dd2 |
10 changed files with 337 additions and 62 deletions
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
|
|
@ -4,6 +4,9 @@ on:
|
||||||
push:
|
push:
|
||||||
tags: ["v*"]
|
tags: ["v*"]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DL_DIR: /srv/breadway-dl
|
DL_DIR: /srv/breadway-dl
|
||||||
ECOSYSTEM_DIR: /home/breadway/Projects/bread-ecosystem
|
ECOSYSTEM_DIR: /home/breadway/Projects/bread-ecosystem
|
||||||
|
|
@ -14,8 +17,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: install system deps
|
- name: install build deps
|
||||||
run: sudo pacman -S --noconfirm gtk4 gtk4-layer-shell iw 2>/dev/null || true
|
run: sudo apt-get install -y libgtk-4-dev libdbus-1-dev pkg-config iw 2>/dev/null || true
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: cargo build --release --locked
|
run: cargo build --release --locked
|
||||||
|
|
@ -30,7 +33,7 @@ jobs:
|
||||||
sha256sum "${PKG_DIR}/breadbar-x86_64" | awk '{print $1}' \
|
sha256sum "${PKG_DIR}/breadbar-x86_64" | awk '{print $1}' \
|
||||||
> "${PKG_DIR}/breadbar-x86_64.sha256"
|
> "${PKG_DIR}/breadbar-x86_64.sha256"
|
||||||
cp bakery.toml "${PKG_DIR}/bakery.toml"
|
cp bakery.toml "${PKG_DIR}/bakery.toml"
|
||||||
ln -sfn "${PKG_DIR}" "${DL_DIR}/breadbar/latest"
|
ln -sfn "${VERSION}" "${DL_DIR}/breadbar/latest"
|
||||||
|
|
||||||
- name: ensure bread-ecosystem
|
- name: ensure bread-ecosystem
|
||||||
run: |
|
run: |
|
||||||
|
|
@ -50,6 +53,8 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
VERSION="${GITHUB_REF_NAME#v}"
|
VERSION="${GITHUB_REF_NAME#v}"
|
||||||
PKG_DIR="${DL_DIR}/breadbar/${VERSION}"
|
PKG_DIR="${DL_DIR}/breadbar/${VERSION}"
|
||||||
|
gh release create "${GITHUB_REF_NAME}" \
|
||||||
|
--title "breadbar v${VERSION}" --generate-notes 2>/dev/null || true
|
||||||
gh release upload "${GITHUB_REF_NAME}" \
|
gh release upload "${GITHUB_REF_NAME}" \
|
||||||
"${PKG_DIR}/breadbar-x86_64" \
|
"${PKG_DIR}/breadbar-x86_64" \
|
||||||
"${PKG_DIR}/breadbar-x86_64.sha256" \
|
"${PKG_DIR}/breadbar-x86_64.sha256" \
|
||||||
|
|
|
||||||
99
Cargo.lock
generated
99
Cargo.lock
generated
|
|
@ -66,19 +66,20 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "autocfg"
|
name = "autocfg"
|
||||||
version = "1.5.0"
|
version = "1.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.11.1"
|
version = "2.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
|
checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bread-theme"
|
name = "bread-theme"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
source = "git+https://github.com/Breadway/bread-ecosystem?tag=v0.1.0#6b5f4f475f66a645b08cb865e6dda8228d23679b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dirs",
|
"dirs",
|
||||||
"gtk4",
|
"gtk4",
|
||||||
|
|
@ -88,7 +89,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "breadbar"
|
name = "breadbar"
|
||||||
version = "0.1.0"
|
version = "0.1.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bread-theme",
|
"bread-theme",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
|
|
@ -104,9 +105,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.20.2"
|
version = "3.20.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
|
checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
|
|
@ -139,9 +140,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-expr"
|
name = "cfg-expr"
|
||||||
version = "0.20.7"
|
version = "0.20.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3c6b04e07d8080154ed4ac03546d9a2b303cc2fe1901ba0b35b301516e289368"
|
checksum = "fb693542bcafa528e198be0ebd9d3632ca5b7c93dbe7237460e199910835997c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"target-lexicon",
|
"target-lexicon",
|
||||||
|
|
@ -223,9 +224,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
version = "1.15.0"
|
version = "1.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
|
checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "endi"
|
name = "endi"
|
||||||
|
|
@ -854,9 +855,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.98"
|
version = "0.3.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "67df7112613f8bfd9150013a0314e196f4800d3201ae742489d999db2f979f08"
|
checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
|
@ -908,15 +909,15 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.29"
|
version = "0.4.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.8.0"
|
version = "2.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memoffset"
|
name = "memoffset"
|
||||||
|
|
@ -929,9 +930,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.2.0"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
|
checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
|
|
@ -1174,9 +1175,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.149"
|
version = "1.0.150"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
|
checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
@ -1229,9 +1230,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.3"
|
version = "0.6.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e"
|
checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
|
|
@ -1272,9 +1273,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "target-lexicon"
|
name = "target-lexicon"
|
||||||
version = "0.13.3"
|
version = "0.13.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c"
|
checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
|
|
@ -1363,9 +1364,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
version = "0.25.11+spec-1.1.0"
|
version = "0.25.12+spec-1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b59c4d22ed448339746c59b905d24568fcbb3ab65a500494f7b8c3e97739f2b"
|
checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
|
|
@ -1438,9 +1439,9 @@ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.13.2"
|
version = "1.13.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
|
checksum = "c6f5d3c3b1bf09027a88a6bc961fc00497d651009560b5463668dc81b0fa87a8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
|
|
@ -1450,9 +1451,9 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.23.1"
|
version = "1.23.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
|
checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"serde_core",
|
"serde_core",
|
||||||
|
|
@ -1491,9 +1492,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.121"
|
version = "0.2.122"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49ace1d07c165b0864824eee619580c4689389afa9dc9ed3a4c75040d82e6790"
|
checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
|
@ -1504,9 +1505,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.121"
|
version = "0.2.122"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e68e6f4afd367a562002c05637acb8578ff2dea1943df76afb9e83d177c8578"
|
checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
|
|
@ -1514,9 +1515,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.121"
|
version = "0.2.122"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d95a9ec35c64b2a7cb35d3fead40c4238d0940c86d107136999567a4703259f2"
|
checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
@ -1527,9 +1528,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.121"
|
version = "0.2.122"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4e0100b01e9f0d03189a92b96772a1fb998639d981193d7dbab487302513441"
|
checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
@ -1760,9 +1761,9 @@ checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus"
|
name = "zbus"
|
||||||
version = "5.15.0"
|
version = "5.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3bcbf15c8708d7fc1be0c993622e0a5cbd5e8b52bfa40afa4c3e0cd8d724ac1"
|
checksum = "eee682d202a77e4a9f3b2c2bdf48a7b28af5c08c34ddf66f98c93e5e39464285"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-broadcast",
|
"async-broadcast",
|
||||||
"async-recursion",
|
"async-recursion",
|
||||||
|
|
@ -1790,9 +1791,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_macros"
|
name = "zbus_macros"
|
||||||
version = "5.15.0"
|
version = "5.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "51fa5406ad9175a8c825a931f8cf347116b531b3634fcb0b627c290f1f2516ff"
|
checksum = "adf1bd45a81a103745b1757754762a26e8cd01e4532e4d6c8ec431624b80d1d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
@ -1822,9 +1823,9 @@ checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant"
|
name = "zvariant"
|
||||||
version = "5.11.0"
|
version = "5.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c1567a6ec68df868cbbfde844cfc6d81649fe5109a62b116b19fabd53e618ee"
|
checksum = "a192a0bde63360d77a7523c833d4b4ce6070a927e2c53246e4c540b1a3e27be0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"endi",
|
"endi",
|
||||||
"enumflags2",
|
"enumflags2",
|
||||||
|
|
@ -1836,9 +1837,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant_derive"
|
name = "zvariant_derive"
|
||||||
version = "5.11.0"
|
version = "5.12.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c7d5b780599bbde114e39d9a0799577fad1ced5105d38515745f7b3099d8ceda"
|
checksum = "90bc6cde9c01c511074be97f7ccb6c19d0da89e3f8662e812e999dcfd4638737"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
|
@ -1849,9 +1850,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zvariant_utils"
|
name = "zvariant_utils"
|
||||||
version = "3.3.1"
|
version = "3.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d464f5733ffa07a3164d656f18533caace9d0638596721355d73256a410d691"
|
checksum = "1e8535915cfa75547e559d8c68e8139909a4aeee076831e4ef7fc59d8172c4d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "breadbar"
|
name = "breadbar"
|
||||||
version = "0.1.0"
|
version = "0.1.2"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "Minimal status bar and notification daemon for Hyprland on Wayland"
|
description = "Minimal status bar and notification daemon for Hyprland on Wayland"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
@ -10,9 +10,7 @@ keywords = ["wayland", "hyprland", "bar", "status-bar", "gtk4"]
|
||||||
categories = ["gui"]
|
categories = ["gui"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Path dep for local dev; replace with git dep on first tag:
|
bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "v0.1.0", features = ["gtk"] }
|
||||||
# bread-theme = { git = "https://github.com/Breadway/bread-ecosystem", tag = "theme-v0.1.0", features = ["gtk"] }
|
|
||||||
bread-theme = { path = "../bread-ecosystem/bread-theme", features = ["gtk"] }
|
|
||||||
gtk4 = { version = "0.11", features = ["v4_12"] }
|
gtk4 = { version = "0.11", features = ["v4_12"] }
|
||||||
gtk4-layer-shell = "0.8"
|
gtk4-layer-shell = "0.8"
|
||||||
relm4 = { version = "0.11", features = ["macros"] }
|
relm4 = { version = "0.11", features = ["macros"] }
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
Minimal status bar and notification daemon for [Hyprland](https://hyprland.org/) on Wayland.
|
Minimal status bar and notification daemon for [Hyprland](https://hyprland.org/) on Wayland.
|
||||||
|
|
||||||
A single Rust binary that provides a full-width top bar and a standards-compliant D-Bus notification daemon, with no system tray, no launcher, and no wallpaper logic.
|
A single Rust binary that provides a full-width top bar, a system tray, and a standards-compliant D-Bus notification daemon. No launcher, no wallpaper logic.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|
@ -10,7 +10,7 @@ A single Rust binary that provides a full-width top bar and a standards-complian
|
||||||
|
|
||||||
- Left: live workspace buttons sourced from Hyprland IPC, active workspace highlighted
|
- Left: live workspace buttons sourced from Hyprland IPC, active workspace highlighted
|
||||||
- Centre: clock (`HH:MM`, updates at the top of each minute)
|
- Centre: clock (`HH:MM`, updates at the top of each minute)
|
||||||
- Right: CPU%, RAM, power draw (W), battery level + AC indicator, Bluetooth state, WiFi SSID with signal strength
|
- Right: CPU%, RAM, power draw (W), battery level + AC indicator, Bluetooth state, WiFi SSID with signal strength, system tray (SNI)
|
||||||
|
|
||||||
**Notification daemon**:
|
**Notification daemon**:
|
||||||
|
|
||||||
|
|
@ -105,6 +105,7 @@ Example — change the font size:
|
||||||
| `src/bar/workspaces.rs` | Hyprland IPC event stream, workspace buttons |
|
| `src/bar/workspaces.rs` | Hyprland IPC event stream, workspace buttons |
|
||||||
| `src/bar/clock.rs` | Minute-tick clock |
|
| `src/bar/clock.rs` | Minute-tick clock |
|
||||||
| `src/bar/stats.rs` | Polling loop: CPU, RAM, power, battery, Bluetooth, WiFi |
|
| `src/bar/stats.rs` | Polling loop: CPU, RAM, power, battery, Bluetooth, WiFi |
|
||||||
|
| `src/bar/tray.rs` | `org.kde.StatusNotifierWatcher` D-Bus service, SNI item rendering |
|
||||||
| `src/notifications/mod.rs` | `org.freedesktop.Notifications` zbus service |
|
| `src/notifications/mod.rs` | `org.freedesktop.Notifications` zbus service |
|
||||||
| `src/notifications/popup.rs` | Layer-shell popup window and card stack |
|
| `src/notifications/popup.rs` | Layer-shell popup window and card stack |
|
||||||
| `src/theme.rs` | pywal reader, GTK CSS provider injection |
|
| `src/theme.rs` | pywal reader, GTK CSS provider injection |
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
name = "breadbar"
|
name = "breadbar"
|
||||||
description = "Minimal status bar and notification daemon for Hyprland"
|
description = "Minimal status bar and notification daemon for Hyprland"
|
||||||
binaries = ["breadbar"]
|
binaries = ["breadbar"]
|
||||||
system_deps = ["gtk4", "gtk4-layer-shell", "iw"]
|
system_deps = ["gtk4", "gtk4-layer-shell", "iw", "libpulse"]
|
||||||
|
optional_system_deps = ["hyprland"]
|
||||||
bread_deps = []
|
bread_deps = []
|
||||||
|
|
||||||
[config]
|
[config]
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod clock;
|
pub mod clock;
|
||||||
pub mod stats;
|
pub mod stats;
|
||||||
|
pub mod tray;
|
||||||
pub mod workspaces;
|
pub mod workspaces;
|
||||||
|
|
|
||||||
240
src/bar/tray.rs
Normal file
240
src/bar/tray.rs
Normal file
|
|
@ -0,0 +1,240 @@
|
||||||
|
use crate::{App, AppInput};
|
||||||
|
use futures_lite::StreamExt;
|
||||||
|
use gtk4::prelude::Cast;
|
||||||
|
use relm4::ComponentSender;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use zbus::{interface, object_server::SignalEmitter};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TrayIconData {
|
||||||
|
Pixels { width: i32, height: i32, data: Vec<u8> },
|
||||||
|
Name(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum TrayUpdate {
|
||||||
|
Add { id: String, icon: Option<TrayIconData>, title: String },
|
||||||
|
Remove { id: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WatcherState {
|
||||||
|
items: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Watcher {
|
||||||
|
state: Arc<Mutex<WatcherState>>,
|
||||||
|
tx: tokio::sync::mpsc::UnboundedSender<(String, String)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[interface(name = "org.kde.StatusNotifierWatcher")]
|
||||||
|
impl Watcher {
|
||||||
|
async fn register_status_notifier_item(
|
||||||
|
&self,
|
||||||
|
service: String,
|
||||||
|
#[zbus(header)] header: zbus::message::Header<'_>,
|
||||||
|
#[zbus(signal_emitter)] ctx: SignalEmitter<'_>,
|
||||||
|
) {
|
||||||
|
let sender_name = header.sender().map(|s| s.to_string()).unwrap_or_default();
|
||||||
|
let (bus, path) = parse_service(&service, &sender_name);
|
||||||
|
let full = format!("{}{}", bus, path);
|
||||||
|
{
|
||||||
|
let mut state = self.state.lock().unwrap();
|
||||||
|
if !state.items.contains(&full) {
|
||||||
|
state.items.push(full.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let _ = Self::status_notifier_item_registered(&ctx, &full).await;
|
||||||
|
let _ = self.tx.send((bus, path));
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn register_status_notifier_host(
|
||||||
|
&self,
|
||||||
|
_service: String,
|
||||||
|
#[zbus(signal_emitter)] ctx: SignalEmitter<'_>,
|
||||||
|
) {
|
||||||
|
let _ = Self::status_notifier_host_registered(&ctx).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[zbus(property)]
|
||||||
|
fn registered_status_notifier_items(&self) -> Vec<String> {
|
||||||
|
self.state.lock().unwrap().items.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[zbus(property)]
|
||||||
|
fn is_status_notifier_host_registered(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
#[zbus(property)]
|
||||||
|
fn protocol_version(&self) -> i32 {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[zbus(signal)]
|
||||||
|
async fn status_notifier_item_registered(
|
||||||
|
ctx: &SignalEmitter<'_>,
|
||||||
|
service: &str,
|
||||||
|
) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
#[zbus(signal)]
|
||||||
|
async fn status_notifier_item_unregistered(
|
||||||
|
ctx: &SignalEmitter<'_>,
|
||||||
|
service: &str,
|
||||||
|
) -> zbus::Result<()>;
|
||||||
|
|
||||||
|
#[zbus(signal)]
|
||||||
|
async fn status_notifier_host_registered(ctx: &SignalEmitter<'_>) -> zbus::Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_service(service: &str, sender: &str) -> (String, String) {
|
||||||
|
if service.starts_with('/') {
|
||||||
|
return (sender.to_string(), service.to_string());
|
||||||
|
}
|
||||||
|
match service.find('/') {
|
||||||
|
Some(slash) => (service[..slash].to_string(), service[slash..].to_string()),
|
||||||
|
None => (service.to_string(), "/StatusNotifierItem".to_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_item(
|
||||||
|
conn: &zbus::Connection,
|
||||||
|
bus: &str,
|
||||||
|
path: &str,
|
||||||
|
) -> (Option<TrayIconData>, String) {
|
||||||
|
let Ok(proxy) = zbus::Proxy::new(conn, bus, path, "org.kde.StatusNotifierItem").await else {
|
||||||
|
return (None, String::new());
|
||||||
|
};
|
||||||
|
let icon = read_icon(&proxy).await;
|
||||||
|
let title = proxy.get_property::<String>("Title").await.unwrap_or_default();
|
||||||
|
(icon, title)
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn read_icon(proxy: &zbus::Proxy<'_>) -> Option<TrayIconData> {
|
||||||
|
let pixmaps: Vec<(i32, i32, Vec<u8>)> =
|
||||||
|
proxy.get_property("IconPixmap").await.unwrap_or_default();
|
||||||
|
|
||||||
|
if !pixmaps.is_empty() {
|
||||||
|
return pixmaps
|
||||||
|
.into_iter()
|
||||||
|
.filter(|(w, h, _)| *w > 0 && *h > 0)
|
||||||
|
.min_by_key(|(w, h, _)| (w.max(h) - 22).abs())
|
||||||
|
.map(|(width, height, data)| TrayIconData::Pixels { width, height, data });
|
||||||
|
}
|
||||||
|
|
||||||
|
let name: String = proxy.get_property("IconName").await.ok()?;
|
||||||
|
if name.is_empty() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
Some(TrayIconData::Name(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call `Activate(0, 0)` on the SNI item identified by `id` (`{bus}{path}`).
|
||||||
|
pub fn spawn_activate(id: String) {
|
||||||
|
relm4::spawn(async move {
|
||||||
|
let (bus, path) = match id.find('/') {
|
||||||
|
Some(slash) => (id[..slash].to_string(), id[slash..].to_string()),
|
||||||
|
None => (id, "/StatusNotifierItem".to_string()),
|
||||||
|
};
|
||||||
|
let Ok(conn) = zbus::Connection::session().await else { return };
|
||||||
|
let Ok(proxy) = zbus::Proxy::new(&conn, bus.as_str(), path.as_str(), "org.kde.StatusNotifierItem").await else { return };
|
||||||
|
let _ = proxy.call_method("Activate", &(0i32, 0i32)).await;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn spawn_watcher(sender: ComponentSender<App>) {
|
||||||
|
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<(String, String)>();
|
||||||
|
// Maps bus name → item ids, shared between registration and cleanup tasks.
|
||||||
|
let bus_map: Arc<Mutex<HashMap<String, Vec<String>>>> = Arc::new(Mutex::new(HashMap::new()));
|
||||||
|
let bus_map_cleanup = bus_map.clone();
|
||||||
|
let sender_cleanup = sender.clone();
|
||||||
|
|
||||||
|
// Registration task — owns the watcher service and processes new items.
|
||||||
|
relm4::spawn(async move {
|
||||||
|
let watcher = Watcher {
|
||||||
|
state: Arc::new(Mutex::new(WatcherState { items: Vec::new() })),
|
||||||
|
tx,
|
||||||
|
};
|
||||||
|
// Builder steps fail only on invalid static strings — safe to unwrap.
|
||||||
|
let conn = zbus::connection::Builder::session()
|
||||||
|
.unwrap()
|
||||||
|
.name("org.kde.StatusNotifierWatcher")
|
||||||
|
.unwrap()
|
||||||
|
.serve_at("/StatusNotifierWatcher", watcher)
|
||||||
|
.unwrap()
|
||||||
|
.build()
|
||||||
|
.await
|
||||||
|
.expect("failed to register org.kde.StatusNotifierWatcher");
|
||||||
|
|
||||||
|
while let Some((bus, path)) = rx.recv().await {
|
||||||
|
let (icon, title) = read_item(&conn, &bus, &path).await;
|
||||||
|
let id = format!("{}{}", bus, path);
|
||||||
|
bus_map.lock().unwrap().entry(bus).or_default().push(id.clone());
|
||||||
|
sender.input(AppInput::TrayUpdate(TrayUpdate::Add { id, icon, title }));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cleanup task — watches NameOwnerChanged and removes items when their owner exits.
|
||||||
|
relm4::spawn(async move {
|
||||||
|
let Ok(conn) = zbus::Connection::session().await else { return };
|
||||||
|
let Ok(proxy) = zbus::fdo::DBusProxy::new(&conn).await else { return };
|
||||||
|
let Ok(mut stream) = proxy.receive_name_owner_changed().await else { return };
|
||||||
|
while let Some(signal) = stream.next().await {
|
||||||
|
let Ok(args) = signal.args() else { continue };
|
||||||
|
if args.new_owner().is_none() {
|
||||||
|
let gone = args.name().to_string();
|
||||||
|
if let Some(ids) = bus_map_cleanup.lock().unwrap().remove(&gone) {
|
||||||
|
for id in ids {
|
||||||
|
sender_cleanup.input(AppInput::TrayUpdate(TrayUpdate::Remove { id }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert SNI ARGB pixel data (network byte order) to a GTK4 `Image`.
|
||||||
|
/// Falls back to an icon-name lookup or a placeholder on failure.
|
||||||
|
pub fn make_tray_image(icon: Option<&TrayIconData>) -> gtk4::Image {
|
||||||
|
let img = match icon {
|
||||||
|
Some(TrayIconData::Pixels { width, height, data }) => pixels_to_image(*width, *height, data),
|
||||||
|
Some(TrayIconData::Name(name)) => {
|
||||||
|
let img = gtk4::Image::from_icon_name(name);
|
||||||
|
img.set_pixel_size(16);
|
||||||
|
Some(img)
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
img.unwrap_or_else(|| {
|
||||||
|
let img = gtk4::Image::from_icon_name("image-missing");
|
||||||
|
img.set_pixel_size(16);
|
||||||
|
img
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pixels_to_image(width: i32, height: i32, data: &[u8]) -> Option<gtk4::Image> {
|
||||||
|
if data.len() != (width * height * 4) as usize {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
// SNI delivers ARGB big-endian: bytes are [A, R, G, B] per pixel.
|
||||||
|
// GTK4 R8g8b8a8 expects [R, G, B, A] per pixel.
|
||||||
|
let mut rgba = Vec::with_capacity(data.len());
|
||||||
|
for chunk in data.chunks_exact(4) {
|
||||||
|
rgba.push(chunk[1]);
|
||||||
|
rgba.push(chunk[2]);
|
||||||
|
rgba.push(chunk[3]);
|
||||||
|
rgba.push(chunk[0]);
|
||||||
|
}
|
||||||
|
let bytes = gtk4::glib::Bytes::from_owned(rgba);
|
||||||
|
let tex = gtk4::gdk::MemoryTexture::new(
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
gtk4::gdk::MemoryFormat::R8g8b8a8,
|
||||||
|
&bytes,
|
||||||
|
(width * 4) as usize,
|
||||||
|
);
|
||||||
|
let tex: gtk4::gdk::Texture = tex.upcast();
|
||||||
|
let img = gtk4::Image::from_paintable(Some(&tex));
|
||||||
|
img.set_pixel_size(16);
|
||||||
|
Some(img)
|
||||||
|
}
|
||||||
30
src/main.rs
30
src/main.rs
|
|
@ -34,6 +34,8 @@ pub struct App {
|
||||||
wifi_img: gtk4::Image,
|
wifi_img: gtk4::Image,
|
||||||
// Pre-loaded textures indexed by constant pointer values.
|
// Pre-loaded textures indexed by constant pointer values.
|
||||||
wifi_textures: std::collections::HashMap<usize, gtk4::gdk::Texture>,
|
wifi_textures: std::collections::HashMap<usize, gtk4::gdk::Texture>,
|
||||||
|
tray_box: gtk4::Box,
|
||||||
|
tray_items: std::collections::HashMap<String, gtk4::Button>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
@ -42,6 +44,7 @@ pub enum AppInput {
|
||||||
ActiveWorkspace(WorkspaceId),
|
ActiveWorkspace(WorkspaceId),
|
||||||
ClockTick,
|
ClockTick,
|
||||||
StatsUpdate(bar::stats::Stats),
|
StatsUpdate(bar::stats::Stats),
|
||||||
|
TrayUpdate(bar::tray::TrayUpdate),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[relm4::component(pub)]
|
#[relm4::component(pub)]
|
||||||
|
|
@ -153,6 +156,8 @@ impl SimpleComponent for App {
|
||||||
wifi_lbl: wifi_lbl.clone(),
|
wifi_lbl: wifi_lbl.clone(),
|
||||||
wifi_img: wifi_img.clone(),
|
wifi_img: wifi_img.clone(),
|
||||||
wifi_textures,
|
wifi_textures,
|
||||||
|
tray_box: gtk4::Box::new(gtk4::Orientation::Horizontal, 4),
|
||||||
|
tray_items: std::collections::HashMap::new(),
|
||||||
};
|
};
|
||||||
let widgets = view_output!();
|
let widgets = view_output!();
|
||||||
model.workspace_box = widgets.workspace_box.clone();
|
model.workspace_box = widgets.workspace_box.clone();
|
||||||
|
|
@ -179,12 +184,15 @@ impl SimpleComponent for App {
|
||||||
wifi_pair.append(&wifi_img);
|
wifi_pair.append(&wifi_img);
|
||||||
wifi_pair.append(&wifi_lbl);
|
wifi_pair.append(&wifi_lbl);
|
||||||
stats_box.append(&wifi_pair);
|
stats_box.append(&wifi_pair);
|
||||||
|
model.tray_box.add_css_class("tray-box");
|
||||||
|
stats_box.append(&model.tray_box);
|
||||||
widgets.center_box.set_end_widget(Some(&stats_box));
|
widgets.center_box.set_end_widget(Some(&stats_box));
|
||||||
|
|
||||||
theme::apply();
|
theme::apply();
|
||||||
bar::workspaces::spawn_watcher(sender.clone());
|
bar::workspaces::spawn_watcher(sender.clone());
|
||||||
bar::clock::spawn_ticker(sender.clone());
|
bar::clock::spawn_ticker(sender.clone());
|
||||||
bar::stats::spawn_poller(sender);
|
bar::stats::spawn_poller(sender.clone());
|
||||||
|
bar::tray::spawn_watcher(sender.clone());
|
||||||
notifications::spawn();
|
notifications::spawn();
|
||||||
osd::spawn();
|
osd::spawn();
|
||||||
|
|
||||||
|
|
@ -228,6 +236,26 @@ impl SimpleComponent for App {
|
||||||
self.wifi_img.set_paintable(Some(tex));
|
self.wifi_img.set_paintable(Some(tex));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AppInput::TrayUpdate(bar::tray::TrayUpdate::Add { id, icon, title }) => {
|
||||||
|
if self.tray_items.contains_key(&id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let btn = gtk4::Button::new();
|
||||||
|
btn.add_css_class("tray-btn");
|
||||||
|
btn.set_child(Some(&bar::tray::make_tray_image(icon.as_ref())));
|
||||||
|
if !title.is_empty() {
|
||||||
|
btn.set_tooltip_text(Some(&title));
|
||||||
|
}
|
||||||
|
let id_click = id.clone();
|
||||||
|
btn.connect_clicked(move |_| bar::tray::spawn_activate(id_click.clone()));
|
||||||
|
self.tray_box.append(&btn);
|
||||||
|
self.tray_items.insert(id, btn);
|
||||||
|
}
|
||||||
|
AppInput::TrayUpdate(bar::tray::TrayUpdate::Remove { id }) => {
|
||||||
|
if let Some(btn) = self.tray_items.remove(&id) {
|
||||||
|
self.tray_box.remove(&btn);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,7 +70,7 @@ impl NotifServer {
|
||||||
(
|
(
|
||||||
"breadbar".into(),
|
"breadbar".into(),
|
||||||
"breadway".into(),
|
"breadway".into(),
|
||||||
"0.1.0".into(),
|
env!("CARGO_PKG_VERSION").into(),
|
||||||
"1.2".into(),
|
"1.2".into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ fn volume_watcher(tx: mpsc::Sender<OsdEvent>) {
|
||||||
let stdout = child.stdout.take().unwrap();
|
let stdout = child.stdout.take().unwrap();
|
||||||
let reader = BufReader::new(stdout);
|
let reader = BufReader::new(stdout);
|
||||||
|
|
||||||
for line in reader.lines().flatten() {
|
for line in reader.lines().map_while(Result::ok) {
|
||||||
if line.contains("'change' on sink") {
|
if line.contains("'change' on sink") {
|
||||||
if let Some(evt) = query_volume() {
|
if let Some(evt) = query_volume() {
|
||||||
let _ = tx.blocking_send(evt);
|
let _ = tx.blocking_send(evt);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue