diff --git a/pkgbuilds/slack-desktop/.omarchy/package.json b/pkgbuilds/slack-desktop/.omarchy/package.json new file mode 100644 index 0000000..0eca1ed --- /dev/null +++ b/pkgbuilds/slack-desktop/.omarchy/package.json @@ -0,0 +1,9 @@ +{ + "source": "local", + "upstream": { + "watch": { + "json": "https://slack.com/api/desktop.latestRelease?arch=x64&variant=deb", + "path": "version" + } + } +} diff --git a/pkgbuilds/slack-desktop/PKGBUILD b/pkgbuilds/slack-desktop/PKGBUILD new file mode 100644 index 0000000..2d8a089 --- /dev/null +++ b/pkgbuilds/slack-desktop/PKGBUILD @@ -0,0 +1,160 @@ +# Maintainer: Ryan Hughes + +pkgname=slack-desktop +pkgver=4.52.171 +pkgrel=1 +# Slack publishes Linux builds for x86_64 only. Its application code runs +# unchanged on the AArch64 build of the Electron release it ships with; see +# README.md for the native modules that are replaced or dropped. +_electronver=44.4.5 +pkgdesc='Slack Desktop for Linux on a native AArch64 Electron runtime' +arch=('aarch64') +url='https://slack.com/downloads' +license=('custom') +depends=( + 'alsa-lib' + 'at-spi2-core' + 'cairo' + 'dbus' + 'expat' + 'fontconfig' + 'gcc-libs' + 'glib2' + 'glibc' + 'gtk3' + 'libcups' + 'libnotify' + 'libsecret' + 'libx11' + 'libxcb' + 'libxcomposite' + 'libxdamage' + 'libxext' + 'libxfixes' + 'libxkbcommon' + 'libxrandr' + 'mesa' + 'nspr' + 'nss' + 'pango' + 'systemd-libs' + 'xdg-utils' +) +optdepends=( + 'libappindicator-gtk3: Systray indicator support' + 'org.freedesktop.secrets: Keyring password store support' +) +makedepends=('asar') +options=('!debug' '!strip') +source=( + "slack-desktop-${pkgver}-amd64.deb::https://downloads.slack-edge.com/desktop-releases/linux/x64/${pkgver}/slack-desktop-${pkgver}-amd64.deb" + "electron-v${_electronver}-linux-arm64.zip::https://github.com/electron/electron/releases/download/v${_electronver}/electron-v${_electronver}-linux-arm64.zip" + 'slack.desktop' + 'slack-desktop-utils.js' + 'file-handler-info.js' + 'electron-native-auth.js' +) +noextract=( + "slack-desktop-${pkgver}-amd64.deb" + "electron-v${_electronver}-linux-arm64.zip" +) +sha256sums=('c6199816e6d842289869a9e84a05042af6e0de68959df7a15e7273873b86dc36' + '3bf0acab49c4ea3c9283cdb86bf3dd7204bd52a6fba6c8ae51101bdba2adae0e' + 'e438e78265f3e566990300946afb4ea5d09bcd8c426738ab8f486ae9ddb86c0f' + '6de40409af5a04605c3287cb3c661132eb55a4f636f7cd9bbfd456f4adf41971' + 'a2a8fd45daa4f493ad4487da9f01477233feecfef360ed366bfb0a58f804890a' + '9cd53c84fdc407c83f2ca6e9485916296f3712b2742dcc0acf22fda5195ead50') + +# x86_64 addons in Slack's app that can never load on AArch64. The three that +# Slack requires on Linux are replaced by the JavaScript files above; the rest +# are Windows/macOS helpers or degrade on failure (native-keymap). Any other +# foreign binary fails the build so a new native module gets reviewed. +_x86_addons=( + '@tinyspeck/slack-desktop-utils/lib/binding/napi-v8/slackdesktoputils.node' + 'file-handler-info/build/Release/file_handler_info.node' + 'electron-native-auth/build/Release/electron_native_auth.node' + '@tinyspeck/native-keymap/build/Release/keymapping.node' + 'cf-prefs/build/Release/cf-prefs.node' + 'macos-notification-state/build/Release/notificationstate.node' + 'registry-js/build/Release/registry.node' + 'windows-focus-assist/build/Release/focusassist.node' +) + +prepare() { + rm -rf slack electron app + mkdir slack electron + bsdtar -O -xf "slack-desktop-${pkgver}-amd64.deb" 'data.tar.*' | bsdtar -C slack -xf - + bsdtar -C electron -xf "electron-v${_electronver}-linux-arm64.zip" + + local slack_electron + slack_electron=$(/dev/null | + sed -n 's/^[[:space:]]*Machine:[[:space:]]*//p') + case "$machine" in + '' | AArch64) ;; + *) error "Unexpected ${machine} binary: ${file#"$pkgdir"}"; return 1 ;; + esac + done < <(find "$lib" -type f -print0) + + find "$lib" -type d -exec chmod 755 {} + + find "$lib" -type f -exec chmod 644 {} + + # Chromium sandboxes through unprivileged user namespaces, which Arch-family + # kernels allow; a setuid-root helper is not needed. + chmod 755 "$lib/slack" "$lib/chrome_crashpad_handler" "$lib/chrome-sandbox" + + install -d "$pkgdir/usr/bin" + ln -s /usr/lib/slack/slack "$pkgdir/usr/bin/slack" + install -Dm644 slack.desktop "$pkgdir/usr/share/applications/slack.desktop" + install -Dm644 slack/usr/share/pixmaps/slack.png \ + "$pkgdir/usr/share/icons/hicolor/512x512/apps/slack.png" + + local licenses="$pkgdir/usr/share/licenses/$pkgname" + install -Dm644 slack/usr/lib/slack/LICENSE "$licenses/LICENSE" + install -Dm644 slack/usr/share/doc/slack-desktop/OPEN_SOURCE_LICENSE_ATTRIBUTIONS \ + "$licenses/OPEN_SOURCE_LICENSE_ATTRIBUTIONS" + install -Dm644 electron/LICENSE "$licenses/LICENSE.electron.txt" + install -Dm644 electron/LICENSES.chromium.html "$licenses/LICENSES.chromium.html" +} diff --git a/pkgbuilds/slack-desktop/README.md b/pkgbuilds/slack-desktop/README.md new file mode 100644 index 0000000..b186dbe --- /dev/null +++ b/pkgbuilds/slack-desktop/README.md @@ -0,0 +1,22 @@ +# Slack on ARM + +Slack publishes Linux builds for x86_64 only, and the AUR `slack-desktop` recipe repackages that `.deb`. This package runs the same application code on the AArch64 build of the Electron release Slack ships with, so `yay -S slack-desktop` on an ARM Omarchy install resolves to a working package. + +## Electron version + +`_electronver` must equal the Electron version inside Slack's `.deb` (`usr/lib/slack/version`). `prepare()` refuses to build when they differ and prints the version to set. A Slack release that moves to a new Electron therefore fails its sync PR build until `_electronver` and the Electron checksum are updated; the upstream watch only tracks Slack's version. + +## Native modules + +Slack's app carries eight x86_64 Node addons. None can load on AArch64, so they are removed, and the build fails on any other foreign binary so a new native module is reviewed before it ships. + +Three are required while Slack boots on Linux and are replaced by JavaScript: + +- `file-handler-info` and `electron-native-auth` are MIT-licensed and their Linux builds compile no-op implementations (`impl_none.cc`, `addon_none.cc`). The replacements return the same results. +- `@tinyspeck/slack-desktop-utils` is closed source. Its replacement throws `Method not implemented` from every native call, which is the error Slack's own wrapper uses for methods a platform lacks. Slack catches it, so these Linux features are unavailable: double-press and combo global shortcuts, the huddle screen-share border overlay, audio device detail lookups, clipboard set-and-paste, and haptics. + +`@tinyspeck/native-keymap` already catches a missing addon and returns defaults, so keyboard layout detection reports `unknown`. The other four addons are Windows/macOS helpers that Slack does not use on Linux. + +## Validation + +Installed and used on an aarch64 Omarchy machine (N1x). Features listed above as unavailable were not expected to work and were not checked. diff --git a/pkgbuilds/slack-desktop/electron-native-auth.js b/pkgbuilds/slack-desktop/electron-native-auth.js new file mode 100644 index 0000000..db163c4 --- /dev/null +++ b/pkgbuilds/slack-desktop/electron-native-auth.js @@ -0,0 +1,14 @@ +// Linux builds of electron-native-auth (github.com/clavin/electron-native-auth) +// compile src/addon_none.cc: native auth sessions are unavailable and +// constructing a request throws. This is the same facade in JavaScript. +class AuthRequest { + static isAvailable() { + return false; + } + + constructor() { + throw new Error('this function is not implemented for this platform'); + } +} + +exports.AuthRequest = AuthRequest; diff --git a/pkgbuilds/slack-desktop/file-handler-info.js b/pkgbuilds/slack-desktop/file-handler-info.js new file mode 100644 index 0000000..fabea00 --- /dev/null +++ b/pkgbuilds/slack-desktop/file-handler-info.js @@ -0,0 +1,9 @@ +// Linux builds of file-handler-info (github.com/clavin/node-file-handler-info) +// compile src/impl_none.cc, which finds no handler. This is the same result +// without an architecture-specific addon. +exports.getHandlerInfo = (filePath) => { + if (typeof filePath !== 'string') { + throw new TypeError('Expected 1st argument to be string'); + } + return { handlerPath: null, friendlyName: null }; +}; diff --git a/pkgbuilds/slack-desktop/slack-desktop-utils.js b/pkgbuilds/slack-desktop/slack-desktop-utils.js new file mode 100644 index 0000000..350dc67 --- /dev/null +++ b/pkgbuilds/slack-desktop/slack-desktop-utils.js @@ -0,0 +1,53 @@ +// Stand-in for Slack's closed-source native helpers, which ship no aarch64 +// build. Slack's main bundle requires this module while booting, so a missing +// addon stops the window from ever opening. Every native call throws the same +// error the vendor wrapper uses for methods a platform lacks, and Slack's call +// sites already catch it and fall back. +const unavailable = () => { + throw new Error('Method not implemented'); +}; + +const namespace = new Proxy( + {}, + { + get: (_, key) => + typeof key === 'symbol' || key === 'then' ? undefined : unavailable, + }, +); + +const constants = { + AppRestartFlags: { NoCrash: 1, NoHang: 2, NoPatch: 4, NoReboot: 8 }, + WindowsNotifierState: { + NotificationPlatformUnavailable: -2, + Error: -1, + Enabled: 0, + DisabledForApplication: 1, + DisabledForUser: 2, + DisabledByGroupPolicy: 3, + DisabledByManifest: 4, + }, + StartupTaskState: { + Error: -1, + Disabled: 0, + DisabledByUser: 1, + Enabled: 2, + DisabledByPolicy: 3, + EnabledByPolicy: 4, + }, + ActivationType: { Error: -1, StartupTask: 1020 }, +}; + +module.exports = new Proxy(constants, { + get: (target, key) => { + if (key in target) return target[key]; + if ( + typeof key === 'symbol' || + key === '__esModule' || + key === 'default' || + key === 'then' + ) { + return undefined; + } + return namespace; + }, +}); diff --git a/pkgbuilds/slack-desktop/slack.desktop b/pkgbuilds/slack-desktop/slack.desktop new file mode 100644 index 0000000..3567251 --- /dev/null +++ b/pkgbuilds/slack-desktop/slack.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Name=Slack +StartupWMClass=Slack +Comment=Slack Desktop +GenericName=Slack Client for Linux +Exec=/usr/bin/slack %U +Icon=slack +Type=Application +StartupNotify=true +Categories=GNOME;GTK;Network;InstantMessaging; +MimeType=x-scheme-handler/slack;