Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
170 commits
Select commit Hold shift + click to select a range
d7883e8
chore(tauri): add initial setup
hazre Mar 5, 2026
06d3c79
feat(tauri): disable web push notifications
hazre Mar 5, 2026
e01c01c
feat(tauri): use deep link for sso authentication
hazre Mar 5, 2026
6932dcb
feat(tauri): custom windows titlebar
hazre Mar 5, 2026
2e10f73
feat(tauri): add desktop system tray and option to close to tray
hazre Mar 5, 2026
9e4a814
fix(tauri): ignore formatting on generated tauri bindings
hazre Mar 6, 2026
5823d23
fix(tauri): deep linking breaking due to specta export
hazre Mar 6, 2026
80dce7a
feat(tauri): add sso callback page
hazre Mar 6, 2026
84e71cf
feat(tauri): keep track of window state and position
hazre Mar 6, 2026
535ded2
chore: add tauri.conf.json to knope.toml
hazre Mar 6, 2026
55da9f1
style: fix formatting of Router.tsx
hazre Mar 7, 2026
b709f38
feat(tauri): add android support and splash screen tauri plugin (WIP)
hazre Mar 7, 2026
782626a
chore: add crates to knip ignore list
hazre Mar 7, 2026
46e5650
fix: broken Router and linting issues
hazre Mar 7, 2026
880efc4
chore: ignore false positive for tauri-plugin-splashscreen-api in knip
hazre Mar 8, 2026
fd3f341
fix: merge conflicts in package-lock.json
hazre Mar 8, 2026
cb0413c
chore: remove accidentally committed build files and adjusted .gitignore
TastelessVoid Mar 9, 2026
f0a9f4f
fix: bypass service worker for media authentication on Android
TastelessVoid Mar 9, 2026
751c2fc
fix(build): allow PWA build with large wasm assets and split vendor c…
hazre Mar 8, 2026
46092a8
feat: Add UnifiedPush for Fairphones or phones that have been "de-goo…
TastelessVoid Mar 9, 2026
f5d90c0
feat: Add build.gradle.kts to specify a higher kotlin version and upd…
TastelessVoid Mar 9, 2026
0aa9cf8
fix: Commit the gen folder as the nested .gitignore should keep the r…
TastelessVoid Mar 9, 2026
f9f37a1
fix: Adjusted .gitignore and tracked files
TastelessVoid Mar 9, 2026
daeec60
feat(tauri): Implement media caching and notification enhancements
TastelessVoid Mar 10, 2026
ade84fa
feat(tauri): Addressed review, updated package
TastelessVoid Mar 10, 2026
c064680
feat(tauri): Fixed dynamical import warning, removed local crate due …
TastelessVoid Mar 10, 2026
2d8609b
fix(tauri): Fixed avatars in the notification not showing
TastelessVoid Mar 11, 2026
9c84d92
Merge branch 'dev' into feat/tauri-integration
TastelessVoid Mar 11, 2026
93bca4b
chore(tauri): Merge dev into feat/tauri-integration and resolved conf…
TastelessVoid Mar 11, 2026
0b97f55
Merge pull request #139 from TastelessVoid/feat/tauri-integration
hazre Mar 12, 2026
65e83ed
fix: make android actually build
hazre Mar 12, 2026
8667938
chore: merge dev into feat/tauri-integration
hazre Mar 12, 2026
abfaab5
chore: make quality checks happy
hazre Mar 12, 2026
fd6a135
chore: remove binary files
hazre Mar 12, 2026
bf36d2b
fix: sso login on mobile
hazre Mar 12, 2026
01d5cdc
chore: add nix devshell flake (android not tested)
hazre Mar 14, 2026
e867034
feat: add cef support and switch to tauri-typegen for bindings (wip)
hazre Mar 14, 2026
4795fb3
fix: move window creation into rust side for easier control
hazre Mar 14, 2026
187c592
chore: merge dev into feat/tauri-integration
hazre Mar 14, 2026
9c89e18
chore: merge dev into feat/tauri-integration
hazre Mar 25, 2026
3b63e35
refactor(tauri): remove splashscreen plugin integration
hazre Mar 25, 2026
6472652
chore: refresh tauri mobile dependencies
hazre Mar 26, 2026
08e044b
feat: unify background push transport
hazre Mar 26, 2026
4efba43
fix: gate service worker bootstrap by platform
hazre Mar 26, 2026
be4dd23
fix: repair android package and window startup
hazre Mar 26, 2026
3631575
feat: unify background push transport (#553)
hazre Mar 26, 2026
61febb8
feat: add edge-to-edge app shell
hazre Mar 28, 2026
5578658
fix: linux startup
hazre Apr 7, 2026
abb65ca
feat: add desktop tray settings
hazre Apr 7, 2026
a81199a
chore: update cargo dependencies
hazre Apr 7, 2026
6aa7d72
chore: merge dev into feat/tauri-integration
hazre Apr 7, 2026
e2e9426
fix: resolve post-merge regressions
hazre Apr 10, 2026
5c93992
chore: merge dev into feat/tauri-integration
hazre Apr 10, 2026
69d6cb6
refactor: unify authenticated media transport
hazre Apr 10, 2026
d54e671
refactor: add tauri-aware fetch wrapper
hazre Apr 10, 2026
1963bbd
fix: add linux startup env workaround
hazre Apr 11, 2026
f9e6a72
build: update tauri stack for dbus
hazre Apr 11, 2026
f616a00
build: use patched tauri-typegen
hazre Apr 11, 2026
5dc8487
(Tauri/fix):Android APK crashing and UnifiedPush not registering
TastelessVoid May 5, 2026
2c38acb
Fixed ESLint errors
TastelessVoid May 5, 2026
bfcb24c
fix(tauri): android APK crashing and UnifiedPush not registering (#747)
TastelessVoid May 5, 2026
8e3411f
build: update tauri deps
hazre May 5, 2026
ca2cf3f
chore: add android signing step on release
hazre May 5, 2026
7d49e48
git
TastelessVoid May 14, 2026
d780c45
Fix Tauri desktop builds and media caching
TastelessVoid May 14, 2026
68d02a1
Add keystore to gitignore, fixed AppImage failing due to GStreamer pl…
TastelessVoid May 15, 2026
be9a7c7
fix: harden media sanitization
7w1 Jun 26, 2026
e89de8c
feat: show unread count in page title
eleboucher Jul 15, 2026
5123fa0
fix: stop presence sync from resetting user status to online
eleboucher Jul 15, 2026
2ec3083
fix: re-anchor new messages divider at last read when tabbing out
eleboucher Jul 16, 2026
e6ddedd
Merge branch 'pr-134' into test/tauri-134-850
eleboucher Jul 17, 2026
ec91c35
Merge remote-tracking branch 'origin/dev' into feat/tauri-desktop
eleboucher Jul 17, 2026
d0c5d7d
fix: reconcile tauri integration with dev (media modules, routes, vit…
eleboucher Jul 17, 2026
6f07237
fix: use es2022 vite target for tauri builds to avoid top-level-await…
eleboucher Jul 17, 2026
b180c23
fix: show tauri window via TauriFrontendReady in App
eleboucher Jul 17, 2026
e786c20
feat(tauri): native OIDC login via system browser + sable:// deep-lin…
eleboucher Jul 17, 2026
f8d7c05
fix(tauri): render authenticated inline images via token blob-fetch w…
eleboucher Jul 17, 2026
78c9b52
feat(tauri): apply niki's tauri fixes; render mxc emoji/reactions via…
eleboucher Jul 17, 2026
56382a9
fix(tauri): unconditional banner media hook; real loadImageElementFro…
eleboucher Jul 17, 2026
cce5758
feat: handle image via uri scheme protocol
eleboucher Jul 17, 2026
d0cec4a
Fix notifications
nikiwastaken Jul 17, 2026
35510f1
Do not show desktop settings on mobile
nikiwastaken Jul 17, 2026
a2ce65d
fix(tauri): use valid origin for call widget parentUrl
eleboucher Jul 17, 2026
d936986
fix(tauri): declare camera/mic usage strings and allow inline styles
eleboucher Jul 17, 2026
213b1b8
fix(tauri): disable native drag-drop handler for HTML5 DnD
eleboucher Jul 17, 2026
5670c9e
fix(tauri): use getAppOrigin() for all origin-dependent paths
eleboucher Jul 17, 2026
95acdfd
fix(linux): declare GStreamer WebRTC plugin deps for deb/rpm
eleboucher Jul 17, 2026
64310c7
fix(linux): enable WebKitGTK WebRTC settings and auto-allow media per…
eleboucher Jul 17, 2026
4ab6572
fix(android): bump tao to 0.35.3 to prevent deep-link onNewIntent panic
eleboucher Jul 17, 2026
04a44ea
fix(android): register moe.sable.app deep-link scheme in manifest
eleboucher Jul 17, 2026
1c5b1b0
fix(android): guard release signing config when keystore.properties i…
eleboucher Jul 17, 2026
d1eea80
fix(tauri): route custom-protocol hosts through native fetch so encry…
eleboucher Jul 17, 2026
a69fbfb
Fix android assets
nikiwastaken Jul 17, 2026
7abb7b4
perf(tauri): reuse a shared reqwest client in the media protocol
eleboucher Jul 17, 2026
7c6114c
fix(tauri): only enable devtools in debug builds
eleboucher Jul 17, 2026
352b613
fix(linux): only auto-grant camera/mic webkit permissions, deny the rest
eleboucher Jul 17, 2026
e2b3e6f
fix(tauri): set native media session token so authenticated media loads
eleboucher Jul 17, 2026
32c9021
fix(notifications): start the foreground push transport listener at c…
eleboucher Jul 17, 2026
2f5ac8e
fix(tauri): use native clipboard plugin so copy/paste works on linux
eleboucher Jul 17, 2026
a3e3b8b
feat(tauri): add macOS menu and allow desktop notifications on linux
eleboucher Jul 17, 2026
0a4b1c4
feat(tauri): prompt for and remember webview permissions on linux
eleboucher Jul 17, 2026
eb445e1
feat(tauri): depend on geoclue for webview geolocation on linux
eleboucher Jul 17, 2026
38fd34f
fix(android): save downloaded attachments via native file system plugin
eleboucher Jul 17, 2026
328288c
chore(android): prepare native FCM push (Sygnal) wiring behind google…
eleboucher Jul 17, 2026
505cc1f
fix(android): declare camera/mic permissions so WebRTC calls can requ…
eleboucher Jul 17, 2026
7fbb64e
chore(tauri): drop unused macOS location usage string
eleboucher Jul 17, 2026
2da28be
fix(notifications): establish and refresh the unifiedpush pusher via …
eleboucher Jul 17, 2026
82a389c
fix(notifications): re-persist selected unifiedpush distributor on re…
eleboucher Jul 17, 2026
417bbe9
Move service worker initialization
nikiwastaken Jul 17, 2026
93b7de8
feat(android): tint native status bar with the open screen's surface …
eleboucher Jul 17, 2026
95ae0d9
fix(pdf): contain render failures instead of crashing the app
eleboucher Jul 17, 2026
6eed3a5
feat(mobile): finger-tracked swipe drawer for room list navigation
eleboucher Jul 18, 2026
6734fea
refactor(swipe): track overlay swipe via live-seeded offset
eleboucher Jul 18, 2026
93d32a8
perf(avatar): lazy-load avatars and drop SVG refetch reprocessing
eleboucher Jul 18, 2026
668886c
chore(tauri): regenerate command bindings
eleboucher Jul 18, 2026
94b97d0
fix(mobile): restore room-list scroll and reliable swipe reveal
eleboucher Jul 18, 2026
35a9396
perf(room): navigate to rooms in a transition to keep the UI responsive
eleboucher Jul 18, 2026
2006bb3
fix(lint): correct hook usage, drop unused imports, and type test mocks
eleboucher Jul 18, 2026
aedfa7a
Merge branch 'dev' into feat/tauri-desktop
eleboucher Jul 18, 2026
fcc0599
Refresh icons again
nikiwastaken Jul 18, 2026
40fe62d
feat(notifications): swap SableClient fork for Choochmeque tauri-plug…
eleboucher Jul 18, 2026
ac77907
fix(android): use HTTPS scheme for secure-context APIs
eleboucher Jul 18, 2026
93c9bc7
fix(deps): use npm registry for choochmeque notifications-api
eleboucher Jul 18, 2026
b676fb5
fix(android): remove invalid unified-push permission names from mobil…
eleboucher Jul 18, 2026
1fe606e
Merge origin/dev into feat/tauri-desktop
eleboucher Jul 18, 2026
3a8bd64
format
eleboucher Jul 18, 2026
86403ae
fix(notifications): handle missing UnifiedPush distributor command on…
eleboucher Jul 18, 2026
e478112
feat(android): add tauri-plugin-unifiedpush for intent-based UnifiedPush
eleboucher Jul 18, 2026
719f987
fix(android): route theme fetch through Tauri HTTP plugin
eleboucher Jul 18, 2026
0208d8a
fix(android): fix plugin build.rs API and route remaining fetch throu…
eleboucher Jul 18, 2026
87378da
fix(android): import mobile module and use State::inner() in commands
eleboucher Jul 18, 2026
46e162d
fix(android): import Manager trait for State access
eleboucher Jul 18, 2026
895c0da
fix(android): add Serialize derive to plugin arg structs
eleboucher Jul 18, 2026
7a51c66
fix(android): add queries intent for UnifiedPush distributor visibility
eleboucher Jul 18, 2026
eaabb52
fix(ios): properly guard serviceWorker in navigator
mortebrume Jul 18, 2026
61da323
feat(android): add tauri-plugin-unifiedpush and route fetch through T…
eleboucher Jul 18, 2026
c69f4b0
add generated files
eleboucher Jul 18, 2026
ee1b50e
chore: add apple outputs to gitignore
mortebrume Jul 18, 2026
cb71ffc
fix(android): make UnifiedPush notifications work when app is open or…
eleboucher Jul 18, 2026
eff9eea
fix(ios): correctly calculate keyboard offset position
mortebrume Jul 18, 2026
b1a9455
fix(ios): hide the WKWebView input accessory bar
mortebrume Jul 18, 2026
b89b198
fix(ios): capitalize name
mortebrume Jul 18, 2026
f94897a
fix(android): apply CSP nonce so custom themes render in the WebView
eleboucher Jul 18, 2026
90647a8
fix(android): declare location permissions so navigator.geolocation w…
eleboucher Jul 18, 2026
49479f3
feat(tauri): add CEF (Chromium) runtime on Linux for WebRTC calling
eleboucher Jul 18, 2026
c968f72
fix(ios-android): remove bottom border
mortebrume Jul 18, 2026
cc66b11
fix(macos): titlebar adjustements
mortebrume Jul 18, 2026
adcc7cd
fix(macos): remove tray
mortebrume Jul 18, 2026
48592aa
fix(macos): regenerate icons with tahoe 26+ format
mortebrume Jul 18, 2026
0f3297a
feat(tauri): tint navigation bar with the adjacent surface and remove…
eleboucher Jul 18, 2026
b123a52
ci(tauri): build desktop apps and native packages on release
eleboucher Jul 18, 2026
ca3b2ed
feat(tauri): show desktop notifications via the native plugin on Linu…
eleboucher Jul 18, 2026
44206cf
feat(tauri): add desktop auto-updater with signed release artifacts
eleboucher Jul 18, 2026
6a2502e
fix(tauri): package full CEF runtime and correct AppImage sandbox han…
eleboucher Jul 18, 2026
4598d67
fix(android): keep system bars transparent so the webview strips colo…
eleboucher Jul 18, 2026
538b386
fix(tauri): add CEF switches for NVIDIA GPU crash and blurry fonts
eleboucher Jul 18, 2026
346c6f0
fix(sync): reconnect immediately on mobile app resume
eleboucher Jul 18, 2026
c02ddb4
Fix account page UI
nikiwastaken Jul 18, 2026
7aac4ed
Add RUST_SRC in flake
nikiwastaken Jul 18, 2026
68101dc
feat(tauri): native file downloads on desktop and Android with save t…
eleboucher Jul 18, 2026
75dd045
feat(tauri): smoother mobile sidebar drawer transition on iOS/Android
eleboucher Jul 18, 2026
81f561c
feat(tauri): use fork notifications plugin with native macOS backend
eleboucher Jul 18, 2026
a5cda5d
fix(sync): debounce connection-lost banner instead of ineffective res…
eleboucher Jul 18, 2026
17aa711
chore(tauri): stop tracking generated .typecache cache
eleboucher Jul 18, 2026
5c5c9d6
Merge remote-tracking branch 'origin/dev' into feat/tauri-desktop
eleboucher Jul 18, 2026
60da298
fix fmt
eleboucher Jul 18, 2026
228684b
fix(ci): use console.warn in updater manifest script to satisfy no-co…
eleboucher Jul 18, 2026
e911fc0
feat(desktop): improve notification logic and add badges
mortebrume Jul 18, 2026
9bb2208
test(settings): await notifications section render after menu navigation
eleboucher Jul 18, 2026
ab4538a
style(tauri): format tauri.conf.json to satisfy fmt check
eleboucher Jul 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 5 additions & 0 deletions .changeset/fix-presence-reset.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
default: patch
---

Fix presence status resetting to "online".
64 changes: 64 additions & 0 deletions .github/scripts/build-updater-manifest.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Composes the Tauri updater manifest (latest.json) from the per-platform .sig
// assets already attached to the release.
// Required env: TAG, REPO, GH_TOKEN.

import { execSync } from 'node:child_process';
import { readFileSync, readdirSync, writeFileSync, mkdtempSync } from 'node:fs';
import { tmpdir } from 'node:os';
import { join } from 'node:path';

const TAG = process.env.TAG;
const REPO = process.env.REPO;
if (!TAG || !REPO) {
console.error('TAG and REPO env vars are required');
process.exit(1);
}
const version = TAG.replace(/^v/, '');

const dir = mkdtempSync(join(tmpdir(), 'sable-sigs-'));
execSync(`gh release download "${TAG}" --repo "${REPO}" --pattern '*.sig' --dir "${dir}"`, {
stdio: 'inherit',
});

const urlFor = (name) =>
`https://github.com/${REPO}/releases/download/${TAG}/${encodeURIComponent(name)}`;

const platforms = {};
let windowsIsNsis = false;

for (const sig of readdirSync(dir).filter((f) => f.endsWith('.sig'))) {
const artifact = sig.replace(/\.sig$/, '');
const entry = { signature: readFileSync(join(dir, sig), 'utf8').trim(), url: urlFor(artifact) };
const name = artifact.toLowerCase();

if (name.endsWith('.app.tar.gz')) {
platforms['darwin-aarch64'] = entry;
platforms['darwin-x86_64'] = entry;
} else if (name.endsWith('.appimage')) {
platforms['linux-x86_64'] = entry;
} else if (name.endsWith('-setup.exe') || name.endsWith('.nsis.zip')) {
platforms['windows-x86_64'] = entry;
windowsIsNsis = true;
} else if (name.endsWith('.msi') && !windowsIsNsis) {
platforms['windows-x86_64'] = entry;
}
}

if (Object.keys(platforms).length === 0) {
console.error('No .sig assets found on the release; nothing to publish.');
process.exit(1);
}

let notes = `Sable ${version}`;
try {
notes =
execSync(`gh release view "${TAG}" --repo "${REPO}" --json body -q .body`, {
encoding: 'utf8',
}).trim() || notes;
} catch {
// keep the default note
}

const manifest = { version, notes, pub_date: new Date().toISOString(), platforms };
writeFileSync('latest.json', JSON.stringify(manifest, null, 2));
console.warn(JSON.stringify(manifest, null, 2));
20 changes: 20 additions & 0 deletions .github/scripts/set-tauri-version.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env node
/* oxlint-disable no-console */

// Stamps a version into src-tauri/tauri.conf.json, which can drift from the
// package.json version Knope tags on. Used by tauri-build.yml.

import { readFileSync, writeFileSync } from 'node:fs';
import process from 'node:process';

const version = process.argv[2];
if (!version || !/^\d+\.\d+\.\d+/.test(version)) {
console.error(`Usage: set-tauri-version.mjs <version> (got: ${version ?? '<none>'})`);
process.exit(1);
}

const file = 'src-tauri/tauri.conf.json';
const config = JSON.parse(readFileSync(file, 'utf8'));
config.version = version;
writeFileSync(file, `${JSON.stringify(config, null, 2)}\n`);
console.log(`Set ${file} version to ${version}`);
264 changes: 264 additions & 0 deletions .github/workflows/tauri-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
name: Build desktop apps

on:
push:
tags: ['v*']
workflow_dispatch:
inputs:
tag:
description: 'Release tag to build and attach desktop bundles to (e.g. v1.20.0)'
required: true
type: string

permissions: {}

concurrency:
group: tauri-build-${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
cancel-in-progress: false

jobs:
build:
name: Build ${{ matrix.name }}
runs-on: ${{ matrix.platform }}
permissions:
contents: write
strategy:
fail-fast: false
matrix:
include:
- name: macOS
platform: macos-latest
rust-targets: aarch64-apple-darwin,x86_64-apple-darwin
args: --target universal-apple-darwin
- name: Windows
platform: windows-latest
rust-targets: ''
args: ''
- name: Linux (CEF)
platform: ubuntu-22.04
rust-targets: ''
cef: true
env:
TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
NODE_OPTIONS: --max-old-space-size=8192
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_SIGNING_PRIVATE_KEY_PASSWORD }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
persist-credentials: false

- name: Wait for release to exist
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
for i in $(seq 1 12); do
if gh release view "$TAG" >/dev/null 2>&1; then
echo "Release $TAG found."
exit 0
fi
echo "Waiting for release $TAG to be published ($i/12)…"
sleep 15
done
echo "Release $TAG was not found." >&2
exit 1

- name: Install Linux build dependencies
if: matrix.cef
shell: bash
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libgtk-3-dev \
libayatana-appindicator3-dev \
librsvg2-dev \
libsoup-3.0-dev \
libssl-dev \
libxdo-dev \
build-essential \
file \
rpm \
ruby \
ruby-dev
sudo gem install --no-document fpm

- name: Setup app
uses: ./.github/actions/setup

- name: Setup Rust
uses: dtolnay/rust-toolchain@2c7215f132e9ebf062739d9130488b56d53c060c # stable
with:
toolchain: stable
targets: ${{ matrix.rust-targets }}

- name: Cache Rust build
uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
workspaces: src-tauri

- name: Stamp release version into tauri.conf.json
shell: bash
run: node .github/scripts/set-tauri-version.mjs "${TAG#v}"

# --- macOS / Windows: standard wry build via tauri-action ---
- name: Build desktop bundles
id: tauri
if: ${{ !matrix.cef }}
uses: tauri-apps/tauri-action@1deb371b0cd8bd54025b384f1cd735e725c4060f # action-v1.0.0
with:
args: ${{ matrix.args }}

- name: Attach bundles to release
if: ${{ !matrix.cef }}
shell: bash
env:
GH_TOKEN: ${{ github.token }}
ARTIFACTS: ${{ steps.tauri.outputs.artifactPaths }}
run: |
echo "$ARTIFACTS" | jq -r '.[]' | while read -r path; do
[ -n "$path" ] || continue
echo "Uploading $path"
gh release upload "$TAG" "$path" --clobber
done

# --- Linux: CEF runtime, packaged as deb / rpm / AppImage ---
- name: Build frontend
if: matrix.cef
shell: bash
run: pnpm build

- name: Build CEF binary
if: matrix.cef
shell: bash
run: |
cargo build --release --features cef --no-default-features \
--manifest-path src-tauri/Cargo.toml

- name: Build native packages
if: matrix.cef
shell: bash
run: |
VERSION="${TAG#v}"
STAGE="src-tauri/target/release"

# Binary plus the full CEF runtime (cef-copy-libs is the single source
# of truth for the runtime file set).
stage_runtime() {
local dest="$1"
mkdir -p "$dest"
cp "$STAGE/sable" "$dest/"
scripts/cef-copy-libs.sh release "$dest"
}

write_desktop() {
cat > "$1" <<'EOF'
[Desktop Entry]
Type=Application
Name=Sable
Comment=A Matrix client
Exec=sable %U
Icon=sable
Terminal=false
Categories=Network;InstantMessaging;Chat;
StartupWMClass=sable
MimeType=x-scheme-handler/sable;x-scheme-handler/moe.sable.app;
EOF
}

ROOT="pkgroot"
stage_runtime "$ROOT/opt/sable"
mkdir -p "$ROOT/usr/bin" "$ROOT/usr/share/applications" \
"$ROOT/usr/share/icons/hicolor/128x128/apps"
cat > "$ROOT/usr/bin/sable" <<'EOF'
#!/bin/sh
exec /opt/sable/sable "$@"
EOF
chmod 755 "$ROOT/usr/bin/sable"
write_desktop "$ROOT/usr/share/applications/sable.desktop"
cp src-tauri/icons/128x128.png "$ROOT/usr/share/icons/hicolor/128x128/apps/sable.png"

COMMON=(-s dir -n sable -v "$VERSION" --iteration 1
--description "Sable — a Matrix client"
--url "https://sable.moe" --maintainer "SableClient"
--category net)
# Stable-named deps only: version-suffixed names (e.g. the 24.04 t64
# set) would break install on other releases; CEF bundles its own libs.
DEB_DEPS=(--depends libwebkit2gtk-4.1-0 --depends libgtk-3-0
--depends libnss3 --depends libnspr4 --depends libgbm1
--depends libdrm2 --depends libxkbcommon0 --depends xdg-utils)
fpm "${COMMON[@]}" -t deb -a amd64 "${DEB_DEPS[@]}" -C "$ROOT" .

RPM_DEPS=(--depends webkit2gtk4.1 --depends gtk3 --depends nss
--depends nspr --depends mesa-libgbm --depends libdrm
--depends libxkbcommon --depends xdg-utils)
fpm "${COMMON[@]}" -t rpm -a x86_64 "${RPM_DEPS[@]}" -C "$ROOT" .

APPDIR="Sable.AppDir"
stage_runtime "$APPDIR/usr/bin"
# nosuid mount: a setuid chrome-sandbox can't work here and would stop
# Chromium from starting, so drop it and use the user-namespace sandbox.
rm -f "$APPDIR/usr/bin/chrome-sandbox"
write_desktop "$APPDIR/sable.desktop"
cp src-tauri/icons/128x128.png "$APPDIR/sable.png"
cat > "$APPDIR/AppRun" <<'EOF'
#!/bin/sh
HERE="$(dirname "$(readlink -f "$0")")"
exec "$HERE/usr/bin/sable" "$@"
EOF
chmod 755 "$APPDIR/AppRun"

curl -fsSL -o appimagetool \
https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage
chmod +x appimagetool
# Runner has no FUSE; extract-and-run instead of mounting.
APPIMAGE_EXTRACT_AND_RUN=1 ARCH=x86_64 \
./appimagetool "$APPDIR" "Sable_${VERSION}_amd64.AppImage"

- name: Sign the AppImage for the updater
if: ${{ matrix.cef && env.TAURI_SIGNING_PRIVATE_KEY != '' }}
shell: bash
run: |
for f in Sable_*_amd64.AppImage; do
[ -e "$f" ] || continue
pnpm tauri signer sign "$f"
done

- name: Attach native packages to release
if: matrix.cef
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
for f in sable_*.deb sable-*.rpm Sable_*_amd64.AppImage Sable_*_amd64.AppImage.sig; do
[ -e "$f" ] || continue
echo "Uploading $f"
gh release upload "$TAG" "$f" --clobber
done

updater-manifest:
name: Publish updater manifest
needs: build
runs-on: ubuntu-latest
permissions:
contents: write
env:
TAG: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref_name }}
REPO: ${{ github.repository }}
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.tag || github.ref }}
persist-credentials: false

- name: Build and upload latest.json
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
node .github/scripts/build-updater-manifest.mjs
gh release upload "$TAG" latest.json --clobber
29 changes: 28 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ devAssets

.DS_Store
.idea

*.code-workspace
.env

.wrangler
Expand All @@ -24,6 +24,33 @@ build.sh
# the following line was added with the "git ignore" tool by itsrye.dev, version 0.1.0
.lh

# Tauri
/build
/target/
/gen/schemas
dist-js

# Gradle / Android build artifacts
**/android/build/
**/android/.tauri/
**/android/.gradle/
**/.gradle/

# Rust build artifacts
src-tauri/target/
# Tauri Android build outputs
src-tauri/gen/android/app/build/
# Tauri Apple outputs
src-tauri/gen/apple/*
# Tauri Android release keystore
*.jks

# Tauri-typegen cache
.typecache

# Worktrees
.worktrees

# the following line was added with nvim by Shea because its annoying to clear every so often
.vscode/bookmarks.json

Expand Down
Loading
Loading