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

This commit is contained in:
Florian Klink
2025-04-01 18:26:48 +01:00
committed by GitHub
5 changed files with 589 additions and 0 deletions

View File

@@ -0,0 +1,87 @@
{
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;
})

View File

@@ -0,0 +1,228 @@
{
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
];
};
})

View File

@@ -0,0 +1,129 @@
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({

View File

@@ -0,0 +1,105 @@
{
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}"
'';
}

View File

@@ -0,0 +1,40 @@
{
'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@',
]
}
},
],
}