LineInkGuide/lib/settings_screens.dart

391 lines
12 KiB
Dart

import 'package:flutter/material.dart';
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher.dart';
import 'app_theme.dart';
import 'managers.dart';
import 'game_components.dart';
class SettingsScreen extends StatelessWidget {
const SettingsScreen({super.key});
static const _privacyUrl = 'https://example.com/privacy'; // TODO: replace
Future<void> _openPrivacy() async {
final uri = Uri.parse(_privacyUrl);
if (await canLaunchUrl(uri)) {
await launchUrl(uri, mode: LaunchMode.externalApplication);
}
}
void _shareGame() {
Share.share(
'Check out LineInkGuide! Draw lines and guide the ball to collect stars.',
subject: 'LineInkGuide',
);
}
void _showAbout(BuildContext context) {
showDialog(
context: context,
builder: (_) => AlertDialog(
backgroundColor: AppTheme.paperBg,
title: const Text('About'),
content: const Text(
'LineInkGuide\n\n'
'A notebook-style physics puzzle.\n'
'Draw ink lines, collect stars, and reach the goal basket.',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context),
child: const Text('OK'),
),
],
),
);
}
Future<void> _clearCache(BuildContext context) async {
final confirmed = await showDialog<bool>(
context: context,
builder: (_) => AlertDialog(
backgroundColor: AppTheme.paperBg,
title: const Text('Reset Progress'),
content: const Text(
'This will clear all level progress, stars and skins.\n'
'Are you sure?',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(context, false),
child: const Text('CANCEL'),
),
TextButton(
onPressed: () => Navigator.pop(context, true),
child: const Text('RESET'),
),
],
),
);
if (confirmed == true) {
await LevelManager.instance.clearAll();
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Progress cleared.'),
duration: Duration(seconds: 2),
),
);
}
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.paperBg,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
iconTheme: const IconThemeData(color: AppTheme.inkPrimary),
title: const Text(
'SETTINGS',
style: TextStyle(
color: AppTheme.inkPrimary,
fontWeight: FontWeight.bold,
),
),
),
body: Stack(
children: [
// subtle notebook grid background
Positioned.fill(child: CustomPaint(painter: GridPainter())),
SafeArea(
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'TUNE YOUR NOTEBOOK',
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
letterSpacing: 2,
color: AppTheme.inkPrimary,
),
),
const SizedBox(height: 12),
Expanded(
child: ListView(
children: [
// Game section
Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: AppTheme.inkPrimary,
width: 1.5,
),
),
child: Column(
children: [
_SectionHeader(title: 'GAME'),
_SettingsTile(
icon: Icons.share,
label: 'Share Game',
onTap: _shareGame,
),
const Divider(height: 1),
_SettingsTile(
icon: Icons.info_outline,
label: 'About',
onTap: () => _showAbout(context),
),
],
),
),
const SizedBox(height: 16),
// Privacy & support section
Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: AppTheme.inkPrimary,
width: 1.5,
),
),
child: Column(
children: [
_SectionHeader(title: 'SUPPORT'),
_SettingsTile(
icon: Icons.privacy_tip_outlined,
label: 'Privacy Policy',
onTap: _openPrivacy,
),
const Divider(height: 1),
_SettingsTile(
icon: Icons.feedback_outlined,
label: 'Feedback',
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) => const FeedbackScreen(),
),
);
},
),
],
),
),
const SizedBox(height: 16),
// Danger zone
Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: AppTheme.inkPrimary,
width: 1.5,
),
),
child: Column(
children: [
_SectionHeader(title: 'DATA'),
_SettingsTile(
icon: Icons.delete_sweep_outlined,
label: 'Clear Progress & Cache',
iconColor: Colors.redAccent,
labelColor: Colors.redAccent,
onTap: () => _clearCache(context),
),
],
),
),
],
),
),
],
),
),
),
],
),
);
}
}
class _SectionHeader extends StatelessWidget {
final String title;
const _SectionHeader({required this.title});
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
color: AppTheme.paperBg,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
child: Text(
title,
style: const TextStyle(
fontSize: 11,
fontWeight: FontWeight.bold,
letterSpacing: 2,
color: AppTheme.inkPrimary,
),
),
);
}
}
class _SettingsTile extends StatelessWidget {
final IconData icon;
final String label;
final VoidCallback onTap;
final Color? iconColor;
final Color? labelColor;
const _SettingsTile({
required this.icon,
required this.label,
required this.onTap,
this.iconColor,
this.labelColor,
});
@override
Widget build(BuildContext context) {
return ListTile(
leading: Container(
width: 32,
height: 32,
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(
color: iconColor ?? AppTheme.inkPrimary,
width: 1.5,
),
),
child: Icon(icon, size: 18, color: iconColor ?? AppTheme.inkPrimary),
),
title: Text(
label,
style: TextStyle(
fontWeight: FontWeight.w600,
color: labelColor ?? AppTheme.inkPrimary,
),
),
trailing: const Icon(Icons.chevron_right, color: AppTheme.gridLine),
onTap: onTap,
);
}
}
class FeedbackScreen extends StatefulWidget {
const FeedbackScreen({super.key});
@override
State<FeedbackScreen> createState() => _FeedbackScreenState();
}
class _FeedbackScreenState extends State<FeedbackScreen> {
final TextEditingController _controller = TextEditingController();
bool _submitting = false;
Future<void> _submit() async {
if (_controller.text.trim().isEmpty || _submitting) return;
setState(() {
_submitting = true;
});
await Future.delayed(const Duration(milliseconds: 500));
if (!mounted) return;
Navigator.pop(context);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: AppTheme.paperBg,
appBar: AppBar(
backgroundColor: Colors.transparent,
elevation: 0,
iconTheme: const IconThemeData(color: AppTheme.inkPrimary),
title: const Text(
'FEEDBACK',
style: TextStyle(
color: AppTheme.inkPrimary,
fontWeight: FontWeight.bold,
),
),
),
body: Padding(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
const Text(
'Tell us what you think:',
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: AppTheme.inkPrimary,
),
),
const SizedBox(height: 12),
Expanded(
child: TextField(
controller: _controller,
maxLines: null,
expands: true,
decoration: const InputDecoration(
hintText:
'Bugs, level ideas, or anything you want to share...',
border: OutlineInputBorder(),
filled: true,
fillColor: Colors.white,
),
),
),
const SizedBox(height: 16),
SizedBox(
height: 44,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.inkPrimary,
elevation: 0,
),
onPressed: _submitting ? null : _submit,
child: _submitting
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
valueColor: AlwaysStoppedAnimation<Color>(
Colors.white,
),
),
)
: const Text(
'SUBMIT',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
],
),
),
);
}
}