# Maintainer: Ryan Hughes <ryan@omarchy.org>

pkgname=slack-desktop
pkgver=4.52.171
pkgrel=2
# Slack publishes Linux builds for x86_64 only, which this package installs
# unchanged. On AArch64 the same application code runs on the AArch64 build
# of the Electron release Slack ships with; see README.md for the native
# modules that are replaced or dropped there.
_electronver=44.4.5
pkgdesc='Slack Desktop for Linux'
arch=('x86_64' '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_aarch64=('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"
  'slack.desktop'
)
source_aarch64=(
  "electron-v${_electronver}-linux-arm64.zip::https://github.com/electron/electron/releases/download/v${_electronver}/electron-v${_electronver}-linux-arm64.zip"
  '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'
            'e438e78265f3e566990300946afb4ea5d09bcd8c426738ab8f486ae9ddb86c0f')
sha256sums_aarch64=('3bf0acab49c4ea3c9283cdb86bf3dd7204bd52a6fba6c8ae51101bdba2adae0e'
                    '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
  bsdtar -O -xf "slack-desktop-${pkgver}-amd64.deb" 'data.tar.*' | bsdtar -C slack -xf -

  [[ $CARCH == aarch64 ]] || return 0

  local slack_electron
  slack_electron=$(<slack/usr/lib/slack/version)
  if [[ $slack_electron != "$_electronver" ]]; then
    error "Slack $pkgver ships Electron $slack_electron, but _electronver is $_electronver."
    plain "Set _electronver=$slack_electron and update its checksum."
    return 1
  fi

  mkdir electron
  bsdtar -C electron -xf "electron-v${_electronver}-linux-arm64.zip"
  # Electron loads resources/app ahead of app.asar, so the extracted tree can
  # carry the replacement modules without repacking the archive.
  asar extract slack/usr/lib/slack/resources/app.asar app
}

_install_aarch64_runtime() {
  local lib=$1
  local app="$lib/resources/app"

  cp -a --no-preserve=ownership electron/. "$lib/"
  mv "$lib/electron" "$lib/slack"
  rm -f "$lib/resources/default_app.asar" "$lib/LICENSE"
  find slack/usr/lib/slack/resources -maxdepth 1 -type f ! -name app.asar \
    -exec cp --no-preserve=ownership -t "$lib/resources" {} +
  cp -a --no-preserve=ownership app "$app"

  local shim target
  for shim in \
    'slack-desktop-utils.js:@tinyspeck/slack-desktop-utils/lib/index.js' \
    'file-handler-info.js:file-handler-info/index.js' \
    'electron-native-auth.js:electron-native-auth/index.js'; do
    target="$app/node_modules/${shim#*:}"
    if [[ ! -f $target ]]; then
      error "Slack $pkgver no longer ships ${shim#*:}; review the replacement modules."
      return 1
    fi
    install -m644 "$srcdir/${shim%%:*}" "$target"
  done

  local addon
  for addon in "${_x86_addons[@]}"; do
    rm -f "$app/node_modules/$addon"
  done
}

package() {
  local lib="$pkgdir/usr/lib/slack"
  local expected_machine

  install -d "$lib"
  case "$CARCH" in
    x86_64)
      cp -a --no-preserve=ownership slack/usr/lib/slack/. "$lib/"
      rm -f "$lib/LICENSE"
      rm -rf "$lib/src"
      expected_machine='Advanced Micro Devices X86-64'
      ;;
    aarch64)
      _install_aarch64_runtime "$lib" || return 1
      expected_machine=AArch64
      ;;
  esac

  local file machine
  while IFS= read -r -d '' file; do
    machine=$(readelf -h "$file" 2>/dev/null |
      sed -n 's/^[[:space:]]*Machine:[[:space:]]*//p')
    if [[ -n $machine && $machine != "$expected_machine" ]]; then
      error "Unexpected ${machine} binary: ${file#"$pkgdir"}"
      return 1
    fi
  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"
  if [[ $CARCH == aarch64 ]]; then
    install -Dm644 electron/LICENSE "$licenses/LICENSE.electron.txt"
    install -Dm644 electron/LICENSES.chromium.html "$licenses/LICENSES.chromium.html"
  else
    install -Dm644 slack/usr/lib/slack/resources/LICENSES.chromium.html \
      "$licenses/LICENSES.chromium.html"
  fi
}
