138 lines
4.2 KiB
Dart
138 lines
4.2 KiB
Dart
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,
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|