Commit Graph
14362 Commits
Author SHA1 Message Date
Anton Iakimov a72edc23e2 i 2026-08-27 17:24:52 +03:00
Anton Iakimov 49cfd65ce3 i 2026-08-27 16:11:09 +03:00
Anton Iakimov dc7549cc14 i 2026-08-27 15:32:28 +03:00
Anton Iakimov 46ae0e1157 i 2026-08-27 15:07:43 +03:00
Anton Iakimov 565449ec39 i 2026-08-27 14:40:06 +03:00
Anton Iakimov 4159cf3175 i 2026-08-27 13:56:34 +03:00
Anton Iakimov 5ed8a54e2f i 2026-08-27 13:20:47 +03:00
Anton Iakimov 83ded9261e i 2026-08-27 13:19:13 +03:00
Anton Iakimov f4841218dc fixes 2026-08-27 13:12:35 +03:00
Anton Iakimov a79dceee79 update to 26.05 2026-08-24 13:30:42 +03:00
Anton Iakimov 12cb3ddbfd nix: add devshell 2026-08-24 13:30:41 +03:00
Anastasiya a6728b41f3 chore(@e2e): update requirements.txt 2026-08-24 09:38:15 +03:00
Anastasiya 03eedba8f0 chore(@e2e): fix eth-accounts 2026-08-24 09:38:15 +03:00
Alex Jbanca a152a8bd55 chore(android): drop unused permissions, widen the device catalog
ACCESS_FINE_LOCATION, ACCESS_WIFI_STATE and RECEIVE_BOOT_COMPLETED have no
consumer: no LocationManager or WifiManager call anywhere in the Java sources,
no QtPositioning/QtBluetooth in the package, and no BOOT_COMPLETED receiver is
declared. All three arrived together as boilerplate in 11e22b3d8e.

The first two were not inert: Play derives android.hardware.location and
android.hardware.wifi as required features from them, so devices without wifi
or location hardware were filtered out of the catalog. Removing the permissions
removes the filters at the source.

Metered-network detection is unaffected: StatusGoService classifies transport
and expensiveness through ConnectivityManager and NetworkCapabilities, and Qt's
QNetworkInformation Android backend behind NetworkChecker uses the same two
APIs. ACCESS_NETWORK_STATE covers both; Qt6Network's android-dependencies.xml
declares no other permission.

Resulting requirements: Android 9+, arm64-v8a, normal or larger screen,
internet, and a pointer device (faketouch, which a mouse satisfies).
2026-08-22 09:27:25 +03:00
Andrey Bocharnikov 6784c4472d test: guards for the critical findings of the perf stack review (#21998)
Three tests locking in the fixes for the defects found while reviewing
the perf/loading-skeletons..perf/mobile-section-extras stack:

- tst_WalletLoaderDeepLink (PR #21918): deep-link/toast redirects while
  the asynchronous WalletLoader is still incubating must be queued and
  replayed, not dropped.
- tst_incubationcontroller (PR #21921): the boosted incubation
  controller must keep a non-zero gap between incubation bursts so the
  event loop breathes during long incubation runs.
- tst_CollapsedCategoryVirtualization (PR #21943): rows hidden by a
  collapsed category are filtered out of the chat list via the
  model-computed hidden role — zero-height delegates would all be
  instantiated by the ListView.
2026-08-22 08:13:54 +03:00
Alex Jbanca 2fb1589483 perf: mobile section extras (#21975)
* perf: port mobile section extras onto the virtualized chat stack

Ported from perf/section-loading-skeletons (the mobile mega-branch) onto
perf/chat-list-virtualization, keeping the stack's reworked chat-list
virtualization and section skeletons where the two overlapped:

- message row diet: lazy tooltips, header slimming, async avatar,
  clock-free rows, lazy sender lookup
- per-message mention resolution (MentionResolver)
- context menus built on first use (chat list and message rows)
- long-press opens the message context menu over text
- deferred first chats build until the section transition settles
  (seaqt QTimer fallback + QML settle notification)
- MessagesListHeader extracted and shared with the section skeleton
- chat/community section skeleton composition in AppMain
- StatusBaseButton emoji created on demand
- emoji and stickers popups loaded asynchronously
- day-granularity counter on StatusSharedUpdateTimer
- icon badge count from section + activity-center notifications
- QR capture, onboarding AOT-friendliness and misc row fixes

revert(navbar): drop the async PrimaryNavSidebar content and its benchmark

Back to the synchronous contentItem; the slideAnimationRunning alias stays
for AppMain's transition-settled notification.

chore(tests): drop tst_ChatListVirtualization, covered by the virtualization PR's suites

fix(chat): hide incubating panels behind their skeletons

- ChatView: left and center panel loaders stay invisible until Ready so
  the section skeleton isn't overdrawn by half-built panels. No gate on
  the right panel loader — it would hide the nested membersPanelSkeleton.
- ChatContentView: the message-rows skeleton moves out of the gated
  loader (a child would inherit the invisibility) and the messages view
  is gated the same way.
- tst_CommunityChatLoaderSection: gestures wait for a full render pass
  after the panels flip visible; drop the flaky empty-area right-click
  test.

chore: update translations

revert timestamp and long press

fix: add StatusLazyToolTip to qrc

undo DnD

* fix(chat): restore first-channel fallback on the deferred section build

If the persisted last-open chat no longer exists, buildChatSectionUI
selects nothing and the deferred path had no repair step (the loaded
path in onActiveSectionChange has one). Re-check after the build and
fall back to the first channel, before completeActiveSectionChange so
the active-chat notification carries the repaired id. Runs inside the
deferred tick — the tap/skeleton/animation path is untouched.

* fix(statusq): don't restyle detached subtrees through the Light fallback

Unparenting an item re-links its Theme attached node to the engine-level
fallback node, which is Light by default. attachedParentChange inherited
that style immediately, so every LayoutItemProxy handoff (section
switches hand panels between proxies) round-tripped the whole subtree
through Light and back in a dark app, re-firing every Theme.palette
binding — 224 message rich-text re-renders and a measured 2.3s
GUI-thread freeze per section switch on device (light theme: 96ms).

Defer the inherit while the item has no window; attachWindowReadySync
already re-inherits at window landing, before anything renders, so the
anti-flash intent of the previous order is preserved and first-attach
of incubated panels still gets exactly one style application.

* test: provide the hidden role in the ported chat-list mocks

The chat list filters rows on the model-computed "hidden" role
(PR #21943); rows without it are filtered out by design. The mocks
introduced by the mobile port predate the role, so their lists rendered
empty in CI (tst_ChatLoaderSection count 0/300, tst_ChatListContextMenu
right-click found no row). Add the role to the row builders and mirror
the backend recompute in CommunitySectionMock.setCategoryOpened.

* fix(chat): tolerate optional/lazy dependencies in the chat views

Cleans up the TypeErrors the loader test suites surfaced, three of
which are real product races:

- ChatLayout projected community stores off a null newCommunityStore —
  always null for the personal chat section and transiently while
  CommunityChatLoader swaps sections
- MessageView dereferenced the emoji popup for the message context
  menu and the add-reaction path, but the popup loads lazily after
  startup and either can run first
- ChatColumnView.restoreInputState is scheduled via Qt.callLater and
  can fire while the view tears down, after the dying context dropped
  its functions

Plus the tst_ChatLoaderSection mock gaps (clearLinkPreviewCache,
pinnedMessagesModel) behind the remaining warnings.

* chore: update translations

* test(chat): retry the synthesized drag gesture in the reorder tests

The automatic drag's nested loop occasionally misses the synthesized
press-move-release on a loaded machine (~1/35 locally, seen on CI's
Xvfb), killing the gesture mid-flight and leaving no reorder to assert.
Both reorder tests now share a dragRowVertically helper that re-runs
the whole gesture up to three times, re-reading the row's live position
and letting the rows settle between attempts. The correctness asserts
are unchanged.

* chore: update translations

* perf: tweak the incubation controller

boost mode will freeze until completion

* fix(chat): don't raise the soft keyboard on first chat open

The mention suggestion box restores focus to the composer whenever it
becomes invisible. SuggestionBoxPanel is a Control, so `visible` starts
true and the binding resolving it to false runs during construction —
firing the handler once per StatusChatInput, before the chat is on
screen, and raising the Android soft keyboard.

That branch exists only to undo the `listView.forceActiveFocus()` grab
three lines below it, which is already guarded desktop-only. On mobile it
can therefore only ever be a no-op (the user was already typing) or this
bug; the one mobile path that does need focus back — tapping a
suggestion — restores it itself in selectItem().

Reachable because the centre panel now loads asynchronously: the existing
guard in ChatColumnView only arms on a `visible -> false` edge, which no
longer occurs now that the column is born effectively invisible.

Device-verified on a Redmi A5: showSoftInput() calls during a cold start
plus first chat open went from 4 to 1, the survivor being the login
password field.

* perf: don't build a Home page before the active section is known

On cold start a complete HomePage was constructed synchronously on the
GUI thread and immediately discarded. Two independent causes, both
needed:

SectionType's zero value is HomePage, so the default-initialised
SectionDetails read as a real destination for the whole of Module.load()
— from the moment mainModule is exposed to QML until setActiveSection
resolves. Seed it with LoadingSection instead, which is already what
load() falls back to when no section resolves.

HomePageLoader keyed its `active` off appView.currentIndex, and
StackLayout initialises currentIndex to 0 — the home page's own index —
before its own binding first evaluates. Since that loader is
synchronous, the transient was enough to build the whole page. Key it
off the section type instead, which has no such default. Only this
loader was affected; nothing else sits at index 0.

Also restores the startup overlay's opaque backgrounds. The skeleton
panels that superseded ChatLayoutLoading paint tiles only, so the
overlay had become fully transparent and whatever the stack layout was
showing underneath bled through — which is how the discarded Home page
was visible in the first place.

Device-verified: runtime HomePageLoader warnings went from 3 to 0, and
no HomePage type is instantiated during startup.

* perf(chat): release the section skeleton before the messages view builds

Two fixes to what the centre panel waits for and what it builds.

The section skeleton — the one that draws its own input bar — covered
the entire message build instead of handing over to the per-chat
skeleton. centerPanelReady is `centerPanelLoader.status === Loader.Ready`,
and that loader did not resolve until the messages view had finished,
even though chatMessagesLoader is asynchronous: incubated alongside the
column, it is what the column's own Loader ends up waiting on. Gate
chatMessagesLoader on the centre panel having reported Ready, so the
shell appears first and the messages fill in behind the per-chat
skeleton — the behaviour the surrounding comments already described.

Measured on a Redmi A5, from the chat tap: the repeater's loader used to
sit 2553ms after ChatContentView had already been created; it now takes
15ms. Section skeleton retires at ~950ms instead of 3546ms. Note this
re-orders work rather than removing it — time to messages on screen is
roughly unchanged; what changes is that the user gets real chrome and a
usable composer about 2.5s earlier.

Second, a chat was given a content view without ever having been shown.
setActiveItem latches loaderActive, and the section build calls it for
the restored last-open chat — which in portrait is never displayed,
because the centre panel is lazy. Opening a different chat therefore
built two content views, and the one nobody was looking at held the GUI
thread for 2183ms after the tapped chat was already ready. Build on
"has been the active chat while this column existed" instead; the
backend latch still governs lifetime from there.

Kept in QML rather than changing the Nim latch so desktop is unaffected:
there the column exists from section load with the restored chat active,
so it is marked shown immediately.

* fix: match the startup overlay to the shape the section opens on

In portrait the chat section lands on the left panel — the chat list —
but the startup overlay drew the centre panel: chat header, message rows
and an input bar. The layout therefore changed under the user the moment
the real section arrived. Show the chat-list skeleton in portrait and
keep the three-panel arrangement for landscape.

Also corrects the panel colours. They were taken from the ChatLayoutLoading
view this overlay replaced, which used secondaryMenuBackground; the chrome
it now stands in for uses baseColor4 for the side panels and the section
background for the centre (StatusSectionLayoutPortrait, Landscape).

* fix: don't assert a section title in the startup overlay

The startup overlay paints before the backend has said which section is
active, but it drew MessagesListHeader — which hardcodes the title
"Messages" and offers invite / start-chat / search. None of that is right
for a section that may turn out to be a community, and in that mode the
header's signals are not connected, so the two enabled buttons rendered
as tappable and did nothing.

Give MessagesListSkeleton a `sectionKnown` flag. When false it draws a
placeholder row of the same shape — headline left, three round buttons
right — sized from the same theme values so it follows the font-size
setting. ChatLoader keeps the default and the real, working header.

`createChatOpened` stops being an alias: the header now sits behind a
Loader, and an alias into a deferred subtree does not work.

* test(chat): pick channel rows the view has actually placed

The reorder and click tests picked their rows by scanning the list's
contentItem for StatusChatListItem and sorting by scene y. A ListView
incubates its cache-buffer delegates asynchronously, and an incubating
delegate is already parented, visible and sized but not yet positioned,
so it sits at y 0 and ties with the real top row. Under load it won the
sort, the upward drag then started on the real top row and dragged it
out of the list into no drop target, and no reorder ever landed.

Select rows through itemAtIndex instead, which only ever returns placed
delegates, and settle on those too. The gesture retry added for the same
red is gone: it was treating a symptom, and the drag lands first try in
90 loaded offscreen runs.
2026-08-22 08:13:54 +03:00
Alex Jbanca 27a1e20c6b perf(chat): virtualize the chat and contacts channel lists (#21943)
* perf(chat): virtualize the chat and contacts channel lists

StatusChatList's ListView now owns its viewport instead of expanding to
contentHeight inside an outer ScrollView, which built every delegate up
front (~2.4ms per chat, no ceiling). Row heights are fixed constants so
the list never needs to build a delegate to know its geometry.

- StatusChatList: hardcoded chat/category row heights; hosts size the
  list; drag-and-drop is untouched and keeps working in the interactive
  list (preventStealing, reorder within the viewport)
- CommunityColumnView: ScrollView dropped; the admin banners move into
  the list footer so they still scroll below the channels
- ContactsColumnView: ScrollView dropped, list fills the column

Verified by tst_ContactsColumnVirtualization and the reworked
tst_CommunityChatLoaderSection (member and admin lists virtualized,
drag reorder, banner footer).

* perf(chat): incubate the contacts column and center panel asynchronously

The two panels are now built off the critical path, so the loader-owned
chrome paints its skeletons immediately and each slot swaps in as its own
panel finishes. This is only safe here: the channel and contact lists are
virtualized by this branch, and the message view attaches its model on
first show (lazy-load-messages), so async incubation no longer walks the
whole chat history or builds a delegate per channel.

* fixup! perf(chat): incubate the contacts column and center panel asynchronously

The 120 s ceilings were sized for a test engine running async Loaders on
Qt's render-loop budget; the boosted controller now installed in the test
harness makes them a way for a wedged suite to look like a slow one. The
whole suite runs in ~6 s.

Also spells out that contactColumnLoader's explicit size covers the
parentless incubation phase and the anchors take over afterwards.

* fixup! perf(chat): virtualize the chat and contacts channel lists

Harden the drag-reorder tests: wait for every panel's ready flag and
for row geometry to settle before the gesture (rows materialize under
async incubation and shift mid-drag), drop the irrelevant 2000-message
payload, and give the drop target a rendered frame between the final
move and the release. Failure rate goes from ~2-in-3 to ~1-in-12 on a
fast machine; the residual escape is still open (task tracking).

* refactor(chat): drop ChatsLoadingPanel, superseded by the section skeletons

The section skeleton chrome shows skeleton rows for the chat and community
columns while the section loads, so the "Loading chats..." strip below the
search box is a second, competing loading affordance.

Both call sites go with it. `chatsLoaded` has no remaining QML consumer, and
neither view uses anything else from shared.panels, so those imports are
dropped too.

* chore: update translations

* perf(chat): filter collapsed-category rows out of the chat list

Zero-height delegates were still instantiated by the ListView, so a
large collapsed category cost hundreds of delegates despite the
viewport bound. The visibility predicate now lives in the backend as a
cached per-row "hidden" role (recomputed on dependent-field writes,
never in data()), and StatusChatList drops hidden rows with a plain
ValueFilter so they never reach the view. Covered by chat_section
model tests and a large-collapsed-category virtualization test.

* fix(chat): chat list review fixes — scrollbar geometry, handler captures

- StatusChatList owns the scrollbar space: the list reserves it via its
  own rightMargin and delegates/footer size to availableWidth, so the
  overlaid scrollbar sits at the column edge instead of covering row
  controls; hosts drop their external right margins
- context-menu handlers capture signal params explicitly instead of
  relying on deprecated injected parameters
- guard contactColumnLoader.item deref while the panel incubates
- restore the master menu pattern: onClosed destroy() belongs to
  adminPopupMenuComp itself

* test(chat): drop timing-fragile instant row-count assertions

The skeleton tests asserted how many delegate rows existed at the exact
instant a skeleton cleared, racing delegate incubation against the
Loader.Ready swap — deterministic-fail under the offscreen platform and
flaky under CI's Xvfb. The skeleton coverage checks stay; row population
is now awaited with tryVerify instead of sampled at the swap instant.

* chore: update translations
2026-08-22 08:13:54 +03:00
Alex Jbanca 10b8d518e7 perf(chat): don't unroll the messages on creation (#21925)
* perf(chat): attach the messages model only when the view is shown

The message view is bottom-anchored but the model streams in top-down:
attached during the initial fetch or while the view incubates, the
ListView unwinds the entire history — one (mostly cancelled) delegate
incubation per row — before settling at the bottom. The delegate now defaults to 50px height until the row is materialized.

Chat-switch cost becomes independent of history size (a 5000-message
history went from tens of seconds of unwinding on slow devices to
building ~a viewport of rows).

Release the messages skeleton instead of hiding it: an alive invisible
skeleton re-evaluates its tile geometry bindings on every resize for the
lifetime of the chat (24k-36k evaluations in a 10s resize profile).

perf: don't unroll messages view

* fix(chat): reset keepUnread on activation in the backend

With the messages view incubated asynchronously, activeChanged fires
before the view exists, so its onActiveChanged side effects were lost on
a cold open. The keepUnread reset is backend state and now happens in
onMadeActive, independent of the view; the initial history load was
already backend-driven and mark-read is covered by the state-driven
view triggers (guarded by a new QML test).
2026-08-22 08:13:53 +03:00
Alex Jbanca 98b70ae653 perf(statusq): event-loop-driven QML incubation controller (#21921)
* perf(statusq): event-loop-driven QML incubation controller

The QQuickWindow default incubation controller collapses its time budget
when frames are slow, starving async Loaders exactly when load is
heaviest — on low-end devices this stretches section incubation into
multi-second skeletons. Drive incubation from a permanently armed timer
instead: 20ms slices per event-loop tick, a 12ms gentle phase during the
first 300ms of a burst so section-switch animations keep their frame
budget, and a 128ms idle backstop so a missed count callback can never
wedge incubation. Input stays responsive between ticks.

A/B on the community section page (STORYBOOK_INCUBATION_MS=20, gentle
phase off): idle machine 857 -> 441ms for a 210-channel load; CPU-
contended machine (the low-end condition) 5.4-8.1s with the default
controller vs a flat 400-490ms with this one.

* fixup! perf(statusq): event-loop-driven QML incubation controller

Without it the QML test engine runs async Loaders on Qt's render-loop
budget — the configuration the benchmark measured at tens of seconds per
section load, and the one nothing in the app ever uses. Tests were pinning
a configuration that does not ship, and paying for it with 120 s waits.

externc casts to QQmlEngine now: the test harness owns a plain one, not a
QQmlApplicationEngine. The HomePage grid lookup waits for its delegate
instead of assuming it exists on the same tick.

* fixup! perf(statusq): event-loop-driven QML incubation controller

* chore(statusq): env-gated incubation debug HUD

STATUS_INCUBATION_HUD=1 shows a top-right overlay with the live incubator
count (16ms refresh + 1s peak) and the controller pacing phase
(idle/gentle/boost, plus held gentle hints). Debug-only; drop before merge
if unwanted.
2026-08-22 08:13:53 +03:00
Alex Jbanca 68eb973c84 perf(chat): lazy, async member loading for user list and mention suggstions (#21920)
* perf(chat): lazy, async member loading for user list and mention suggestions

The members panel builds on first show only (latched), asynchronously
behind MembersListSkeleton — it must never delay a chat switch. Once
built, UserListPanel binds its users model only while the right panel is
actually visible, and it adopts the shared MembersPanelHeader introduced
with the skeletons. The mention suggestions adaptor stays detached from
the members model until the first mention entry (short wire delay,
loading skeleton in the suggestion box meanwhile; the latch drops on
usersModel swap so chat switches never pay for sorting the members
model). Together these were ~1.5s of the chat-switch freeze on large
communities.

* fixup! perf(chat): lazy, async member loading for user list and mention suggestions

The members panel is shared across the section's chats, so once built it
stayed visible through a chat switch: it showed the previous chat's
members while sorting the incoming model on the switch frame. A latch
drops it back behind MembersListSkeleton on every active-chat change and
re-arms on a short delay, the same shape as the mention suggestions
wiring. rightPanelReady now follows the loader it was named after.

* fixup! perf(chat): lazy, async member loading for user list and mention suggestions

Keying the latch on the active chat id dropped it on every switch, but a
community channel without permissions hands the view the *same* members
model object — so the panel was torn down and fully re-sorted for nothing,
on the dominant path. Key it on the model identity instead: same object,
same members, no work; different object, the protection the latch is for.

rightPanelReady must fold the latch in, or the chrome retires its members
skeleton exactly while the panel is showing one. membersWireDelay moves
into `d` (tests reach it through the view's private object), and the
panel's own skeleton is released like the others rather than kept alive
and hidden.

The switch test now targets the permissioned channel, whose model really
differs, and a new test pins that the shared-model switch costs nothing.

* fixup! perf(chat): lazy, async member loading for user list and mention suggestions

Extract the fully-wired CommunityChatLoader test harness (mock stack,
loader wiring, type-prefix finders) into a shared helpers component.
The members-skeleton suite is the first consumer; the community section
suite above adopts it at the next stack rebase, removing ~90 duplicated
lines per suite.

* chore: update translations

* perf: sorted users_model and PR comments

* perf: Avoid swapping skeleton for the real view when swipeview animations are running

* chore: update translations

* chore: update translations
2026-08-22 08:13:52 +03:00
Alex Jbanca 69b8a1ba1e perf(wallet): load panel content asynchronously with skeletons (#21918)
* perf(wallet): load panel content asynchronously with skeletons

WalletLoader owns the section chrome and shows the accounts/asset-list/
center-panel skeletons while LeftTabView's account list and
RightTabView's tab content incubate behind asynchronous Loaders.

* fixup! perf(wallet): load panel content asynchronously with skeletons

RightTabView already releases its skeleton with a Loader; these three were
left alive for the section's lifetime, re-evaluating their tile geometry
on every resize. Same idiom everywhere.

* fixup! perf(wallet): load panel content asynchronously with skeletons
2026-08-22 08:13:52 +03:00
Alex JbancaandAnastasiya bd3fccc449 perf: load the chat and community sections asynchronously with skeletons (#21917)
* perf: load chat and community sections asynchronously with skeletons

The section loaders own the chrome (StatusSectionLayout) and show the
matching skeleton — with the real, functional header — while the actual
section incubates behind an asynchronous Loader; the section's panels
are proxied back into the loader-owned chrome once ready (full-page
community views hide it). The communities portal loader turns
asynchronous too. The pre-ready startup overlay recomposes from the
skeleton panels, replacing the ChatLayoutLoading placeholder view (whose
AppMain reference had been left dangling).

* fixup! perf: load chat and community sections asynchronously with skeletons

Each skeleton slot was gated on the whole section loader reaching Ready, so
the header, chat list, message column and member list all swapped in at once,
paced by the slowest panel. ChatView now publishes per-panel readiness and
ChatLayout forwards it, letting each slot retire on its own. `root.item` is
null until the section itself loads, so the old whole-loader behaviour remains
the floor.

The right panel is not deferred at this point in the stack, so its flag is
constant; it becomes meaningful once the members panel moves behind a loader.

Also drops `signal ready()` from both section loaders: `mainReady` is fed to
AppMain by AppMainLoader and nothing has ever connected to `ready`, so the
signal and the comment claiming AppMain owns the spinner toggle are both dead.

* fixup! perf: load chat and community sections asynchronously with skeletons

The startup overlay predates the loader-owned chrome. ChatLoader and
CommunityChatLoader declare their skeleton panels as plain children, which Qt
instantiates and paints even while the loader is inactive, so for the chat
section the overlay now covers an already-correct skeleton with a duplicate of
itself.

Scoped to the two cases where nothing else paints yet: the communities portal
(CommunitiesPortalLoader is gated on mainReady and owns no skeleton), and a
community section during the window where activeSectionType is already
`community` but the repeater has not produced any delegate — the same window
the currentIndex fallback below already accounts for.

* fixup! perf: load chat and community sections asynchronously with skeletons

Release the chrome skeletons instead of hiding them: permanent
visible:-gated skeletons re-evaluate their tile geometry bindings on
every resize for the lifetime of the section (same class as the
ChatContentView messages skeleton, caught in a resize profile). Each
skeleton now lives behind a Loader gated on its slot's readiness.

* fixup! perf: load chat and community sections asynchronously with skeletons

The slots fell through to the real panel as soon as `root.item` existed.
ChatView's panels are non-null Loader objects from the moment the section
loads, so `?? skeleton` never saw the readiness flags: the LayoutItemProxy
retargeted to an empty Loader, released the skeleton with
setParentItem(null)/setVisible(false), and the slot painted nothing until
the panel incubated. Gate each slot on its own flag instead.

The skeletons collapse to bare Loaders keyed on `!ready`, dropping the
wrapper Item whose `visible` the proxy also writes.

tst_SectionLoaderChrome drives both loaders with a stub section whose
flags are writable, so the contract is pinned as a binding rather than as
a race against incubation.

* fixup! perf: load chat and community sections asynchronously with skeletons

The startup overlay's only remaining case was a community section with no
repeater delegate yet, and it painted the chat-list skeleton there — wrong
shape, replaced a frame later by CommunityChannelsSkeleton. Keep the
overlay for the communities portal, which has nothing else painting, and
let a missing community delegate fall back to the currentIndex loader,
which already shows the right shape.

* fixup! perf: load chat and community sections asynchronously with skeletons

* chore(@e2e): fix tests according to the changes

* fixup! perf: load chat and community sections asynchronously with skeletons

* fixup! perf: load chat and community sections asynchronously with skeletons

---------

Co-authored-by: Anastasiya <anastasija.ig@gmail.com>
2026-08-22 08:13:51 +03:00
Alex Jbanca 9e6d2e1a21 feat(storybook): chat and community section pages with configurable mocks (#21892)
* feat(storybook): chat and community section pages with configurable mocks

ChatLoaderPage and CommunityChatLoaderPage load the real section loaders
against stubbed stores. CommunitySectionMock builds a full community
behind the section-module interface — configurable join state, member
role, categories, channels, private channels with their own members,
token permissions and scale knobs (members/categories/channels/messages,
positional args for benchmarking) — and applies mutations (reorder,
category collapse, active chat) to its models so interactions give real
feedback. Store stubs extended accordingly (Messaging tree, chat/
community/shared stores, section context-property mocks).

* fixup! feat(storybook): chat and community section pages with configurable mocks

Migrate ChatContentView/ChatHeaderContentView store imports from relative
to the identified module import so the storybook stubs can intercept them.
With the relative import the real typed RootStore/MessageStore load in
storybook, the stub RootStore instance cannot be assigned to the typed
property, and the messages area is stuck on its loading skeleton.

* fixup! feat(storybook): chat and community section pages with configurable mocks

Declare chatsLoaded on the chat section module mock: the real module
exposes it and ContactsColumnView gates its loading spinner on it, so the
undefined property kept the spinner permanently visible on the page.

* fixup! feat(storybook): chat and community section pages with configurable mocks
2026-08-22 08:13:51 +03:00
Alex Jbanca e6033215f2 Perf/loading skeletons (#21890)
* feat(StatusQ): add LoadingSkeletonGroup/Tile skeleton primitives

Lightweight placeholders for section loading states: plain rounded
tiles plus a group wrapper running a single masked shimmer sweep for
the whole group (one animator, no per-tile effects). Storybook page
included.

* feat: section loading skeleton panels for chat, communities and wallet

Skeletons matching each section's layout, shown while the section
incubates: messages list (with real, functional header and disabled
search), chat header/input, members list (with panel header), community
channels (with the real community identity header) and wallet
accounts/asset-list/center panels. One storybook page per panel plus
grouped preview pages.

* fixup! feat: section loading skeleton panels for chat, communities and wallet

Dropping ChatsLoadingPanel took the last QML reader of the chatsLoaded
property, so the QtProperty, its signal and its backing field are dead
weight. The one remaining Nim reader goes to the module's own flag, which
is set in the same handler.

* chore: update translations

* fixup! feat: section loading skeleton panels for chat, communities and wallet

* chore: update translations
2026-08-22 08:13:50 +03:00
Anastasiya c78e3ac13b tests(@qml): add QML tests for PasswordChangeModal 2026-08-21 23:22:58 +02:00
Anastasiya d2e639a549 tests(@e2e): fix password change tests and reduce timeout to 5 seconds 2026-08-21 23:22:58 +02:00
Sale Djenic 8a449f6572 feat(onboarding): skip app restart after lost-keycard conversion for DEK profiles 2026-08-21 23:22:58 +02:00
Sale Djenic 64ca2fb8ca feat: fast password change with optional rekey
Profiles on the DEK encryption scheme change their password by re-wrapping the profile key file
means no database re-encryption, no restart.

The change-password modal has options:
- do fast password change re-wrap the DEK
- do deep password change in case of legacy profiles (one-time migration), or the new profiles for
  which "also re-encrypt my data" (rekey) checkbox is checked

Closes #21877
2026-08-21 23:22:58 +02:00
Andrey Bocharnikov 8415c54eee fix(contract): point wakuext gate at pkg/services after the status-go move
The gate still read services/wakuv2ext, so CI treated a present submodule
as missing. Skip .claude so nested worktrees are not scanned as call sites.
2026-08-21 20:27:38 +04:00
Andrey Bocharnikov 391969226f feat(settings): add a Storage stats section to Advanced
A bug reporter can now export a quantitative profile of their own account -
message counts, per-chat distribution, sync gap, wallet and per-table sizes -
and paste it into a ticket. Reproducing status-im/status-app#21605 cost days
precisely because that shape had to be guessed.

Pressing Collect data starts the status-go walk and returns; the section then
shows a real "N of M" (status-go enumerates the table list before counting
anything), a small histogram of chats by message count, a few headline
numbers, and a Copy to clipboard button carrying the profile as JSON. The
same JSON is written into the log directory, so the existing "collect logs"
flow bundles it with no extra wiring - and the timestamp in its name is what
makes its age visible once bundled.

Nothing is collected until the button is pressed: COUNT(*) on a sqlcipher
table is a full decrypting scan, and the whole point of this feature is to
describe an account's performance, not to degrade it. The result is kept by
the service for the session, because this page is built by a Loader and would
otherwise throw away minutes of scanning every time the user navigates away.

The section is gated on non-production builds. Turning it on in production is
a separate change with its own privacy review.
2026-08-21 16:21:35 +04:00
Anastasiya 1ec328a596 fix(@onboarding): show a dialog when accounts fail to load at startup 2026-08-21 13:59:35 +03:00
Anastasiya 3a17fec992 chore(@e2e): document generating the local Waku fleets JSON 2026-08-21 13:59:35 +03:00
Anastasiya e0cc613309 fix(@onboarding): show an error when openedAccounts fails 2026-08-21 13:59:35 +03:00
Jonathan Rainville 1fd9ebba8d feat(gifs): hide GIF-only message URLs when previewing
Fixes #21990

- detect direct HTTP(S) `.gif` URLs generically, including query/fragment variants
- hide the text bubble only when a message contains GIF URLs and nothing else
- retain raw URLs in mixed messages, copy, and edit flows
- show `GIF` for GIF-only reply and Activity Center text previews
- add QML utility coverage for GIF link and GIF-only message detection
2026-08-20 13:01:14 -04:00
Anastasiya 233fa7d065 chore(@e2e): remove keypair renaming test in favor of QML 2026-08-20 17:17:44 +03:00
Anastasiya f6821e9e8c tests(@qml): cover keypair rename menu and popup in Storybook 2026-08-20 17:17:44 +03:00
Anastasiya df11b74877 test(@e2e): import recover phrase onto keycard from settings 2026-08-20 17:17:44 +03:00
Anastasiya 89fd97a8ea chore(@qml): add object names 2026-08-20 17:17:44 +03:00
Sale Djenic e7710a39b7 fix(biometrics): make biometrics work for keycard profiles 2026-08-20 16:02:01 +02:00
Anastasiya cfa05c2a14 chore(@e2e): fix object types 2026-08-20 15:56:15 +02:00
Lukáš Tinkl ba29516446 fix(ProfileLayout): speed up initial creation
- replace the StackLayout with a StackView, simplify the
SettingsLeftTabView and SettingsList to avoid circular bindings; the
`settingsSubsection` and `settingsSubSubsection` are only modified now
from outside, and passed down via bindings
- do not transform the base model (for retranslation) on startup; we do
not even support that
- cache the `subsection` model role, it's used in a hotpath for every
delegate

Fixes #21960
2026-08-20 15:56:15 +02:00
Lukáš Tinkl 74467475bb fix(ProfileLoader): mark Profile as selected
- on desktop, we are preloading the MyProfileView, so make it selected
in the left pane
2026-08-20 15:56:15 +02:00
Lukáš Tinkl c2cd6716da fix(SettingsContentBase): fix empty gap at top
- no need to autoscroll on desktop, was leaving an empty gap on top of
every page
2026-08-20 15:56:15 +02:00
Lukáš Tinkl 0813dca271 fix(LogosNetworkView): fix link color and text alignment 2026-08-20 15:56:15 +02:00
Lukáš Tinkl c664f44024 chore(ProfileUtils): type-annotate function prototypes
- suppresses lots of runtime QML warnings
2026-08-20 15:56:15 +02:00
Anastasiya 1f8f216215 chore(@e2e): update macOS script for Squish setup 2026-08-20 15:16:15 +03:00
Jacek Sieka 32a05a3599 avoid linking pcre (#22018) 2026-08-20 10:10:26 +02:00
Jonathan Rainville a435c8619d chore: fix FR translations and clean up some bad strings + layout fixes 2026-08-19 22:34:02 +02:00
Lukáš Tinkl 2f09e40136 feat(l10n): introduce new French translation
- codename `fr`
- adjust cmake

Fixes #21993
2026-08-19 22:34:02 +02:00
Jonathan Rainville 64e829b108 fix(main): show loading section while restoring chat/community
Fixes #21965

Activate the existing loading section when the persisted active section is
not available until chats and communities finish loading. This prevents the
HomePage from briefly rendering after startup.

Keep the loading item active until the restored section is resolved, fall
back to Messages if it no longer exists, and avoid persisting the temporary
loading section. Map the loading type to the startup chat skeleton in QML.
2026-08-19 10:40:28 -04:00