Merge branch 'spike/block2-derisking'
This commit is contained in:
commit
8a55034118
12 changed files with 131 additions and 66 deletions
|
|
@ -344,12 +344,12 @@
|
||||||
"near": "Near you",
|
"near": "Near you",
|
||||||
"contact": "Message",
|
"contact": "Message",
|
||||||
"configTitle": "Sharing setup",
|
"configTitle": "Sharing setup",
|
||||||
"setupIntro": "Sharing with people nearby is optional. To turn it on, set your rough area and join a community you trust — a seed network or collective that runs a shared meeting point for passing messages. No company in the middle.",
|
"setupIntro": "Sharing with people nearby is optional. Just set your rough area — you're already connected to shared community servers so people can find what you offer, with no company in the middle. You can change the servers below.",
|
||||||
"areaLabel": "Your area",
|
"areaLabel": "Your area",
|
||||||
"areaHelp": "Kept rough on purpose — your zone, never an exact spot.",
|
"areaHelp": "Kept rough on purpose — your zone, never an exact spot.",
|
||||||
"serversAdvanced": "Join a community (advanced)",
|
"serversLabel": "Community servers",
|
||||||
"serversHelp": "Your seed network or collective gives you a web address to connect to. Paste one per line. Leave empty if you don't have one yet.",
|
"serversHelp": "Pick one or more shared servers. Anyone can use them — or add your own community's below.",
|
||||||
"serversLabel": "Web address",
|
"serversAdvanced": "Add another server",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"saved": "Saved",
|
"saved": "Saved",
|
||||||
"wanted": "Wanted",
|
"wanted": "Wanted",
|
||||||
|
|
|
||||||
|
|
@ -344,12 +344,12 @@
|
||||||
"near": "Cerca de ti",
|
"near": "Cerca de ti",
|
||||||
"contact": "Mensaje",
|
"contact": "Mensaje",
|
||||||
"configTitle": "Configuración de compartir",
|
"configTitle": "Configuración de compartir",
|
||||||
"setupIntro": "Compartir con gente cercana es opcional. Para activarlo, indica tu zona aproximada y únete a una comunidad de confianza — una red de semillas o un colectivo que mantiene un punto de encuentro compartido para pasar mensajes. Sin ninguna empresa en medio.",
|
"setupIntro": "Compartir con gente cercana es opcional. Solo indica tu zona aproximada — ya estás conectado a servidores comunitarios compartidos para que otras personas encuentren lo que ofreces, sin ninguna empresa en medio. Puedes cambiar los servidores abajo.",
|
||||||
"areaLabel": "Tu zona",
|
"areaLabel": "Tu zona",
|
||||||
"areaHelp": "Se mantiene aproximado a propósito — tu zona, nunca un punto exacto.",
|
"areaHelp": "Se mantiene aproximado a propósito — tu zona, nunca un punto exacto.",
|
||||||
"serversAdvanced": "Unirse a una comunidad (avanzado)",
|
"serversLabel": "Servidores de la comunidad",
|
||||||
"serversHelp": "Tu red de semillas o colectivo te da una dirección web para conectarte. Pega una por línea. Déjalo vacío si aún no tienes ninguna.",
|
"serversHelp": "Elige uno o más servidores compartidos. Cualquiera puede usarlos — o añade abajo el de tu comunidad.",
|
||||||
"serversLabel": "Dirección web",
|
"serversAdvanced": "Añadir otro servidor",
|
||||||
"save": "Guardar",
|
"save": "Guardar",
|
||||||
"saved": "Guardado",
|
"saved": "Guardado",
|
||||||
"wanted": "Busco",
|
"wanted": "Busco",
|
||||||
|
|
|
||||||
|
|
@ -340,12 +340,12 @@
|
||||||
"near": "Perto de ti",
|
"near": "Perto de ti",
|
||||||
"contact": "Mensagem",
|
"contact": "Mensagem",
|
||||||
"configTitle": "Configuração de partilha",
|
"configTitle": "Configuração de partilha",
|
||||||
"setupIntro": "Partilhar com pessoas por perto é opcional. Para ativar, indica a tua zona aproximada e junta-te a uma comunidade de confiança — uma rede de sementes ou um coletivo que mantém um ponto de encontro partilhado para passar mensagens. Sem nenhuma empresa no meio.",
|
"setupIntro": "Partilhar com pessoas por perto é opcional. Basta indicar a tua zona aproximada — já estás ligado a servidores comunitários partilhados para que outras pessoas encontrem o que ofereces, sem nenhuma empresa no meio. Podes mudar os servidores abaixo.",
|
||||||
"areaLabel": "A tua zona",
|
"areaLabel": "A tua zona",
|
||||||
"areaHelp": "Mantém-se aproximado de propósito — a tua zona, nunca um ponto exato.",
|
"areaHelp": "Mantém-se aproximado de propósito — a tua zona, nunca um ponto exato.",
|
||||||
"serversAdvanced": "Juntar-te a uma comunidade (avançado)",
|
"serversLabel": "Servidores da comunidade",
|
||||||
"serversHelp": "A tua rede de sementes ou coletivo dá-te um endereço web para te ligares. Cola um por linha. Deixa vazio se ainda não tiveres nenhum.",
|
"serversHelp": "Escolhe um ou mais servidores partilhados. Qualquer pessoa os pode usar — ou adiciona abaixo o da tua comunidade.",
|
||||||
"serversLabel": "Endereço web",
|
"serversAdvanced": "Adicionar outro servidor",
|
||||||
"save": "Guardar",
|
"save": "Guardar",
|
||||||
"saved": "Guardado",
|
"saved": "Guardado",
|
||||||
"wanted": "Procuro",
|
"wanted": "Procuro",
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
/// Locales: 3
|
/// Locales: 3
|
||||||
/// Strings: 986 (328 per locale)
|
/// Strings: 986 (328 per locale)
|
||||||
///
|
///
|
||||||
/// Built on 2026-07-10 at 09:08 UTC
|
/// Built on 2026-07-10 at 09:19 UTC
|
||||||
|
|
||||||
// coverage:ignore-file
|
// coverage:ignore-file
|
||||||
// ignore_for_file: type=lint, unused_import
|
// ignore_for_file: type=lint, unused_import
|
||||||
|
|
|
||||||
|
|
@ -1093,8 +1093,8 @@ class Translations$market$en {
|
||||||
/// en: 'Sharing setup'
|
/// en: 'Sharing setup'
|
||||||
String get configTitle => 'Sharing setup';
|
String get configTitle => 'Sharing setup';
|
||||||
|
|
||||||
/// en: 'Sharing with people nearby is optional. To turn it on, set your rough area and join a community you trust — a seed network or collective that runs a shared meeting point for passing messages. No company in the middle.'
|
/// en: 'Sharing with people nearby is optional. Just set your rough area — you're already connected to shared community servers so people can find what you offer, with no company in the middle. You can change the servers below.'
|
||||||
String get setupIntro => 'Sharing with people nearby is optional. To turn it on, set your rough area and join a community you trust — a seed network or collective that runs a shared meeting point for passing messages. No company in the middle.';
|
String get setupIntro => 'Sharing with people nearby is optional. Just set your rough area — you\'re already connected to shared community servers so people can find what you offer, with no company in the middle. You can change the servers below.';
|
||||||
|
|
||||||
/// en: 'Your area'
|
/// en: 'Your area'
|
||||||
String get areaLabel => 'Your area';
|
String get areaLabel => 'Your area';
|
||||||
|
|
@ -1102,14 +1102,14 @@ class Translations$market$en {
|
||||||
/// en: 'Kept rough on purpose — your zone, never an exact spot.'
|
/// en: 'Kept rough on purpose — your zone, never an exact spot.'
|
||||||
String get areaHelp => 'Kept rough on purpose — your zone, never an exact spot.';
|
String get areaHelp => 'Kept rough on purpose — your zone, never an exact spot.';
|
||||||
|
|
||||||
/// en: 'Join a community (advanced)'
|
/// en: 'Community servers'
|
||||||
String get serversAdvanced => 'Join a community (advanced)';
|
String get serversLabel => 'Community servers';
|
||||||
|
|
||||||
/// en: 'Your seed network or collective gives you a web address to connect to. Paste one per line. Leave empty if you don't have one yet.'
|
/// en: 'Pick one or more shared servers. Anyone can use them — or add your own community's below.'
|
||||||
String get serversHelp => 'Your seed network or collective gives you a web address to connect to. Paste one per line. Leave empty if you don\'t have one yet.';
|
String get serversHelp => 'Pick one or more shared servers. Anyone can use them — or add your own community\'s below.';
|
||||||
|
|
||||||
/// en: 'Web address'
|
/// en: 'Add another server'
|
||||||
String get serversLabel => 'Web address';
|
String get serversAdvanced => 'Add another server';
|
||||||
|
|
||||||
/// en: 'Save'
|
/// en: 'Save'
|
||||||
String get save => 'Save';
|
String get save => 'Save';
|
||||||
|
|
@ -1947,12 +1947,12 @@ extension on Translations {
|
||||||
'market.near' => 'Near you',
|
'market.near' => 'Near you',
|
||||||
'market.contact' => 'Message',
|
'market.contact' => 'Message',
|
||||||
'market.configTitle' => 'Sharing setup',
|
'market.configTitle' => 'Sharing setup',
|
||||||
'market.setupIntro' => 'Sharing with people nearby is optional. To turn it on, set your rough area and join a community you trust — a seed network or collective that runs a shared meeting point for passing messages. No company in the middle.',
|
'market.setupIntro' => 'Sharing with people nearby is optional. Just set your rough area — you\'re already connected to shared community servers so people can find what you offer, with no company in the middle. You can change the servers below.',
|
||||||
'market.areaLabel' => 'Your area',
|
'market.areaLabel' => 'Your area',
|
||||||
'market.areaHelp' => 'Kept rough on purpose — your zone, never an exact spot.',
|
'market.areaHelp' => 'Kept rough on purpose — your zone, never an exact spot.',
|
||||||
'market.serversAdvanced' => 'Join a community (advanced)',
|
'market.serversLabel' => 'Community servers',
|
||||||
'market.serversHelp' => 'Your seed network or collective gives you a web address to connect to. Paste one per line. Leave empty if you don\'t have one yet.',
|
'market.serversHelp' => 'Pick one or more shared servers. Anyone can use them — or add your own community\'s below.',
|
||||||
'market.serversLabel' => 'Web address',
|
'market.serversAdvanced' => 'Add another server',
|
||||||
'market.save' => 'Save',
|
'market.save' => 'Save',
|
||||||
'market.saved' => 'Saved',
|
'market.saved' => 'Saved',
|
||||||
'market.wanted' => 'Wanted',
|
'market.wanted' => 'Wanted',
|
||||||
|
|
|
||||||
|
|
@ -616,12 +616,12 @@ class _Translations$market$es extends Translations$market$en {
|
||||||
@override String get near => 'Cerca de ti';
|
@override String get near => 'Cerca de ti';
|
||||||
@override String get contact => 'Mensaje';
|
@override String get contact => 'Mensaje';
|
||||||
@override String get configTitle => 'Configuración de compartir';
|
@override String get configTitle => 'Configuración de compartir';
|
||||||
@override String get setupIntro => 'Compartir con gente cercana es opcional. Para activarlo, indica tu zona aproximada y únete a una comunidad de confianza — una red de semillas o un colectivo que mantiene un punto de encuentro compartido para pasar mensajes. Sin ninguna empresa en medio.';
|
@override String get setupIntro => 'Compartir con gente cercana es opcional. Solo indica tu zona aproximada — ya estás conectado a servidores comunitarios compartidos para que otras personas encuentren lo que ofreces, sin ninguna empresa en medio. Puedes cambiar los servidores abajo.';
|
||||||
@override String get areaLabel => 'Tu zona';
|
@override String get areaLabel => 'Tu zona';
|
||||||
@override String get areaHelp => 'Se mantiene aproximado a propósito — tu zona, nunca un punto exacto.';
|
@override String get areaHelp => 'Se mantiene aproximado a propósito — tu zona, nunca un punto exacto.';
|
||||||
@override String get serversAdvanced => 'Unirse a una comunidad (avanzado)';
|
@override String get serversLabel => 'Servidores de la comunidad';
|
||||||
@override String get serversHelp => 'Tu red de semillas o colectivo te da una dirección web para conectarte. Pega una por línea. Déjalo vacío si aún no tienes ninguna.';
|
@override String get serversHelp => 'Elige uno o más servidores compartidos. Cualquiera puede usarlos — o añade abajo el de tu comunidad.';
|
||||||
@override String get serversLabel => 'Dirección web';
|
@override String get serversAdvanced => 'Añadir otro servidor';
|
||||||
@override String get save => 'Guardar';
|
@override String get save => 'Guardar';
|
||||||
@override String get saved => 'Guardado';
|
@override String get saved => 'Guardado';
|
||||||
@override String get wanted => 'Busco';
|
@override String get wanted => 'Busco';
|
||||||
|
|
@ -1307,12 +1307,12 @@ extension on TranslationsEs {
|
||||||
'market.near' => 'Cerca de ti',
|
'market.near' => 'Cerca de ti',
|
||||||
'market.contact' => 'Mensaje',
|
'market.contact' => 'Mensaje',
|
||||||
'market.configTitle' => 'Configuración de compartir',
|
'market.configTitle' => 'Configuración de compartir',
|
||||||
'market.setupIntro' => 'Compartir con gente cercana es opcional. Para activarlo, indica tu zona aproximada y únete a una comunidad de confianza — una red de semillas o un colectivo que mantiene un punto de encuentro compartido para pasar mensajes. Sin ninguna empresa en medio.',
|
'market.setupIntro' => 'Compartir con gente cercana es opcional. Solo indica tu zona aproximada — ya estás conectado a servidores comunitarios compartidos para que otras personas encuentren lo que ofreces, sin ninguna empresa en medio. Puedes cambiar los servidores abajo.',
|
||||||
'market.areaLabel' => 'Tu zona',
|
'market.areaLabel' => 'Tu zona',
|
||||||
'market.areaHelp' => 'Se mantiene aproximado a propósito — tu zona, nunca un punto exacto.',
|
'market.areaHelp' => 'Se mantiene aproximado a propósito — tu zona, nunca un punto exacto.',
|
||||||
'market.serversAdvanced' => 'Unirse a una comunidad (avanzado)',
|
'market.serversLabel' => 'Servidores de la comunidad',
|
||||||
'market.serversHelp' => 'Tu red de semillas o colectivo te da una dirección web para conectarte. Pega una por línea. Déjalo vacío si aún no tienes ninguna.',
|
'market.serversHelp' => 'Elige uno o más servidores compartidos. Cualquiera puede usarlos — o añade abajo el de tu comunidad.',
|
||||||
'market.serversLabel' => 'Dirección web',
|
'market.serversAdvanced' => 'Añadir otro servidor',
|
||||||
'market.save' => 'Guardar',
|
'market.save' => 'Guardar',
|
||||||
'market.saved' => 'Guardado',
|
'market.saved' => 'Guardado',
|
||||||
'market.wanted' => 'Busco',
|
'market.wanted' => 'Busco',
|
||||||
|
|
|
||||||
|
|
@ -612,12 +612,12 @@ class _Translations$market$pt extends Translations$market$en {
|
||||||
@override String get near => 'Perto de ti';
|
@override String get near => 'Perto de ti';
|
||||||
@override String get contact => 'Mensagem';
|
@override String get contact => 'Mensagem';
|
||||||
@override String get configTitle => 'Configuração de partilha';
|
@override String get configTitle => 'Configuração de partilha';
|
||||||
@override String get setupIntro => 'Partilhar com pessoas por perto é opcional. Para ativar, indica a tua zona aproximada e junta-te a uma comunidade de confiança — uma rede de sementes ou um coletivo que mantém um ponto de encontro partilhado para passar mensagens. Sem nenhuma empresa no meio.';
|
@override String get setupIntro => 'Partilhar com pessoas por perto é opcional. Basta indicar a tua zona aproximada — já estás ligado a servidores comunitários partilhados para que outras pessoas encontrem o que ofereces, sem nenhuma empresa no meio. Podes mudar os servidores abaixo.';
|
||||||
@override String get areaLabel => 'A tua zona';
|
@override String get areaLabel => 'A tua zona';
|
||||||
@override String get areaHelp => 'Mantém-se aproximado de propósito — a tua zona, nunca um ponto exato.';
|
@override String get areaHelp => 'Mantém-se aproximado de propósito — a tua zona, nunca um ponto exato.';
|
||||||
@override String get serversAdvanced => 'Juntar-te a uma comunidade (avançado)';
|
@override String get serversLabel => 'Servidores da comunidade';
|
||||||
@override String get serversHelp => 'A tua rede de sementes ou coletivo dá-te um endereço web para te ligares. Cola um por linha. Deixa vazio se ainda não tiveres nenhum.';
|
@override String get serversHelp => 'Escolhe um ou mais servidores partilhados. Qualquer pessoa os pode usar — ou adiciona abaixo o da tua comunidade.';
|
||||||
@override String get serversLabel => 'Endereço web';
|
@override String get serversAdvanced => 'Adicionar outro servidor';
|
||||||
@override String get save => 'Guardar';
|
@override String get save => 'Guardar';
|
||||||
@override String get saved => 'Guardado';
|
@override String get saved => 'Guardado';
|
||||||
@override String get wanted => 'Procuro';
|
@override String get wanted => 'Procuro';
|
||||||
|
|
@ -1299,12 +1299,12 @@ extension on TranslationsPt {
|
||||||
'market.near' => 'Perto de ti',
|
'market.near' => 'Perto de ti',
|
||||||
'market.contact' => 'Mensagem',
|
'market.contact' => 'Mensagem',
|
||||||
'market.configTitle' => 'Configuração de partilha',
|
'market.configTitle' => 'Configuração de partilha',
|
||||||
'market.setupIntro' => 'Partilhar com pessoas por perto é opcional. Para ativar, indica a tua zona aproximada e junta-te a uma comunidade de confiança — uma rede de sementes ou um coletivo que mantém um ponto de encontro partilhado para passar mensagens. Sem nenhuma empresa no meio.',
|
'market.setupIntro' => 'Partilhar com pessoas por perto é opcional. Basta indicar a tua zona aproximada — já estás ligado a servidores comunitários partilhados para que outras pessoas encontrem o que ofereces, sem nenhuma empresa no meio. Podes mudar os servidores abaixo.',
|
||||||
'market.areaLabel' => 'A tua zona',
|
'market.areaLabel' => 'A tua zona',
|
||||||
'market.areaHelp' => 'Mantém-se aproximado de propósito — a tua zona, nunca um ponto exato.',
|
'market.areaHelp' => 'Mantém-se aproximado de propósito — a tua zona, nunca um ponto exato.',
|
||||||
'market.serversAdvanced' => 'Juntar-te a uma comunidade (avançado)',
|
'market.serversLabel' => 'Servidores da comunidade',
|
||||||
'market.serversHelp' => 'A tua rede de sementes ou coletivo dá-te um endereço web para te ligares. Cola um por linha. Deixa vazio se ainda não tiveres nenhum.',
|
'market.serversHelp' => 'Escolhe um ou mais servidores partilhados. Qualquer pessoa os pode usar — ou adiciona abaixo o da tua comunidade.',
|
||||||
'market.serversLabel' => 'Endereço web',
|
'market.serversAdvanced' => 'Adicionar outro servidor',
|
||||||
'market.save' => 'Guardar',
|
'market.save' => 'Guardar',
|
||||||
'market.saved' => 'Guardado',
|
'market.saved' => 'Guardado',
|
||||||
'market.wanted' => 'Procuro',
|
'market.wanted' => 'Procuro',
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,21 @@
|
||||||
import '../security/secret_store.dart';
|
import '../security/secret_store.dart';
|
||||||
|
|
||||||
|
/// A suggested community server the user can join with one tap.
|
||||||
|
class RelayPreset {
|
||||||
|
const RelayPreset(this.name, this.url);
|
||||||
|
final String name;
|
||||||
|
final String url;
|
||||||
|
}
|
||||||
|
|
||||||
/// User choices for the (Block 2) social layer: the coarse area to publish/
|
/// 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
|
/// browse offers in, and which community relays to talk to. Backed by the OS
|
||||||
/// keystore (via [SecretStore]) to honour "no plaintext at rest" — no
|
/// keystore (via [SecretStore]) to honour "no plaintext at rest" — no
|
||||||
/// shared_preferences.
|
/// shared_preferences.
|
||||||
///
|
///
|
||||||
/// Both default to "unset": empty area and no relays mean the social layer is
|
/// Relays default to a small set of well-known public servers so the market
|
||||||
/// simply unavailable, and the app stays fully usable offline.
|
/// 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 {
|
class SocialSettings {
|
||||||
SocialSettings(this._store);
|
SocialSettings(this._store);
|
||||||
|
|
||||||
|
|
@ -15,6 +24,17 @@ class SocialSettings {
|
||||||
static const _areaKey = 'tane.social.area_geohash';
|
static const _areaKey = 'tane.social.area_geohash';
|
||||||
static const _relaysKey = 'tane.social.relays';
|
static const _relaysKey = 'tane.social.relays';
|
||||||
|
|
||||||
|
/// Suggested servers shown as one-tap options in the sharing setup.
|
||||||
|
static const List<RelayPreset> presets = [
|
||||||
|
RelayPreset('nos.lol', 'wss://nos.lol'),
|
||||||
|
RelayPreset('Damus', 'wss://relay.damus.io'),
|
||||||
|
RelayPreset('Primal', 'wss://relay.primal.net'),
|
||||||
|
];
|
||||||
|
|
||||||
|
/// Applied automatically for new users (a subset of [presets]) so sharing
|
||||||
|
/// works from the first launch, until the user changes it.
|
||||||
|
static const List<String> defaultRelays = ['wss://nos.lol', 'wss://relay.damus.io'];
|
||||||
|
|
||||||
/// The user's coarse area as a low-precision geohash (may be empty). Set
|
/// The user's coarse area as a low-precision geohash (may be empty). Set
|
||||||
/// manually or from device location; the transport coarsens it further.
|
/// manually or from device location; the transport coarsens it further.
|
||||||
Future<String> areaGeohash() async => (await _store.read(_areaKey)) ?? '';
|
Future<String> areaGeohash() async => (await _store.read(_areaKey)) ?? '';
|
||||||
|
|
@ -22,11 +42,12 @@ class SocialSettings {
|
||||||
Future<void> setAreaGeohash(String geohash) =>
|
Future<void> setAreaGeohash(String geohash) =>
|
||||||
_store.write(_areaKey, geohash.trim().toLowerCase());
|
_store.write(_areaKey, geohash.trim().toLowerCase());
|
||||||
|
|
||||||
/// Configured community relay URLs (empty by default — the user adds their
|
/// The relays to talk to. When the user has never configured any, falls back
|
||||||
/// own; we bundle none, to avoid leaking metadata to third-party relays).
|
/// 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<List<String>> relayUrls() async {
|
Future<List<String>> relayUrls() async {
|
||||||
final raw = await _store.read(_relaysKey);
|
final raw = await _store.read(_relaysKey);
|
||||||
if (raw == null || raw.isEmpty) return const [];
|
if (raw == null) return const [...defaultRelays]; // never configured
|
||||||
return raw.split('\n').where((s) => s.trim().isNotEmpty).toList();
|
return raw.split('\n').where((s) => s.trim().isNotEmpty).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -409,6 +409,7 @@ class _ConfigSheet extends StatefulWidget {
|
||||||
class _ConfigSheetState extends State<_ConfigSheet> {
|
class _ConfigSheetState extends State<_ConfigSheet> {
|
||||||
final _area = TextEditingController();
|
final _area = TextEditingController();
|
||||||
final _servers = TextEditingController();
|
final _servers = TextEditingController();
|
||||||
|
final Set<String> _selectedRelays = {};
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
bool _locationBusy = false;
|
bool _locationBusy = false;
|
||||||
String? _locationError;
|
String? _locationError;
|
||||||
|
|
@ -421,13 +422,22 @@ class _ConfigSheetState extends State<_ConfigSheet> {
|
||||||
|
|
||||||
Future<void> _load() async {
|
Future<void> _load() async {
|
||||||
_area.text = await widget.settings.areaGeohash();
|
_area.text = await widget.settings.areaGeohash();
|
||||||
_servers.text = (await widget.settings.relayUrls()).join('\n');
|
final current = await widget.settings.relayUrls();
|
||||||
|
final presetUrls = SocialSettings.presets.map((p) => p.url).toSet();
|
||||||
|
_selectedRelays
|
||||||
|
..clear()
|
||||||
|
..addAll(current.where(presetUrls.contains));
|
||||||
|
// Any relays that aren't presets go in the "add another" field.
|
||||||
|
_servers.text = current.where((u) => !presetUrls.contains(u)).join('\n');
|
||||||
if (mounted) setState(() => _loading = false);
|
if (mounted) setState(() => _loading = false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _save() async {
|
Future<void> _save() async {
|
||||||
await widget.settings.setAreaGeohash(_area.text);
|
await widget.settings.setAreaGeohash(_area.text);
|
||||||
await widget.settings.setRelayUrls(_servers.text.split('\n'));
|
await widget.settings.setRelayUrls([
|
||||||
|
..._selectedRelays,
|
||||||
|
..._servers.text.split('\n'),
|
||||||
|
]);
|
||||||
if (mounted) Navigator.of(context).pop(true);
|
if (mounted) Navigator.of(context).pop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -523,9 +533,40 @@ class _ConfigSheetState extends State<_ConfigSheet> {
|
||||||
style: const TextStyle(color: Color(0xFFB3261E), fontSize: 12),
|
style: const TextStyle(color: Color(0xFFB3261E), fontSize: 12),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 16),
|
||||||
// The technical web address lives under progressive disclosure —
|
// Pick from a short list of shared servers — pre-selected so it
|
||||||
// most people won't have one, and jargon shouldn't greet them.
|
// works out of the box; no jargon-y blank field to puzzle over.
|
||||||
|
Text(
|
||||||
|
t.market.serversLabel,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: seedOnSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
t.market.serversHelp,
|
||||||
|
style: const TextStyle(color: seedMuted, fontSize: 12, height: 1.3),
|
||||||
|
),
|
||||||
|
for (final preset in SocialSettings.presets)
|
||||||
|
CheckboxListTile(
|
||||||
|
key: Key('market.relay.${preset.name}'),
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
dense: true,
|
||||||
|
controlAffinity: ListTileControlAffinity.leading,
|
||||||
|
value: _selectedRelays.contains(preset.url),
|
||||||
|
title: Text(preset.name),
|
||||||
|
subtitle: Text(preset.url,
|
||||||
|
style: const TextStyle(fontSize: 11, color: seedMuted)),
|
||||||
|
onChanged: (checked) => setState(() {
|
||||||
|
if (checked ?? false) {
|
||||||
|
_selectedRelays.add(preset.url);
|
||||||
|
} else {
|
||||||
|
_selectedRelays.remove(preset.url);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
// A rarely-needed escape hatch for a community's own server.
|
||||||
Theme(
|
Theme(
|
||||||
data: Theme.of(context)
|
data: Theme.of(context)
|
||||||
.copyWith(dividerColor: Colors.transparent),
|
.copyWith(dividerColor: Colors.transparent),
|
||||||
|
|
@ -535,21 +576,16 @@ class _ConfigSheetState extends State<_ConfigSheet> {
|
||||||
childrenPadding: const EdgeInsets.only(bottom: 8),
|
childrenPadding: const EdgeInsets.only(bottom: 8),
|
||||||
title: Text(
|
title: Text(
|
||||||
t.market.serversAdvanced,
|
t.market.serversAdvanced,
|
||||||
style: const TextStyle(
|
style: const TextStyle(fontSize: 13, color: seedMuted),
|
||||||
fontSize: 14,
|
|
||||||
color: seedOnSurface,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
TextField(
|
TextField(
|
||||||
key: const Key('market.servers'),
|
key: const Key('market.servers'),
|
||||||
controller: _servers,
|
controller: _servers,
|
||||||
minLines: 2,
|
minLines: 1,
|
||||||
maxLines: 4,
|
maxLines: 3,
|
||||||
decoration: InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: t.market.serversLabel,
|
hintText: 'wss://…',
|
||||||
helperText: t.market.serversHelp,
|
|
||||||
helperMaxLines: 4,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -15,12 +15,18 @@ void main() {
|
||||||
late SocialSettings settings;
|
late SocialSettings settings;
|
||||||
setUp(() => settings = SocialSettings(FakeSecretStore()));
|
setUp(() => settings = SocialSettings(FakeSecretStore()));
|
||||||
|
|
||||||
test('defaults: empty area, no relays, not configured', () async {
|
test('defaults: empty area, but relays fall back to the defaults', () async {
|
||||||
expect(await settings.areaGeohash(), '');
|
expect(await settings.areaGeohash(), '');
|
||||||
expect(await settings.relayUrls(), isEmpty);
|
expect(await settings.relayUrls(), SocialSettings.defaultRelays);
|
||||||
|
// Not configured yet: the area is still unset.
|
||||||
expect(await settings.isConfigured, isFalse);
|
expect(await settings.isConfigured, isFalse);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('an explicitly empty relay choice turns the network off', () async {
|
||||||
|
await settings.setRelayUrls(const []);
|
||||||
|
expect(await settings.relayUrls(), isEmpty);
|
||||||
|
});
|
||||||
|
|
||||||
test('stores and normalises the area geohash (trim + lowercase)', () async {
|
test('stores and normalises the area geohash (trim + lowercase)', () async {
|
||||||
await settings.setAreaGeohash(' SP3E9 ');
|
await settings.setAreaGeohash(' SP3E9 ');
|
||||||
expect(await settings.areaGeohash(), 'sp3e9');
|
expect(await settings.areaGeohash(), 'sp3e9');
|
||||||
|
|
@ -36,10 +42,9 @@ void main() {
|
||||||
['wss://relay.comunes.org', 'wss://seeds.example.org']);
|
['wss://relay.comunes.org', 'wss://seeds.example.org']);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('is configured only with both an area and at least one relay', () async {
|
test('is configured once an area is set (relays are defaulted)', () async {
|
||||||
|
expect(await settings.isConfigured, isFalse); // no area yet
|
||||||
await settings.setAreaGeohash('sp3e9');
|
await settings.setAreaGeohash('sp3e9');
|
||||||
expect(await settings.isConfigured, isFalse);
|
|
||||||
await settings.setRelayUrls(['wss://relay.comunes.org']);
|
|
||||||
expect(await settings.isConfigured, isTrue);
|
expect(await settings.isConfigured, isTrue);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ void main() {
|
||||||
(tester) async {
|
(tester) async {
|
||||||
final social = await SocialService.fromRootSeedHex('00' * 32);
|
final social = await SocialService.fromRootSeedHex('00' * 32);
|
||||||
final settings = SocialSettings(InMemorySecretStore());
|
final settings = SocialSettings(InMemorySecretStore());
|
||||||
|
await settings.setRelayUrls(const []); // offline: don't hit the network
|
||||||
LocaleSettings.setLocaleSync(AppLocale.en);
|
LocaleSettings.setLocaleSync(AppLocale.en);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ void main() {
|
||||||
(tester) async {
|
(tester) async {
|
||||||
final social = await SocialService.fromRootSeedHex('00' * 32);
|
final social = await SocialService.fromRootSeedHex('00' * 32);
|
||||||
final settings = SocialSettings(InMemorySecretStore());
|
final settings = SocialSettings(InMemorySecretStore());
|
||||||
|
await settings.setRelayUrls(const []); // offline: don't hit the network
|
||||||
LocaleSettings.setLocaleSync(AppLocale.en);
|
LocaleSettings.setLocaleSync(AppLocale.en);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
|
|
@ -136,6 +137,7 @@ void main() {
|
||||||
(tester) async {
|
(tester) async {
|
||||||
final social = await SocialService.fromRootSeedHex('00' * 32);
|
final social = await SocialService.fromRootSeedHex('00' * 32);
|
||||||
final settings = SocialSettings(InMemorySecretStore());
|
final settings = SocialSettings(InMemorySecretStore());
|
||||||
|
await settings.setRelayUrls(const []); // offline: don't hit the network
|
||||||
LocaleSettings.setLocaleSync(AppLocale.en);
|
LocaleSettings.setLocaleSync(AppLocale.en);
|
||||||
|
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue