tane/apps/app_seeds/lib/services/offer_outbox.dart
vjrj 08d8dc1172 feat(block2): offline outbox — share now, publish when connected
Sender-side offline delivery hardening.
- OfferOutbox: a keystore-backed (no plaintext) queue of lot ids to publish
  later. Stores ids, not offers, so on flush each offer is rebuilt from the
  lot's CURRENT state — an offline edit is respected, a deleted lot drops out.
- flushOutbox(): on reconnect, republishes queued lots and clears them (no-op
  offline; drops ids whose lot is gone).
- Market screen: sharing offline parks the lots ('we'll share these when you're
  connected'); opening the market online auto-flushes the queue first.
- Wired via DI + TaneApp(outbox); i18n en/es/pt.

Tests: 4 outbox + 3 flush + market UI, 20 green. Analyzer clean for new code.
2026-07-10 10:45:53 +02:00

37 lines
1.2 KiB
Dart

import '../security/secret_store.dart';
/// A durable "to publish when connected" queue of lot ids. When sharing is
/// attempted offline, the lot ids are parked here (keystore-backed, so no
/// plaintext at rest) and flushed once a relay is reachable — offline delivery
/// for the sender side.
///
/// We store lot ids, not serialized offers: on flush the offer is rebuilt from
/// the lot's current state, so an edit made while offline is respected and a
/// since-deleted lot simply drops out.
class OfferOutbox {
OfferOutbox(this._store);
final SecretStore _store;
static const _key = 'tane.social.outbox';
/// Lot ids waiting to be published.
Future<Set<String>> pending() async {
final raw = await _store.read(_key);
if (raw == null || raw.isEmpty) return <String>{};
return raw.split('\n').where((s) => s.isNotEmpty).toSet();
}
Future<void> enqueue(Iterable<String> lotIds) async {
final next = await pending()..addAll(lotIds);
await _write(next);
}
Future<void> remove(Iterable<String> lotIds) async {
final next = await pending()..removeAll(lotIds.toSet());
await _write(next);
}
Future<void> clear() => _store.write(_key, '');
Future<void> _write(Set<String> ids) => _store.write(_key, ids.join('\n'));
}