Commit Graph
175 Commits
Author SHA1 Message Date
Evgeny @ SimpleX Chat 5cc0cda62a review 2026-10-05 12:49:53 +00:00
Evgeny @ SimpleX Chat 7120ab9a3d Merge branch 'master' into ab/names-lookup-api 2026-10-05 12:14:34 +00:00
Evgeny Poberezkin 6b596c0c35 Merge branch 'stable' 2026-10-03 08:05:19 +01:00
EvgenyandNarasimha-sc 53e6d435bc android, desktop: blur media thumbnails in reply quotes and the chat list (#7639)
"Blur media" hid images and videos in a chat but showed the same media
sharp as the thumbnail of a quoted message and as the last message's
image, video or link preview in the chat list.

Small views are now blurred with the same reveal as chat media. They are
resampled relative to the width they are drawn at, so a thumbnail is
blurred as much on screen as media in a chat, and drawn as the centre
crop the thumbnail shows. In-chat media keeps the same blur.

Blurring the chat list also needs: each last message gets its own blur
state, loaded chat-list videos use it and hide their full-screen play
button while blurred, a right-click on a thumbnail no longer leaves it
revealed on desktop, and leaving a chat mid-scroll no longer undoes
reveals in the list on Android.

Co-authored-by: Narasimha-sc <166327228+Narasimha-sc@users.noreply.github.com>
2026-10-03 07:17:20 +01:00
Narasimha-sc 205d17e2fa android, desktop: make media blur much lighter on CPU (#7483)
* ui: blur media by resampling the preview, not a per-frame effect

Modifier.blur put a BlurEffect on a display-sized graphics layer, so the
Gaussian was re-evaluated on every frame the media was drawn. It also
requires RenderEffect, which Android applies only from API 31, so below
Android 12 media was drawn unblurred while the setting read as on.

A blur and a downscale discard the same thing - detail finer than their
radius - so the preview is now resampled to about one pixel per radius and
stretched back. That runs once when the item composes, needs no
RenderEffect, and removes the detail irreversibly rather than convolving
it. The first resampling step bounds both sides, so no image, however
shaped, can produce a large intermediate.

While the blur hides the media the file is also left unread, so an image
scrolled past is no longer read, decoded at its full size and kept in the
image cache only to be hidden again. blurHidesMedia() is the single
definition that both the drawing and the loading decision use, so they
cannot disagree about whether the media is on screen.

* plans: blur media by resampling the preview

* ui: shorten comments in media blur

* ui: smooth the media blur and match its strength to the old one

Stretching the resampled preview straight to the screen showed its pixel grid. Double it back
up until its longest side is at least half the reference width before drawing, so the last
stretch is short and the tents compose into a bell. The reference width moves from 360 to 400:
fitted against Gaussians, 360 blurred 5-75% more than Modifier.blur did, 400 is within 10% at
every setting.

(cherry picked from commit c0344a9a61)
2026-10-02 15:59:38 +01:00
Alain Brenzikofer 7089d128f5 27 rounds of /goal 2026-10-01 07:56:24 +02:00
Alain Brenzikofer 6bc2f4450e align and simplify core/UI/UXcanvas 2026-09-30 20:11:51 +02:00
Alain Brenzikofer 10c456b057 align excalidraw 2026-09-30 17:24:12 +02:00
Alain Brenzikofer 22e89573aa iterations on /goal 2026-09-30 15:15:54 +02:00
Alain Brenzikofer 13e3d5a6e9 docs fixes 2026-09-30 11:30:55 +02:00
Alain Brenzikofer 86556408ba align app divergences 2026-09-30 10:55:55 +02:00
Alain Brenzikofer ddc18b326b fix freshness bug with local chats: When core marks a chat verified for a name, it now first un-verifies the user's other chats of the same kind:
- a contact name covers contacts and business chats;
  - a channel name covers channels.
2026-09-30 10:10:29 +02:00
Alain Brenzikofer 8028247e87 iterate on /goal 2026-09-29 16:32:33 +02:00
Alain Brenzikofer baf485b8d6 review round on UX coverage 2026-09-29 15:15:58 +02:00
Alain Brenzikofer 42a4cc8adf commit wireframe collab doc to repo as README 2026-09-29 10:56:27 +02:00
Alain Brenzikofer 03c8f242a4 cosmetics 2026-09-29 10:42:52 +02:00
Alain Brenzikofer a0578803ee add excalidraw normalizer script and test git hook 2026-09-29 09:55:59 +02:00
Alain Brenzikofer 5b67eaf618 simplify and normalize diagram 2026-09-29 09:44:46 +02:00
Alain Brenzikofer 38b79929ca refactor core-UI API to NameWarning with logic in core 2026-09-29 08:06:05 +02:00
Alain Brenzikofer b78d76ae64 Merge branch 'master' of https://github.com/simplex-chat/simplex-chat into ab/names-lookup-api 2026-09-28 08:34:34 +02:00
Narasimha-scandEvgeny Poberezkin 294fbf1b7d desktop: fix crash at startup on Windows when WMI does not answer (#7581)
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2026-09-26 13:42:02 +01:00
Narasimha-scandEvgeny 8e35c05fc0 android: match app links by exact path so simplex.chat pages open in the browser (#7565)
* android: match app links by exact path so simplex.chat pages open in the browser

* simpler

---------

Co-authored-by: Evgeny <evgeny@poberezkin.com>
2026-09-26 13:23:54 +01:00
Narasimha-scandEvgeny 11ecd0f5b7 android: match app links by exact path so simplex.chat pages open in the browser (#7565)
* android: match app links by exact path so simplex.chat pages open in the browser

* simpler

---------

Co-authored-by: Evgeny <evgeny@poberezkin.com>
2026-09-26 13:21:05 +01:00
Narasimha-sc b85313b61f desktop: fix app freeze when a video is stopped during format negotiation (#7582)
video().track() in the buffer format callback takes the libvlc input lock,
which stop() holds while it waits for the decoder thread running that
callback. Take the video track from the media info only.
2026-09-26 13:14:13 +01:00
Narasimha-scandEvgeny Poberezkin 67c619acff android, desktop: open group member profile without waiting for the core (#7485)
* android, desktop: open group member profile without waiting for the core

Tapping a member avatar awaited apiGroupMemberInfo and apiGetGroupMemberCode
before the profile modal was created. Both are single-row queries, 1-2 ms when
the core is idle, but sendCmd is serialized against everything else the core is
doing, so while it is busy - startup, a batch of incoming events, a long database
operation - the tap produces nothing at all until the core drains.

The modal is now opened first and the two values arrive in state the tap handler
creates, so the profile opens at the speed of the UI. The card is shown from the
member that is already known at the tap, preferring the model's copy once it is
there, so the member no longer has to be written to the model before the modal
can be shown.

* plans: open member profile without waiting for the core

* android, desktop: keep member profile rows in place while they load

The security code and the connection stats arrive after the profile is shown, so
"Verify security code" and the Servers section appeared under the already
visible card and pushed the rows below them down.

They are now rendered from the first frame in their final positions, disabled,
and enabled in place when the data arrives - SectionItemView already drops the
clickable modifier when disabled, so nothing moves. Only what can be decided from
the member known at the tap is reserved: "Fix connection" is not, as it applies
only while a ratchet needs syncing and a placeholder for it would disappear on
nearly every open.

* android, desktop: reserve the network status row with the servers

The reserved Servers section had three rows where the loaded one has four, so
everything below it - "Block member" - moved down by one row when the stats
arrived.

Network status looks like agent state that cannot be predicted before loading,
but connSubStatus returns Just whenever the connection has receiving queues, and
that is the same list that decides whether "Receiving via" is rendered. The two
rows appear together, so the status row is now reserved with them.

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2026-09-26 13:13:36 +01:00
Narasimha-sc c0344a9a61 android, desktop: make media blur much lighter on CPU (#7483)
* ui: blur media by resampling the preview, not a per-frame effect

Modifier.blur put a BlurEffect on a display-sized graphics layer, so the
Gaussian was re-evaluated on every frame the media was drawn. It also
requires RenderEffect, which Android applies only from API 31, so below
Android 12 media was drawn unblurred while the setting read as on.

A blur and a downscale discard the same thing - detail finer than their
radius - so the preview is now resampled to about one pixel per radius and
stretched back. That runs once when the item composes, needs no
RenderEffect, and removes the detail irreversibly rather than convolving
it. The first resampling step bounds both sides, so no image, however
shaped, can produce a large intermediate.

While the blur hides the media the file is also left unread, so an image
scrolled past is no longer read, decoded at its full size and kept in the
image cache only to be hidden again. blurHidesMedia() is the single
definition that both the drawing and the loading decision use, so they
cannot disagree about whether the media is on screen.

* plans: blur media by resampling the preview

* ui: shorten comments in media blur

* ui: smooth the media blur and match its strength to the old one

Stretching the resampled preview straight to the screen showed its pixel grid. Double it back
up until its longest side is at least half the reference width before drawing, so the last
stretch is short and the tents compose into a bell. The reference width moves from 360 to 400:
fitted against Gaussians, 360 blurred 5-75% more than Modifier.blur did, 400 is within 10% at
every setting.
2026-09-26 12:49:36 +01:00
Narasimha-scandEvgeny Poberezkin ef66e5e520 desktop: fix laggy bars blur by blurring a narrower offscreen copy (#7556)
Skia's raster blur runs at full resolution, so each bar blurred width x (bar + 6 sigma) pixels every frame: about
80 ms per frame for the two bars of a chat at the default radius, which cut scrolling to 5-9 fps on the software
renderer. Scaling the layer cannot help, because a layer's filter is evaluated in device space and the scale is
applied to the sigma too. The bar is now drawn into an offscreen surface up to 8x narrower and blurred there, which
measured 5-6x cheaper and within 0.25/255 of the original.

Blurring a copy means the bar no longer follows the content on its own, so the scroll containers bump a version on
the app bar handler and the bar depends on it.

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2026-09-26 12:42:36 +01:00
19e70faeec badges: webapp feature branch (#7548)
* badges: webapp (#7433)

* badges: service migrations, store and catalog

* badges: BTCPay provider and settlement poller

* badges: web listener and /api endpoints

* web: checkout single-page app

* badges: tests and BTCPay fixtures

* badges: README and ini reference

* badges: fix hex16 build on GHC 8.10.7

* badges: Stripe card lane

* badges: fix Stripe card checkout, add theming

* badges: add a discount row to the order summary

* badges: site navbar, embedding, theme, Forget move

* badges: use SB code prefix in web checkout

* badges: rename sxb app namespace to sb

* badges: embed checkout nav via site; keep original app navbar

* badges: post iframe height, apply site background when embedded

* badges: embed dark surfaces, steadier iframe height

* badges: hide app footer when embedded

* badges: size embedded body to content, not viewport

* badges: declare color-scheme to stop reload flash

* badges: fade shell in on load, no reload blank

* badges: prerender app shell into index.html

* badges: pre-paint theme, hide shell on deep reload

* badges: logo returns to landing client-side

* badges: embedded wizard back, buy-a-code, resume

* badges: signal app-managed screens, resume across reload

* badges: rebuild wizard history on deep load so Back walks it

* badges: carry welcome-page height as the iframe floor

* badges: keep selection on Buy a code; rename to Your codes

* badges: read web shell as UTF-8, not locale

* badges: resume the exact paid order after Stripe card redirect

* badges: move docker deploy under scripts

* badges: add serve_webapp toggle and webapp export

* badges: wire split webapp deploy in docker config

* badges: quiet agent logs by default

* badges: resume card redirect in the embedded frame

* badges: migrate Stripe adapter to PaymentIntents

* badges: correct Stripe restricted key scopes in ini example

* badges: card via Payment Element and PaymentIntents

* badges: fix stale Checkout Session wording in Stripe adapter

* badges: fix stale CheckoutActions reference in card comment

* badges: order shell stylesheet before bootstrap script

* badges: remove development card stand-in

* badges: theme the Stripe card form with the site palette

* badges: exclude web from the Haskell build stage

* badges: unify invoice cancel and mark canceled

* badges: default log level to info

* badges: unify closed-invoice buy-again button

* badges: mute agent connection logs at info level

* badges: show purchase time in local timezone in Your codes

* badges: log service events on own channel, quiet agent

* badges: fold service migrations into one baseline

* badges: run compose on postgres over host network

* badges: use high-res hero art

* badges: add web CI to catch stale builds

* badges: rebuild web shell from committed source

* badges: normalize invoice-code link and columns

* badges: drop unused columns, rename index

* badges: note deferred receipt_hash in migrations

* badges: apply code-review fixes

* badges: reduce comments across service and web

---------

Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>

* badges: improve web page (#7546)

* badges: improve web page

* improve layout

* improve layout

* fix

* small changes

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>

* badges: read one issuer key from the ini

* badges: move and group the service tests

* badges: service fixes (#7567)

* badges: match the redeem error wording in tests

* badges: drop unused imports in the bot tests

* badges: cancel Stripe orders when they expire

* badges: correct the Stripe config and docs

* badges: refuse to revoke a redeemed code

* badges: make the fake Stripe cancel like Stripe

* badges: limit replayed webhook deliveries

---------

Co-authored-by: sh <37271604+shumvgolove@users.noreply.github.com>
Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
Co-authored-by: shum <github.shum@liber.li>
Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2026-09-25 09:01:51 +00:00
Alain Brenzikofer a8235b9440 fixes EP review 2026-09-24 11:28:38 +02:00
Alain Brenzikofer 75b59f4dec Merge remote-tracking branch 'origin/master' into ab/names-lookup-api 2026-09-23 19:39:09 +02:00
spaced4ndy 150897d637 core, ui: alert the user when badge renewal is failing (#7532) 2026-09-22 12:55:08 +00:00
Alain Brenzikofer 54bc83d803 manual renaming 2026-09-22 13:41:26 +02:00
Alain Brenzikofer a8cfa06e42 update name lookup API 2026-09-22 13:23:53 +02:00
Evgeny Poberezkin 29b5c2124c corrections 2026-09-22 09:59:58 +01:00
Alain Brenzikofer bdbb159e88 diagram edits 2026-09-19 16:04:32 +02:00
Narasimha-scandEvgeny Poberezkin ecb9d87157 android, desktop: fix Submit button not visible in passcode view in split screen (#7497)
Co-authored-by: Evgeny Poberezkin <evgeny@poberezkin.com>
2026-09-19 10:13:52 +01:00
Alain Brenzikofer f4d30f4349 add UX flow for name lookups 2026-09-18 15:03:37 +02:00
EvgenyandEvgeny @ SimpleX Chat c8466b2010 core: refactor groups (#7503)
* core: refactor groups

* refactor

* refactor

* refactor

* refactor

* refactor

* rename

* refactor

* remove

* rename

* diff

* simplify

* relay requests

* bot types

* check useRelays

* refactor

* query plans

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-09-18 10:18:10 +01:00
spaced4ndy 069efad7a2 core: consolidate badges schema (#7513) 2026-09-15 10:15:34 +00:00
spaced4ndy bac8d187ba Merge branch 'master' into badges 2026-09-14 17:13:58 +04:00
EvgenyandEvgeny @ SimpleX Chat 5ffbe733a8 core: attach badge proofs to files over size limit (#7455)
* core: attach badge proofs to files over size limit

* types

* more types

* implement file badge proofs

* tests

* move file limits to config, add tests

* more tests, work correctly in "send as group" case

* fix races in tests

* group badge tests

* query plans

* add history support, fixes

* simplify

* refactor

* refactor

* type

* restructure schema for proofs

* rename, refactor

* refactor

* fix, refactor

* refactor

* ui

* comments

* alerts

* update nix, ios library

* updare sharing

* update simplexmq

* update text

* improve messages

* api types

* postgres schema

* fix

* test

* query plans

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-09-12 14:33:52 +01:00
EvgenyandEvgeny @ SimpleX Chat 44773d0412 core: support message signing in p2p groups (#7312)
* core: support message signing in p2p groups

* improve

* add member key

* distribute keys and sign

* refactor

* better query

* map

* sign in relay groups too

* clean up

* list

* fix test

* update bot types

* some refactor

* remove unnecessary condition

* simplify

* refactor

* simplify

* move

* clean up

* diff

* diff

* limit attempts for key sending

* optimize

* fix test

* split

* fuse

* null

* only mark as "key sent" when forwarder supports binary encoding

* fix bot apis

* fix some tests

* add key distribution steps, and fix some tests

* fix test

* increase timeout

* fix tests

* fix more tests

* simplify

* disable test output

* mark keys sent with invitations

* fix test

* fix test, query plans

* unify signing of connection info packets

* revert change to createNewGroup

* create key at group/member creation

* rename, remove liftIO

* clean up

* fix type

* remove ad hoc key sending

* update bot api

* diff

* reduce diff

* failing test

* fix sending messages in groups with members before version 18

* remove test delays

* update query plans

* update test

* add tests

* fix tests

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-09-11 12:33:07 +01:00
spaced4ndy bd97e4df34 core: verify the badge ledger sent by the service (#7480) 2026-09-11 09:41:23 +00:00
spaced4ndy f9bab17643 core: renew badges monthly and alert when support ends (#7448) 2026-09-09 14:31:05 +00:00
spaced4ndy c623f4284c Merge branch 'master' into badges 2026-09-02 13:53:35 +04:00
EvgenyandEvgeny @ SimpleX Chat f99c474ca6 core: send badge ZK-proofs to XFTP servers, add file expiry time (#7430)
* core: send badge ZK-proofs to XFTP servers

* update simplexmq, use keys and header from simplexmq

* core: add file expiry time

* refactor

* remove posix module

* rename migrations

* bot api

* update UI

* import

* show item from loaded information

* ios: update core library

* text

* send entitlements in handshake

* simplexmq

* query plans

* update simplexmq

---------

Co-authored-by: Evgeny @ SimpleX Chat <259188159+evgeny-simplex@users.noreply.github.com>
2026-09-01 23:16:15 +01:00
Evgeny Poberezkin 9c77703017 Merge branch 'master' into badges 2026-08-28 19:37:10 +01:00
spaced4ndy e80a174f13 core: badge codes schema, plan (#7427) 2026-08-28 09:31:24 +00:00
Narasimha-sc d7e0f85976 desktop: fix rotated video squashed on playback and preview rotated twice (#7413)
* desktop: fix rotated video squashed on playback and preview rotated twice

vlc applies the display matrix before a frame reaches the vmem callback, so the
buffer has to be requested with the sides swapped for the transposed orientations,
and the snapshot must not be rotated again by hand. Read the snapshot on the event
thread, where the render callback writes it, and draw the inline playback surface
with FillWidth so a video narrower than the item fills it like its preview does.

Bound the requested buffer: the size comes from a received file, so it is capped by
area, cannot be zero, and a frame that does not fill the bitmap is dropped.

* desktop: harden the video frame path against crafted files

Only transpose the buffer for the track's own sides - the size libvlc passes is
already rotated, so swapping it would recreate the squash for a file declaring a
rotation with a zero-sized track. Copy the frame inside the render callback, on
vlc's thread, where the native buffer is guaranteed to exist, and hand only the
copy to the event thread. Drop a frame rendered with a format the bitmap was not
sized by, or arriving before any buffer was allocated. Divide the pixel budget by
a side pinned at 1 instead of scaling both sides, so a 2000000000x1 declaration
cannot take 45 times the budget. Publish the bitmap only when skia took the
pixels, size the copy after a rewind, and log a failed snapshot conversion
instead of throwing it into callers that have no handler for it.
2026-08-27 11:08:05 +01:00
Evgeny Poberezkin 78332d0c73 Merge branch 'master' into badges 2026-08-27 07:59:57 +01:00