New STATUSQ_BUNDLE_QML option (default ON, desktop/storybook unchanged);
mobile passes OFF and bundles statusq.qrc + asset qrcs via Status.pro so
the Qt Quick Compiler processes StatusQ's QML (57% of its bindings
AOT-compile, tree 46% -> 48%). Resource paths are unchanged.
First-launch cold start on device: 5.65s -> 4.83s; runtime QML
compilation is now fully eliminated (warm == cold).
- enable qtquickcompiler and split browser web scripts into their own
qrc excluded from compilation (browser-engine JS, not QML-engine)
- pass the runtime import paths to qmlcachegen; qtquickcompiler.prf only
passes --resource, leaving all in-repo modules unresolvable
(11% -> 32% of bindings AOT-compiled)
- shim the Universal style in as QtQuick.Controls for the compiler;
qmlcachegen cannot follow the selector module's optional imports
(32% -> 46%)
- emit per-binding .aotstats next to each generated .cpp for coverage
tracking
Extend the cross-platform web view seam with the download vocabulary the
Downloads feature builds on (ADR 0006):
- AbstractWebView: DownloadState gains DownloadPaused (WebEngine-shaped
numbering, Paused = 5 matches MobileWebViewDownload), a host-side
downloadUrl() re-issue used for Retry, a linkLongPressed(link, image,
position) signal for mobile Backends, supportsPdfViewer, and a
'retained' flag for Web Views kept alive after their tab closes.
The downloadsStore / isDownloadView coupling is gone: adapters map
Backend downloads into the seam and the UI never branches on Backend.
- WebViewAdapter / MobileWebViewAdapter / LazyWebViewAdapter implement
the seam; the desktop path gains an injectable isBrowsableLocalUrlFn
local-URL guard exception, and LazyWebViewAdapter forwards Retry
through ensureLoaded().
- ProfileManager survives a WebEngine profile data-path collision.
- StatusQ C++: BrowserProfileUtils (QWebEnginePage::download re-issue,
profile plumbing) and SystemUtilsInternal additions, iOS share-sheet
support via NSItemProvider in ios_utils.mm, Android accept path in
StatusQtActivity, mobilewebview pin bump, and Common.mk tracks
CMakeLists.txt so the pin invalidates mobile builds.
* fix(ios): paste without triggering the system paste permission prompt
On iOS any programmatic read of UIPasteboard shows the "Allow Paste?"
alert. Our Paste buttons read the clipboard directly, so they prompted
every time. Replace them with UIPasteControl, where the system performs
the read and hands over the contents, making the tap itself the consent.
- add NativePasteButtonItem, hosting a native UIPasteControl, and the
StatusPasteButton wrapper (native on iOS, StatusButton elsewhere)
- use it for every Paste button: sync code, WalletConnect URI,
watch-only address, private key, chat key and both send recipient
inputs
- disable AppMain's passive clipboard watcher on iOS: it read the
clipboard with no user action at all, which is what prompted on launch
- drop the now-dead iOS guards left over from #21365
A native view composites above the whole Qt scene, so the control is
clipped to its visible viewport and hidden whenever something is stacked
above it - a popup over the page, or another popup over the one holding
it. That state is recomputed per frame from afterAnimating and pushed to
UIKit only when it changes; it must not call polish(), which requests a
new frame and would keep the window rendering forever.
The paste completion captures the target view rather than a raw C++
pointer, so a control destroyed while the item provider loads - closing
the modal it lives in - cannot deliver into freed memory.
Desktop keeps its existing Paste button styling: the wrapper forwards
size, border, font weight and focus policy, and each site passes what it
used before. Desktop buttons are now disabled rather than always enabled
when the clipboard has no text.
Also track *.mm in STATUS_Q_FILES: the mobile build only watched .cpp
and .h, so no Objective-C++ change in StatusQ ever triggered a rebuild
and stale binaries were shipped to the simulator.
Text editors are unaffected: StatusTextArea is a Controls TextArea, so
long-press gives the OS edit menu, whose Paste the system authorises.
Closes#21438
* fix(StatusPasteButton): apply review feedback
- base the wrapper on Control and forward the font group, so a site can
set the label's family, weight or pixelSize. They are forwarded one by
one on purpose: StatusBaseButton binds each of them itself, and a
whole-group `font:` assignment is silently ignored - verified by
checking that a bigger pixelSize actually widens the button.
- keep the wrapper out of the tab chain. Control brings its own
focusPolicy, so the button's is `buttonFocusPolicy`; otherwise the
composite would add a tab stop in front of the button.
- derive the Qt -> UIKit scale from the window's devicePixelRatio over
the view's contentScaleFactor rather than parsing QT_SCALE_FACTOR. The
ratio is exactly the extra Qt scaling, whatever asked for it.
- mark foregroundColor/backgroundColor REQUIRED: UIKit picks each tint's
default on its own, so setting only one can leave the glyph unreadable
against the fill.
* fix(NativePasteButtonItem): make the zero-scale guard obvious
contentScaleFactor was already checked before the division, but far
enough above it to read like an unguarded divide. Bail out on the null
view and window first, then guard the divisor right where it is used.
On iOS, Nim builds --app:staticlib, so the .a ships bitcode, and the actual LTO + codegen happens at Xcode's final link.
ThinLTO is aggressive about cross-module optimization, and it occasionally miscompiles code with subtle semantics.
The exact pattern that's failing — Nim's ORC move/destructor handling around std/json's ref-based JsonNode built
via %* (a newJObject() followed by a run of OrderedTable inserts) — is a classic place for an over-eager optimizer to
wrongly drop the populated temporary or elide the inserts, yielding an empty {}.
- Deleted the status-keycard-go submodule from .gitmodules and Makefile.
- Updated config.nims to reference STATUSKEYCARD_QT_LIBDIR instead of STATUSKEYCARDGO_LIBDIR.
- Adjusted build scripts and feature flags to remove dependencies on status-keycard-go.
- The code aligned.
* chore: remove Node Management page
Remove the experimental Node Management section end-to-end: the QML page
and section loader, sidebar/section wiring, the node_section backend
module, the now-dead status-go shim procs, the page-only Stats and
ChroniclesLogs signal plumbing, and the Profile > Advanced toggle.
Network-connectivity detection is preserved by relocating the peer ->
connected bridge from the deleted node section into node_service.init.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: update-translations
* test: drop Node Management refs from storybook
Remove the now-dangling nodeEnabled property usage and the node section
fixtures left behind in storybook after the PrimaryNavSidebarAdaptor lost
its nodeEnabled property: the tst_PrimaryNavSidebar test/page bindings and
the Node entry in the mock SectionsModel.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The issue only manifests when:
The mobile Makefile exports CC=clangWrap.sh (via EnvVariables.mk)
clangWrap.sh has the echo to stdout
Go's linker discovers ar via CombinedOutput() which captures both stdout and stderr
When invoked through the mobile Makefile, CC=clangWrap.sh leaks into the Go build's environment (despite the shell-level CC="$(xcrun ...)" override in the status-go recipe). Go's linker then runs clangWrap.sh --print-prog-name ar, and the echo output to stdout gets combined with clang's actual output, corrupting the ar path.
Removing the echo fixed the issue.
* feat(ios): wire-up push notifications
- wire push notifications endpoints with qml access
- split NotificationsView.qml into 2 different components. The general component preserving the current behavior and a reduced functionality for centralized push notifications (similar to the Status legacy)
- wire bundle id from EnvVariables.mk to the push notifications status-go calls. We need the bundle id as topic.
- Tweak the Push permissions request flow to account for platform specifics
* fix: mobile-run doesn't work for all targets
- remove `androidMinimizeToBackground` as it's not used anymore
- status-go client and server use configurable compilation flags based on `DEBUG` flag
- remove verbose logging in StatusGoService.java
Add an option to run status-go as a service on android using Androdi Binder as a transport.
See ADR for more details docs/adr/0001-android-status-go-as-a-service.md
- `mobile/Makefile` -> Added `apk-fdroid` build target, used by
`fdroid/build-app.sh`. F-Droid requires an unsigned APK without Google
Play services.
- `mobile/android/qt6/build.gradle` -> Added F-Droid gradle build
flavor, used during `apk-fdroid` target. Separates F-Droid builds from
Play Store builds and no signing configuration since it's supposed to be
unsigned.
- `mobile/scripts/buildApp.sh` -> Updated to copy F-Droid APK instead
of usual locations from Jenkins build.
- `mobile/scripts/buildOpenSSL.sh` -> Moved from iOS dir, shared
between iOS and F-Droid builds. Reusing the OpenSSL build logic that was
previously iOS-only but is now needed for F-Droid's from-source
requirement.
- `mobile/scripts/Common.mk` -> Updated path to `buildOpenSSL.sh`
which is no longer inside iOS dir.
- `mobile/scripts/openssl-patch.diff` -> Moved from iOS dir, applied
by `buildOpenSSL.sh`, so that the patch is co-located with the script
that uses it.
- `ci/Jenkinsfile.fdroid` -> Had to make a new pipeline script because
integrating this into `ci/Jenkinsfile.android` was causing issues with
the generated `AppImage` and steps had to be fully sequential, so I
figured it's good to separate them out.
- `fdroid/entrypoint-fdroid.sh` -> Docker entrypoint, used by
`fdroid/Dockerfile`. Sets up the container user/permissions before the
F-Droid build starts.
- `fdroid/Dockerfile` -> A minimalistic Docker image for the F-Droid
Jenkins build environment, used by `ci/Jenkinsfile.fdroid`. I didn't add
to existing Qt Android `Dockerfile` because this one only needs a
minimal environment with Docker-in-Docker to run the `fdroidserver` VM.
- `fdroid/build-app.sh` -> Called by `fdroiddata` metadata build step.
Sets up Qt and Android NDK environment, detects `JAVA_HOME`, configures
`Go`/`Nim` env vars, and runs the `make` targets for the F-Droid APK.
- `fdroid/build-openssl.sh` -> F-Droid requires OpenSSL to be built
from source rather than using prebuilt binaries.
- `fdroid/build-qt-android.sh` -> F-Droid requires Qt to be built from
source; this handles the Android cross-compilation.
- `fdroid/build-qt-host.sh` -> Qt's cross-compilation requires host
tools (`moc`, `rcc`, etc.) to be built first.
- `fdroid/cleanup-binaries.sh` -> Removes binaries flagged by `fdroid`
scanner, called by `fdroiddata` metadata `prebuild` step. F-Droid's
scanner rejects repos containing prebuilt binaries in test/vendor
directories.
- `fdroid/cleanup-fdroiddata.sh` -> Removes stale `fdroiddata` clones,
called by `ci/Jenkinsfile.fdroid`. Prevents disk space issues from
accumulating `fdroiddata` clones across builds.
- `fdroid/fdroid-container-build.sh` -> Runs `fdroid build` inside
Docker container, called by `scripts/fdroid-local-build.sh`. Isolates
the build in a container to match F-Droid's official build environment.
- `scripts/fdroid-local-build.sh` -> A handy script to build F-Droid
locally, also called by `ci/Jenkinsfile.fdroid`. Manages the full
lifecycle of cloning `fdroiddata`, launching the `fdroidserver`, and
extracting the output APK.
- `fdroid/generate-keystore.sh` -> Generates a single-use keystore for
signing the F-Droid APK. Sourced by `buildApp.sh` to export signing
credentials into the build environment.
fixes: https://github.com/status-im/status-app/issues/19741
Otherwise they would fail like this :
```
[2026-02-17T01:17:53.201Z] * What went wrong:
[2026-02-17T01:17:53.201Z] Task 'assembleRelease bundleRelease' not
found in root project 'android-build'.
```
fixes :
```
0m=[94mqrc:/app/AppLayouts/Profile/views/EnsView.qml:4
[0m [33mtext[0m=[94m"module \"QtQml.StateMachine\" is not installed"[0m
```
and
```
E FATAL EXCEPTION: qtMainLoopThread
Process: app.status.mobile.debug, PID: 18150
java.lang.UnsatisfiedLinkError: dlopen failed: library "libStatus
Debug_arm64-v8a.so" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:1097)
at java.lang.Runtime.loadLibrary0(Runtime.java:1019)
at java.lang.System.loadLibrary(System.java:1765)
at
org.qtproject.qt.android.QtLoader.loadLibraryHelper(QtLoader.java:486)
at
org.qtproject.qt.android.QtLoader.lambda$loadMainLibrary$0$org-qtproject-qt-android-QtLoader(QtLoader.java:535)
at
org.qtproject.qt.android.QtLoader$$ExternalSyntheticLambda1.run(D8$$SyntheticClass:0)
at org.qtproject.qt.android.QtThread.lambda$run$0(QtThread.java:57)
at
org.qtproject.qt.android.QtThread$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0)
at org.qtproject.qt.android.QtThread$1.run(QtThread.java:25)
at java.lang.Thread.run(Thread.java:1563)
```
- re applies this commit :
https://github.com/status-im/status-app/commit/9381d0d06c2bee8e902be3bcf49e9680fe055b0d
- I also adjust the qml lint job to catch this kind of import failure in
CI :
```
[2026-02-03T07:06:17.215Z] Running: QML Lint (Mobile)
[2026-02-03T07:06:17.215Z] qmllint: /opt/qt/6.9.2/gcc_64/bin/qmllint
[2026-02-03T07:06:17.215Z] Qt modules:
/opt/qt/6.9.2/android_arm64_v8a/qml
[2026-02-03T07:06:17.215Z]
[2026-02-03T07:06:17.215Z] Checking 1200 files...
[2026-02-03T07:06:33.882Z]
[2026-02-03T07:06:33.882Z] ERRORS:
[2026-02-03T07:06:33.882Z]
/home/jenkins/workspace/status-app-android/13/ui/app/AppLayouts/Profile/views/EnsView.qml:4:1:
Failed to import QtQml.StateMachine. Are your import paths set up
properly?
```
- Add debug android variant for local builds.
- Fix container builds makefile target for running locally.
- Switch from compiling QT ourselves to relying on `aqtinstall`
- uses fewer qt modules
- adds cleanup stage to save space
- fix make translation target for macos
GlobalPlatform crypto needs the legacy providers. While it will potentially work OOTB with android since we're using dynamic linking, for IOS we need to compile with `no-module`. This will bundle the providers in the lib.
This commit adds the status-keycard-qt submodule and updates the build configuration to support it.
In this initial version the `status-keycard-qt` option can be enabled by using the `USE_STATUS_KEYCARD_QT` flag.
- desktop: `USE_STATUS_KEYCARD_QT` will enable/disable the qt implementation. By default the go version is used
- ios: `USE_STATUS_KEYCARD_QT` will enable/disable the qt implementation
- android: the qt implementation is enabled by default
to squash - first commit
- points to `fix-ios-signing-with-fastlane` branch of
`status-jenkins-lib` which provides development certs for PR builds and
distribution certs for release builds.
- adds nix flake to provide ruby dependencies for `fastlane`
- adds config for new build identifier for PRs: `app.status.mobile.pr`
- swaps testflight script with fastlane action
- adds job to build iOS in release
- updates status-go to use nim-sds from
https://github.com/logos-messaging/nim-sds/pull/41
- update status-jenkins-lib to v1.9.30 which provides iOS provisioning
profile and appstore certs.
- builds signed iOS app and pushes to testflight.
- updates testflight metadata with PR link and commit sha it was built
from
- adds `scripts/testflight-changelog.mjs` script used by CI to update PR
metadata.
- set `ITSAppUsesNonExemptEncryption` to `false`