Unverified Commit f680a9ec authored by Florian Klink's avatar Florian Klink Committed by GitHub
Browse files

signal-desktop-source: init at 7.46.0 (#388586)

parents cf28f0fa 4b91de61
Loading
Loading
Loading
Loading
+87 −0
Original line number Diff line number Diff line
{
  stdenv,
  rustPlatform,
  fetchNpmDeps,
  npmHooks,
  protobuf,
  clang,
  gitMinimal,
  cmake,
  boringssl,
  runCommand,
  fetchFromGitHub,
  python3,
  nodejs,

}:
let
  # boring-sys expects the static libraries in build/ instead of lib/
  boringssl-wrapper = runCommand "boringssl-wrapper" { } ''
    mkdir $out
    cd $out
    ln -s ${boringssl.out}/lib build
    ln -s ${boringssl.dev}/include include
  '';
in
rustPlatform.buildRustPackage (finalAttrs: {
  pname = "libsignal-node";
  version = "0.67.0";

  src = fetchFromGitHub {
    owner = "signalapp";
    repo = "libsignal";
    tag = "v${finalAttrs.version}";
    hash = "sha256-Cwra5o9g2+M3dboQUuBikRWyaydL/CGwOfJbImsFRoI=";
  };
  useFetchCargoVendor = true;
  cargoHash = "sha256-KVt4ESHaHDtD+pcaMMG/DMMznYGpWleEf7uTZB45Ud0=";

  npmRoot = "node";
  npmDeps = fetchNpmDeps {
    name = "${finalAttrs.pname}-npm-deps";
    inherit (finalAttrs) version src;
    sourceRoot = "${finalAttrs.src.name}/${finalAttrs.npmRoot}";
    hash = "sha256-TXRZFfdl86PLJ1FWOkTcXjbx8aZV7gEvs22Pu8b5uFU=";
  };

  nativeBuildInputs = [
    python3
    protobuf
    nodejs
    clang
    gitMinimal
    cmake
    npmHooks.npmConfigHook
    rustPlatform.bindgenHook
  ];
  env.BORING_BSSL_PATH = "${boringssl-wrapper}";
  env.NIX_LDFLAGS = if stdenv.hostPlatform.isDarwin then "-lc++" else "-lstdc++";

  patchPhase = ''
    runHook prePatch

    substituteInPlace node/binding.gyp \
      --replace-fail "'--out-dir', '<(PRODUCT_DIR)/'," \
                     "'--out-dir', '$out/lib/<(NODE_OS_NAME)-<(target_arch)/'," \
      --replace-fail "'target_name': 'libsignal_client_<(NODE_OS_NAME)_<(target_arch).node'," \
                     "'target_name': '@signalapp+libsignal-client',"

    substituteInPlace node/build_node_bridge.py \
      --replace-fail "dst_base = 'libsignal_client_%s_%s' % (node_os_name, node_arch)" \
                     "dst_base = '@signalapp+libsignal-client'"

    runHook postPatch
  '';

  buildPhase = ''
    runHook preBuild

    pushd node
    npx node-gyp rebuild
    popd

    runHook postBuild
  '';

  dontCargoInstall = true;
})
+228 −0
Original line number Diff line number Diff line
{
  stdenv,
  lib,
  nodejs_20,
  pnpm_10,
  electron_34,
  python3,
  makeWrapper,
  callPackage,
  libpulseaudio,
  fetchFromGitHub,
  runCommand,
  fetchzip,
  autoPatchelfHook,
  makeDesktopItem,
  copyDesktopItems,
  replaceVars,
  noto-fonts-color-emoji,
  nixosTests,
  withAppleEmojis ? false,
}:
let
  nodejs = nodejs_20;
  pnpm = pnpm_10;
  electron = electron_34;

  electron-headers = runCommand "electron-headers" { } ''
    mkdir -p $out
    tar -C $out --strip-components=1 -xvf ${electron.headers}
  '';

  sqlcipher-signal-extension = callPackage ./sqlcipher-signal-extension.nix { };
  libsignal-node = callPackage ./libsignal-node.nix { inherit nodejs; };

  ringrtc = stdenv.mkDerivation (finalAttrs: {
    pname = "ringrtc-bin";
    version = "2.50.1";
    src = fetchzip {
      url = "https://build-artifacts.signal.org/libraries/ringrtc-desktop-build-v${finalAttrs.version}.tar.gz";
      hash = "sha256-KHNTw5ScBdYAAyKFdJ6PTmFr+7GYHqgnb4mmNUJZvzM=";
    };

    installPhase = ''
      cp -r . $out
    '';

    nativeBuildInputs = [ autoPatchelfHook ];
    buildInputs = [ libpulseaudio ];
    meta = {
      homepage = "https://github.com/signalapp/ringrtc";
      license = lib.licenses.agpl3Only;
      sourceProvenance = with lib.sourceTypes; [ binaryNativeCode ];
    };
  });

  # 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 (finalAttrs: {
  pname = "signal-desktop-source";
  version = "7.46.0";

  src = fetchFromGitHub {
    owner = "signalapp";
    repo = "Signal-Desktop";
    tag = "v${finalAttrs.version}";
    hash = "sha256-pV28jcIQcPjyZL8q+gisnlfAGf0SOKDQ7OxacTM3B0M=";
  };

  nativeBuildInputs = [
    nodejs
    (pnpm.override { inherit nodejs; }).configHook
    makeWrapper
    copyDesktopItems
    python3
  ];
  buildInputs = (lib.optional (!withAppleEmojis) noto-fonts-color-emoji-png);

  patches = lib.optional (!withAppleEmojis) (
    replaceVars ./replace-apple-emoji-with-noto-emoji.patch {
      noto-emoji-pngs = "${noto-fonts-color-emoji-png}/share/noto-fonts-color-emoji-png";
    }
  );

  pnpmDeps = pnpm.fetchDeps {
    inherit (finalAttrs)
      pname
      version
      src
      patches
      ;
    hash =
      if withAppleEmojis then
        "sha256-keG+ymMD4ma0dt6N4Fai9u0+rh9VzkQD6tClPKoQXkM="
      else
        "sha256-qImY0s8UQmuKGf8dvgO3YrJlrqqdoZtvbtLgvgMVnnE=";
  };

  env = {
    ELECTRON_SKIP_BINARY_DOWNLOAD = "1";
    SIGNAL_ENV = "production";
    SOURCE_DATE_EPOCH = 1741810629;
  };

  preBuild = ''
    cp ${sqlcipher-signal-extension}/share/sqlite3.gyp node_modules/@signalapp/better-sqlite3/deps/sqlite3.gyp

    cp -r ${ringrtc} node_modules/@signalapp/ringrtc/build

    rm -fr node_modules/@signalapp/libsignal-client/prebuilds
    cp -r ${libsignal-node}/lib node_modules/@signalapp/libsignal-client/prebuilds
  '';

  buildPhase = ''
    runHook preBuild

    export npm_config_nodedir=${electron-headers}
    cp -r ${electron.dist} electron-dist
    chmod -R u+w electron-dist

    pnpm run generate
    pnpm exec electron-builder \
      --dir \
      --config.extraMetadata.environment=$SIGNAL_ENV \
      -c.electronDist=electron-dist \
      -c.electronVersion=${electron.version}

    runHook postBuild
  '';

  installPhase = ''
    runHook preInstall

    mkdir -p $out/share/
    cp -r dist/*-unpacked/resources $out/share/signal-desktop

    for icon in build/icons/png/*
    do
      install -Dm644 $icon $out/share/icons/hicolor/`basename ''${icon%.png}`/apps/signal-desktop.png
    done

    makeWrapper '${lib.getExe electron}' "$out/bin/signal-desktop" \
      --add-flags "$out/share/signal-desktop/app.asar" \
      --set-default ELECTRON_FORCE_IS_PACKAGED 1 \
      --add-flags "\''${NIXOS_OZONE_WL:+\''${WAYLAND_DISPLAY:+--ozone-platform-hint=auto --enable-features=WaylandWindowDecorations --enable-wayland-ime=true}}"

    runHook postInstall
  '';

  desktopItems = [
    (makeDesktopItem {
      name = finalAttrs.pname;
      desktopName = "Signal";
      exec = "${finalAttrs.meta.mainProgram} %U";
      type = "Application";
      terminal = false;
      icon = "signal-desktop";
      comment = "Private messaging from your desktop";
      startupWMClass = "signal";
      mimeTypes = [
        "x-scheme-handler/sgnl"
        "x-scheme-handler/signalcaptcha"
      ];
      categories = [
        "Network"
        "InstantMessaging"
        "Chat"
      ];
    })
  ];

  passthru = {
    inherit sqlcipher-signal-extension libsignal-node;
    tests.application-launch = nixosTests.signal-desktop;
  };

  meta = {
    description = "Private, simple, and secure messenger (nixpkgs build)";
    longDescription = ''
      Signal Desktop is an Electron application that links with your
      "Signal Android" or "Signal iOS" app.
    '';
    homepage = "https://signal.org/";
    changelog = "https://github.com/signalapp/Signal-Desktop/releases/tag/v${finalAttrs.version}";
    license =
      with lib.licenses;
      [
        agpl3Only

        # Various npm packages
        free
      ]
      ++ lib.optional withAppleEmojis unfree;
    maintainers = with lib.maintainers; [
      marcin-serwin
    ];
    mainProgram = "signal-desktop";
    platforms = [
      "x86_64-linux"
      "aarch64-linux"
    ];
    sourceProvenance = with lib.sourceTypes; [
      fromSource

      # ringrtc
      binaryNativeCode
    ];
  };
})
+129 −0
Original line number Diff line number Diff line
diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md
index aed1048..e4c1f50 100644
--- a/ACKNOWLEDGMENTS.md
+++ b/ACKNOWLEDGMENTS.md
@@ -745,30 +745,6 @@ Signal Desktop makes use of the following open source projects.
     OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     SOFTWARE.
 
-## emoji-datasource-apple
-
-    The MIT License (MIT)
-
-    Copyright (c) 2013 Cal Henderson
-
-    Permission is hereby granted, free of charge, to any person obtaining a copy
-    of this software and associated documentation files (the "Software"), to deal
-    in the Software without restriction, including without limitation the rights
-    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-    copies of the Software, and to permit persons to whom the Software is
-    furnished to do so, subject to the following conditions:
-
-    The above copyright notice and this permission notice shall be included in all
-    copies or substantial portions of the Software.
-
-    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-    SOFTWARE.
-
 ## emoji-regex
 
     Copyright Mathias Bynens <https://mathiasbynens.be/>
diff --git a/app/protocol_filter.ts b/app/protocol_filter.ts
index 68dceea..4b35bb1 100644
--- a/app/protocol_filter.ts
+++ b/app/protocol_filter.ts
@@ -59,6 +59,7 @@ function _createFileHandler({
   const allowedRoots = [
     userDataPath,
     installPath,
+    "@noto-emoji-pngs@",
     getAvatarsPath(userDataPath),
     getBadgesPath(userDataPath),
     getDraftPath(userDataPath),
diff --git a/package.json b/package.json
index 3a6ac26..40cdb25 100644
--- a/package.json
+++ b/package.json
@@ -130,7 +130,6 @@
     "dashdash": "2.0.0",
     "direction": "1.0.4",
     "emoji-datasource": "15.1.2",
-    "emoji-datasource-apple": "15.1.2",
     "emoji-regex": "10.4.0",
     "encoding": "0.1.13",
     "fabric": "4.6.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ba2f205..705e454 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -169,9 +169,6 @@ importers:
       emoji-datasource:
         specifier: 15.1.2
         version: 15.1.2
-      emoji-datasource-apple:
-        specifier: 15.1.2
-        version: 15.1.2
       emoji-regex:
         specifier: 10.4.0
         version: 10.4.0
@@ -4790,9 +4787,6 @@ packages:
     resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==}
     engines: {node: '>=12'}
 
-  emoji-datasource-apple@15.1.2:
-    resolution: {integrity: sha512-32UZTK36x4DlvgD1smkmBlKmmJH7qUr5Qut4U/on2uQLGqNXGbZiheq6/LEA8xRQEUrmNrGEy25wpEI6wvYmTg==}
-
   emoji-datasource@15.1.2:
     resolution: {integrity: sha512-tXAqGsrDVhgCRpFePtaD9P4Z8Ro2SUQSL/4MIJBG0SxqQJaMslEbin8J53OaFwEBu6e7JxFaIF6s4mw9+8acAQ==}
 
@@ -14929,8 +14923,6 @@ snapshots:
 
   emittery@0.13.1: {}
 
-  emoji-datasource-apple@15.1.2: {}
-
   emoji-datasource@15.1.2: {}
 
   emoji-regex@10.4.0: {}
diff --git a/ts/components/conversation/Emojify.tsx b/ts/components/conversation/Emojify.tsx
index f0b1115..7613230 100644
--- a/ts/components/conversation/Emojify.tsx
+++ b/ts/components/conversation/Emojify.tsx
@@ -35,8 +35,15 @@ function getImageTag({
   }
 
   let srcSet: string | undefined;
+  const emojiToNotoName = (emoji: string): string =>
+    `emoji_u${
+      [...emoji]
+        .filter(c => c != "\ufe0f")
+        .map(c => c.codePointAt(0)?.toString(16).padStart(4, "0"))
+        .join("_")
+    }.png`;
   if (sizeClass != null && JUMBO_SIZES.has(sizeClass)) {
-    srcSet = `emoji://jumbo?emoji=${encodeURIComponent(match)} 2x, ${img}`;
+    srcSet = `file://@noto-emoji-pngs@/${emojiToNotoName(match)} 2x, ${img}`;
   }
 
   return (
diff --git a/ts/components/emoji/lib.ts b/ts/components/emoji/lib.ts
index 9753017..cf51d3d 100644
--- a/ts/components/emoji/lib.ts
+++ b/ts/components/emoji/lib.ts
@@ -102,7 +102,10 @@ const ROOT_PATH = get(
 );
 
 const makeImagePath = (src: string) => {
-  return `${ROOT_PATH}node_modules/emoji-datasource-apple/img/apple/64/${src}`;
+  const datasourceToNoto = (name: string): string =>
+    `emoji_u${name.slice(0,-4).split("-").filter(c => c != "fe0f").join("_")}.png`;
+
+  return `@noto-emoji-pngs@/${datasourceToNoto(src)}`;
 };
 
 const imageQueue = new PQueue({
+105 −0
Original line number Diff line number Diff line
{
  rustPlatform,
  lib,
  fetchFromGitHub,
  sqlcipher,
  fetchpatch,
  stdenv,
  openssl,
  tcl,
  buildEnv,
  rust-cbindgen,
}:
let
  signal-sqlcipher-extension = rustPlatform.buildRustPackage (finalAttrs: {
    pname = "signal-sqlcipher-extension";
    version = "0.2.1";

    src = fetchFromGitHub {
      owner = "signalapp";
      repo = "Signal-Sqlcipher-Extension";
      tag = "v${finalAttrs.version}";
      hash = "sha256-INSkm7ZuetPASuIqezzzG/bXoEHClUb9XpxWbxLVXRc=";
    };
    useFetchCargoVendor = true;
    cargoHash = "sha256-qT4HM/FRL8qugKKNlMYM/0zgUsC6cDOa9fgd1d4VIrc=";

    meta = {
      description = "SQLite extension used by Signal Desktop";
      homepage = "https://github.com/signalapp/Signal-Sqlcipher-Extension";
      license = lib.licenses.agpl3Only;
      maintainers = with lib.maintainers; [ marcin-serwin ];
      platforms = lib.platforms.all;
    };
  });

  sqlcipher-amalgamation = stdenv.mkDerivation {
    pname = "sqlcipher-with-signal-extension";

    inherit (sqlcipher) version src meta;

    patches = [
      (fetchpatch {
        # https://github.com/sqlcipher/sqlcipher/pull/529
        name = "custom-crypto-provider.patch";
        url = "https://github.com/sqlcipher/sqlcipher/commit/0e3b20c155df8a2943b62a9f3cc0f4d3dba9e152.patch";
        hash = "sha256-OKh6qCGHBQWZyzXfyEveAs71wrNwlWLuG9jNqDeKNG4=";
      })
    ];

    nativeBuildInputs = [ tcl ];

    buildInputs = [ openssl ];

    CFLAGS = [ "-DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1" ];

    makeFlags = [ "sqlite3.c" ];

    installPhase = ''
      install -Dm644 sqlite3.c $out/src/sqlite3.c
      install -Dm644 sqlite3.h $out/include/sqlite3.h
      install -Dm644 sqlite3ext.h $out/include/sqlite3ext.h
    '';
  };

  signal-tokenizer-headers = rustPlatform.buildRustPackage (finalAttrs: {
    pname = "Signal-FTS5-Extension";
    version = "0.2.1";

    src = fetchFromGitHub {
      owner = "signalapp";
      repo = "Signal-FTS5-Extension";
      tag = "v${finalAttrs.version}";
      hash = "sha256-MzgdRuRsfL3yhlVU0RAAUtAaOukMpqSSa42nRYhpmh0=";
    };
    useFetchCargoVendor = true;
    cargoHash = "sha256-0DDX3ciXk5/3MqsHzxV8s4qEhqYmrwGg7cSbrkFRZbw=";

    nativeBuildInputs = [ rust-cbindgen ];

    buildPhase = ''
      cbindgen --profile release . -o signal-tokenizer.h
    '';
    installPhase = ''
      install -Dm644 signal-tokenizer.h $out/include/signal-tokenizer.h
    '';
    doCheck = false;
  });

in
buildEnv {
  name = "sqlcipher-signal";

  paths = [
    sqlcipher-amalgamation
    signal-tokenizer-headers
    signal-sqlcipher-extension
  ];

  postBuild = ''
    install -Dm644 ${./sqlite3.gyp} $out/share/sqlite3.gyp
    substituteInPlace $out/share/sqlite3.gyp \
      --replace-fail "@extension@" "$out" \
      --replace-fail "@static_lib_ext@" "${stdenv.hostPlatform.extensions.staticLibrary}"
  '';
}
+40 −0
Original line number Diff line number Diff line
{
  'includes': ['common.gypi'],
  'targets': [
    {
      'target_name': 'locate_sqlite3',
      'type': 'none',
      'copies': [{
        'files': [
          '@extension@/src/sqlite3.c',
        ],
        'destination': '<(SHARED_INTERMEDIATE_DIR)/sqlite3',
      }],
    },
    {
      'target_name': 'sqlite3',
      'type': 'static_library',
      'dependencies': ['locate_sqlite3'],
      'sources': ['<(SHARED_INTERMEDIATE_DIR)/sqlite3/sqlite3.c'],
      'include_dirs': [
        '<(SHARED_INTERMEDIATE_DIR)/sqlite3/',
      ],
      'direct_dependent_settings': {
        'include_dirs': [
          '@extension@/include',
        ],
      },
      'cflags': ['-std=c99', '-w'],
      'xcode_settings': {
        'OTHER_CFLAGS': ['-std=c99'],
        'WARNING_CFLAGS': ['-w'],
      },
      'includes': ['defines.gypi'],
      'link_settings': {
        'libraries': [
          '@extension@/lib/libsignal_sqlcipher_extension@static_lib_ext@',
        ]
      }
    },
  ],
}