diff --git a/assets/icons/peerspeak-128.png b/assets/icons/peerspeak-128.png new file mode 100644 index 0000000..ffb3e59 Binary files /dev/null and b/assets/icons/peerspeak-128.png differ diff --git a/assets/icons/peerspeak-128.rgba b/assets/icons/peerspeak-128.rgba new file mode 100644 index 0000000..9222d40 Binary files /dev/null and b/assets/icons/peerspeak-128.rgba differ diff --git a/assets/icons/peerspeak-16.png b/assets/icons/peerspeak-16.png new file mode 100644 index 0000000..97609c2 Binary files /dev/null and b/assets/icons/peerspeak-16.png differ diff --git a/assets/icons/peerspeak-24.png b/assets/icons/peerspeak-24.png new file mode 100644 index 0000000..f39d021 Binary files /dev/null and b/assets/icons/peerspeak-24.png differ diff --git a/assets/icons/peerspeak-256.png b/assets/icons/peerspeak-256.png new file mode 100644 index 0000000..50ac6a6 Binary files /dev/null and b/assets/icons/peerspeak-256.png differ diff --git a/assets/icons/peerspeak-32.png b/assets/icons/peerspeak-32.png new file mode 100644 index 0000000..b2e0d10 Binary files /dev/null and b/assets/icons/peerspeak-32.png differ diff --git a/assets/icons/peerspeak-48.png b/assets/icons/peerspeak-48.png new file mode 100644 index 0000000..b163bf4 Binary files /dev/null and b/assets/icons/peerspeak-48.png differ diff --git a/assets/icons/peerspeak-512.png b/assets/icons/peerspeak-512.png new file mode 100644 index 0000000..c60cf96 Binary files /dev/null and b/assets/icons/peerspeak-512.png differ diff --git a/assets/icons/peerspeak-64.png b/assets/icons/peerspeak-64.png new file mode 100644 index 0000000..05b7a44 Binary files /dev/null and b/assets/icons/peerspeak-64.png differ diff --git a/assets/icons/peerspeak.svg b/assets/icons/peerspeak.svg new file mode 100644 index 0000000..4d2444a --- /dev/null +++ b/assets/icons/peerspeak.svg @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packaging/PKGBUILD b/packaging/PKGBUILD new file mode 100644 index 0000000..932feea --- /dev/null +++ b/packaging/PKGBUILD @@ -0,0 +1,68 @@ +# Maintainer: mollusk +pkgname=peerspeak-git +_pkgname=peerspeak +pkgver=0.1.0 +pkgrel=1 +pkgdesc="Decentralized peer-to-peer voice chat (Rust/iroh/PipeWire/Opus/iced)" +arch=('x86_64') +url="https://gitbutter.xyz/mollusk/peerspeak" +license=('custom') +depends=('pipewire' 'opus') +makedepends=('git' 'cargo' 'pkgconf') +optdepends=('pixelpass: screen sharing inside a room' + 'mpv: screen-share viewer (vlc is used as a fallback)') +provides=('peerspeak') +conflicts=('peerspeak') +options=('!lto' '!debug') +source=("$_pkgname::git+ssh://git@gitbutter.xyz/mollusk/peerspeak.git") +sha256sums=('SKIP') + +pkgver() { + cd "$srcdir/$_pkgname" + # 0.1.0.r.g — sorts monotonically across rebuilds. + printf '%s.r%s.g%s' \ + "$(awk -F'\"' '/^version =/{print $2; exit}' Cargo.toml)" \ + "$(git rev-list --count HEAD)" \ + "$(git rev-parse --short HEAD)" +} + +prepare() { + cd "$srcdir/$_pkgname" + # Vendor deps up front so build() can run --frozen (no surprise network). + export CARGO_HOME="$srcdir/cargo-home" + cargo fetch --locked --target "$(rustc -vV | sed -n 's/host: //p')" +} + +build() { + cd "$srcdir/$_pkgname" + export CARGO_HOME="$srcdir/cargo-home" + export RUSTUP_TOOLCHAIN=stable + export CARGO_TARGET_DIR=target + cargo build --frozen --release --bin "$_pkgname" +} + +check() { + cd "$srcdir/$_pkgname" + export CARGO_HOME="$srcdir/cargo-home" + export RUSTUP_TOOLCHAIN=stable + # Library unit tests only — the integration suites bind real iroh/QUIC + # endpoints and fail in a sandboxed/offline build environment. + cargo test --frozen --release --lib +} + +package() { + cd "$srcdir/$_pkgname" + + install -Dm755 "target/release/$_pkgname" "$pkgdir/usr/bin/$_pkgname" + install -Dm644 "packaging/$_pkgname.desktop" \ + "$pkgdir/usr/share/applications/$_pkgname.desktop" + + # Hicolor icon theme (scalable SVG + the rendered raster sizes). + install -Dm644 "assets/icons/$_pkgname.svg" \ + "$pkgdir/usr/share/icons/hicolor/scalable/apps/$_pkgname.svg" + local s + for s in 16 24 32 48 64 128 256 512; do + install -Dm644 "assets/icons/$_pkgname-$s.png" \ + "$pkgdir/usr/share/icons/hicolor/${s}x${s}/apps/$_pkgname.png" + done +} diff --git a/packaging/peerspeak.desktop b/packaging/peerspeak.desktop new file mode 100644 index 0000000..2f3694b --- /dev/null +++ b/packaging/peerspeak.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Type=Application +Name=PeerSpeak +GenericName=P2P Voice Chat +Comment=Decentralized peer-to-peer voice chat +Exec=peerspeak +Icon=peerspeak +Terminal=false +Categories=Network;Telephony;Chat; +Keywords=voice;chat;voip;p2p;peer; +StartupWMClass=peerspeak diff --git a/src/app/mod.rs b/src/app/mod.rs index d55c044..7765b7f 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -336,6 +336,15 @@ pub fn run_gui() -> iced::Result { // dock doesn't squeeze the controls column). Layout is responsive. size: init_size, position: iced::window::Position::Centered, + // App/taskbar icon (mainly used on X11/XWayland; native Wayland takes + // the icon from the .desktop file matched by app_id instead). + icon: window_icon(), + // app_id must match the .desktop basename so Wayland compositors + // (e.g. KWin) attach our launcher icon to the window. + platform_specific: iced::window::settings::PlatformSpecific { + application_id: "peerspeak".to_string(), + ..Default::default() + }, // We save the final size ourselves on CloseRequested, then exit. exit_on_close_request: false, ..Default::default() @@ -343,6 +352,14 @@ pub fn run_gui() -> iced::Result { .run() } +/// Build the window icon from an embedded 128×128 straight-RGBA blob rendered +/// from `assets/icons/peerspeak.svg`. Using `from_rgba` (always available) keeps +/// us off iced's heavy `image` feature — the blob is raw pixels, no decoder. +fn window_icon() -> Option { + const RGBA: &[u8] = include_bytes!("../../assets/icons/peerspeak-128.rgba"); + iced::window::icon::from_rgba(RGBA.to_vec(), 128, 128).ok() +} + fn subscription(_state: &AppState) -> Subscription { let core_sub = Subscription::run(core_subscription).map(AppMessage::UiEventReceived); let event_sub = iced::event::listen().map(AppMessage::EventOccurred);