refactor(social): one shared relay connection per identity
Every feature (offers, messaging, trust, profile, the inbox listener) used to open its OWN RelayPool via social.openSession — several sockets to the same relays, more battery, and reconnection logic living only in the inbox listener. Add SocialConnection: ONE shared session per identity, lazily connected and reused by all. It watches connectivity — dropping the session when the network goes and reconnecting when it returns, announcing each change on a sessions stream so the inbox listener re-subscribes automatically. Callers get the session via connection.session() and never close it (the connection owns its lifecycle); recreated/disposed on an identity switch. - InboxService now consumes the shared connection (subscribes on its sessions stream) instead of owning its own socket + connectivity code. - createOffersCubit + the chat/market/profile screens use the shared connection; dead createMessagesCubit/createTrustCubit factories removed. - DI registers SocialConnection per identity; Bootstrap starts it (after the inbox subscribes); switchSocialAccount disposes + recreates it. Tests: SocialConnection lifecycle (reuse, concurrent connect, offline drop + reconnect, unreachable retry) with a fake opener + online stream; inbox test updated. nostr added as a dev_dependency for the channel fake.
This commit is contained in:
parent
e2b88b4f26
commit
bb4ee2fd89
19 changed files with 431 additions and 280 deletions
|
|
@ -19,6 +19,7 @@ import 'services/onboarding_store.dart';
|
|||
import 'services/profile_cache.dart';
|
||||
import 'services/profile_store.dart';
|
||||
import 'services/social_account_store.dart';
|
||||
import 'services/social_connection.dart';
|
||||
import 'services/social_service.dart';
|
||||
import 'services/social_settings.dart';
|
||||
import 'services/trust_referents.dart';
|
||||
|
|
@ -53,6 +54,9 @@ class _BootstrapState extends State<Bootstrap> {
|
|||
if (savedLocale != null) LocaleSettings.setLocaleSync(savedLocale);
|
||||
|
||||
final onboarding = getIt<OnboardingStore>();
|
||||
final connection = getIt.isRegistered<SocialConnection>()
|
||||
? getIt<SocialConnection>()
|
||||
: null;
|
||||
final inbox =
|
||||
getIt.isRegistered<InboxService>() ? getIt<InboxService>() : null;
|
||||
final notifications = getIt.isRegistered<NotificationService>()
|
||||
|
|
@ -61,9 +65,10 @@ class _BootstrapState extends State<Bootstrap> {
|
|||
// Ask for notification permission and set up the OS channel (no-op on
|
||||
// unsupported platforms). Done before the inbox starts listening.
|
||||
if (notifications != null) await notifications.initialize();
|
||||
// Listen for incoming private messages app-wide (foreground) so they arrive
|
||||
// and fill the inbox even before their chat is opened.
|
||||
if (inbox != null) unawaited(inbox.start());
|
||||
// Subscribe the inbox listener BEFORE the shared connection starts
|
||||
// connecting, so the first session is caught; then bring the connection up.
|
||||
inbox?.start();
|
||||
connection?.start();
|
||||
|
||||
return TaneApp(
|
||||
repository: getIt<VarietyRepository>(),
|
||||
|
|
@ -72,6 +77,7 @@ class _BootstrapState extends State<Bootstrap> {
|
|||
social:
|
||||
getIt.isRegistered<SocialService>() ? getIt<SocialService>() : null,
|
||||
socialSettings: getIt<SocialSettings>(),
|
||||
connection: connection,
|
||||
location: const GeolocatorCoarseLocation(),
|
||||
outbox: getIt<OfferOutbox>(),
|
||||
messageStore: getIt<MessageStore>(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue