Commit Graph
100 Commits
Author SHA1 Message Date
jack 334c6271b6 Inline comment cleanup: drop legacy 'removed' breadcrumbs across protocols, services, view model, and views 2025-08-25 17:57:21 +02:00
jack 6f4da62e4e Remove 'preparing to share …' system message; send shared content immediately 2025-08-25 17:53:25 +02:00
jack d946c01bfc Share Extension: migrate to UIKit + UTTypes; drop Social/SLComposeServiceViewController 2025-08-25 17:44:07 +02:00
jack ce48720e9a Tests: gate verbose prints under DEBUG; ChatViewModel: remove legacy fingerprint helper and rely on UnifiedPeerService 2025-08-25 17:42:41 +02:00
jack e0db8a2bc8 Remove dead code and artifacts: drop PeerManager, unused views/types; delete LegacyTestProtocolTypes; update .gitignore; purge TestResult.xcresult and build.log 2025-08-25 17:03:48 +02:00
7c4c3f1391 macOS geohash parity: shared LocationChannelsSheet with permission CTA, enable CoreLocation on macOS, unify geohash participants/DMs, update ContentView (unread + QR on macOS), commands: hide/block /fav & /unfav in geohash, remove /help, make /who show geohash participants, fix ViewBuilder mutation+sheet toolbar, entitlements for mac location (#519)
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-25 16:29:52 +02:00
3c06bd6386 Improve BLE mesh flooding: last-hop suppression, K-of-N fanout, and backpressure (#517)
* Improve BLE mesh relay and flooding

Add last-hop suppression using ingress-link tracking to prevent echo. Implement deterministic always-relay for handshakes and directed encrypted/fragments; widen jitter for broadcasts; keep TTL cap only for broadcast. Add deterministic K-of-N broadcast fanout to reduce amplification in dense topologies. Introduce backpressure-aware writes using canSendWriteWithoutResponse with per-peripheral queues and draining on peripheralIsReady. Minor helpers for messageID, deterministic selection, and maintenance cleanup.

* Tests: stabilize FragmentationTests and InputValidatorTests

Make _test_handlePacket mark synthetic peers verified/connected with normalized senderID to avoid drops in public-message reassembly tests. Tighten validatePeerID to reject non-hex strings when length equals 16 or 64; allow internal IDs only for other lengths. All iOS simulator tests pass locally.

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-25 11:51:50 +02:00
jack acc11101ad Fix geohash linking: avoid links in @mentions
Only link #geohash tokens when not directly attached to an @mention (e.g., @name#gh stays plain). Keeps standalone #geohash tappable.
2025-08-25 09:31:41 +02:00
5fd9140ffa QR verification: live challenge/response over Noise; persistence, offline badges, and UX/perf polish (#510)
* QR verification scaffold: add Noise verify payload types, VerificationService with QR schema/signing, placeholder MyQR/Scan views, and UI entry points in header

* QR: fix VerificationQR mutability (sigHex var) and remove duplicate Data hex helpers to resolve redeclaration; wire signed payload assembly

* QR: render actual QR images with CoreImage; add copy button; keep scanner placeholder for now

* QR: fix SwiftUI modifiers — apply .interpolation(.none) and .resizable() to platform Image inside ImageWrapper; remove from wrapper usage

* QR: add iOS camera scanner using AVFoundation; integrate into Scan view; add NSCameraUsageDescription to Info.plist

* QR: make NoisePayloadType exhaustive in ChatViewModel switches by ignoring verifyChallenge/verifyResponse for now (placeholder)

* QR verification: speed + persistence + UX

- Inject live Noise into VerificationService; prewarm QR on app start
- Keep camera active; remove intermediate responder toast
- One-shot/dupe guards and deferred send on handshake
- Persist verified status immediately; standardize fingerprint (SHA-256)
- Show verified badge for offline favorites; mutual verification toast
- VERIFY sheet styling to match peer sheet; UI polish
- Logs to diagnose verified load + favorites mapping

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-24 23:19:58 +02:00
e6903456ab NIP‑17/44: XChaCha20 v2 gift wraps, DM kind=14, receipts + UI fixes (#506)
* NIP-17/44: adopt NIP-44 v2 (XChaCha20-Poly1305, v2: base64url), switch rumor kind to 14, randomize BIP-340 aux; add XChaCha20Poly1305Compat and wire-up

* Nostr DMs: ensure delivered/read acks are sent even without Noise key mapping by falling back to direct Nostr (geohash-style) acks to sender pubkey

* NIP-44 v2 decrypt: try both Y parities for x-only sender pubkeys (even then odd) to fix unwrap authentication failures

* Tests: add NIP-44 v2 ACK round-trip tests (delivered/read) using bitchat1 embedding and gift-wrap decrypt path

* UI: fix DM autoscroll IDs by using dm:<peer>|<id> for private chat item IDs and preserve anchors, ensuring scrollTo targets exist when opening/switching/new messages

* UI: fix string interpolation in DM/geohash context keys (remove escaped interpolation) to resolve 'unused ch' warnings and ensure proper IDs

* UI: MeshPeerList shows transport state icon: radio for mesh-connected, purple globe for mutual favorite/Nostr; fallback dim person for others

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-24 17:56:43 +02:00
85f99984c4 Unify DM notifications and fix geohash self-echo hydration (#505)
* feat(notifications): unify DM notifications across transports; notify for unread+recent even in foreground; delegate suppresses if chat open

* fix(geohash): include own past geohash messages on channel load; skip only very recent self-echo (<15s) to avoid duplicates

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-24 14:40:06 +02:00
75c8933091 Feat/georelay (#504)
* feat(georelay): route geohash kind 20000 via nearest relays; add GeoRelayDirectory; target geohash subscriptions; avoid duplicate connections

* feat(georelay): fetch daily from remote CSV with fallback to bundled; cache to app support; prefetch on app load

* fix(georelay): make CSV parser nonisolated and call as Self.parseCSV to satisfy Swift 6 actor isolation

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-24 12:49:52 +02:00
d2bfbbcfd4 Fix/chat perf (#502)
* perf(chat): batch public inserts, sort batch by ts; add per-sender + per-content token buckets; content-based near-dup suppression; reuse compiled regexes; single token scans per row; disable list animations during batches

* perf(chat): conditional animations via isBatchingPublic; late-arrival binary insert; flush public buffer on channel switch; prewarm formatting on flush

* perf(chat): batching, spam rate-limits, near-dup LRU, adaptive flush, faster trims, regex/detector reuse, conditional animations, late-insert, current-mode prewarm, Swift 6-safe timer/closures

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-24 11:11:49 +02:00
0260798712 Fix/UI (#500)
* Remove link previews: link URLs inline\n\n- Delete LinkPreviewView and all references\n- Strip preview usage from ContentView\n- Make detected URLs tappable via .link attribute\n- Add MessageTextHelpers for tokens/length checks\n- Wire helpers into iOS/macOS targets

* Peer list UX: match message colors, use map pin icon, stable ordering\n\n- Color list names and icons with same peer color as messages\n- Default icon mappin; teleported uses face.dashed (iOS)\n- Geohash: move teleported peers to bottom\n- Maintain stable order: append new peers, remove missing\n- Mesh list: replace state icons with colored mappin/person

* Fix peer list build errors: remove ambiguous Set type, avoid guard in ViewBuilder, remove duplicate bindings, and simplify person lookup

* Peer list: remove onChange expressions to avoid type-check issues; rely on ObservedObject updates

* Peer lists: simplify view structure to satisfy SwiftUI type checker (replace Group with VStack, flatten body)

* Peer lists: move ordering mutations to onAppear/onChange, keep body pure; fix result builder errors

* Fix: remove trailing modifiers outside if/else to avoid ViewBuilder type issues

* Color parity: fix seed cache to include color scheme; normalize Nostr seeds; switch to mappin.circle icon

* Peer colors: ensure exact match with message colors\n\n- Mesh list uses same seed logic as messages (getNoiseKeyForShortID fallback)\n- Color cache keyed by theme; normalize nostr seeds\n- Icons: use mappin.and.ellipse (default) and face.dashed for teleported\n- Teleport tag: accept "teleported" in addition to "teleport" and presence events

* Fix geohash color mismatch: populate nostrKeyMapping before building messages in resubscribe; also honor t,teleport tag for teleported state

* Message actions: username tap opens sheet via clickable AttributedString; message tap inserts @mention; rename to 'direct message'

* Cashu UX: suppress 'Show more' when message contains a Cashu token (chips handle rendering)

* Cashu detection: broaden regex (allow '.') + shorter min length; avoid long-text fallback when Cashu present so chips render and no full blob

* Geohash levels: rename region->province, country->region; update labels, precision, UI, manager mapping, tests; add Codable backward-compat for renamed cases

* Fix braces in LocationChannel.swift: close enum before extension to satisfy file-scope declarations

* Geohash links: make #geohash tappable and open that channel (bitchat://geohash/<gh>); handle in ContentView.onOpenURL with validation and selection

* Underline tappable #geohash mentions for clarity

* Geochat: sanitize timeline on channel switch to remove any blank-content entries (prevents blank rows)

* Xcode project: sync sources after UI changes (remove LinkPreview, add helpers, update build refs)

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-24 02:05:02 +02:00
jack 2758afa126 ux(chat): scroll to bottom on geohash open; add infinite scroll up with stable anchor; track window size per chat 2025-08-22 19:01:29 +02:00
jack 2229a28bb4 perf(chat): reduce rendering cost and improve stability for large chats\n\n- Window last 300 messages (up from 100) while keeping timeline cap at 1337+\n- Remove .textSelection from message rows to avoid expensive layout\n- Limit link previews per message to 2\n- Keep deferred autoscroll and channel-aware IDs for smooth scrolling 2025-08-22 18:56:26 +02:00
dadc896ed8 Fix/geohash blocks (#483)
* fix(geo-block): enable block/unblock for geohash users and enforce blocks\n\n- Add persisted set of blocked Nostr pubkeys in SecureIdentityStateManager\n- Check Nostr blocks for incoming messages (public + geo DMs)\n- Prevent sending geo DMs to blocked users\n- Extend /block and /unblock to resolve geohash display names to pubkeys and act accordingly\n- Improve /block list to show geohash blocks (visible names or #suffix)

* fix(geo-block): enforce blocks on geohash public and DM receive; add block/unblock actions to geohash people list

* fix: mark handlePublicMessage as @MainActor to call isMessageBlocked safely

* ui(block): show blocked indicator (nosign icon) next to blocked peers in mesh and geohash lists

* fix(geo-block): early-drop blocked pubkeys on geohash receive; filter blocked users from participants list

* fix(geo-block): purge existing geohash messages/DMs on block; block directly from chat using Nostr sender ID when available

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-22 18:44:11 +02:00
b2504a7ff5 Feat/b links (#481)
* feat(cashu): auto-link cashu tokens in chat

- Detect cashuA/cashuB tokens via regex and render as tappable links
- Style like URLs (underline; blue for others, orange for self)
- Add openURL handler for cashu: scheme to delegate to wallet on iOS
- Respect existing heavy-content gating and long-message collapsing

* feat(ln): auto-link Lightning invoices and LNURL + lightning: scheme\n\n- Detect BOLT11 (lnbc/lntb/lnbcrt...), LNURL bech32, and lightning: URIs\n- Render as tappable links with lightning: scheme; consistent styling\n- Handle lightning: in openURL alongside cashu:

* feat(links): replace raw Cashu/Lightning tokens with compact chips (🥜 pay via cashu /  pay via lightning) while keeping them tappable

* style(links): add subtle background highlight to cashu/lightning chips

* ui(links): render Lightning/Cashu as rounded chips under message with padding; remove inline chip text

* ui(links): increase chip padding and corner radius; add extra top padding for chip row

* scroll: auto-scroll to bottom when sending a new message (public + private), regardless of current scroll position

* scroll(geo): when switching geohashes, scroll to top of chat (first visible message)

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-22 17:20:26 +02:00
7f2cbd6621 chat: fix blanking and gaps when switching geohashes; channel-aware row IDs + deferred autoscroll\n\n- Add channel-aware UI IDs (mesh|id, geo:<gh>|id, dm:<peer>|id) to prevent SwiftUI reuse gaps\n- Defer scrollTo to next runloop for stability; auto-scroll on appear/switch\n- Collapse very long messages with Show more/less; skip heavy parsing for huge content\n- Simplify LazyLinkPreviewView (remove GeometryReader in list) (#480)
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-22 16:38:40 +02:00
jack 60a42ffecb Merge feature/peer-colors: per-peer colors, mention action, teleport persistence + logs, geohash count consistency, scroll gating, hashtag styling, copy message context menu 2025-08-22 13:08:15 +02:00
jack 27e5e2962c Scroll: move bottom detection to View state and pass Binding to messagesView; autoscroll only when bound is true to prevent jumps when user scrolled up 2025-08-22 13:04:56 +02:00
jack 9d5105a8bf Geohash list: gate empty/render using visibleGeohashPeople() so header count and list visibility are consistent 2025-08-22 13:02:34 +02:00
jack d4b779080a Fix header string interpolation: simplify accessibilityLabel to avoid unterminated string; use '\(headerOtherPeersCount) people' 2025-08-22 12:58:08 +02:00
jack 4bfe9ac80d Geohash count: use the same pruned/sorted list for toolbar and peer list (visibleGeohashPeople) to ensure consistency 2025-08-22 12:51:40 +02:00
adffe7dfd6 Feature/peer colors (#476)
* Feature: assign stable per-peer colors (non-self) across mesh/geohash/DM; keep self orange and mentions-to-me orange; cache colors

* Fix compile warnings: remove unused primaryColor in formatMessageAsText; remove unused CryptoKit import; mark peerColor/formatMessageAsText @MainActor to call main-actor helpers

* Fix: re-import CryptoKit for SHA256 usage in ChatViewModel

* Peer lists: apply same per-peer colors as chat (self orange); suffix uses lighter variant; geohash uses Nostr pubkey, mesh uses Noise key

* Fix warning: remove unused peerNicknames in MeshPeerList

* UI: add 'mention' action in message actions to prefill input with @nick#abcd and focus input

* UX: long-press a message to prefill @mention with sender's full nick#abcd and focus input

* UX: remove long-press mention; add context menu 'Copy message' that copies only the message body (no nick/timestamp)

* Geo teleported: robust tag detection (accept 't', 'teleport', and boolean-like values); mark self on send when tagging; should fix peer list icons

* Logs: add GeoTeleport diagnostics (incoming tags, self/peer marking, counts) to debug peer list dashed icon behavior

* Teleport persistence: store per-geohash teleported state in UserDefaults; initialize on startup; OR with location-derived status; sheet writes persisted flag on select/teleport

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-22 12:41:26 +02:00
jack 16fdb7b49e Teleport persistence: store per-geohash teleported state in UserDefaults; initialize on startup; OR with location-derived status; sheet writes persisted flag on select/teleport 2025-08-22 12:34:44 +02:00
jack ff5fd3f3fe Logs: add GeoTeleport diagnostics (incoming tags, self/peer marking, counts) to debug peer list dashed icon behavior 2025-08-22 12:29:23 +02:00
jack f8a955214b Geo teleported: robust tag detection (accept 't', 'teleport', and boolean-like values); mark self on send when tagging; should fix peer list icons 2025-08-22 12:24:17 +02:00
jack d5e712e27f UX: remove long-press mention; add context menu 'Copy message' that copies only the message body (no nick/timestamp) 2025-08-22 12:18:33 +02:00
jack 244c8cdf81 UX: long-press a message to prefill @mention with sender's full nick#abcd and focus input 2025-08-22 12:13:59 +02:00
jack 0d064084aa UI: add 'mention' action in message actions to prefill input with @nick#abcd and focus input 2025-08-22 12:12:49 +02:00
jack 7b49268694 Fix warning: remove unused peerNicknames in MeshPeerList 2025-08-22 11:51:17 +02:00
jack 5650e1f2c2 Peer lists: apply same per-peer colors as chat (self orange); suffix uses lighter variant; geohash uses Nostr pubkey, mesh uses Noise key 2025-08-22 11:49:44 +02:00
jack c4b422ad3f Fix: re-import CryptoKit for SHA256 usage in ChatViewModel 2025-08-22 11:47:21 +02:00
jack e82fda1093 Fix compile warnings: remove unused primaryColor in formatMessageAsText; remove unused CryptoKit import; mark peerColor/formatMessageAsText @MainActor to call main-actor helpers 2025-08-22 11:45:49 +02:00
jack 806d451135 Feature: assign stable per-peer colors (non-self) across mesh/geohash/DM; keep self orange and mentions-to-me orange; cache colors 2025-08-22 11:43:44 +02:00
13f8b0c636 Fix/geohash work (#475)
* Scroll UX: auto-scroll only when last item visible; preserve user position when scrolled up for mesh/geohash/DM; reduce blanking after very long messages

* iOS: re-enable keyboard autocomplete and default capitalization for message input

* Styling: stop blue/underline styling for #hashtags; render as normal text color (self=orange, others=green)

* Geo UI: ensure self shows teleported (face.dashed) if either per-session tag or manager flag is true

* Geo teleported: publish UI updates by assigning @Published Set instead of in-place insert; update on tag receipt and channel switch

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-22 11:38:44 +02:00
83ee5abb60 Fix: stabilize per-geohash identity seed by storing in Keychain with kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly and caching in memory to avoid transient regenerations (#473)
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-22 01:05:44 +02:00
bc27e16899 Fix/visuals (#469)
* Geohash peers: show face.dashed for self when channel selected via teleport; face.smiling otherwise

* Geo presence: broadcast 'teleport' tag on geochat join; track teleported participants and show face.dashed for them in peer list

* Teleport tag: attach to actual geohash chat events (sendMessage, emotes, screenshots) instead of separate presence; remove presence emit

* Fix: show face.dashed for any teleported peer (not just self) in geohash list

* Geo list: show self immediately on channel switch and mark teleported state; clear teleported flags on leaving geochat

* Teleport persistence: recompute teleported based on current location vs selected geohash; add face.dashed icon to Teleport button label

* Styling: use lighter green/orange for #abcd suffix after nicknames in all chats (senders and @mentions)

* Peer lists: render #abcd suffix as lighter green/orange (self orange) in geohash and mesh lists

* Toolbar: move unread icon next to #channel badge and allow dynamic width; Peer lists: increase top spacing before first item

* Toolbar: prevent geohash channel badge from truncating; give it layout priority and fixed width

* Toolbar: make unread envelope independent from channel button (sits left of badge); fix accidental taps opening channel selector

* Toolbar: make unread envelope open most recent unread/private chat directly

* Geohash peer list: render self row fully orange (icon, base, suffix, '(you)')

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-21 11:15:18 +02:00
jack d3d9a22757 Mentions: color @mentions orange only when directed at me; otherwise use normal color (respect geohash suffix) 2025-08-21 03:26:46 +02:00
jack 8a269d4fec UI: grey #abcd suffix in geohash peer list; keep base name (and '(you)') styled normally 2025-08-21 03:02:42 +02:00
jack 33fbca67d6 UI: render self-authored messages in orange (sender and content); keep links/hashtags orange for self 2025-08-21 03:01:14 +02:00
jack c63350a4d3 UI: bold entire message text for self in mesh, DM, and geohash; adjust caching to include self flag 2025-08-21 02:51:14 +02:00
jack 222854c60a UI: rename AppInfoView toolbar button to 'close' for consistency 2025-08-21 02:45:20 +02:00
jack c624611e7d Merge fixes/location-channels into main: resolve LocationChannelsSheet conflict (retain title bolding only) 2025-08-21 02:23:03 +02:00
jack eb0debd52a Fix: route /hug and /slap to active public channel using sendPublicRaw (geohash when selected) 2025-08-21 01:59:47 +02:00
jack 916f535503 Fix: send screenshot notice to active public channel (geohash when selected), not always mesh 2025-08-21 01:52:54 +02:00
jack de39ab6687 UI: stop bolding location subtitle names; only bold the channel label when count > 0 2025-08-21 01:18:44 +02:00
a0a973eb81 Fixes/location channels (#465)
* Remove "street" location channel; add coverage + names; style mesh

- Drop GeohashChannelLevel.street and update mappings/tests\n- Map geohash lengths >=8 to Block in teleport, no Street\n- Show ~distance coverage (mi/km via Locale.measurementSystem) next to each #geohash\n- Add reverse geocoding to display coarse names (country/region/city/neighborhood) per level\n- Style "#mesh" row title with toolbar blue\n- Fix iOS 16 deprecation: use Locale.measurementSystem

* Project: update Xcode project (auto)

* UI: use '~' without trailing space before location name in sheet

* Location sheet: poll for location at regular intervals while open (replace significant-move updates)

* UI: show Bluetooth range next to #bluetooth in location sheet

* UI: remove leading '#' from mesh title in location sheet

* UI: bold location name in sheet when geohash has >0 people; refactor row to render subtitle pieces

* UI: bold mesh/level titles when participant count > 0; factor meshCount()

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-21 01:01:29 +02:00
jack ba1dd100ec UI: bold mesh/level titles when participant count > 0; factor meshCount() 2025-08-21 00:56:29 +02:00
jack 97b1463b30 UI: bold location name in sheet when geohash has >0 people; refactor row to render subtitle pieces 2025-08-21 00:54:14 +02:00
jack 28c87a41c1 UI: remove leading '#' from mesh title in location sheet 2025-08-21 00:51:18 +02:00
jack 68c61476d8 UI: show Bluetooth range next to #bluetooth in location sheet 2025-08-21 00:49:12 +02:00
jack 602e93d1b2 Location sheet: poll for location at regular intervals while open (replace significant-move updates) 2025-08-21 00:46:53 +02:00
jack e7706fc9cb UI: use '~' without trailing space before location name in sheet 2025-08-21 00:44:37 +02:00
jack f30677403f Project: update Xcode project (auto) 2025-08-21 00:41:28 +02:00
jack b4fcea2672 Remove "street" location channel; add coverage + names; style mesh
- Drop GeohashChannelLevel.street and update mappings/tests\n- Map geohash lengths >=8 to Block in teleport, no Street\n- Show ~distance coverage (mi/km via Locale.measurementSystem) next to each #geohash\n- Add reverse geocoding to display coarse names (country/region/city/neighborhood) per level\n- Style "#mesh" row title with toolbar blue\n- Fix iOS 16 deprecation: use Locale.measurementSystem
2025-08-21 00:34:17 +02:00
jack 43166bcd64 iOS: keep mesh alive in background; remove stopServices() on scenePhase .background so incoming messages can still arrive and trigger notifications. 2025-08-20 18:09:57 +02:00
496972dcc9 Mesh robustness optimizations (#463)
* Mesh robustness: link-aware fragmentation, relay jitter, connection budget, adaptive scanning; fix BLE queue deadlock

- Link-aware fragmentation using per-link write/notify limits
- Directed fragments for one-to-one; exclude from relays
- Add relay jitter with cancel-on-duplicate to reduce floods
- Cap central links and rate-limit connect attempts with queue
- Foreground duty-cycled scanning when connected; continuous when isolated
- Fix deadlock by avoiding sync on BLE queue when already on it
- Silence Keychain var->let warnings

* Mesh: add relay jitter; dynamic RSSI threshold; candidate scoring/backoff; fix misplaced lines in BLEService extension

* macOS UI: restore mesh peer list when geohash feature is iOS-only by moving mesh list outside iOS switch (ContentView)

* ContentView: add macOS mesh peer list under #else to fix missing People section on macOS

* Refactor People section: extract MeshPeerList and GeohashPeopleList into separate views to reduce SwiftUI type-checking complexity; integrate in ContentView

* BLE: prevent re-fragmentation loops; UI: darker mesh blue + first-row spacing in peer list

* Mesh flood/battery: probabilistic relays, adaptive TTL caps, fragment pacing + scan pause, assembly cap; enable relayed DMs with direct-first then flood fallback.

* Refactor BLEService broadcast: split pad policy, encrypted/direct-first handler, and link-aware sender; simplify broadcastPacket to delegate by type.

* Extract relay decision into RelayController with RelayDecision; simplify handleReceivedPacket to use it.

* Move RelayController and RelayDecision into their own file under Services; keep BLEService leaner.

* UI: adjust mesh blue to a darker, less purple tone; apply consistently for count and #mesh badge.

* Project: include RelayController.swift in target and sync project file changes.

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-20 16:27:49 +02:00
3074fa0fcb Refactor/repo hardening 01 (#462)
* BinaryProtocol: add optional padding control; BitchatPacket API for padded/unpadded bytes; BLEService: use unpadded encoding and remove ad-hoc unpadding on BLE writes

* BLEService: balance BLE padding — pad Noise handshake/encrypted frames; leave public/announce/leave unpadded; keep fragmentation consistent with chosen padding

* BLEService: replace Timer with DispatchSourceTimer on bleQueue; NostrTransport: cache placeholder NoiseEncryptionService to avoid reallocation

* Unify peerID validation: InputValidator handles 16-hex, 64-hex, or alnum-/_; NoiseSecurityValidator now delegates to InputValidator

* UI: use standard green for geohash toolbar badge and count (less bright in light mode)

* UI: standardize geohash sheet green to app standard (dark: system green, light: darker green) for buttons and checkmark

* Docs: align BinaryProtocol compression docs to zlib; Logs: reduce NostrTransport DELIVERED ack logs to debug to cut noise

* Tests: add InputValidator peerID coverage and BinaryProtocol padding round-trip/length tests

* Project: ensure Xcode project reflects new tests (references added)

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-20 13:29:53 +02:00
jack bdbcbb5d2b Remove unused getPeers(): use Transport.getPeerNicknames() instead 2025-08-20 12:15:05 +02:00
jack ed4d8b667e Remove stale message-type whitelist from InputValidator: rely on MessageType/NoisePayloadType at decode to prevent drift 2025-08-20 12:15:05 +02:00
jack a29f517783 Harden Keychain access-group usage: avoid -34018 without entitlements; fallback to no access group on macOS/simulator; retry without group on iOS 2025-08-20 12:15:05 +02:00
jack 78917fa7c9 BLE announces: delay after subscribe, queue announce on notify buffer full, and raise announce throttle (min interval + forced min) 2025-08-20 11:54:43 +02:00
jack eb16d128f2 BLE: avoid self-message drop warnings by pre-marking own public broadcasts in dedup and ignoring self-origin public packets 2025-08-20 11:37:47 +02:00
b09710a7aa Feature/location channels (#459)
* Require signed announces; add Ed25519 key/signature/timestamp TLVs and verify

- Protocol: AnnouncementPacket now requires ed25519PublicKey (0x03), announceSignature (0x04), and announceTimestamp (0x05). Encoder emits, decoder requires; unknown TLVs still tolerated.
- NoiseEncryptionService: add canonical announce sign/verify helpers using context 'bitchat-announce-v1'.
- BLEService: sign Announce, include TLVs; on receive verify (±5 min skew) and ignore unverified; store ed25519 key and isVerifiedNickname in PeerInfo.
- Preserve 8-byte on-wire IDs to keep BLE headers small; no per-message bloat.

* Fix Data.append usage for timestamp bytes in Packets and NoiseEncryptionService (use append(contentsOf:) on UnsafeRawBufferPointer)

* BLEService: fix non-optional announce fields and unwrap signature result; enforce required verification path

* Enforce verified-only public messages; append peerID suffix on nickname collisions in handleMessage

* Suffix duplicate nicknames with peerID prefix in snapshots and getPeerNicknames; ensures lists and messages disambiguate 'jack' vs 'jack'

* Include self nickname in collision detection: suffix remote 'jack' when it matches our nickname in lists and public chat

* UI labels: remove space before '#abcd' suffix in names (public chat, peer lists, snapshots)

* Style '#abcd' suffix light gray:
- Public chat: color suffix in sender via AttributedString segments
- People list: split name and color suffix segment; add helper splitNameSuffix()

* Debounce 'bitchatters nearby' notification: add 60s grace before reset when mesh goes empty; cancel reset when peers return

* Lighten '#abcd' suffix: use Color.secondary.opacity(0.6) in public chat sender and People list

* Toolbar peers indicator: use blue when Bluetooth peers present (was default text color)

* Toolbar peers indicator: use grey when zero peers (was red)

* Toolbar peers indicator: use system grey (Color.secondary) when zero peers, not green

* Fix crash: mutate peripherals dict on BLE queue (not main). Move scan restart to BLE queue as well.

* Reduce connect timeout churn: back off peripherals that time out (15s), increase timeout to 8s, skip non-connectable adverts, and demote timeout log to debug; clean backoff map periodically

* Mentions: support '@name#abcd' disambiguation; filter hashtag/URL styling inside mentions; deliver notifications only to the specified suffixed target when collisions exist

* Fix string interpolation in mention log (escape sequence)

* Mentions: parse '@name#abcd' in sender/receiver; render mention suffix grey (not orange/blue/underlined); ensure receiver notifications trigger for suffixed tokens

* Mentions: include own suffixed token 'name#<myIDprefix>' in valid tokens so '@name#abcd' to self is recognized and notified

* Public actions: show own system message by processing own public messages (remove early-return). Private /hug: add local system message for sender's chat.

* Grammar: change local '/hug' message to past tense ('you hugged/slapped'). Notifications: only fire 'bitchatters nearby' on rising-edge; remove 5-min re-fire and increase empty reset grace to 10m.

* Public /hug echo: add local system message so sender sees action immediately (no reliance on echo)

* Fix visibility: expose addPublicSystemMessage on ChatViewModel and use it from CommandProcessor

* Implement iOS Location Channels (geohash public chats)

- Domain: add ChannelID, GeohashChannel(Level), lightweight geohash encoder
- Identity: derive per-geohash Nostr keys (HMAC-SHA256 device seed)
- Nostr: kind 20000 + #g tag, nickname tag (n), filter helper
- iOS: LocationChannelManager (permissions, one-shot location), Info.plist string
- UI: toolbar # badge (#mesh or #<level>), sheet (irc style, full-row taps, settings link)
- VM: subscribe/send for active channel, clear timeline on switch, nickname cache
- Emotes: route public via Nostr/mesh without echo, local system confirmation, emojis restored
- Haptics: detect hugs/slaps for nickname#abcd and trigger on receiver
- Rendering: remove hashtag/mention formatting (plain monospaced)

Note: iOS-only; macOS unaffected.

* Lifecycle and persistence: resubscribe on foreground/relay connect, cap dedup set, persist mesh timeline.

- ChatViewModel: resubscribe geohash on app foreground and relay reconnect
- Add processed Nostr events cap (2k) with eviction
- Persist mesh public messages in meshTimeline; hydrate on switching to #mesh
- Local geochat messages use nostr: senderPeerID for classification
- Tests: fix JSON contains assertion for #g tag

* Fix Swift 6 concurrency warnings: remove closure-based NC observer, wrap relay reconnect resubscribe in Task @MainActor, resubscribe in appDidBecomeActive selector.

* Location Channels polish: live geohash refresh while sheet open; keep selection stable; toolbar shows #<geohash>; sheet labels show human level + #geohash.

* Add per-geohash in-memory timelines and cap private chats to 1337.

- ChatViewModel: persist geohash messages in geoTimelines[geohash] with cap; hydrate timeline on channel switch
- PrivateChatManager: trim per-peer chats to 1337 on send/receive
- Toolbar badge: prevent wrapping with lineLimit(1)/truncation

* Toolbar badge layout + brand color; Teleport custom geohash; Live refresh uses startUpdatingLocation with significant distance.

- Toolbar: right-justify geohash, head truncation, use brand green
- Sheet: add #custom geohash textfield + join; keep minimal IRClike style
- Manager: startUpdatingLocation()/stopUpdatingLocation() with distanceFilter=250 while sheet is open

* Location sheet live updates: reduce distanceFilter to 21m for more frequent geohash refreshes while open.

* Toolbar badge spacing/width; Sheet: rename to #geohash and button 'teleport'.

- Move # label closer to peer count and widen to avoid truncation
- Change custom field placeholder to '#geohash' and action button to 'teleport' with monospaced font

* Sheet polish: style 'teleport' button with subtle background, disable until valid; prefix '#' label and placeholder 'geohash'; center + style 'remove location permission' and hide separators for these rows.  Toolbar: adjust spacing/width for # label.

* Sheet UX: restrict custom geohash input to valid base32 (lowercase, max 12), reduce spacing so placeholder sits closer to '#', add divider under country row, style 'remove permission' and hide row separators as before. Toolbar: minor spacing/width already adjusted.

* Sheet behavior: show channel list even without permission; add green 'get location and my geohash' button; ensure only one separator between country and teleport by removing manual Divider and showing default row separator; refine teleport input filtering and spacing.

* Channel activity nudges: notify after 9 minutes inactivity only in background; triple-tap clear also clears persistent timelines.

- ChatViewModel: track last activity per channel; send local notification when new activity resumes while app in background (with small cooldown)
- CommandProcessor: /clear clears current public channel persistence via viewModel helper

* Fix compile: add activeChannelDisplayName() and clearCurrentPublicTimeline() helpers in ChatViewModel.

* Fix concurrent dictionary access in BLEService.broadcastPacket: snapshot shared collections under collectionsQueue to avoid CocoaDictionary iterator crashes.

* People: channel-aware list and counts

- Sidebar: NETWORK → PEOPLE; removed PEOPLE subheader/icon
- Toolbar: blue #mesh badge; green #<geohash> badge; count color by channel
- Geohash participants: track per-geohash unique senders with 5m decay; publish list
- Update on geohash send/receive; 30s prune timer; channel switch hooks

No changes to mesh peer UX; mesh list retained as-is.

* BLE: snapshot collections for thread-safe access; stopServices uses snapshot; safe characteristic snapshot in broadcast path

LocationChannelsSheet: rename button label to 'remove location access'

* Channel sheet: show current peer counts

- Mesh row shows connected mesh peers count
- Geohash rows show 5m-active participant counts via ViewModel
- Live-updates while sheet is open

* Channel sheet: pluralize counts as 'person/people' in titles

* Geohash sampling: subscribe to all available channels while sheet open

- ViewModel: add multi-channel sampling subscriptions and per-geohash participant updates
- Sheet: start sampling on appear, sync on list changes, stop on disappear

* Channel sheet: render counts '(N person/people)' in smaller font next to label

* Channel sheet: use square brackets for counts and adjust parsing; fix mesh title to '#mesh'

* Geohash DMs: implement send/receive via NIP-17 with per-geohash identity

- NostrEmbeddedBitChat: add no-recipient encoder for geohash DMs
- NostrTransport: add sendPrivateMessageGeohash(using provided identity)
- ChatViewModel:
  • startGeohashDM + mapping helpers
  • subscribe to per-geohash gift wraps; store DMs in conversations keyed by 'nostr_<prefix>'
  • route sendPrivateMessage() for 'nostr_' to Nostr geohash send; local echo and status
  • map pubkeys from geohash public events for DM initiation
  • resubscribe DM feed on reconnect and channel switch; unsubscribe on leave
- ContentView: long-press 'private message' starts geohash DM when sender is nostr

* Geohash DMs UX: tap participants to DM; support /msg nickname in geohash; DM notifications

- People (geohash) list: bold 'you', sort to top, tap to open DM
- ChatViewModel.getPeerIDForNickname resolves geohash names to nostr_ conv keys
- Geohash DM receive: send local notification when not viewing

* Geohash DMs polish: header title, star hidden, self-DM blocked, message icon, delivered/read ACKs

- Header shows '#<geohash>/@name#abcd' for geohash DMs; hide favorite star
- Geohash people row: add small message icon; prevent self tap
- Prevent sending geohash DM to self
- Send delivery/read ACKs on receive; handle delivered/read to update status

* Geohash DMs: hide encryption status icon in DM header

* BLE: fix data race in broadcast path

- Snapshot peripherals via Array(values) and filter outside sync
- Snapshot subscribedCentrals and centralToPeerID under collectionsQueue
- Mutate subscribedCentrals under collectionsQueue barriers in didSubscribe/unsubscribe

* LocationChannelsSheet: open fully by default (large detent only)

* BLE: remove unused centralMapSnapshot variable

* Geohash DMs: only notify on incoming PM when app is backgrounded; avoid foreground noise

* GeoDM: reliable delivered/read receipts, background-only notifications, and UI tweak

- Implement delivered + read receipts for geohash DMs; send READ on open\n- Handle relay OK acks for gift-wrap sends; resubscribe processes PM/DELIVERED/READ\n- Prevent mesh Noise handshakes for virtual geohash peers (nostr_*)\n- Notify GeoDMs only in background; suppress alerts for already-read msgs\n- Logging: promote key GeoDM receive logs; demote/remove verbose noise\n- UI: remove trailing envelope button from geohash People list

* Fix: remove duplicate variable declarations in AnnouncementPacket.decode()

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-20 01:10:23 +02:00
a30b73dd99 Feature/fragmentation fixes (#453)
* Fix fragmentation + BLE long-write + padding

- Accumulate CBATTRequest long writes by offset and decode once per central
- Decode original packet after fragment reassembly (preserve flags/compression)
- Switch MessagePadding to strict PKCS#7 and validate before unpadding
- Make BinaryProtocol.decode robust: try raw first, then unpad fallback
- Unpad frames before BLE notify; fragment when exceeding centrals' max update length
- Skip notify path when max update length < 21 bytes (protocol minimum)

Verified large PMs and announces route without decode errors and peers show reliably.

* Tests: fix weak delegate lifetime, legacy constants, and unused vars; fragment unpadded frames

- BLEServiceTests: hold strong reference to MockBitchatDelegate
- IntegrationTests: fix inline comment braces; replace removed types with test-safe values; use numeric 0x06 for legacy handshake resp checks
- BinaryProtocolTests: remove unused minResult variable
- BLEService: fragment the unpadded frame so fragments are efficient

* tests: add Noise rehandshake recovery test; document in-memory test bus and autoFlood; stabilize large-network broadcast

* tests: align suite with current behavior (compression, padding, routing, nonce); deflake and stabilize

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-19 01:22:21 +02:00
4f1ac30f12 Feat/mesh robustness efficiency (#451)
* chat: de-dup private chats across ephemeral/stable IDs; prefer most advanced delivery status\n\n- Fixes LazyVStack duplicate ID warnings and blank row in PM\n- Merges messages by id from ephemeral and Noise-key stores\n- Chooses read > delivered > partiallyDelivered > sent > sending > failed (newer wins on tie)\n- Ensures status icon updates immediately without waiting for another send\n- Adds exhaustive handling for DeliveryStatus in ranking

* logging: reduce noisy info logs to debug; keep errors/warnings\n\n- Downgrade routing/ACK/subscription/connect logs to debug\n- Retain security/fingerprint/keychain info logs\n- Keep errors and warnings intact\n\ndocs: add docs/privacy-assessment.md covering BLE privacy, routing TTL/jitter, Nostr E2E gift wraps, ACK throttling, and logging posture

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-17 21:25:25 +02:00
6fbf7eee25 Refactor/ble nostr boundaries (#449)
* Refactor: move Nostr embedding and TLVs out of BLE; add NostrEmbeddedBitChat, Packets, PeerIDUtils; centralize MessageDeduplicator; update ChatViewModel to use new helpers; remove AI_CONTEXT.md and CLAUDE.md

* Rename class to BLEService with compatibility alias; move mention parsing out of BLE; emit low-level BLE events to delegate; unify hex helpers; accept 64-hex in isPeerConnected; add PeerIDResolver

* Project: rename file to BLEService.swift and update Xcode project; keep typealias SimplifiedBluetoothService = BLEService for compatibility

* Remove SimplifiedBluetoothService alias; update app code to use BLEService explicitly

* Tests: rename MockSimplifiedBluetoothService to MockBLEService; update typealiases and Xcode project

* Docs: update comments to refer to BLEService (tests, protocol, noise service)

* Tests: rename SimplifiedBluetoothServiceTests to BLEServiceTests; update project references and class names

* Introduce Transport protocol; BLEService conforms; document delegate-only event pattern in BLEService; keep publishers internal for UnifiedPeerService

* Adopt Transport end-to-end: add TransportPeerSnapshot + publishers; BLEService maps to Transport snapshots; UnifiedPeerService consumes Transport; ChatViewModel holds Transport

* Fix Transport integration: replace getPeerFingerprint with getFingerprint(for:); update PrivateChatManager and CommandProcessor to use Transport; add BLEService.getFingerprint(for:); update PeerManager to use Transport

* Refactor transport and BLE/Nostr layers; unify UI events; fix MainActor isolation

- Rename SimplifiedBluetoothService to BLEService and slim responsibilities
- Introduce Transport protocol and peerEventsDelegate for UI updates
- Add NostrTransport and MessageRouter to route PM/read/favorite via BLE or Nostr
- Centralize TLVs, PeerID utils, and MessageDeduplicator outside BLE
- Update UnifiedPeerService and ChatViewModel to use Transport and delegate events
- Fix MainActor isolation: route delegate calls via Task on MainActor; update notifyUI helper
- Adjust related files and tests accordingly

* BLEService: remove internal publishers; switch to delegate-only events

- Drop legacy messages/peers/fullPeers publishers
- Provide lightweight peerSnapshotSubject only to satisfy Transport
- Rework publishFullPeerData to build snapshots from internal state and notify delegate + subject
- Remove all peersPublisher.send call sites
- Keep UnifiedPeerService on delegate updates exclusively

* Remove inlined Nostr send helpers from ChatViewModel; route via MessageRouter

- Replace direct Nostr sends (PM, ACKs, favorites) with MessageRouter
- Add router method for delivery ACKs and implement NostrTransport.sendDeliveryAck
- Simplify ChatViewModel favorite notification path to use router
- Keep Nostr receive handling intact; reduce duplication

* Fix ReadReceipt initializer usage in ChatViewModel (readerID + readerNickname)

* Fix unused variable warning: replace shadowed 'nostrPubkey' bind with boolean check in ChatViewModel

* Fix queued PM format: use TLV for pending messages after Noise handshake

- Pending messages (including first-time favorite notifications) now use the same TLV encoding as normal sends
- Ensures ChatViewModel can decode on first send, even if handshake completes after queuing

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-17 15:17:04 +02:00
3ebfa85e90 Feature/nostr embedded bitchat (#448)
* UI: prefer mesh radio icon when connected; map short peer ID to full Noise key; rename ephemeral mapping to shortIDToNoiseKey; ensure header flips to purple globe on disconnect and keeps name.

* chore: stop tracking build artifacts; ignore .DerivedData and .Result*

* logging: add global threshold via BITCHAT_LOG_LEVEL and demote chatty logs to debug; keep critical errors/warnings and key state transitions

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-17 11:25:42 +02:00
fb1988ac27 BLE privacy: derive peerID from Noise fingerprint; remove BLE Local Name from advertising; verify announces against key-derived ID; auto-initiate Noise handshake when encrypted message arrives without session; drop rotating alias option. (#447)
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-17 02:20:49 +02:00
845ffc601b Refactor/robustness (#446)
* Refactor BitChat for improved robustness and performance

Major refactoring to simplify architecture and fix critical issues:

Architecture Improvements:
- Replace complex BluetoothMeshService with simplified SimplifiedBluetoothService
- Consolidate message routing and peer management into unified services
- Remove redundant caching layers and optimize performance

Bug Fixes:
- Fix critical BLE peer mapping corruption in mesh networks
- Fix encrypted message routing failures in multi-peer scenarios
- Fix app freezes and Main Thread Checker warnings
- Fix BLE message delivery in dual-role connections
- Fix favorite toggle UI not updating instantly
- Fix Nostr offline messaging with 24-hour message filtering

Features:
- Add command processor for chat commands
- Add autocomplete service for mentions and commands
- Improve private chat management with dedicated service
- Add unified peer service for consistent state management

Performance:
- Optimize BLE reconnection speed
- Reduce excessive logging throughout codebase
- Improve message deduplication efficiency
- Optimize UI updates and state management

* Improvements refactor robust (#441)

* remove unused code

* remove more

* TLV for announcement

* restore

* restore

* restore?

* messages tlv too (#442)

* Fix Nostr notification and read receipt issues, add TLV encoding, cleanup unused code

## Notification & Read Receipt Fixes
- Fixed toolbar notification icon appearing incorrectly on app restart for already-read messages
- Fixed read receipts being incorrectly deleted on startup when privateChats was empty
- Fixed messages not being marked as read when opening chat for first time
- Fixed senderPeerID not being updated during message consolidation
- Added startup phase logic to block old messages (>30s) while allowing recent ones
- Fixed unread status checking across all storage locations (ephemeral, stable Noise keys, temporary Nostr IDs)

## TLV Encoding Implementation
- Implemented Type-Length-Value encoding for private message payloads
- Added PrivateMessagePacket struct with TLV encode/decode methods
- Enhanced message structure for better extensibility and robustness

## Code Cleanup
- Removed unused PeerStateManager class and related dependencies
- Removed dead protocol types (DeliveryAck, ProtocolAck/Nack, NoiseIdentityAnnouncement)
- Cleaned up BitchatDelegate by removing unused methods
- Removed excessive debug logging throughout ChatViewModel
- Added test-only ProtocolNack helper for integration tests

## Technical Details
- Messages stored under three ID types: ephemeral peer IDs, stable Noise key hexes, temporary Nostr IDs
- Fixed cleanupOldReadReceipts() to skip when privateChats is empty or during startup
- Updated message consolidation to properly update senderPeerID
- Restored NIP-17 timestamp randomization (±15 minutes) for privacy

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: callebtc <93376500+callebtc@users.noreply.github.com>
2025-08-17 01:51:54 +02:00
db3c3b77f5 Remove dead store-and-forward and message aggregation code (#438)
- Remove completely unused message aggregation system (100% dead code)
- Remove broken store-and-forward implementation that only worked for relayed messages to offline favorites
- Update documentation to reflect actual functionality
- Net reduction of 312 lines of unmaintained code

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-12 20:08:37 +02:00
jack 26bcdf72d7 Merge remote-tracking branch 'origin/main' into code-cleanup 2025-08-12 11:43:52 +02:00
275f0ebaaf Remove dead code and simplify codebase (#436)
* refactor: remove dead code and consolidate system messages

- Delete 3 unused functions in ShareViewController (36 lines)
- Extract addSystemMessage() helper to eliminate duplication (120+ lines)
- Remove 22 'let _ =' wasteful computations across multiple files
- Net reduction of 215 lines of dead/duplicate code
- Improves maintainability and reduces technical debt

* fix: remove remaining unused variables to eliminate compiler warnings

- Remove unused senderNoiseKey in ChatViewModel
- Remove unused lastSuccess variable in BluetoothMeshService
- Eliminates all compiler warnings related to unused values

* refactor: remove all dead legacy and migration code

- Remove unused migrateSession() functions (never called in production)
  - NoiseSession.migrateSession() - 13 lines
  - NoiseEncryptionService.migratePeerSession() - 18 lines
  - Test for migration functionality - 17 lines

- Remove unnecessary keychain cleanup code (no legacy data existed)
  - cleanupLegacyKeychainItems() - 62 lines
  - aggressiveCleanupLegacyItems() - 72 lines
  - resetCleanupFlag() - 4 lines
  - Simplified panic mode to just use deleteAllKeychainData()

Total removed: 194 lines of dead/unnecessary code

Analysis revealed:
- KeychainManager introduced July 5, 2025
- Cleanup code added July 15, 2025 (10 days later)
- Legacy service names were never used in production
- Migration functions were incomplete implementation never called
- Peer ID rotation remains active (not legacy)

* Remove dead code and simplify codebase

- Remove unused BinaryEncodable protocol and BinaryMessageType enum
- Delete MockNoiseSession.swift (never used in tests)
- Remove all relay detection code (hardcoded to false)
  - Removed isRelayConnected property from BitchatPeer
  - Removed relayConnected case from ConnectionState enum
  - Cleaned up relay-related UI indicators in ContentView
  - Removed relay status checks from ChatViewModel
- Simplified peer connection logic by removing relay layer

Total: 169 lines removed across 5 files

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-12 11:33:08 +02:00
jack f4b8168ef9 Remove dead code and simplify codebase
- Remove unused BinaryEncodable protocol and BinaryMessageType enum
- Delete MockNoiseSession.swift (never used in tests)
- Remove all relay detection code (hardcoded to false)
  - Removed isRelayConnected property from BitchatPeer
  - Removed relayConnected case from ConnectionState enum
  - Cleaned up relay-related UI indicators in ContentView
  - Removed relay status checks from ChatViewModel
- Simplified peer connection logic by removing relay layer

Total: 169 lines removed across 5 files
2025-08-12 11:03:31 +02:00
jack 63f05b5d7e refactor: remove all dead legacy and migration code
- Remove unused migrateSession() functions (never called in production)
  - NoiseSession.migrateSession() - 13 lines
  - NoiseEncryptionService.migratePeerSession() - 18 lines
  - Test for migration functionality - 17 lines

- Remove unnecessary keychain cleanup code (no legacy data existed)
  - cleanupLegacyKeychainItems() - 62 lines
  - aggressiveCleanupLegacyItems() - 72 lines
  - resetCleanupFlag() - 4 lines
  - Simplified panic mode to just use deleteAllKeychainData()

Total removed: 194 lines of dead/unnecessary code

Analysis revealed:
- KeychainManager introduced July 5, 2025
- Cleanup code added July 15, 2025 (10 days later)
- Legacy service names were never used in production
- Migration functions were incomplete implementation never called
- Peer ID rotation remains active (not legacy)
2025-08-12 10:15:05 +02:00
jack a36eda3fbe fix: remove remaining unused variables to eliminate compiler warnings
- Remove unused senderNoiseKey in ChatViewModel
- Remove unused lastSuccess variable in BluetoothMeshService
- Eliminates all compiler warnings related to unused values
2025-08-12 09:43:06 +02:00
jack 99c0f6523e refactor: remove dead code and consolidate system messages
- Delete 3 unused functions in ShareViewController (36 lines)
- Extract addSystemMessage() helper to eliminate duplication (120+ lines)
- Remove 22 'let _ =' wasteful computations across multiple files
- Net reduction of 215 lines of dead/duplicate code
- Improves maintainability and reduces technical debt
2025-08-12 09:41:12 +02:00
7a7c89e689 Remove protocol versioning and handshake logic (#433)
Simplified the protocol by removing version negotiation and handshake sequences.
All devices now use protocol version 1 without negotiation. This eliminates
unnecessary connection overhead and complexity while maintaining full
compatibility across the network.

Changes:
- Removed versionHello and versionAck message types
- Simplified connection flow to use announce packets only
- Removed version negotiation state tracking
- Cleaned up handshake timeout logic
- Reduced connection establishment overhead

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-12 02:24:34 +02:00
3226b9cd14 Optimize logging to reduce verbosity while preserving critical network events (#432)
- Remove excessive verbose logging (DISCOVERY, INCOMING, PEER-UPDATE, etc.)
- Preserve critical network state logs (RESTORE, handshake failures, security events)
- Change routine key operations from info to debug level
- Add successful peer connection log after handshake completion
- Fix compiler warnings for unused variables
- Achieve ~95% reduction in log volume while maintaining debugging capability

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-11 23:45:59 +02:00
7876c8d96f Fix network flakiness and improve peer discovery (#405)
- Extend timeouts for better stability (availability: 30s->60s, cleanup: 3min->5min)
- Enable 30% relay probability for small networks to help discovery
- Add macOS-specific fixes for CoreBluetooth compatibility
- Implement rescan rate limiting to prevent battery drain
- Add comprehensive debug logging for network diagnostics
- Fix peripheral mapping and connection state management
- Improve relay-only session handling

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-05 10:13:41 +02:00
3ed37dfd0b Improve UI interactions (#390)
- Increase tap target size for back button in private message view
- Limit @mentions autocomplete to top 4 matches for better usability

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-02 11:48:19 +02:00
327fca9cb1 Remove cover traffic functionality (#389)
- Remove cover traffic variables and timer
- Remove cover traffic methods (startCoverTraffic, scheduleCoverTraffic, sendDummyMessage, generateDummyContent)
- Remove cover traffic initialization in startSession()
- Remove cover traffic check in handleReceivedPacket
- Remove timer invalidation in reset()
- Update README.md and AI_CONTEXT.md to remove cover traffic mentions

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-02 11:36:20 +02:00
871456896d Remove connection/disconnection system messages (#386)
- Remove system messages for peer connections to reduce chat noise
- Keep essential state management (ephemeral sessions, read receipts)
- Users can still see who's online via /w command

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 22:05:29 +02:00
b4b22e0e05 Add Bluetooth status alerts (#385)
- Add alert UI to notify users when Bluetooth is off/unauthorized
- Monitor Bluetooth state changes in BluetoothMeshService
- Show appropriate messages for different Bluetooth states
- Add Settings button to open system settings on iOS
- Check initial Bluetooth state on app startup

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 21:51:32 +02:00
jack 8ec39f566d Fix runtime crashes and reduce excessive logging
- Fix Dictionary crash in ChatViewModel by adding deduplication logic for peer IDs
- Fix compilation errors: PeerData -> BitchatPeer type correction
- Fix Task async context issue with cancellables
- Remove excessive debug logging for handshake coordination
- Remove repetitive keep-alive timer logs
- Remove version cache logging spam
2025-08-01 21:39:09 +02:00
jack 172b06721b Revert "Fix compilation errors in ChatViewModel"
This reverts commit e2d50e3684.
2025-08-01 20:26:28 +02:00
jack e2d50e3684 Fix compilation errors in ChatViewModel
- Fixed PeerData type reference (should be BitchatPeer)
- Fixed Task initialization in init() method with proper async/await syntax
- Fixed cancellables binding issue with proper unwrapping
- Maintained duplicate peer ID protection in peerIndex dictionary
2025-08-01 20:24:09 +02:00
jack d605a0b6db Fix crash from duplicate peer IDs in Dictionary initialization
- Added deduplication logic in ChatViewModel to handle duplicate peer IDs gracefully
- Enhanced PeerManager to prevent duplicate peers by tracking both nicknames and IDs
- Added final safety check to ensure no duplicates in peers array
- This fixes crash when Dictionary(uniqueKeysWithValues:) encounters duplicate keys
2025-08-01 19:04:36 +02:00
jack 1d698c2006 Fix @Unknown entries in autocomplete by improving nickname resolution
- Added getBestAvailableNickname() method to resolve nicknames from multiple sources
- Updated all PeerSession creations to use better nickname resolution
- Changed fallback from 'Unknown' to 'anon[peerID]' format for distinguishability
- Modified getPeerNicknames() to proactively update Unknown entries
- This ensures autocomplete shows meaningful nicknames instead of @Unknown
2025-08-01 19:01:07 +02:00
jack a92828471b Fix App Store submission: remove invalid background-processing from UIBackgroundModes 2025-08-01 16:58:13 +02:00
jack 69c8161cf8 Fix crash in BinaryProtocol.decode due to out-of-bounds data access
- Add comprehensive bounds checking before all data access operations
- Validate payload lengths don't exceed available data
- Protect against integer overflow in size calculations
- Handle malformed compressed packets gracefully
- Add extensive test coverage for edge cases

This fixes crashes when receiving malformed Bluetooth packets that claim
payload sizes larger than the actual data available.
2025-08-01 16:52:21 +02:00
aa1ecf40fc Fix iOS background Bluetooth connectivity issues (#378)
- Implement Core Bluetooth state restoration with restoration identifiers
- Add background task management to protect critical BLE operations
- Fix aggressive battery optimization that killed background connectivity
- Disable scan duty cycling in background (was causing 89-97% downtime)
- Add missing didEnterBackground/willEnterForeground notifications
- Fix advertising cutoff in low battery conditions (now only <10%)
- Add background-processing entitlement to Info.plist
- Optimize scan parameters for background vs foreground modes

These changes address the issue where devices lose mesh connectivity when
the app is backgrounded, ensuring continuous Bluetooth operation within
iOS background execution limits.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 12:18:14 +02:00
b004bfa4aa Remove message batching system for simpler, faster UI updates (#377)
- Remove dual-timer batching architecture (100ms message timer, 50ms UI timer)
- Delete pending message queues and all batching infrastructure
- Simplify to direct message appends with duplicate detection
- Trust SwiftUI's built-in update optimization instead of manual batching
- Results in instant message display and 208 lines of code removed
- Eliminates timer management complexity and potential race conditions

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 11:38:53 +02:00
a6c2e751d2 Performance optimizations: LazyVStack, UI batching, timer consolidation (#375)
- Replace VStack with LazyVStack for message list to enable on-demand rendering
- Batch UI updates in ChatViewModel to reduce main thread operations
- Consolidate 12 timers into 3 (high/medium/low frequency) in BluetoothMeshService
- Fix thread safety in scheduleUIUpdate with main thread check

These changes significantly improve app responsiveness and reduce CPU usage.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-01 01:05:59 +02:00
8f32edaa64 Security fixes and improvements (#374)
- Fix force unwrapping in NostrIdentity bech32 functions that could crash on non-ASCII input
- Add comprehensive input validation for all protocol messages (peer IDs, nicknames, timestamps)
- Strengthen keychain security with better sandbox detection and consistent app group usage
- Implement secure memory clearing for cryptographic keys and shared secrets
- Fix panic mode not reconnecting to mesh by restarting services after emergency disconnect

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-07-31 23:42:08 +02:00
jackandGitHub d85c9e226b Update README.md 2025-07-31 18:13:51 +02:00
jack f953c50565 Remove 'back' text from PM view, keep only chevron 2025-07-31 12:43:28 +02:00
2a081f65fc Group Connectivity Improvements (#365)
* Implement dynamic connection limits based on network size

Fixes connection thrashing in group scenarios by dynamically adjusting the connection limit based on the number of nearby peers.

Changes:
- Replace fixed maxConnectedPeripherals with dynamic calculation
- Maintain full mesh connectivity for small groups (<10 peers)
- Scale connection limit up to 2x for larger groups
- Override battery-based limits when needed to prevent thrashing
- Add logging to track dynamic limit changes

This solves the "perfect storm" issue where 6-8 people would constantly disconnect/reconnect when the power saver mode limited connections to 5.

* Implement optimistic version negotiation with caching

Skip version negotiation for known peers by caching negotiated versions for 24 hours.

Changes:
- Add version cache that persists beyond session lifetime
- Check cache before sending version hello
- Skip negotiation entirely for cached peers (instant connection)
- Cache cleanup runs every 60 seconds
- Invalidate cache on protocol errors for automatic fallback
- Log when using cached versions

This reduces protocol messages by ~40% for reconnecting peers and enables instant connections for known devices.

* Fix unused variable warning

* Implement protocol message deduplication

Suppress duplicate protocol messages within configurable time windows to reduce overhead.

Changes:
- Add deduplication tracker with per-message-type time windows
- Suppress duplicate announces within 5 seconds
- Suppress duplicate version negotiations within 10 seconds
- Track messages by peer ID and optional content hash
- Automatic cleanup of expired entries every 60 seconds
- Log when duplicates are suppressed

This reduces protocol message overhead by 20-30% in group scenarios where multiple connection attempts trigger redundant announcements and version negotiations.

* Fix MessageType enum case name

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-07-31 11:36:49 +02:00