Commit Graph
509 Commits
Author SHA1 Message Date
jack eb63a62590 Revert notes geohash selection back to block-level (precision 7); keep building level available but unused; update counter and sheet accordingly 2025-09-13 11:29:49 +02:00
jack 939adcf1cb Location notes: change notes toolbar icon to SF Symbol 'long.text.page.and.pencil' 2025-09-13 11:27:46 +02:00
jack 46ca37ceaa Switch location notes and UI helpers to building-level geohash (precision 8): add GeohashChannelLevel.building, map length 8, use building for notes selection and counter, add building name mapping 2025-09-13 11:08:38 +02:00
jack ead1d1e9a2 Location notes: append 'ago' to relative timestamps (within 7 days) 2025-09-13 10:37:05 +02:00
jack e0f69d7f59 Location notes: show timestamp as relative within 7 days, else absolute date (MMM d or MMM d, y); keep monospaced styling 2025-09-13 10:36:26 +02:00
jack cd3dea3dc4 Location notes: drop 'teleport' tag from kind-1 events; simplify note builder API and usage 2025-09-13 10:32:35 +02:00
jack 086699961d Location notes: restore timestamps in notes list; remove loading state from manager and sheet (no spinner/animation) 2025-09-13 10:31:17 +02:00
jack d0bfb179ed Location notes: move notes icon to the right of #mesh badge in toolbar 2025-09-13 01:15:15 +02:00
jack 52bdf6745b Location notes: add background counter service and show count next to notes icon on mesh; auto-subscribe to current block geohash 2025-09-13 01:12:49 +02:00
jack bef4a30ea7 Location notes: fix intermittent first load by ensuring resubscribe after geohash change, removing over-eager subscribe guard, and widening note fetch window (no since filter) 2025-09-13 01:09:35 +02:00
jack c97de7a2f8 Location notes: remove per-note relative timestamp from sheet (no seconds display) 2025-09-13 01:07:32 +02:00
jack 9fd5957f46 Location notes: remove Matrix animation; use simple spinner when acquiring location; simplify notes view layout 2025-09-13 01:04:58 +02:00
jack 7eba856f13 Location notes: inline sheet wrapper to avoid missing file in target; force location refresh and show Matrix loader until block geohash resolves 2025-09-13 01:02:20 +02:00
jack 3a3da2f66d Location notes: acquire geohash on open (force refresh) and show Matrix loader until block-level geohash resolves; add LocationNotesSheet wrapper 2025-09-13 01:00:55 +02:00
jack 52933568d7 Location notes: add close (x) button in sheet header (upper-right) using @Environment(\.dismiss) 2025-09-13 00:55:47 +02:00
jack abeab5ae94 Location notes: render note bodies with monospaced font in notes list 2025-09-13 00:52:01 +02:00
jack 4a2d83ec78 Location notes: fix duplicate state redeclaration in ContentView 2025-09-13 00:48:12 +02:00
jack 56590c8ac3 Location notes: prevent duplicate loading/subscriptions (StateObject manager, geohash captured at open, guard subscribe) 2025-09-13 00:46:50 +02:00
jack d809351ab3 Location notes: Matrix loader with 1–3s minimum display; allow multiple notes; wire notes UI from mesh toolbar 2025-09-13 00:40:41 +02:00
920dc31795 Refactor: Testable Keychain and Identity Manager (#584)
* Make static functions instance functions to be testable

* Injectable KeychainManager + Mock + updated tests

* Remove `pendingActions` from identity manager (dead code)

* Remove `getHandshakeState` from identity manager (dead code)

* Remove `getAllSocialIdentities` from identity manager (dead code)

* Remove `getCryptographicIdentity` from identity manager (dead code)

* Remove `resolveIdentity` from identity manager (dead code)

* Identity Manager: minor clean up

* Put Identity Manager behind a protocol

* Remove Keychain and Identity Manager singletons

* Tests: include MockKeychain/MockIdentityManager in project; init identityManager in CommandProcessorTests

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-09-12 14:37:34 +02:00
bb3d99bdca Fix repeated favorite notifications; route system messages to mesh; simplify favorites (#588)
* Favorites: mesh-only system message; stop reconnect resends; gate system on state change

* Favorites: remove npub resend tracking and nickname-based key migration; rely on Noise key as identity

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-09-12 14:36:32 +02:00
jackandGitHub b01cac4649 Delete Frameworks/README.md 2025-09-12 13:16:08 +02:00
4b0634d1d0 Fix/general queue (#580)
* Fix emote targeting and grammar; add tests

Prevent 'system' mis-target via peerID-derived display name in actions sheet. Correct /hug and /slap usage/error grammar by passing base command name. Improve geohash nickname resolution to match displayName with #suffix. Add CommandProcessor tests.

* Geohash ordering: strict in-order inserts and timestamp clamp

Use channel-aware late-insert threshold with 0s for geohash to keep strict chronological order. Clamp future Nostr event timestamps to 'now' to avoid future-dated items skewing order in geohash timelines.

* Trim trailing/leading spaces in geohash nicknames and tag emission

Sanitize Nostr 'n' tag values on ingest and emit by trimming whitespace/newlines to prevent trailing spaces in displayed usernames. Local nickname is already trimmed on focus loss and submit.

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
v1.3.4
2025-09-11 21:02:48 +02:00
jack 97cbe37f09 Project: add OSLog+Categories.swift to iOS/macOS targets to fix missing OSLog categories (noise/security/keychain/etc.) 2025-09-11 20:14:00 +02:00
jack b5d6e4eeb5 Merge branch 'pr/575' 2025-09-11 20:07:04 +02:00
islam a1edf29bd3 Remove unnecessary import os.logs 2025-09-11 19:03:08 +01:00
islam 5f402698a1 Extract private functions into a separate extension 2025-09-11 19:03:08 +01:00
islam 1e997e1387 Statically typed logging of KeyOperations 2025-09-11 19:03:08 +01:00
islam e602024617 Remove dead code 2025-09-11 19:03:08 +01:00
islam deb464f5d8 Remove redundant .noise 2025-09-11 19:03:08 +01:00
islam e5a415d885 Overloading .debug/.error for ‘.logSecurityEvent’
Search/Replace Strategies:

1.
Search regex: `SecureLogger\.logSecurityEvent\(\s*(.*?),\s*level:\s*\.(\w+)\s*\)`
Replace regex: `SecureLogger.$2($1)`

Sample input:
`SecureLogger.logSecurityEvent(.authenticationFailed(peerID: peerID), level: .warning)`

Sample output:
`SecureLogger.warning(.authenticationFailed(peerID: peerID))`

---

2.
Search regex: `SecureLogger\.logSecurityEvent\(\s*(.*?)\s*\)`
Replace regex: `SecureLogger.info($1)`  (`info` is the default level)

Sample input:
`SecureLogger.logSecurityEvent(.handshakeStarted(peerID: peerID))`

Sample output:
`SecureLogger.info(.handshakeStarted(peerID: peerID))`
2025-09-11 19:03:08 +01:00
islam b5382b129e Rename logError(…) to error(…) 2025-09-11 19:03:08 +01:00
islam 5d6aecfc83 Replace .log w/ explicit .debug/.error functions
This would make the intention more explicit so we can overload different logging types as well like keychain, security events, etc…

Search/Replace Strategies:

1.
Search regex: `SecureLogger\.log\(\s*(.*?),\s*category:\s*(.*?),\s*level:\s*\.(\w+)\s*\)`
Replace regex: `SecureLogger.$3($1, category: $2)`

Sample input:
```
SecureLogger.log(
    "🔄 Found favorite for '\(peerInfo.nickname)' by nickname, updating noise key",
    category: .session,
    level: .debug
)
```

Sample output:
`SecureLogger.debug("🔄 Found favorite for '\(peerInfo.nickname)' by nickname, updating noise key", category: .session)`

---

2.
Search regex: `SecureLogger\.log\((.*?)\)`
Replace regex: `SecureLogger.debug($1)` (as it’s the default level)

Sample input:
`SecureLogger.log("some text")`

Sample output:
`SecureLogger.debug("some text")`

---

3
Manual changes:
ChatViewModel line 5393 (commented code)
NostrRelayManager line 196 (commented code)
NostrRelayManager lines 346-350 (if/else logic)
NostrRelayManager line 371 (commented code)
2025-09-11 19:03:08 +01:00
islam 5ca9222fc2 Make logging categories static properties of OSLog
So we can use `.<category name>` to simplify the code.

Search/Replace Strategy:
Search text: `category: SecureLogger.`
Replace text: `category: .`
2025-09-11 19:02:32 +01:00
jack ee16ff5ff4 Fix Nostr subscriptions: connect on subscribe; handle inbound frames correctly\n\n- Call ensureConnections(to:) in subscribe() so queued REQs open sockets immediately and flush after ping\n- Correct ParsedInbound failable initializer to return parsed EVENT/EOSE/OK/NOTICE instead of always nil\n- Improves chat receipt of geohash and DM events after Tor readiness 2025-09-11 19:53:19 +02:00
IslamandGitHub 2f83433247 Refactor parsing inbound messages (#577)
* DRY + helper extension to get data from Message

* Flatten guard > do > if > switch + use `try?`

* Use failable init instead of a global function
2025-09-11 19:18:06 +02:00
IslamandGitHub e72fe50ffa Perf: Add final to classes that are not inherited (#574) 2025-09-11 19:17:04 +02:00
IslamandGitHub 56f1c37129 Regenerate info.plist by adding the missing keys (#576)
`xcodegen` probably uses alphabetical sorting so had to commit the info.plist to avoid discrepancies
2025-09-11 19:14:27 +02:00
IslamandGitHub 2ade3a3300 Add TransportConfig to bitchatShareExtension target (#579)
ShareViewController uses TransportConfig and without this target membership the code doesn’t compile
2025-09-11 19:13:54 +02:00
5f44af19da tor by default, small (#564)
* feat(tor): Tor-by-default scaffold and integration

- Add TorManager with static/dlopen start, torrc generation, SOCKS probe
- Add TorURLSession; route Nostr/Web fetches via SOCKS proxy
- Add chat system messages for Tor status; show progress (macOS) and ready
- Disable ControlPort bootstrap monitor on iOS; keep it on macOS
- Make Tor waits non-blocking; avoid main-actor stalls on startup
- Queue & flush Nostr subscriptions on relay connect; skip duplicates
- Always rewrite torrc at launch to fix iOS container path mismatches
- Link libz; add project wiring for tor-nolzma.xcframework
- Minor fixes: SOCKS probe resumeOnce guard, entitlement for network.server (macOS)

* iOS: deterministic Tor recovery + 100% gating; BLE-first; session rebuild

- Restart/wake Tor on foreground via ControlPort (ACTIVE/SHUTDOWN),
  avoid restarts during bootstrap; add NWPathMonitor to trigger checks
- Use NWConnection control polling for GETINFO; remove blocking CFStream
  readers to avoid QoS inversions; compute readiness from SOCKS + 100%
- Rebuild TorURLSession on resume; reset Nostr connections to rebind
- Gate all internet after full bootstrap; keep BLE mesh startup fast
- Fix Swift 6 capture issues; hop UI updates to @MainActor
- Remove Tor progress spam; persist initial "starting tor..." system message

* UI: show Tor system messages only in geohash channels (not mesh)

- Gate "starting tor..." and readiness/timeout messages to geohash view
- Add helper addGeohashOnlySystemMessage() to avoid posting to mesh timeline
- Persist system messages in geohash backing store via addPublicSystemMessage()

* Relays: treat repeated -1011 handshake failures as permanent; skip reconnects

- Classify NSURLErrorBadServerResponse as permanent and stop retrying
- Filter permanently-failed relays from subscribe/connect attempts
- Avoid reconnect scheduling for permanently failed relays

* Embed Tor via tor_api; deterministic restart + Nostr gating; add Tor notifications

- Run Tor via tor_api in a dedicated thread with OwningControllerFD
- Cleanly stop Tor on background; restart on .active (single instance)
- Avoid fallback to tor_main/dlopen; add is-running check to prevent duplicates
- Fix argv lifetime in C glue to avoid strcmp crash on start
- Gate Nostr connect/subscribe/send until Tor is fully ready
- Rebuild URLSession + reset relays after Tor readiness (scene-based)
- Remove TorDidBecomeReady double-reset and appDidBecomeActive resubscribe
- Add TorWillRestart/TorDidBecomeReady notifications and chat system messages
- Debounce path-change restarts; ACTIVE poke first; coalesce subs; cancel stale reconnect timers
- Project: add CTorHost.c and TorNotifications.swift to targets; fix libz.tbd path

* Defer Nostr setup logs until Tor is ready; fix subscribe coalescing and reconnect generation

- Move "Connecting to Nostr relays" log after awaitReady()
- Log "Queuing subscription" when Tor not ready; only coalesce when handler exists
- Clear coalescer on unsubscribe
- Cancel stale reconnect timers using connectionGeneration
- Remove app-level TorDidBecomeReady reset to avoid duplicate reconnects
- Debounce path-change restarts

* Gate Nostr init/subscription logs until Tor is ready

- ChatViewModel: await Tor readiness before initializing Nostr and logging
- Only log GeoDM subscription when Tor is ready to avoid early noise

* Make Nostr connect single-sourced; defer DM subscription until connected

- Remove duplicate connect call from ChatViewModel; let scene-based flow connect
- Setup DM subscription once on first connection via  sink
- Reduce early subscription send/cancel noise after Tor restarts

* On launch, queue Nostr subscriptions without initiating connects; let centralized connect handle it

- In subscribe(), if no connections exist, just list relays and queue subs
- Avoids early send/cancel churn before connect() runs post-Tor-ready

* Always queue subscriptions and flush on connection; avoid immediate sends

- Prevents early send/cancel churn at launch and during reconnects
- If relays are already connected, flush immediately; otherwise pending until connected

* UI: scope Tor restart messages to geohash channels; skip initial foreground restart on cold launch to avoid confusing system message in #mesh

* geo: disable background sampling + notifications\n- Gate sampling to foreground only (beginGeohashSampling, watchers)\n- Suppress geohash activity notifications unless app is active\n- Stop sampling explicitly on background scene phase

* Update BitchatApp.swift

Co-authored-by: asmo <asmogo@protonmail.com>

* Update BitchatApp.swift

Co-authored-by: asmo <asmogo@protonmail.com>

* Update BitchatApp.swift

Co-authored-by: asmo <asmogo@protonmail.com>

* Update bitchat/BitchatApp.swift

Co-authored-by: asmo <asmogo@protonmail.com>

* Update bitchat/BitchatApp.swift

Co-authored-by: asmo <asmogo@protonmail.com>

* fix(iOS App): resolve merge artifacts in scenePhase handler\n- Remove duplicate didEnterBackground state\n- Fix switch/if braces and logic for foreground restart gating

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: asmo <asmogo@protonmail.com>
2025-09-11 19:08:43 +02:00
lollerfirstandGitHub 6e1fb15edf feat: weekly update bundled georelays (#524)
* update bundled georelays

* fix typo
2025-09-11 13:30:33 +02:00
IslamandGitHub 9166c9e28b Update iOS App Icon to the new single-size format (#573) 2025-09-11 11:15:57 +02:00
0ce68bc762 Perf/optimizations (#563)
* Perf: reduce hot‑path overhead (logger autoclosure, zero‑copy BinaryProtocol.decode, prealloc encoders)

* Compression: revert to zlib per request (compatibility)

* Nostr: parse inbound messages off-main, then update state on main; BLE: debounce peer snapshot publishing to reduce churn

* Fix: Swift 6 concurrency - avoid capturing self in detached tasks; deliver parsed Nostr messages via MainActor singleton

* Fix: move ParsedInbound + parseInboundMessage to file scope (non-isolated) to satisfy Swift 6; update detached tasks to call free function

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-09-06 12:47:32 +02:00
5273f13512 Fix critical routing and buffer issues\n\n- Preserve unsent items in MessageRouter outbox (no data loss)\n- Drain and bound Nostr send queue; flush on relay connect\n- Cap BLE pending write buffers per peripheral to avoid OOM\n- Enable Nostr fallback for short peer IDs via favorites mapping\n- Route favorite notifications via MessageRouter (mesh/Nostr) (#559)
Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-09-04 21:26:58 +02:00
e79bcf531b Feature/screenshot privacy warning (#541)
* Screenshot privacy: warn on location sheet; gate screenshot broadcasts to chat only\n\n- Track sheet presentation in ChatViewModel\n- Show privacy alert when screenshot taken on location channels\n- Ignore screenshots for App Info and Location sheet for broadcast\n- ContentView wires sheet onAppear/onDisappear and presents alert\n- Fix location sheet subtitle wrapping: render as single Text to avoid orphaned bullets

* Fix duplicate messages after channel switch\n\n- Dedup on per-geohash append (skip if ID exists)\n- Dedup and sort timeline by timestamp when switching into a geohash\n- Keep content/layout unchanged; add lightweight debug logs for empty rows

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-28 14:37:17 +02:00
jack 3e5043f875 Harden text formatting against Unicode range mismatches
- Use NSString.length for all NSRange regex scans
- Guard string slicing when lastEnd > match.lowerBound
- Advance lastEnd safely to avoid backtracking overlaps
- Apply to formatMessageContent, formatMessage, formatMessageAsText, parseMentions
v1.3.3
2025-08-28 09:22:34 +01:00
jack 11cd5527ed Fix crash in formatMessageAsText: use NSString length for NSRanges and guard slicing before matches to avoid invalid ranges with multi-byte content 2025-08-28 09:18:11 +01:00
cf1bfdac6b Geohash Bookmarks + Rising‑Edge Notifications + Friendly Names (#538)
* Add geohash bookmarks: persistence, sampling integration, and UI\n\n- Add GeohashBookmarksStore with UserDefaults persistence and toggle API\n- Sample union of regional + bookmarked geohashes for activity notifications\n- LocationChannelsSheet: bookmark icons on nearby rows and a Bookmarked section\n- Header toolbar: toggle bookmark for current geohash\n- Tests: GeohashBookmarksStoreTests for normalization and persistence\n\nRationale: Bookmarked geohashes are always sampled for new activity notifications and quickly selectable from the sheet.

* Notifications: remove background 'new chats!' nudge; geohash activity only on zero→alive; mesh 'nearby' only on zero→alive\n\n- Geohash sampling: notify only when previous participant count in last 5m was zero, with 30s freshness gate\n- Suppress old sampled events after (re)subscribe\n- Remove channel inactivity nudge\n- Mesh: reset rising-edge gate immediately when peer list goes empty (strict zero→alive)

* Geohash notifications: ensure triggering message appears\n\n- On zero→alive sampling, pre-populate geoTimelines[gh] with the triggering message\n- Dedup on per-geohash timeline and UI messages by message ID to avoid duplicates after subscribe\n- Keeps participant update, block/self checks, and cooldown intact

---------

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-28 09:10:15 +01:00
b63a595b04 Fix geohash UX: rising-edge notify, correct teleport, sort timeline (#537)
- Remove "new chats!" background nudge; notify only when a regional geohash goes from 0 participants to activity, with content preview and cooldown.\n- Do not mark teleported when selected geohash is in regional channel list; clear persisted teleport when in-region; avoid self teleported state from historical tags; deep links don’t mark teleported for regional geohashes or during cold start.\n- Sort per-geohash timelines chronologically on re-entry and trim whitespace-only content to prevent blank lines.\n- Trim inbound public content and ignore whitespace-only sends.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-28 00:08:01 +01:00
d7b7f1f673 UI: diversify peer colors; smarter geo notifications; 21m live location (#531)
- Use minimal-distance hue palette for mesh and geohash lists; align chat sender colors with list palette.
- Add foreground geo notifications for different channels; deep-link to bitchat://geohash/<gh>; per-geohash 60s cooldown; respect self/blocks.
- Global geohash sampling runs outside the sheet; delegate handles deeplinks and suppresses when already in-channel.
- Switch location channel sheet to continuous CoreLocation with 21m distance filter; add config knob.
- Only link geohash hashtags when standalone (no @name#abcd or word#abcd).
- Include mesh-reachable peers in mesh counts and in "bitchatters nearby" notification.
- Add TransportConfig knobs for palette and geo notifications.

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
2025-08-26 18:43:22 +02:00