about summary refs log tree commit diff
path: root/pkgs/applications/networking/instant-messengers/signal-desktop
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/applications/networking/instant-messengers/signal-desktop')
-rw-r--r--pkgs/applications/networking/instant-messengers/signal-desktop/copy-noto-emoji.py118
-rw-r--r--pkgs/applications/networking/instant-messengers/signal-desktop/default.nix17
-rw-r--r--pkgs/applications/networking/instant-messengers/signal-desktop/generic.nix110
-rw-r--r--pkgs/applications/networking/instant-messengers/signal-desktop/pyproject.toml15
-rw-r--r--pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-aarch64.nix4
-rw-r--r--pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-beta.nix4
-rw-r--r--pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop.nix4
7 files changed, 251 insertions, 21 deletions
diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/copy-noto-emoji.py b/pkgs/applications/networking/instant-messengers/signal-desktop/copy-noto-emoji.py
new file mode 100644
index 0000000000000..393519e5c1f04
--- /dev/null
+++ b/pkgs/applications/networking/instant-messengers/signal-desktop/copy-noto-emoji.py
@@ -0,0 +1,118 @@
+"""Copy Noto Color Emoji PNGs into an extracted Signal ASAR archive.
+
+Signal loads small Apple emoji PNGs directly from
+`node_modules/emoji-datasource-apple/img/apple/64`, and downloads and
+caches large Apple emoji WebP files in `.proto` bundles on the fly. The
+latter are not a copyright concern for the Nixpkgs cache, but would
+result in inconsistent presentation between small and large emoji.
+
+We skip the complexity and buy some additional privacy by replacing the
+`emoji://jumbo?emoji=` URL prefix with a `file://` path to the copied
+PNGs inside the ASAR archive, and linking the `node_modules` PNG paths
+directly to them.
+"""
+
+import json
+import shutil
+import sys
+from pathlib import Path
+
+
+def signal_name_to_emoji(signal_emoji_name: str) -> str:
+    r"""Return the emoji corresponding to a Signal emoji name.
+
+    Signal emoji names are concatenations of UTF‐16 code units,
+    represented in lowercase big‐endian hex padded to four digits.
+
+    >>> signal_name_to_emoji("d83dde36200dd83cdf2bfe0f")
+    '😶‍🌫️'
+    >>> b"\xd8\x3d\xde\x36\x20\x0d\xd8\x3c\xdf\x2b\xfe\x0f".decode("utf-16-be")
+    '😶‍🌫️'
+    """
+    hex_bytes = zip(signal_emoji_name[::2], signal_emoji_name[1::2])
+    emoji_utf_16_be = bytes(
+        int("".join(hex_pair), 16) for hex_pair in hex_bytes
+    )
+    return emoji_utf_16_be.decode("utf-16-be")
+
+
+def emoji_to_noto_name(emoji: str) -> str:
+    r"""Return the Noto emoji name of an emoji.
+
+    Noto emoji names are underscore‐separated Unicode scalar values,
+    represented in lowercase big‐endian hex padded to at least four
+    digits. Any U+FE0F variant selectors are omitted.
+
+    >>> emoji_to_noto_name("😶‍🌫️")
+    '1f636_200d_1f32b'
+    >>> emoji_to_noto_name("\U0001f636\u200d\U0001f32b\ufe0f")
+    '1f636_200d_1f32b'
+    """
+    return "_".join(
+        f"{ord(scalar_value):04x}"
+        for scalar_value in emoji
+        if scalar_value != "\ufe0f"
+    )
+
+
+def emoji_to_emoji_data_name(emoji: str) -> str:
+    r"""Return the npm emoji-data emoji name of an emoji.
+
+    emoji-data emoji names are hyphen‐minus‐separated Unicode scalar
+    values, represented in lowercase big‐endian hex padded to at least
+    four digits.
+
+    >>> emoji_to_emoji_data_name("😶‍🌫️")
+    '1f636-200d-1f32b-fe0f'
+    >>> emoji_to_emoji_data_name("\U0001f636\u200d\U0001f32b\ufe0f")
+    '1f636-200d-1f32b-fe0f'
+    """
+    return "-".join(f"{ord(scalar_value):04x}" for scalar_value in emoji)
+
+
+def _main() -> None:
+    noto_png_path, asar_root = (Path(arg) for arg in sys.argv[1:])
+    asar_root = asar_root.absolute()
+
+    out_path = asar_root / "images" / "nixpkgs-emoji"
+    out_path.mkdir(parents=True)
+
+    emoji_data_out_path = (
+        asar_root
+        / "node_modules"
+        / "emoji-datasource-apple"
+        / "img"
+        / "apple"
+        / "64"
+    )
+    emoji_data_out_path.mkdir(parents=True)
+
+    jumbomoji_json_path = asar_root / "build" / "jumbomoji.json"
+    with jumbomoji_json_path.open() as jumbomoji_json_file:
+        jumbomoji_packs = json.load(jumbomoji_json_file)
+
+    for signal_emoji_names in jumbomoji_packs.values():
+        for signal_emoji_name in signal_emoji_names:
+            emoji = signal_name_to_emoji(signal_emoji_name)
+
+            try:
+                shutil.copy(
+                    noto_png_path / f"emoji_u{emoji_to_noto_name(emoji)}.png",
+                    out_path / emoji,
+                )
+            except FileNotFoundError:
+                print(
+                    f"Missing Noto emoji: {emoji} {signal_emoji_name}",
+                    file=sys.stderr,
+                )
+                continue
+
+            (
+                emoji_data_out_path / f"{emoji_to_emoji_data_name(emoji)}.png"
+            ).symlink_to(out_path / emoji)
+
+    print(out_path.relative_to(asar_root))
+
+
+if __name__ == "__main__":
+    _main()
diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/default.nix b/pkgs/applications/networking/instant-messengers/signal-desktop/default.nix
index 364843e7bfa82..57185f5e42e55 100644
--- a/pkgs/applications/networking/instant-messengers/signal-desktop/default.nix
+++ b/pkgs/applications/networking/instant-messengers/signal-desktop/default.nix
@@ -1,6 +1,13 @@
-{ hostPlatform, callPackage }: {
-  signal-desktop = if hostPlatform.system == "aarch64-linux"
-    then callPackage ./signal-desktop-aarch64.nix { }
-    else callPackage ./signal-desktop.nix { };
-  signal-desktop-beta = callPackage ./signal-desktop-beta.nix{ };
+{ hostPlatform, callPackage }:
+{
+  signal-desktop =
+    if hostPlatform.system == "aarch64-linux" then
+      callPackage ./signal-desktop-aarch64.nix { }
+    else
+      callPackage ./signal-desktop.nix { };
+  signal-desktop-beta = (callPackage ./signal-desktop-beta.nix { }).overrideAttrs (old: {
+    meta = old.meta // {
+      platforms = [ "x86_64-linux" ];
+    };
+  });
 }
diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/generic.nix b/pkgs/applications/networking/instant-messengers/signal-desktop/generic.nix
index e8518c310a7c1..49df948196568 100644
--- a/pkgs/applications/networking/instant-messengers/signal-desktop/generic.nix
+++ b/pkgs/applications/networking/instant-messengers/signal-desktop/generic.nix
@@ -1,9 +1,14 @@
 { stdenv
 , lib
+, callPackage
 , fetchurl
 , autoPatchelfHook
+, noto-fonts-color-emoji
 , dpkg
-, wrapGAppsHook
+, asar
+, rsync
+, python3
+, wrapGAppsHook3
 , makeWrapper
 , nixosTests
 , gtk3
@@ -57,7 +62,29 @@
 let
   inherit (stdenv) targetPlatform;
   ARCH = if targetPlatform.isAarch64 then "arm64" else "x64";
-in stdenv.mkDerivation rec {
+
+  # Noto Color Emoji PNG files for emoji replacement; see below.
+  noto-fonts-color-emoji-png = noto-fonts-color-emoji.overrideAttrs (prevAttrs: {
+    pname = "noto-fonts-color-emoji-png";
+
+    # The build produces 136×128 PNGs by default for arcane font
+    # reasons, but we want square PNGs.
+    buildFlags = prevAttrs.buildFlags or [ ] ++ [ "BODY_DIMENSIONS=128x128" ];
+
+    makeTargets = [ "compressed" ];
+
+    installPhase = ''
+      runHook preInstall
+
+      mkdir -p $out/share
+      mv build/compressed_pngs $out/share/noto-fonts-color-emoji-png
+      python3 add_aliases.py --srcdir=$out/share/noto-fonts-color-emoji-png
+
+      runHook postInstall
+    '';
+  });
+in
+stdenv.mkDerivation rec {
   inherit pname version;
 
   # Please backport all updates to the stable channel.
@@ -70,12 +97,37 @@ in stdenv.mkDerivation rec {
 
   src = fetchurl {
     inherit url hash;
+    recursiveHash = true;
+    downloadToTemp = true;
+    nativeBuildInputs = [ dpkg asar ];
+    # Signal ships the Apple emoji set without a licence via an npm
+    # package and upstream does not seem terribly interested in fixing
+    # this; see:
+    #
+    # * <https://github.com/signalapp/Signal-Android/issues/5862>
+    # * <https://whispersystems.discoursehosting.net/t/signal-is-likely-violating-apple-license-terms-by-using-apple-emoji-in-the-sticker-creator-and-android-and-desktop-apps/52883>
+    #
+    # We work around this by replacing it with the Noto Color Emoji
+    # set, which is available under a FOSS licence and more likely to
+    # be used on a NixOS machine anyway. The Apple emoji are removed
+    # during `fetchurl` to ensure that the build doesn’t cache the
+    # unlicensed emoji files, but the rest of the work is done in the
+    # main derivation.
+    postFetch = ''
+      dpkg-deb -x $downloadedFile $out
+      asar extract "$out/opt/${dir}/resources/app.asar" $out/asar-contents
+      rm -r \
+        "$out/opt/${dir}/resources/app.asar"{,.unpacked} \
+        $out/asar-contents/node_modules/emoji-datasource-apple
+    '';
   };
 
   nativeBuildInputs = [
+    rsync
+    asar
+    python3
     autoPatchelfHook
-    dpkg
-    (wrapGAppsHook.override { inherit makeWrapper; })
+    (wrapGAppsHook3.override { inherit makeWrapper; })
   ];
 
   buildInputs = [
@@ -126,11 +178,13 @@ in stdenv.mkDerivation rec {
     wayland
   ];
 
-  unpackPhase = "dpkg-deb -x $src .";
-
   dontBuild = true;
   dontConfigure = true;
 
+  unpackPhase = ''
+    rsync -a --chmod=+w $src/ .
+  '';
+
   installPhase = ''
     runHook preInstall
 
@@ -146,6 +200,30 @@ in stdenv.mkDerivation rec {
     # Create required symlinks:
     ln -s libGLESv2.so "$out/lib/${dir}/libGLESv2.so.2"
 
+    # Copy the Noto Color Emoji PNGs into the ASAR contents. See `src`
+    # for the motivation, and the script for the technical details.
+    emojiPrefix=$(
+      python3 ${./copy-noto-emoji.py} \
+      ${noto-fonts-color-emoji-png}/share/noto-fonts-color-emoji-png \
+      asar-contents
+    )
+
+    # Replace the URL used for fetching large versions of emoji with
+    # the local path to our copied PNGs.
+    substituteInPlace asar-contents/preload.bundle.js \
+      --replace-fail \
+        'emoji://jumbo?emoji=' \
+        "file://$out/lib/${lib.escapeURL dir}/resources/app.asar/$emojiPrefix/"
+
+    # `asar(1)` copies files from the corresponding `.unpacked`
+    # directory when extracting, and will put them back in the modified
+    # archive if you don’t specify them again when repacking. Signal
+    # leaves their native `.node` libraries unpacked, so we match that.
+    asar pack \
+      --unpack '*.node' \
+      asar-contents \
+      "$out/lib/${dir}/resources/app.asar"
+
     runHook postInstall
   '';
 
@@ -155,10 +233,10 @@ in stdenv.mkDerivation rec {
       --suffix PATH : ${lib.makeBinPath [ xdg-utils ]}
     )
 
-    # Fix the desktop link and fix showing application icon in tray
+    # Fix the desktop link
     substituteInPlace $out/share/applications/${pname}.desktop \
       --replace "/opt/${dir}/${pname}" $out/bin/${pname} \
-      ${if pname == "signal-desktop" then "--replace \"bin/signal-desktop\" \"bin/signal-desktop --use-tray-icon\"" else ""}
+      --replace-fail "StartupWMClass=Signal" "StartupWMClass=signal"
 
     # Note: The following path contains bundled libraries:
     # $out/lib/${dir}/resources/app.asar.unpacked/node_modules/
@@ -179,8 +257,20 @@ in stdenv.mkDerivation rec {
     '';
     homepage = "https://signal.org/";
     changelog = "https://github.com/signalapp/Signal-Desktop/releases/tag/v${version}";
-    license = lib.licenses.agpl3Only;
-    maintainers = with lib.maintainers; [ eclairevoyant mic92 equirosa urandom bkchr ];
+    license = [
+      lib.licenses.agpl3Only
+
+      # Various npm packages
+      lib.licenses.free
+    ];
+    maintainers = with lib.maintainers; [
+      mic92
+      equirosa
+      urandom
+      bkchr
+      teutat3s
+      emily
+    ];
     mainProgram = pname;
     platforms = [ "x86_64-linux" "aarch64-linux" ];
     sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/pyproject.toml b/pkgs/applications/networking/instant-messengers/signal-desktop/pyproject.toml
new file mode 100644
index 0000000000000..eeee9c7287a05
--- /dev/null
+++ b/pkgs/applications/networking/instant-messengers/signal-desktop/pyproject.toml
@@ -0,0 +1,15 @@
+[tool.mypy]
+files = ["*.py"]
+strict = true
+
+[tool.ruff]
+line-length = 80
+
+[tool.ruff.lint]
+select = ["ALL"]
+ignore = ["COM812", "D203", "D213", "ISC001", "T201"]
+allowed-confusables = ["‐"]
+
+[tool.ruff.format]
+docstring-code-format = true
+docstring-code-line-length = "dynamic"
diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-aarch64.nix b/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-aarch64.nix
index cccaa12cc2b03..8f3eabb7bc279 100644
--- a/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-aarch64.nix
+++ b/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-aarch64.nix
@@ -2,7 +2,7 @@
 callPackage ./generic.nix { } rec {
   pname = "signal-desktop";
   dir = "Signal";
-  version = "7.5.1";
+  version = "7.23.0";
   url = "https://github.com/0mniteck/Signal-Desktop-Mobian/raw/${version}/builds/release/signal-desktop_${version}_arm64.deb";
-  hash = "sha256-X7B7eQQXTZ+ADLrrLI9XUsl7rHO9akMeW2zAgduXfLY=";
+  hash = "sha256-fQb2nYE1+q6DNcMF0z5NadGlffYaCFNgcu8IIGVUtf8=";
 }
diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-beta.nix b/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-beta.nix
index a87d49de7621f..f557734764cdc 100644
--- a/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-beta.nix
+++ b/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop-beta.nix
@@ -2,7 +2,7 @@
 callPackage ./generic.nix { } rec {
   pname = "signal-desktop-beta";
   dir = "Signal Beta";
-  version = "7.7.0-beta.1";
+  version = "7.25.0-beta.2";
   url = "https://updates.signal.org/desktop/apt/pool/s/signal-desktop-beta/signal-desktop-beta_${version}_amd64.deb";
-  hash = "sha256-oswS1aRkpiTNSpQ6CqfJnoM412RRwraeht4iqq8L1Bk=";
+  hash = "sha256-7L+ldJYJXB9VkC12s8AyUdECVXnyN8PNo7AFIyEHcS8=";
 }
diff --git a/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop.nix b/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop.nix
index 0b1f3b034cced..40666c4eca308 100644
--- a/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop.nix
+++ b/pkgs/applications/networking/instant-messengers/signal-desktop/signal-desktop.nix
@@ -2,7 +2,7 @@
 callPackage ./generic.nix { } rec {
   pname = "signal-desktop";
   dir = "Signal";
-  version = "7.6.0";
+  version = "7.25.0";
   url = "https://updates.signal.org/desktop/apt/pool/s/signal-desktop/signal-desktop_${version}_amd64.deb";
-  hash = "sha256-sGOWsFZTO9VQDkCqhsOkW5aY+sh0fLH7kPPe/bAzGvg=";
+  hash = "sha256-KcVCQkDSpI+eq2/wvPZxq6ILLQk3xe+wrKfbnJnTQTo=";
 }