Skip to content

V3 magic branch#22

Merged
Magicred-1 merged 7 commits into
v3from
v3-magic-branch
May 3, 2026
Merged

V3 magic branch#22
Magicred-1 merged 7 commits into
v3from
v3-magic-branch

Conversation

@Magicred-1
Copy link
Copy Markdown
Member

No description provided.

Magicred-1 and others added 7 commits May 3, 2026 02:03
* V3 magic branch (#17)

* chore(deps): bump react-native-lxmf to ^0.2.5

* fix(ux): back-navigation lock, exit toast, dedup msg keys, inline new message

- (tabs)/_layout: BackHandler exits app on Android with "press back again to exit"
  toast (spring slide-up, themed, 2s window); gestureEnabled: false blocks iOS swipe-back
- _layout: gestureEnabled: false on (tabs) Stack.Screen; fix duplicate onPress prop
- onboarding: instant redirect (0ms) when already connected on mount — prevents
  LoadingOverlay flash on back-nav; 2200ms stamp delay preserved for fresh connects
- PeersDrawer: collapse two-view nav into single unified component — hash input + QR
  always visible at top, peer list in contained ScrollView; remove NewConvoView split
- MessagesScreen: replace Date.now() IDs with monotonic nextId() — fixes duplicate
  key warning when multiple messages arrive in the same millisecond

* fix(tabs): dynamic tab bar height respects system nav inset

useSafeAreaInsets() — height = 56 + insets.bottom, paddingBottom = insets.bottom.
Fixes overlap on Android gesture-nav and 3-button-nav phones.

* feat(wallet): bento grid redesign with balance, network, peers, activity tiles

Replaces flat scrollable layout with bento-style grid. Balance tile shows
SOL + token breakdown with hide toggle. Network tile shows online/mesh/isolated
state. Peers tile shows total peer count + online count. Activity tile renders
tx history with direction-aware formatting.

Fixes font family fallback on Android by using sansBold/sansSb variants
directly instead of fontWeight overrides.

* feat(ui): bento grid redesign for wallet, receive, and send flow

WalletScreen: activity tile fills remaining screen height, pigeon animation
for online mode (RN Animated, no reanimated SVG), NetworkMode import direct
from hook, online color unified to cyan.

ReceiveScreen: full bento-grid redesign matching WalletScreen — tile cards,
kicker header, inline share/copy action tiles, stealth note, neutral/cyan
segmented control tones.

Send flow: SendScaffold, RecipientPicker, AmountKeypad, ReviewCard, SuccessCard
all restyled with bento tiles, consistent kicker+title headers, Feather icons,
no glass hooks.

SegmentedControl: adds neutral tone for non-accent tab states.

* feat(nodes): wire BeaconRegistry to real isBeacon state and live reachable count

- LxmfContext: add isBeacon state (persisted), setBeaconMode (stop+restart with flag)
- BeaconRegistry: replace local active state with context isBeacon/setBeaconMode
- BeaconRegistry: reachableCount from live beacons + online peers instead of hardcoded 3
- BeaconRegistry: disable register button when offline, show "REQUIRES INTERNET"
- storage: add BEACON_MODE pref key

* feat(nodes): detect anonmesh beacon peers from app_data prefix, show BEACON badge

- LxmfPeer: add isBeaconNode flag
- applyAnnounceEvent: detect 'anonmesh::beacon::v1\0<name>' prefix, extract display name after null separator
- mergeBeacon: always mark beaconDiscovered peers as isBeaconNode
- peerToMapNode: pass beacon flag to NodeData
- NodeRow: show BEACON pill next to handle when n.beacon is true

* fix(peers): full-width search bar with larger tap target in PeersDrawer

* feat(chat): media sending + queue state indicators on message bubbles

- Composer: image picker button (expo-image-picker), MediaPayload callback
- MediaBubble: display received/sent images, tap-to-fullscreen lightbox
- types: MediaMsg type, AnyMsg union extended
- MessagesScreen: handleMedia sends base64-encoded image over LXMF
- parseStructuredMsg: decode incoming {t:'media'} envelope to MediaBubble
- MessagesScreen: seqStates map tracks queued/delivered/failed per-seq
- MessageBubble: sendState prop with icon+label (sent/queued/delivered/failed)
- Pending banner when messages are queued waiting for peer
- app.json: NSPhotoLibraryUsageDescription + expo-image-picker plugin

* feat(chat): migrate to lxmf module API, per-peer threads, file attachments, error banner

API migration (messageReceived):
- Drop old msgpack wire decode (decodeLxmfSender/decodeLxmfContent/e.content)
- Read e.source (sender hash), e.body (base64 UTF-8), e.image, e.files directly
- Inbound images now come via e.image → MediaBubble; removes JSON-body media hack
- Inbound file attachments rendered as tappable rows with name + size in MessageBubble

Media send:
- Pass image as LxmfMedia 3rd arg to send() instead of JSON-encoded body
- send/broadcast types updated in LxmfCtxValue to include media?: LxmfMedia

Per-peer thread persistence:
- threadsRef (Map<destHash, AnyMsg[]>) stores messages per conversation
- pickPeer saves current thread before switching, restores saved or inits fresh
- Incoming messages for non-active peer routed to their thread directly

QR scan UX:
- Scan result immediately starts conversation (removed intermediate contact card + button)

Composer/keyboard:
- Composer bar and field padding reduced (fits tighter)
- Field borderRadius 99→12 (matches icon squircle style)
- Android keyboard: softwareKeyboardLayoutMode=pan + KAV behavior=undefined on Android

Error banner:
- LxmfErrorBanner reads error from LxmfContext, floats above tab bar
- Dismissible per distinct error string, auto-reappears on new error

* fix(android): keyboard overlap — resize mode + hide tab bar on keyboard

* fix(chat): remove dead try/catch, mark failed sends on bubble instead of sys message

send() in useLxmf catches all native errors internally, sets lxmf.error, returns -1.
The try/catch in sendMsg/handleMedia never fired. pendingRef retry logic was unreachable.

- Remove pendingRef + announce-retry useEffect (dead code)
- Remove try/catch from sendMsg and handleMedia
- On seq === -1: write pseudoSeq (-msgId) into seqStates as 'failed' so the
  bubble shows the failed indicator; lxmf.error banner shows the actual reason
- handleGridAction: drop unreachable .catch()

* fix(notifications): use e.source directly, skip pickPeer when already in thread

useMessageNotifications was decoding srcHash from e.content (old wire format) which
doesn't exist in the new API — e.content was always empty string, so decodeLxmfSender
returned null, srcHash fell back to e.source but via a broken path. Suppression check
(srcHash === activeConversationRef) never matched → banner fired even for active peer.

useFocusEffect was calling pickPeer unconditionally on notification tap, resetting the
thread even when the peer was already active. Guard added.

* fix(chat): treat seq=0 as success — only seq<0 is a send error

useLxmf.send() returns -1 on error, passes through native seq otherwise.
Native module may return seq=0 for queued-without-route messages that still
get delivered. Previous check (seq > 0) falsely marked these as failed.

Now: seq < 0 → failed bubble, seq > 0 → tracked with timer, seq = 0 → optimistic.

* fix(chat+notifs): display names, thread routing, keyboard, lxmf bump

- getDisplayName reads knownPeersRef directly (bypasses stale React state)
- Notification dispatch deferred via setTimeout(0) so parent peer-tracking
  effect populates knownPeersRef before display names are resolved
- Thread routing: flip condition to positive form; sync activePeerHexRef
  immediately in pickPeer to close race window on peer switch
- useFocusEffect fallback uses getDisplayName instead of @hash prefix
- Inline from resolution uses getDisplayName (ref) instead of lxmfPeers.find
- keyboard: pan mode + KAV padding + safe-area spacer collapses on keyboard
- bump @magicred-1/react-native-lxmf 0.2.25 → 0.2.26

* Polish mobile bottom navigation (#18)

* feat: polish mobile bottom navigation

* fix: keep polished tabs responsive

---------

Co-authored-by: Excelsior <33706074+epicexcelsior@users.noreply.github.com>
- plugins/withAndroidForegroundService.js: config plugin writes LxmfForegroundService.kt (START_STICKY), LxmfServiceModule.kt (NativeModule start/stop), LxmfServicePackage.kt, patches MainApplication.kt, adds FOREGROUND_SERVICE + FOREGROUND_SERVICE_CONNECTED_DEVICE permissions + service declaration (foregroundServiceType=connectedDevice)
- hooks/useBackgroundService.ts: starts service on mount, stops on unmount, Android-only
- app/_layout.tsx: call useBackgroundService() in AppShell
- app.json: register plugin; add fetch + processing to iOS UIBackgroundModes
- connect(): check pairNusRNode() boolean — false/throw → error msg, stay phase 1
- phase 2: poll getNusUnpairedRNodes() every 500ms until pairedMac disappears from list (= OS bond + GATT connected); 15s timeout → error back to phase 1
- show pairError in phase 1 hint text
- remove fake 1800ms setTimeout that showed success regardless of outcome
- LxmfContext: add groups state, createGroup/joinGroup/leaveGroup/getGroupMembers,
  auto-register groups on node restart, route sendGroup for group dest addrs
- PeersDrawer: CHANNELS section with JOIN/CREATE pill buttons, group rows with
  members icon, long-press to leave; separate DM peers from group peers
- CreateGroupModal: bottom-sheet, input → done phase with QR code + copy rows
- JoinGroupModal: bottom-sheet, prominent SCAN QR CODE button, manual addr+key entry
- GroupMembersSheet: bottom-sheet listing active senders derived from message history
- ChannelShareSheet: QR code + copy addr/key/pair for sharing channel join info
- ThreadHeader: share-2 icon triggers ChannelShareSheet when active peer is a group
- QRScannerModal: extend ScannedAddress with lxmf-group type, parse lxmf://group/… URIs
- Composer: swap arrow-up → bird icon (MaterialCommunityIcons), fix safe-area
  bottom spacer background color to match bar (surface0)
- MeshMap: expand by default on mount
- lxmf bump 0.2.43 → 0.2.53
… README

- PeersDrawer: SwipeableGroupRow with pan gesture — swipe left reveals red
  LEAVE action; removes onLongPress + users icon + onShowMembers prop
- MessagesScreen: drop GroupMembersSheet, membersAddrHex state, onShowMembers
- LoadingOverlay: rewrite from 267 → ~100 lines, drop passport stamp phase,
  same loading card + dots + cursor blink animation
- Composer: bird icon (MaterialCommunityIcons) replaces arrow-up send button;
  safe-area spacer background fixed to surface0
- MeshMap: expanded by default on mount
- README: project manifesto — messaging, channels, mesh networking, Solana
  wallet, identity/privacy, install, architecture, compatibility + banner
@Magicred-1 Magicred-1 merged commit 8e001e2 into v3 May 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant