feat(market): one-time community-rules gate before joining the market, publishing or messaging
This commit is contained in:
parent
a7e10eba7a
commit
5d25f65f76
7 changed files with 311 additions and 1 deletions
138
apps/app_seeds/lib/ui/market_gate.dart
Normal file
138
apps/app_seeds/lib/ui/market_gate.dart
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
|
||||
import '../i18n/strings.g.dart';
|
||||
import '../services/onboarding_store.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.
|
||||
Future<bool> ensureMarketRulesAccepted(
|
||||
BuildContext context,
|
||||
OnboardingStore store,
|
||||
) async {
|
||||
if (await store.marketRulesAccepted()) return true;
|
||||
if (!context.mounted) return false;
|
||||
final accepted = await showModalBottomSheet<bool>(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
isDismissible: false,
|
||||
enableDrag: false,
|
||||
builder: (_) => const MarketGateSheet(),
|
||||
);
|
||||
if (accepted == true) {
|
||||
await store.markMarketRulesAccepted();
|
||||
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,
|
||||
),
|
||||
),
|
||||
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,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue