119 Commits

Author SHA1 Message Date
callebtc
87184eddde globe fixes 2026-07-30 23:09:53 +02:00
callebtc
643f329d9d
Merge pull request #813 from qutad/fix/766-header-location-control
feat: improve location control accessibility and crowding
2026-07-30 19:12:51 +02:00
callebtc
ae70c02149
Merge pull request #833 from a1denvalu3/optimize/geohash-picker-low-end
Optimize geohash globe rendering and gestures
2026-07-30 19:08:38 +02:00
a1denvalu3
6edd361ed3 Fix globe land fill orientation 2026-07-30 15:33:17 +02:00
a1denvalu3
6fc4583a15 Stabilize globe quality selector layout 2026-07-30 15:09:29 +02:00
a1denvalu3
8602db88de Add geohash globe render quality selector 2026-07-30 14:39:29 +02:00
a1denvalu3
5bde4e0b4a Close fully visible geohash outlines 2026-07-30 14:29:22 +02:00
a1denvalu3
2a43265e12 Optimize geohash globe rendering and gestures 2026-07-30 14:01:02 +02:00
callebtc
1a953a17ab Fix private conversation alias isolation 2026-07-30 12:36:46 +02:00
callebtc
b692ec7b44
Merge pull request #828 from moehamade/fix/hotspot-group-consent
fix(hotspot): never disturb another app's Wi-Fi Direct group without consent
2026-07-30 12:30:00 +02:00
callebtc
b6ad8971a8 fix(hotspot): revalidate ownership during teardown 2026-07-30 03:20:48 +02:00
callebtc
1699cc7986 Header: preserve compact channel accessibility state 2026-07-30 03:00:49 +02:00
Moe Hamade
141adf5468 fix(hotspot): only remove our own group; ask consent to replace a foreign one
removeGroup() is device-scoped: it removes whatever Wi-Fi Direct group
exists, including one owned by Cast, Android Auto or Quick Share.
stopHotspot() called it unconditionally, so the path built to protect a
foreign group tore that group down anyway. Removal on stop is now gated on
a createdGroup flag, set once our own createGroup command is accepted; with
nothing of ours on the framework, stop closes the channel and leaves the
group alone.

When a group we did not record creating is active at start, the app no
longer guesses about ownership - it asks. A confirmation dialog explains
that starting will disconnect the current Wi-Fi Direct connection;
confirming retries the start with replacement authorized, cancelling
leaves everything untouched. Consent is bound to the group it was given
for: the conflicting group's name travels through the dialog, and the
policy only authorizes removing a group with exactly that name - one that
appeared later, or swapped in mid-retry, re-prompts instead of riding on
stale approval.

Because consent replaces ownership proof, the DIRECT-BC- prefix heuristic
is gone: a prefix match is not ownership (this device can be connected to
another phone's bitchat group), so only the exact recorded name counts.
The record is also kept honest: never taken from a group we do not host,
and never overwritten while an old group of ours may still exist, so a
BUSY retry cannot misclassify our own stale group as foreign.

Also: SecurityException guards on the removeGroup() sites reached from
framework callbacks (permission revoked mid-session crashed instead of
failing cleanly); stopHotspot() takes a completion callback so the
ViewModel releases its Wi-Fi Aware lease only after the framework
acknowledges the removal, with an idempotent 10s fallback so a dropped
acknowledgement cannot pin the mesh down; and the confirm/cancel handlers
guard on the ConfirmDisconnect state so a tap landing through a screen
transition cannot tear down a just-confirmed session.

Replaces the state-machine approach of #811 - same protection at
proportionate cost.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 01:28:09 +03:00
Moe Hamade
3562ad10d5 fix(wifi-aware): count hotspot radio holds and never drop a restart request
Two fixes to how Wi-Fi Aware yields the radio to the Wi-Fi Direct hotspot.

A restart request could be swallowed: restartIfStillEnabled() coalesces on
an in-flight flag, so a request arriving while an earlier loop was still
burning attempts against the hotspot hold lost the CAS and was dropped.
The loop then exhausted its attempts without ever seeing the cleared hold,
leaving the mesh down despite the user's setting. Requests are now recorded
before coalescing and re-checked after each pass.

The hold itself was a single flag, so overlapping share sessions could
release each other's claim. It is now a counted, once-releasable
HotspotLease: Aware restarts only when no session still needs the radio,
and a duplicate or late release is a no-op. Publication of a started
service is checked against the hold inside the same lock stop() takes, so
a start racing a new hold cannot resurrect NAN while the hotspot owns the
radio.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 00:50:36 +03:00
a1denvalu3
9f0223591f Fix stale peer lifecycle cleanup 2026-07-29 23:15:01 +02:00
callebtc
57cc39dbdf Merge main into fix/766-header-location-control 2026-07-29 20:52:00 +02:00
callebtc
44f62a3c14
Merge pull request #776 from a1denvalu3/feat/cashu-chips-android
feat: add Cashu ecash chips and /pay command
2026-07-29 20:21:12 +02:00
callebtc
b073dc2160
Merge pull request #824 from permissionlesstech/codex/fix-peer-verification-status-badge
Fix peer verification status and private chat badge
2026-07-29 20:18:34 +02:00
callebtc
9f81a1e40d Fix peer verification status and badge 2026-07-29 19:32:28 +02:00
callebtc
79e04ed3cc
Merge pull request #820 from permissionlesstech/codex/fix-wear-private-message-navigation
Improve Watch private-chat navigation and peer identity UI
2026-07-29 19:23:43 +02:00
a1denvalu3
199f95fdbd Fix Cashu payment review issues 2026-07-29 19:09:05 +02:00
a1denvalu3
b9ca8ed3eb Add Cashu payment chips and pay command 2026-07-29 19:06:50 +02:00
callebtc
4f567ecd5f
Merge pull request #800 from a1denvalu3/issue-764-language-picker
Add in-app language picker
2026-07-29 19:03:01 +02:00
callebtc
44560b9792 Add Watch peer profiles and verification 2026-07-29 18:55:56 +02:00
callebtc
00ef72c45e fix: clear peer alerts on mesh shutdown 2026-07-29 15:49:33 +02:00
callebtc
2807a16d1e fix: rate-limit peer availability alerts 2026-07-29 15:29:48 +02:00
callebtc
4fad876944 Merge main and resolve notification conflicts 2026-07-29 15:14:25 +02:00
callebtc
363f8c5aae fix: restore background peer availability alerts 2026-07-29 15:00:13 +02:00
callebtc
a21c0242a6 Fix conversation persistence review issues 2026-07-29 14:43:13 +02:00
callebtc
172d086c23 Fix live conversation identity state updates 2026-07-29 14:23:25 +02:00
callebtc
a105d884cb Polish persistent private conversations 2026-07-29 13:51:55 +02:00
caly
ad05bc5ed5 Header: improve location control accessibility and crowding 2026-07-29 14:20:17 +03:00
callebtc
1dae188cdf
Merge pull request #806 from permissionlesstech/codex/persistent-conversations
Persist private conversations in People
2026-07-29 13:00:57 +02:00
callebtc
ff0578cb88
Merge pull request #808 from moehamade/fix/hotspot-wifi-direct-reliability
fix: make Wi-Fi Direct hotspot sharing reliable
2026-07-29 12:33:16 +02:00
Moe Hamade
41544a6840 fix: make Wi-Fi Direct hotspot sharing reliable
Starting the APK-sharing hotspot failed intermittently with
"Failed to create hotspot: BUSY", sometimes for minutes, then
succeeded for no apparent reason. Two distinct causes, both
confirmed against a Pixel 9a via dumpsys and HAL logs.

1. Wi-Fi Aware holds the radio. The mesh's NAN interface and
   Wi-Fi Direct's P2P interface cannot coexist on common chipsets:

     HalDevMgr: bestIfaceCreationProposal is null, requestIface=P2P,
                existingIface=[name=wlan0 type=STA, name=aware_nmi0 type=NAN]
     WifiP2pNative: Failed to create P2p iface

   The P2P state machine then stays in P2pDisabledState and answers
   every createGroup with BUSY, while still broadcasting
   WIFI_P2P_STATE_ENABLED. Whether sharing worked came down to
   whether Aware happened to be attached, which is what made it look
   random. WifiAwareController now releases Aware for the duration of
   the hotspot and blocks restarts until it finishes.

2. Orphaned groups. A P2P group outlives the process that created
   it, so a crash or swipe-away while hosting leaves one behind, and
   the framework answers BUSY for as long as it exists. Startup now
   removes a stale group first, but only one it can show is ours --
   Wi-Fi Direct is shared with Cast, Android Auto and Quick Share.
   Ownership is the group name we recorded creating, with the SSID
   prefix as a fallback for orphans from older builds.

Also fixed while tracing these:

- Channel leak: initialize() ran on every retry attempt and the
  channel was never closed, leaving a binder registration with
  WifiP2pService per attempt. Observed climbing to 7 stale clients.
  It is now initialised once and closed after removeGroup replies.
- BUSY is the framework's catch-all reply, so retrying was futile
  for permanent causes and too impatient for real contention.
  Retries now back off 1s/2s/4s/8s and only for genuinely transient
  failures; P2P being off fails immediately with a message that says
  so rather than 15 seconds ending in "busy".
- Turning Wi-Fi off mid-session left the UI showing an active
  hotspot forever; it now aborts cleanly.

Retry and startup decisions are extracted into HotspotStartupPolicy,
which has no Android dependencies and is covered by 13 unit tests.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-29 12:54:01 +03:00
callebtc
bf87a80617 Honor private message admission during panic 2026-07-29 11:00:24 +02:00
callebtc
c5ff1ca59a Complete persistent conversation lifecycle 2026-07-29 03:53:29 +02:00
callebtc
d3f01f27c6 persistent 2026-07-29 03:41:24 +02:00
callebtc
7fad2f2202 persist 2026-07-29 03:41:16 +02:00
callebtc
c7720d3847 Fix private media routing for contact conversations 2026-07-29 00:43:39 +02:00
callebtc
9800927b59 Support sharing installed ARM64 APK 2026-07-28 18:42:01 +02:00
a1denvalu3
525ba27e3b refine language picker for iOS parity 2026-07-28 16:24:11 +02:00
a1denvalu3
8f2585d8eb feat: add in-app language picker 2026-07-28 16:18:01 +02:00
callebtc
42a8edf8ed fix: request local network access for hotspot sharing 2026-07-28 16:06:12 +02:00
callebtc
fbb13a33d5 Reject broadcast sends exceeding the receiver fragment cap
Receivers hard-cap reassembly at MAX_FRAGMENTS_PER_ID (256), but the
generic send path fragmented packets with no caller cap (0xFFFF), so
broadcast file transfers above ~120 KB were fully transmitted yet
undeliverable. FragmentingPacketSender now caps fragmentation at
MAX_FRAGMENTS_PER_ID and reports failure via a new
TransferProgressEvent.failed flag, which surfaces as
DeliveryStatus.Failed in the UI and as a file_send error in the debug
test hook instead of an indefinite wait.

Adds FragmentingPacketSenderTest and a file_oversize mesh-lab scenario
asserting sender-side rejection.
2026-07-28 13:17:35 +02:00
callebtc
57d11299da
Merge pull request #781 from permissionlesstech/codex/background-power-optimization
Centralize adaptive background power scheduling
2026-07-28 00:15:08 +02:00
callebtc
15a580aeef
Merge pull request #796 from permissionlesstech/codex/private-message-arrival-order
Fix private message ordering across clock skew
2026-07-27 23:50:05 +02:00
callebtc
c54fdcd9fb Merge remote-tracking branch 'origin/main' into codex/background-power-optimization
# Conflicts:
#	app/src/main/java/com/bitchat/android/mesh/MeshCore.kt
#	app/src/main/java/com/bitchat/android/ui/PrivateChatManager.kt
#	app/src/main/java/com/bitchat/android/wifi-aware/WifiAwareMeshService.kt
2026-07-27 23:29:56 +02:00
callebtc
62926f88d5 fix: preserve arrival order across aliases 2026-07-27 23:29:01 +02:00
callebtc
5b13598bd0
Merge pull request #794 from permissionlesstech/kimi/dm-outbox-retry-scheduler
Retry scheduler for queued DMs and Noise session re-establishment
2026-07-27 23:13:23 +02:00