feat(divination): use DateTimePickerBottomSheet in auto_divination_screen
This commit is contained in:
@@ -7,21 +7,30 @@ import 'package:intl/intl.dart';
|
||||
import 'package:sensors_plus/sensors_plus.dart';
|
||||
import 'package:vibration/vibration.dart';
|
||||
|
||||
import '../../../../core/network/api_problem.dart';
|
||||
import '../../../../core/network/api_problem_mapper.dart';
|
||||
import '../../../../l10n/app_localizations.dart';
|
||||
import '../../../../shared/theme/app_color_palette.dart';
|
||||
import '../../../../shared/theme/design_tokens.dart';
|
||||
import '../../../../shared/widgets/divination/divination_shared_widgets.dart';
|
||||
import '../../../../shared/widgets/divination/divination_terms.dart';
|
||||
import '../../../../shared/widgets/divination/yao_legend.dart';
|
||||
import '../../../../shared/widgets/divination/yao_line_row.dart';
|
||||
import '../../../../shared/widgets/date_time_picker/date_time_picker_bottom_sheet.dart';
|
||||
import '../../../../shared/widgets/toast/toast.dart';
|
||||
import '../../../../shared/widgets/toast/toast_type.dart';
|
||||
import '../../data/models/divination_params.dart';
|
||||
import '../../data/services/divination_result_builder.dart';
|
||||
import '../../data/services/divination_run_service.dart';
|
||||
import 'divination_result_screen.dart';
|
||||
|
||||
class AutoDivinationScreen extends StatefulWidget {
|
||||
const AutoDivinationScreen({super.key, required this.params});
|
||||
const AutoDivinationScreen({
|
||||
super.key,
|
||||
required this.params,
|
||||
required this.runService,
|
||||
});
|
||||
|
||||
final DivinationParams params;
|
||||
final DivinationRunService runService;
|
||||
|
||||
@override
|
||||
State<AutoDivinationScreen> createState() => _AutoDivinationScreenState();
|
||||
@@ -29,7 +38,6 @@ class AutoDivinationScreen extends StatefulWidget {
|
||||
|
||||
class _AutoDivinationScreenState extends State<AutoDivinationScreen>
|
||||
with TickerProviderStateMixin {
|
||||
final DivinationResultBuilder _resultBuilder = DivinationResultBuilder();
|
||||
final Random _random = Random.secure();
|
||||
final List<YaoType> _yaoStates = List<YaoType>.filled(
|
||||
6,
|
||||
@@ -46,6 +54,7 @@ class _AutoDivinationScreenState extends State<AutoDivinationScreen>
|
||||
int _shakeCount = 0;
|
||||
DateTime _lastShake = DateTime.fromMillisecondsSinceEpoch(0);
|
||||
bool _spinLocked = false;
|
||||
bool _submitting = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -83,7 +92,6 @@ class _AutoDivinationScreenState extends State<AutoDivinationScreen>
|
||||
}
|
||||
|
||||
Widget _buildBody(BuildContext context, AppLocalizations l10n) {
|
||||
final palette = Theme.of(context).extension<AppColorPalette>()!;
|
||||
return SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(AppSpacing.xl),
|
||||
child: Column(
|
||||
@@ -109,15 +117,8 @@ class _AutoDivinationScreenState extends State<AutoDivinationScreen>
|
||||
_HexagramCard(yaoStates: _yaoStates),
|
||||
const SizedBox(height: AppSpacing.lg),
|
||||
_ResolveButton(
|
||||
enabled: _shakeCount >= 6,
|
||||
onPressed: _showMockPayload,
|
||||
),
|
||||
const SizedBox(height: AppSpacing.sm),
|
||||
Text(
|
||||
l10n.autoSimBalance(widget.params.coinBalance),
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodySmall?.copyWith(color: palette.warning),
|
||||
enabled: _shakeCount >= 6 && !_submitting,
|
||||
onPressed: _submitRun,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -206,42 +207,56 @@ class _AutoDivinationScreenState extends State<AutoDivinationScreen>
|
||||
}
|
||||
|
||||
Future<void> _pickTime() async {
|
||||
final date = await showDatePicker(
|
||||
final result = await showDateTimePickerBottomSheet(
|
||||
context: context,
|
||||
initialDate: _selectedTime,
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime(2100),
|
||||
initialDateTime: _selectedTime,
|
||||
minDateTime: DateTime(2000),
|
||||
maxDateTime: DateTime(2100),
|
||||
);
|
||||
if (date == null || !mounted) return;
|
||||
final time = await showTimePicker(
|
||||
context: context,
|
||||
initialTime: TimeOfDay.fromDateTime(_selectedTime),
|
||||
);
|
||||
if (time == null || !mounted) return;
|
||||
if (result == null || !mounted) return;
|
||||
setState(() {
|
||||
_selectedTime = DateTime(
|
||||
date.year,
|
||||
date.month,
|
||||
date.day,
|
||||
time.hour,
|
||||
time.minute,
|
||||
);
|
||||
_selectedTime = result;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _showMockPayload() async {
|
||||
final result = _resultBuilder.build(
|
||||
params: widget.params.copyWith(divinationTime: _selectedTime),
|
||||
yaoStates: _yaoStates,
|
||||
);
|
||||
if (!mounted) {
|
||||
return;
|
||||
Future<void> _submitRun() async {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
setState(() {
|
||||
_submitting = true;
|
||||
});
|
||||
try {
|
||||
final aggregate = await widget.runService.run(
|
||||
params: widget.params.copyWith(divinationTime: _selectedTime),
|
||||
yaoStates: _yaoStates,
|
||||
);
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => DivinationResultScreen(
|
||||
data: aggregate.toViewData(
|
||||
widget.params.copyWith(divinationTime: _selectedTime),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
final message = error is ApiProblem
|
||||
? mapApiProblemToMessage(error, l10n)
|
||||
: l10n.errorRequestGeneric;
|
||||
Toast.show(context, message, type: ToastType.error);
|
||||
} finally {
|
||||
if (!mounted) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_submitting = false;
|
||||
});
|
||||
}
|
||||
Navigator.of(context).push(
|
||||
MaterialPageRoute<void>(
|
||||
builder: (_) => DivinationResultScreen(data: result),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _vibrateStrong() async {
|
||||
@@ -325,7 +340,9 @@ class _TimeSelectorCard extends StatelessWidget {
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
DateFormat('yyyy年MM月dd日 HH:mm').format(selectedTime),
|
||||
DateFormat.yMd(
|
||||
Localizations.localeOf(context).toString(),
|
||||
).add_Hm().format(selectedTime),
|
||||
style: Theme.of(context).textTheme.titleMedium,
|
||||
),
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user