fix(market): search your zone by a coarse prefix, not the exact cell
Discovery searched the full 5-char geohash (~2.4 km) with an exact Nostr tag match, so two devices in adjacent cells never found each other even though publish emits the full NIP-52 prefix ladder. Search now coarsens the area to a configurable precision (SocialSettings.searchPrecision, default 4 ~20 km) via searchPrefix(), with a human-worded 'how far' selector (Very close / Around here / My region -> 5/4/3) in the market setup sheet. Also: surface a clear 'couldn't reach the servers' message when no relay accepts a share (instead of 'shared 0'), and add wss://relay.comunes.org as the first default relay (reliable community home; public relays are backup). Tests: settings precision (default/clamp/roundtrip), searchPrefix helper, neighbour-cell discovery regression (offers_cubit + commons_core nostr transports), and the range-selector widget test.
This commit is contained in:
parent
5dd0f243ce
commit
1af0282e00
16 changed files with 268 additions and 10 deletions
|
|
@ -6,6 +6,7 @@ import 'package:go_router/go_router.dart';
|
|||
import '../data/variety_repository.dart';
|
||||
import '../i18n/strings.g.dart';
|
||||
import '../services/coarse_location.dart';
|
||||
import '../services/discovery_area.dart';
|
||||
import '../services/offer_outbox.dart';
|
||||
import '../services/social_service.dart';
|
||||
import '../services/social_settings.dart';
|
||||
|
|
@ -81,7 +82,10 @@ class _MarketScreenState extends State<MarketScreen> {
|
|||
areaGeohash: area,
|
||||
);
|
||||
}
|
||||
if (mounted) await cubit.discover(area);
|
||||
if (mounted) {
|
||||
final precision = await widget.settings.searchPrecision();
|
||||
if (mounted) await cubit.discover(searchPrefix(area, precision));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -132,8 +136,14 @@ class _MarketScreenState extends State<MarketScreen> {
|
|||
);
|
||||
if (!mounted) return;
|
||||
await widget.outbox?.remove(ids); // published now, so unpark any duplicates
|
||||
messenger.showSnackBar(SnackBar(content: Text(t.market.sharedCount(n: count))));
|
||||
await cubit.discover(area); // refresh — now including the just-shared lots
|
||||
// count == 0 with lots to share means every relay refused — say so plainly
|
||||
// rather than "shared 0", which reads like success.
|
||||
messenger.showSnackBar(SnackBar(
|
||||
content: Text(count == 0 ? t.market.shareFailed : t.market.sharedCount(n: count)),
|
||||
));
|
||||
final precision = await widget.settings.searchPrecision();
|
||||
if (!mounted) return;
|
||||
await cubit.discover(searchPrefix(area, precision)); // refresh incl. just-shared
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
@ -527,6 +537,7 @@ class _ConfigSheetState extends State<_ConfigSheet> {
|
|||
bool _loading = true;
|
||||
bool _locationBusy = false;
|
||||
String? _locationError;
|
||||
int _precision = SocialSettings.defaultSearchPrecision;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
|
|
@ -537,12 +548,14 @@ class _ConfigSheetState extends State<_ConfigSheet> {
|
|||
Future<void> _load() async {
|
||||
_area.text = await widget.settings.areaGeohash();
|
||||
_servers.text = (await widget.settings.relayUrls()).join('\n');
|
||||
_precision = await widget.settings.searchPrecision();
|
||||
if (mounted) setState(() => _loading = false);
|
||||
}
|
||||
|
||||
Future<void> _save() async {
|
||||
await widget.settings.setAreaGeohash(_area.text);
|
||||
await widget.settings.setRelayUrls(_servers.text.split('\n'));
|
||||
await widget.settings.setSearchPrecision(_precision);
|
||||
if (mounted) Navigator.of(context).pop(true);
|
||||
}
|
||||
|
||||
|
|
@ -654,6 +667,27 @@ class _ConfigSheetState extends State<_ConfigSheet> {
|
|||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Align(
|
||||
alignment: AlignmentDirectional.centerStart,
|
||||
child: Text(
|
||||
t.market.rangeLabel,
|
||||
style: const TextStyle(fontSize: 13, color: seedMuted),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
SegmentedButton<int>(
|
||||
key: const Key('market.range'),
|
||||
segments: [
|
||||
ButtonSegment(value: 5, label: Text(t.market.rangeNear)),
|
||||
ButtonSegment(value: 4, label: Text(t.market.rangeArea)),
|
||||
ButtonSegment(value: 3, label: Text(t.market.rangeRegion)),
|
||||
],
|
||||
selected: {_precision},
|
||||
showSelectedIcon: false,
|
||||
onSelectionChanged: (s) =>
|
||||
setState(() => _precision = s.first),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Theme(
|
||||
data: Theme.of(context)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue