Files
eryao/apps/lib/shared/widgets/divination/divination_shared_widgets.dart
T

186 lines
5.4 KiB
Dart
Raw Normal View History

2026-04-03 16:56:47 +08:00
import 'package:flutter/material.dart';
import '../../../l10n/app_localizations.dart';
import '../../theme/app_color_palette.dart';
import '../../theme/design_tokens.dart';
class DivinationGuideImage extends StatelessWidget {
const DivinationGuideImage({super.key, required this.paths});
2026-04-03 16:56:47 +08:00
final List<String> paths;
2026-04-03 16:56:47 +08:00
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.lg),
child: paths.length == 1
? Image.asset(paths.first, fit: BoxFit.contain)
: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Expanded(child: Image.asset(paths[0], fit: BoxFit.contain)),
const SizedBox(width: AppSpacing.md),
Expanded(child: Image.asset(paths[1], fit: BoxFit.contain)),
],
),
2026-04-03 16:56:47 +08:00
);
}
}
class DivinationInstructionCard extends StatelessWidget {
const DivinationInstructionCard({
super.key,
required this.text,
required this.onTap,
});
final String text;
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
final palette = Theme.of(context).extension<AppColorPalette>()!;
return InkWell(
onTap: onTap,
borderRadius: BorderRadius.circular(AppRadius.md),
child: Container(
width: double.infinity,
padding: const EdgeInsets.all(AppSpacing.md),
decoration: BoxDecoration(
color: palette.warningContainer,
borderRadius: BorderRadius.circular(AppRadius.md),
),
child: Row(
children: [
Expanded(
child: Text(
text,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: palette.warning,
fontWeight: FontWeight.w600,
),
),
),
const SizedBox(width: AppSpacing.sm),
Text(
'',
style: Theme.of(context).textTheme.bodyLarge?.copyWith(
color: palette.warning,
fontWeight: FontWeight.w700,
),
),
],
),
),
);
}
}
class DivinationGuideDialog extends StatefulWidget {
2026-04-03 16:56:47 +08:00
const DivinationGuideDialog({
super.key,
required this.title,
required this.guideImages,
required this.instructions,
2026-04-03 16:56:47 +08:00
});
final String title;
final List<List<String>> guideImages;
final List<String> instructions;
@override
State<DivinationGuideDialog> createState() => _DivinationGuideDialogState();
}
class _DivinationGuideDialogState extends State<DivinationGuideDialog> {
final PageController _pageController = PageController();
int _currentPage = 0;
bool get _isLastPage => _currentPage == widget.guideImages.length - 1;
@override
void dispose() {
_pageController.dispose();
super.dispose();
}
2026-04-03 16:56:47 +08:00
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final colors = Theme.of(context).colorScheme;
final swipeHint = _guideSwipeHint(Localizations.localeOf(context));
2026-04-03 16:56:47 +08:00
return Dialog(
child: SizedBox(
width: 360,
height: 560,
child: Column(
children: [
const SizedBox(height: AppSpacing.lg),
Text(
widget.title,
2026-04-03 16:56:47 +08:00
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Theme.of(context).colorScheme.primary,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: AppSpacing.md),
Expanded(
child: PageView.builder(
controller: _pageController,
onPageChanged: (index) {
setState(() {
_currentPage = index;
});
},
itemCount: widget.guideImages.length,
itemBuilder: (context, index) {
return DivinationGuideImage(paths: widget.guideImages[index]);
},
2026-04-03 16:56:47 +08:00
),
),
Padding(
padding: const EdgeInsets.all(AppSpacing.lg),
child: Text(
widget.instructions[_currentPage],
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
color: colors.onSurfaceVariant,
height: 1.45,
),
),
2026-04-03 16:56:47 +08:00
),
Padding(
padding: const EdgeInsets.fromLTRB(
AppSpacing.lg,
0,
AppSpacing.lg,
AppSpacing.lg,
),
child: SizedBox(
width: double.infinity,
child: FilledButton(
onPressed: _isLastPage
? () => Navigator.of(context).pop()
: null,
child: Text(
_isLastPage
? l10n.divinationIAcknowledge
: '${_currentPage + 1} / ${widget.guideImages.length} · $swipeHint',
),
2026-04-03 16:56:47 +08:00
),
),
),
],
),
),
);
}
String _guideSwipeHint(Locale locale) {
if (locale.languageCode == 'en') {
return 'Swipe left for the next step';
}
return '左滑查看下一步';
}
2026-04-03 16:56:47 +08:00
}