import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import '../i18n/strings.g.dart'; import '../services/onboarding_store.dart'; import '../services/sharing_switch.dart'; import 'theme.dart'; /// Makes sure the community rules have been accepted once before the user /// joins the market or publishes anything. Returns true when the rules are /// (or become) accepted; false when the user declines. Play/App Store UGC /// policies require this acceptance before content can be created. /// /// This is also where Tane goes online for the first time: agreeing here is the /// opt-in that turns [sharing] on. Keeping both in one step means there is a /// single moment where someone says yes, and it is a moment that explains /// itself — rather than a connection that happened at launch without asking. Future ensureMarketRulesAccepted( BuildContext context, OnboardingStore store, { SharingSwitch? sharing, }) async { if (await store.marketRulesAccepted()) { // Already agreed, but sharing may still be off (they turned it off in the // sharing setup, or agreed on a build that had no switch): honour the ask. if (sharing != null && !sharing.on.value) await sharing.enable(); return true; } if (!context.mounted) return false; final accepted = await showModalBottomSheet( context: context, isScrollControlled: true, isDismissible: false, enableDrag: false, builder: (_) => const MarketGateSheet(), ); if (accepted == true) { await store.markMarketRulesAccepted(); await sharing?.enable(); return true; } return false; } /// The one-time "before you join the market" sheet: the community rules in /// a few bullets, the publish-is-public note, and a link to the full texts. class MarketGateSheet extends StatelessWidget { const MarketGateSheet({super.key}); @override Widget build(BuildContext context) { final t = context.t; final theme = Theme.of(context); return SafeArea( child: SingleChildScrollView( padding: EdgeInsets.only( left: 20, right: 20, top: 24, bottom: 16 + MediaQuery.of(context).viewInsets.bottom, ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [ Text( t.marketGate.title, style: theme.textTheme.titleLarge?.copyWith( color: seedOnSurface, fontWeight: FontWeight.w600, ), ), const SizedBox(height: 12), Text( t.marketGate.intro, style: theme.textTheme.bodyMedium?.copyWith( color: seedOnSurface, height: 1.4, ), ), const SizedBox(height: 12), _Rule(t.marketGate.ruleHonest), _Rule(t.marketGate.ruleLegal), _Rule(t.marketGate.ruleRespect), const SizedBox(height: 12), Text( t.marketGate.publicNote, style: theme.textTheme.bodySmall?.copyWith( color: seedMuted, height: 1.4, ), ), const SizedBox(height: 8), Text( t.marketGate.networkNote, style: theme.textTheme.bodySmall?.copyWith( color: seedMuted, height: 1.4, ), ), TextButton.icon( style: TextButton.styleFrom( padding: EdgeInsets.zero, foregroundColor: seedGreen, ), icon: const Icon(Icons.privacy_tip_outlined, size: 16), label: Text(t.marketGate.viewLegal), onPressed: () => context.push('/legal'), ), const SizedBox(height: 8), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ TextButton( onPressed: () => Navigator.of(context).pop(false), child: Text(t.marketGate.decline), ), const SizedBox(width: 8), FilledButton( onPressed: () => Navigator.of(context).pop(true), child: Text(t.marketGate.accept), ), ], ), ], ), ), ); } } class _Rule extends StatelessWidget { const _Rule(this.text); final String text; @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsetsDirectional.only(bottom: 8), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Icon(Icons.check_circle_outline, size: 18, color: seedGreen), const SizedBox(width: 8), Expanded( child: Text( text, style: Theme.of(context).textTheme.bodyMedium?.copyWith( color: seedOnSurface, height: 1.35, ), ), ), ], ), ); } }