feat(block2): profiles — your identity card + name/about (NIP-01 kind:0)

Drawer 'Profile' is now live.
- commons_core: ProfileTransport + UserProfile + NostrProfileTransport (kind:0
  publish/fetch), exposed as SocialSession.profile. Round-trip tested against the
  in-process relay (fast dart test).
- app: ProfileStore (local name/about, keystore) + ProfileScreen — shows your
  shareable npub with copy, edits display name + 'about', saves locally and (when
  online) publishes kind:0 so peers can recognise you instead of a raw key.
- Drawer 'Profile' -> /profile (gated like Market/Chat).
- i18n en/es/pt. ProfileStore + profile transport covered by plain/dart tests.

Analyzer clean (both packages).
This commit is contained in:
vjrj 2026-07-10 12:37:07 +02:00
parent 7f1c520960
commit 8ef587176f
19 changed files with 562 additions and 4 deletions

View file

@ -12,6 +12,7 @@ import 'services/coarse_location.dart';
import 'services/message_store.dart';
import 'services/offer_outbox.dart';
import 'services/onboarding_store.dart';
import 'services/profile_store.dart';
import 'services/social_service.dart';
import 'services/social_settings.dart';
import 'state/inventory_cubit.dart';
@ -24,6 +25,7 @@ import 'ui/home_screen.dart';
import 'ui/intro_screen.dart';
import 'ui/inventory_list_screen.dart';
import 'ui/market_screen.dart';
import 'ui/profile_screen.dart';
import 'ui/settings_screen.dart';
import 'ui/theme.dart';
import 'ui/variety_detail_screen.dart';
@ -41,6 +43,7 @@ class TaneApp extends StatelessWidget {
this.location,
this.outbox,
this.messageStore,
this.profileStore,
this.showIntro = false,
this.autoBackup,
super.key,
@ -53,6 +56,7 @@ class TaneApp extends StatelessWidget {
location,
outbox,
messageStore,
profileStore,
);
final VarietyRepository repository;
@ -72,6 +76,9 @@ class TaneApp extends StatelessWidget {
/// Optional persistence for chat history.
final MessageStore? messageStore;
/// Optional local store for your own profile (name/about).
final ProfileStore? profileStore;
final bool showIntro;
/// Drives silent periodic backups off the app lifecycle. Null in widget tests
@ -88,6 +95,7 @@ class TaneApp extends StatelessWidget {
CoarseLocationProvider? location,
OfferOutbox? outbox,
MessageStore? messageStore,
ProfileStore? profileStore,
) {
return GoRouter(
initialLocation: showIntro ? '/intro' : '/',
@ -112,6 +120,15 @@ class TaneApp extends StatelessWidget {
path: '/messages',
builder: (context, state) => ChatListScreen(store: messageStore),
),
if (social != null && socialSettings != null && profileStore != null)
GoRoute(
path: '/profile',
builder: (context, state) => ProfileScreen(
social: social,
settings: socialSettings,
profileStore: profileStore,
),
),
if (social != null && socialSettings != null)
GoRoute(
path: '/chat/:pubkey',