V3 magic branch#22
Merged
Merged
Conversation
* 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
…ore message arrives
- 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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.