import '../security/secret_store.dart'; /// User choices for the (Block 2) social layer: the coarse area to publish/ /// browse offers in, and which community relays to talk to. Backed by the OS /// keystore (via [SecretStore]) to honour "no plaintext at rest" — no /// shared_preferences. /// /// Relays default to a small set of well-known public servers so the market /// works out of the box; the exposure is minimal (offers are opt-in and carry /// only a coarse geohash) and the user can swap them for a community server. /// The area stays unset until the user picks one (it's inherently personal). class SocialSettings { SocialSettings(this._store); final SecretStore _store; static const _areaKey = 'tane.social.area_geohash'; static const _relaysKey = 'tane.social.relays'; /// Community servers used automatically so sharing works from the first /// launch. The relay pool skips any that are unreachable, so a dead one never /// breaks the market; the user never has to know these exist. static const List defaultRelays = [ 'wss://nos.lol', 'wss://relay.damus.io', 'wss://relay.primal.net', ]; /// The user's coarse area as a low-precision geohash (may be empty). Set /// manually or from device location; the transport coarsens it further. Future areaGeohash() async => (await _store.read(_areaKey)) ?? ''; Future setAreaGeohash(String geohash) => _store.write(_areaKey, geohash.trim().toLowerCase()); /// The relays to talk to. When the user has never configured any, falls back /// to [defaultRelays]. Once they save a choice (even an empty one), that wins /// — so a privacy-minded user can turn the network off entirely. Future> relayUrls() async { final raw = await _store.read(_relaysKey); if (raw == null) return const [...defaultRelays]; // never configured return raw.split('\n').where((s) => s.trim().isNotEmpty).toList(); } Future setRelayUrls(List urls) => _store.write( _relaysKey, urls.map((u) => u.trim()).where((u) => u.isNotEmpty).join('\n'), ); /// Whether the social layer has enough config to attempt going online. Future get isConfigured async => (await relayUrls()).isNotEmpty && (await areaGeohash()).isNotEmpty; }