summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-x.ci/macos/build.sh2
-rw-r--r--.ci/windows/build.bat2
-rw-r--r--.ci/windows/sign.bat5
-rw-r--r--.gitlab-ci.yml45
-rw-r--r--CMakeLists.txt8
-rw-r--r--resources/AppxManifest.xml4
-rw-r--r--src/MainWindow.cpp5
-rw-r--r--src/MainWindow.h3
-rw-r--r--src/encryption/SelfVerificationStatus.cpp3
-rw-r--r--src/notifications/Manager.h8
-rw-r--r--src/notifications/ManagerLinux.cpp3
-rw-r--r--src/notifications/ManagerWin.cpp52
-rw-r--r--src/timeline/RoomlistModel.cpp8
13 files changed, 111 insertions, 37 deletions
diff --git a/.ci/macos/build.sh b/.ci/macos/build.sh
index 34dee564..ea6da16d 100755
--- a/.ci/macos/build.sh
+++ b/.ci/macos/build.sh
@@ -20,7 +20,7 @@ cmake -GNinja -S. -Bbuild \
       -DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF \
       -DCMAKE_BUILD_TYPE=RelWithDebInfo -DHUNTER_CONFIGURATION_TYPES=RelWithDebInfo \
       -DUSE_BUNDLED_OPENSSL=ON \
-      -DUSE_BUNDLED_KDSINGLEAPPLICATION=ON \
+      -DUSE_BUNDLED_KDSINGLEAPPLICATION=ON -DKDSingleApplication_STATIC=ON \
       -DQt6_DIR=${QT_BASEPATH}/lib/cmake \
       -DCI_BUILD=ON
 cmake --build build
diff --git a/.ci/windows/build.bat b/.ci/windows/build.bat
index a79e2360..d74a2ea6 100644
--- a/.ci/windows/build.bat
+++ b/.ci/windows/build.bat
@@ -15,7 +15,7 @@ echo %DATE%
 

 

 call "C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/Build/vcvarsall.bat" x64

-cmake -G "Visual Studio 17 2022" -A x64 -S. -Bbuild -DHUNTER_ROOT="C:\hunter" -DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF -DUSE_BUNDLED_OPENSSL=ON -DUSE_BUNDLED_KDSINGLEAPPLICATION=ON -DCMAKE_BUILD_TYPE=Release -DHUNTER_CONFIGURATION_TYPES=Release

+cmake -G "Visual Studio 17 2022" -A x64 -S. -Bbuild -DHUNTER_ROOT="C:\hunter" -DHUNTER_ENABLED=ON -DBUILD_SHARED_LIBS=OFF -DUSE_BUNDLED_OPENSSL=ON -DUSE_BUNDLED_KDSINGLEAPPLICATION=ON -DKDSingleApplication_STATIC=ON -DCMAKE_BUILD_TYPE=Release -DHUNTER_CONFIGURATION_TYPES=Release

 cmake --build build --config Release

 

 

diff --git a/.ci/windows/sign.bat b/.ci/windows/sign.bat
new file mode 100644
index 00000000..18cd4931
--- /dev/null
+++ b/.ci/windows/sign.bat
@@ -0,0 +1,5 @@
+@echo off

+

+call "C:/Program Files (x86)/Microsoft Visual Studio/2022/BuildTools/VC/Auxiliary/Build/vcvarsall.bat" x64

+

+@C:\smartcardtools\x64\scsigntool -pin %WINDOWS_SIGNING_KEY_PIN% sign /fd SHA256 /t http://timestamp.digicert.com /a /sha1 %WINDOWS_SIGNING_KEY_THUMBPRINT% nheko.msix >nul 2>&1

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c28efe23..19ce069f 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -8,16 +8,21 @@ variables:
   CCACHE_DIR: "${CI_PROJECT_DIR}/.ccache"
   # prevent configure tzdata hanging apt install commands
   DEBIAN_FRONTEND: noninteractive
+  FF_SCRIPT_SECTIONS: 1
+  FF_USE_FASTZIP: 1
 
 build-windows:
   stage: build
   image: win10-base
   tags: [libvirt,powershell]
+  rules:
+    - if : '$CI_PIPELINE_TRIGGERED == null'
   variables:
     APPVEYOR_REPO_BRANCH: "${CI_COMMIT_REF_NAME}"
     APPVEYOR_REPO_COMMIT: "${CI_COMMIT_SHORT_SHA}"
+    CMAKE_BUILD_PARALLEL_LEVEL: 8
   before_script:
-    - mkdir -p hunter
+    - mkdir -p hunter -f
     - Move-Item -Path hunter -Destination C:/hunter
   script:
     - ./.ci/windows/build.bat
@@ -33,6 +38,28 @@ build-windows:
     paths:
       - nheko.msix
       - nheko_win_64.zip
+    name: nheko-${CI_COMMIT_SHORT_SHA}-windows-unsigned
+    expose_as: 'windows-app-unsigned'
+
+codesign-windows:
+  stage: sign
+  image: win10-base
+  tags: [libvirt,powershell]
+  resource_group: windows_signingA
+  environment: 
+    name: windows_signing
+  #variables:
+  #  GIT_STRATEGY: none
+  script:
+    - Get-ChildItem -Path Cert:CurrentUser\My
+    - ./.ci/windows/sign.bat
+  needs:
+    - job: build-windows
+  rules:
+    - if : '$CI_COMMIT_REF_PROTECTED == "true"'
+  artifacts:
+    paths:
+      - nheko.msix
     name: nheko-${CI_COMMIT_SHORT_SHA}-windows
     expose_as: 'windows-app'
 
@@ -44,9 +71,7 @@ build-clazy:
     CLAZY_CHECKS: level0,level1,no-non-pod-global-static
     TRAVIS_OS_NAME: linux
   before_script:
-    - echo -e "\e[0Ksection_start:`date +%s`:install_deps[collapsed=true]\r\e[0K\e[1m\e[95mInstalling apk dependencies"
-    - apk add	asciidoctor cmake cmark-dev gst-plugins-bad-dev gst-plugins-base-dev gstreamer-dev lmdb-dev lmdbxx nlohmann-json olm-dev openssl-dev qt6-qtbase-dev qt6-qtdeclarative-dev qt6-qtmultimedia-dev qt6-qtsvg-dev qt6-qttools-dev samurai spdlog-dev xcb-util-wm-dev zlib-dev ccache curl-dev libevent-dev meson clazy clang16 gcc musl-dev git re2-dev libsecret-dev clang16
-    - echo -e "\e[0Ksection_end:`date +%s`:install_deps\r\e[0K"
+    - apk add	asciidoctor cmake cmark-dev gst-plugins-bad-dev gst-plugins-base-dev gstreamer-dev lmdb-dev lmdbxx nlohmann-json olm-dev openssl-dev qt6-qtbase-dev qt6-qtdeclarative-dev qt6-qtmultimedia-dev qt6-qtsvg-dev qt6-qttools-dev samurai spdlog-dev xcb-util-wm-dev zlib-dev ccache curl-dev libevent-dev meson clazy clang16 gcc musl-dev git re2-dev libsecret-dev
   script:
     - export PATH="/usr/lib/ccache:${PATH}"
     - export CMAKE_BUILD_PARALLEL_LEVEL=$(cat /proc/cpuinfo | awk '/^processor/{print $3}' | wc -l)
@@ -73,7 +98,6 @@ build-clazy:
   variables:
     TRAVIS_OS_NAME: linux
   before_script:
-    - echo -e "\e[0Ksection_start:`date +%s`:install_deps[collapsed=true]\r\e[0K\e[1m\e[95mInstalling apt dependencies"
     - apt-get update
     - apt-get -y install --no-install-suggests --no-install-recommends ca-certificates build-essential ninja-build cmake gcc make automake ccache liblmdb-dev
         libssl-dev libqt5multimedia5-plugins libqt5multimediagsttools5 libqt5multimediaquick5 libqt5svg5-dev
@@ -84,7 +108,6 @@ build-clazy:
     - apt-get -y install wget
     - /usr/sbin/update-ccache-symlinks
     - rm -rf ../.hunter &&  mv .hunter ../.hunter || true
-    - echo -e "\e[0Ksection_end:`date +%s`:install_deps\r\e[0K"
   script:
     - export PATH="/usr/lib/ccache:${PATH}"
     - cmake -GNinja -H. -Bbuild
@@ -113,7 +136,6 @@ build-tw:
   variables:
     TRAVIS_OS_NAME: linux
   before_script:
-    - echo -e "\e[0Ksection_start:`date +%s`:install_deps[collapsed=true]\r\e[0K\e[1m\e[95mInstalling apt dependencies"
     - >
         zypper --non-interactive install
         "appstream-glib"
@@ -152,7 +174,6 @@ build-tw:
         "pkgconfig(xcb)"
         "pkgconfig(xcb-ewmh)"
         "time"
-    - echo -e "\e[0Ksection_end:`date +%s`:install_deps\r\e[0K"
   script:
     - export PATH="/usr/lib64/ccache:${PATH}"
     - cmake -GNinja -H. -Bbuild
@@ -235,9 +256,7 @@ build-flatpak:
       - ARCH: arm64
         JOBS: 3
   before_script:
-    - echo -e "\e[0Ksection_start:`date +%s`:install_deps[collapsed=true]\r\e[0K\e[1m\e[95mInstalling apt dependencies"
     - apt-get update && apt-get -y install flatpak-builder git python3 curl python3-aiohttp python3-tenacity gir1.2-ostree-1.0
-    - echo -e "\e[0Ksection_end:`date +%s`:install_deps\r\e[0K"
     - flatpak remote-add --user --if-not-exists flathub https://flathub.org/repo/flathub.flatpakrepo
       # see https://github.com/flatpak/flatpak-builder/issues/495
     - git config --global protocol.file.allow always
@@ -245,15 +264,11 @@ build-flatpak:
     - export VERSION=$(git describe)
     - mkdir -p build-flatpak
     - cd build-flatpak
-    - echo -e "\e[0Ksection_start:`date +%s`:build_flatpak[collapsed=true]\r\e[0K\e[1m\e[95mBuilding flatpak"
     - flatpak-builder --install-deps-from=flathub --user --disable-rofiles-fuse --ccache --repo=repo --default-branch=${CI_COMMIT_REF_NAME//\//_} --subject="Build of Nheko ${VERSION} `date` for ${ARCH}" app ../im.nheko.Nheko.yaml --jobs=$JOBS
-    - echo -e "\e[0Ksection_end:`date +%s`:build_flatpak\r\e[0K"
     - flatpak build-bundle repo nheko-${ARCH}.flatpak im.nheko.Nheko ${CI_COMMIT_REF_NAME//\//_}
   after_script:
-    - echo -e "\e[0Ksection_start:`date +%s`:upload_flatpak[collapsed=true]\r\e[0K\e[1m\e[95mUploading flatpak"
     - bash ./.ci/upload-nightly-gitlab.sh build-flatpak/nheko-${ARCH}.flatpak
     - (cd ./scripts && ./upload-to-flatpak-repo.sh ../build-flatpak/repo) || exit_code=$?
-    - echo -e "\e[0Ksection_end:`date +%s`:upload_flatpak\r\e[0K"
   rules:
     - if : '$CI_PIPELINE_TRIGGERED == null'
   cache:
@@ -273,7 +288,6 @@ build-flatpak:
   tags: [docker]
   allow_failure: true
   before_script:
-    - echo -e "\e[0Ksection_start:`date +%s`:install_deps[collapsed=true]\r\e[0K\e[1m\e[95mInstalling apt dependencies"
 
     # Installing the packages needed to download and install third-party tools
     - apt-get update && apt-get install -y software-properties-common git wget curl python3 python3-pip python3-setuptools
@@ -305,7 +319,6 @@ build-flatpak:
     - /usr/sbin/update-ccache-symlinks
     - rm -rf ../.hunter &&  mv .hunter ../.hunter || true
 
-    - echo -e "\e[0Ksection_end:`date +%s`:install_deps\r\e[0K"
     
   script:
     - export PATH="/usr/local/bin/:/usr/lib/ccache:${PATH}"
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 525a3592..af50aff8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -647,14 +647,14 @@ if(APPLE)
     endif()
 elseif(WIN32)
     file(DOWNLOAD
-        "https://raw.githubusercontent.com/mohabouje/WinToast/41ed1c58d5dce0ee9c01dbdeac05be45358d4f57/src/wintoastlib.cpp"
+        "https://raw.githubusercontent.com/mohabouje/WinToast/v1.3.0/src/wintoastlib.cpp"
         ${PROJECT_SOURCE_DIR}/src/wintoastlib.cpp
-        EXPECTED_HASH SHA256=1A1A7CE41C1052B12946798F4A6C67CE1FAD209C967F5ED4D720B173527E2073)
+        EXPECTED_HASH SHA256=1ddf8ee2604e1757d383a2f60d4d597c4f5d9496369e6a22586cedf4af77ca8f)
 
     file(DOWNLOAD
-        "https://raw.githubusercontent.com/mohabouje/WinToast/41ed1c58d5dce0ee9c01dbdeac05be45358d4f57/src/wintoastlib.h"
+        "https://raw.githubusercontent.com/mohabouje/WinToast/v1.3.0/include/wintoastlib.h"
         ${PROJECT_SOURCE_DIR}/src/wintoastlib.h
-        EXPECTED_HASH SHA256=b4481023c5782733795838be22bf1a75f45d87458cd4d9a5a75f664a146eea11)
+        EXPECTED_HASH SHA256=08cb30d28db9c851d3d4259ae6108ce7dafa966957df6735a06cd55e0716fded)
 
     set(SRC_FILES ${SRC_FILES} src/notifications/ManagerWin.cpp src/wintoastlib.cpp src/wintoastlib.h)
 else()
diff --git a/resources/AppxManifest.xml b/resources/AppxManifest.xml
index 57c7188e..417d0229 100644
--- a/resources/AppxManifest.xml
+++ b/resources/AppxManifest.xml
@@ -4,7 +4,7 @@
   xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
   xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
   xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities">
-  <Identity Name="im.nheko.Nheko" Version="0.11.3.4" Publisher="CN=NhekoReborn, O=NhekoReborn, L=Munich, S=Bavaria, C=Germany" ProcessorArchitecture="x64"/>
+  <Identity Name="im.nheko.Nheko" Version="0.11.3.4" Publisher="CN=Nicolas Werner, O=Nicolas Werner, L=Munich, S=Bavaria, C=DE" ProcessorArchitecture="x64"/>
   <Properties>
     <DisplayName>Nheko</DisplayName>
     <PublisherDisplayName>Nheko-Reborn</PublisherDisplayName>
@@ -26,7 +26,7 @@
       uap10:RuntimeBehavior="packagedClassicApp"
       uap10:TrustLevel="mediumIL">
 				<uap:VisualElements DisplayName="Nheko" Description="Matrix client written in Qt"	Square150x150Logo="nheko.png"
-					Square44x44Logo="nheko.png" BackgroundColor="#ffffff" />
+					Square44x44Logo="nheko.png" BackgroundColor="transparent" />
 				<Extensions>
 					<uap:Extension Category="windows.protocol">
 						<uap:Protocol Name="matrix">
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index b7834cba..a4a0eff0 100644
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -201,9 +201,14 @@ NhekoFixupPaletteEventFilter::eventFilter(QObject *obj, QEvent *event)
     // reason?!?
     if (event->type() == QEvent::ChildAdded &&
         obj->metaObject()->className() == QStringLiteral("QQuickRootItem")) {
+        QSet<QWindow *> newWindows;
         for (const auto window : QGuiApplication::topLevelWindows()) {
+            newWindows.insert(window);
+            if (m_postedWindows.contains(window))
+                continue;
             QGuiApplication::postEvent(window, new QEvent(QEvent::ApplicationPaletteChange));
         }
+        m_postedWindows.swap(newWindows);
     }
     return false;
 }
diff --git a/src/MainWindow.h b/src/MainWindow.h
index c493b5b2..928446aa 100644
--- a/src/MainWindow.h
+++ b/src/MainWindow.h
@@ -45,6 +45,9 @@ public:
     }
 
     bool eventFilter(QObject *obj, QEvent *event) override;
+
+private:
+    QSet<QWindow *> m_postedWindows;
 };
 
 class MainWindow : public QQuickView
diff --git a/src/encryption/SelfVerificationStatus.cpp b/src/encryption/SelfVerificationStatus.cpp
index 32e75c4f..b5549ca1 100644
--- a/src/encryption/SelfVerificationStatus.cpp
+++ b/src/encryption/SelfVerificationStatus.cpp
@@ -24,11 +24,12 @@ SelfVerificationStatus::SelfVerificationStatus(QObject *o)
   : QObject(o)
 {
     connect(ChatPage::instance(), &ChatPage::contentLoaded, this, [this] {
+        // We connect INSIDE a lambda, not A lambda...
         connect(cache::client(),
                 &Cache::selfVerificationStatusChanged,
                 this,
                 &SelfVerificationStatus::invalidate,
-                Qt::UniqueConnection);
+                Qt::UniqueConnection); // clazy:exclude=lambda-unique-connection
         cache::client()->markUserKeysOutOfDate({http::client()->user_id().to_string()});
     });
 
diff --git a/src/notifications/Manager.h b/src/notifications/Manager.h
index fbebfcba..707a4fb3 100644
--- a/src/notifications/Manager.h
+++ b/src/notifications/Manager.h
@@ -93,8 +93,12 @@ public:
 
 #if defined(Q_OS_WINDOWS)
 private:
-    void
-    systemPostNotification(const QString &line1, const QString &line2, const QString &iconPath);
+    void systemPostNotification(const QString &roomid,
+                                const QString &eventid,
+                                const QString &line1,
+                                const QString &line2,
+                                const QString &iconPath,
+                                const QString &bodyImagePath);
 #endif
 
     // these slots are platform specific (D-Bus only)
diff --git a/src/notifications/ManagerLinux.cpp b/src/notifications/ManagerLinux.cpp
index b181fdc3..11a7c1a1 100644
--- a/src/notifications/ManagerLinux.cpp
+++ b/src/notifications/ManagerLinux.cpp
@@ -114,7 +114,8 @@ NotificationsManager::postNotification(const mtx::responses::Notification &notif
 
     if (hasMarkup_) {
         if (hasImages_ &&
-            mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image) {
+            (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image ||
+             mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image)) {
             MxcImageProvider::download(
               QString::fromStdString(mtx::accessors::url(notification.event))
                 .remove(QStringLiteral("mxc://")),
diff --git a/src/notifications/ManagerWin.cpp b/src/notifications/ManagerWin.cpp
index 8d200abc..f1d3797b 100644
--- a/src/notifications/ManagerWin.cpp
+++ b/src/notifications/ManagerWin.cpp
@@ -13,6 +13,7 @@
 
 #include "Cache.h"
 #include "EventAccessors.h"
+#include "MxcImageProvider.h"
 #include "Utils.h"
 
 using namespace WinToastLib;
@@ -20,10 +21,21 @@ using namespace WinToastLib;
 class CustomHandler : public IWinToastHandler
 {
 public:
-    void toastActivated() const {}
+    CustomHandler(NotificationsManager *manager_, const QString &roomid_, const QString &eventid_)
+      : manager(manager_)
+      , roomid(roomid_)
+      , eventid(eventid_)
+    {
+    }
+
+    void toastActivated() const { manager->notificationClicked(roomid, eventid); }
     void toastActivated(int) const {}
     void toastFailed() const { std::wcout << L"Error showing current toast" << std::endl; }
     void toastDismissed(WinToastDismissalReason) const {}
+
+    NotificationsManager *manager;
+    QString roomid;
+    QString eventid;
 };
 
 namespace {
@@ -34,9 +46,9 @@ init()
 {
     isInitialized = true;
 
-    WinToast::instance()->setAppName(L"Nheko");
     WinToast::instance()->setAppUserModelId(
       WinToast::configureAUMI(L"NhekoReborn", L"in.nheko.Nheko"));
+    WinToast::instance()->setAppName(L"Nheko");
     if (!WinToast::instance()->initialize())
         std::wcout << "Your system is not compatible with toast notifications\n";
 }
@@ -52,6 +64,8 @@ NotificationsManager::postNotification(const mtx::responses::Notification &notif
                                        const QImage &icon)
 {
     const auto room_name = QString::fromStdString(cache::singleRoomInfo(notification.room_id).name);
+    auto roomid          = QString::fromStdString(notification.room_id);
+    auto eventid         = QString::fromStdString(mtx::accessors::event_id(notification.event));
 
     auto formatNotification = [this, notification] {
         const auto template_ = getMessageTemplate(notification);
@@ -61,20 +75,40 @@ NotificationsManager::postNotification(const mtx::responses::Notification &notif
         }
 
         return template_.arg(utils::stripReplyFallbacks(notification.event, {}, {}).quoted_body);
-    };
+    }();
 
     auto iconPath = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + room_name +
                     "-room-avatar.png";
     if (!icon.save(iconPath))
         iconPath.clear();
 
-    systemPostNotification(room_name, formatNotification(), iconPath);
+    if (mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image ||
+        mtx::accessors::msg_type(notification.event) == mtx::events::MessageType::Image) {
+        MxcImageProvider::download(
+          QString::fromStdString(mtx::accessors::url(notification.event))
+            .remove(QStringLiteral("mxc://")),
+          QSize(200, 80),
+          [this, roomid, eventid, room_name, formatNotification, iconPath](
+            QString, QSize, QImage, QString imgPath) {
+              if (imgPath.isEmpty())
+                  systemPostNotification(
+                    roomid, eventid, room_name, formatNotification, iconPath, "");
+              else
+                  systemPostNotification(
+                    roomid, eventid, room_name, formatNotification, iconPath, imgPath);
+          });
+    } else {
+        systemPostNotification(roomid, eventid, room_name, formatNotification, iconPath, "");
+    }
 }
 
 void
-NotificationsManager::systemPostNotification(const QString &line1,
+NotificationsManager::systemPostNotification(const QString &roomid,
+                                             const QString &eventid,
+                                             const QString &line1,
                                              const QString &line2,
-                                             const QString &iconPath)
+                                             const QString &iconPath,
+                                             const QString &bodyImagePath)
 {
     if (!isInitialized)
         init();
@@ -85,8 +119,12 @@ NotificationsManager::systemPostNotification(const QString &line1,
 
     if (!iconPath.isNull())
         templ.setImagePath(iconPath.toStdWString());
+    if (!bodyImagePath.isNull())
+        templ.setHeroImagePath(bodyImagePath.toStdWString(), true);
+
+    templ.setAudioPath(WinToastTemplate::IM);
 
-    WinToast::instance()->showToast(templ, new CustomHandler());
+    WinToast::instance()->showToast(templ, new CustomHandler(this, roomid, eventid));
 }
 
 // clang-format off
diff --git a/src/timeline/RoomlistModel.cpp b/src/timeline/RoomlistModel.cpp
index cdaa02ec..da639843 100644
--- a/src/timeline/RoomlistModel.cpp
+++ b/src/timeline/RoomlistModel.cpp
@@ -271,11 +271,13 @@ RoomlistModel::addRoom(const QString &room_id, bool suppressInsertNotification)
 {
     if (!models.contains(room_id)) {
         // ensure we get read status updates and are only connected once
+        // WORKAROUND(Nico): This is not a lambda, but clazy on alpine currently doesn't
+        // believe us...
         connect(cache::client(),
                 &Cache::roomReadStatus,
                 this,
                 &RoomlistModel::updateReadStatus,
-                Qt::UniqueConnection);
+                Qt::UniqueConnection); // clazy:exclude=lambda-unique-connection
 
         QSharedPointer<TimelineModel> newRoom(new TimelineModel(manager, room_id));
         newRoom->setDecryptDescription(ChatPage::instance()->userSettings()->decryptSidebar());
@@ -529,11 +531,13 @@ RoomlistModel::sync(const mtx::responses::Sync &sync_)
         addRoom(qroomid);
         const auto &room_model = models.value(qroomid);
 
+        // WORKAROUND(Nico): This is not a lambda, but clazy on alpine currently doesn't
+        // believe us
         connect(room_model.data(),
                 &TimelineModel::newCallEvent,
                 ChatPage::instance()->callManager(),
                 &CallManager::syncEvent,
-                Qt::UniqueConnection);
+                Qt::UniqueConnection); // clazy:exclude=lambda-unique-connection
 
         room_model->sync(room);