feat: add sound and vibration feedback for registration actions
Integrate audioplayers, vibration, and file_picker packages to provide audio/haptic feedback on registration success/failure. Add sound settings UI in SettingsPage for customizing notification sounds. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:vibration/vibration.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:pad_scanner/services/scanner_service.dart';
|
||||
import 'package:pad_scanner/services/code_parser.dart';
|
||||
import 'package:pad_scanner/services/api_service.dart';
|
||||
import 'package:pad_scanner/services/sound_service.dart';
|
||||
import 'package:pad_scanner/pages/settings_page.dart';
|
||||
|
||||
class RegistrationPage extends StatefulWidget {
|
||||
@@ -15,6 +18,8 @@ class RegistrationPage extends StatefulWidget {
|
||||
class _RegistrationPageState extends State<RegistrationPage> {
|
||||
final _scannerService = ScannerService();
|
||||
final _apiService = ApiService();
|
||||
final _soundService = SoundService();
|
||||
final _focusNode = FocusNode();
|
||||
|
||||
final _zongpaiNos = <String>[];
|
||||
String? _locationCode;
|
||||
@@ -30,6 +35,23 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_scannerService.scanResults.listen(_onScan);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_focusNode.requestFocus();
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.dispose();
|
||||
_soundService.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onKeyEvent(KeyEvent event) {
|
||||
if (event is KeyDownEvent &&
|
||||
event.logicalKey == LogicalKeyboardKey.enter) {
|
||||
_submit();
|
||||
}
|
||||
}
|
||||
|
||||
void _onScan(ScanResult result) {
|
||||
@@ -137,6 +159,7 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
setState(() => _isSubmitting = false);
|
||||
|
||||
if (result.success) {
|
||||
_vibrateSuccess();
|
||||
setState(() {
|
||||
_zongpaiNos.remove(zongpaiNo);
|
||||
if (!_isLocked) {
|
||||
@@ -151,8 +174,10 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
if (mounted) setState(() => _successMessage = null);
|
||||
});
|
||||
} else if (result.isDuplicate) {
|
||||
_vibrateError();
|
||||
_showDuplicateDialog(zongpaiNo, result.duplicateInfo);
|
||||
} else {
|
||||
_vibrateError();
|
||||
_showFeedback(result.errorMessage ?? '提交失败', isError: true);
|
||||
}
|
||||
}
|
||||
@@ -193,12 +218,24 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
});
|
||||
|
||||
if (failed.isEmpty) {
|
||||
_vibrateSuccess();
|
||||
_showFeedback('批量上架成功($successCount 条)', isError: false);
|
||||
} else {
|
||||
_vibrateError();
|
||||
_showFeedback('成功 $successCount 条,失败 ${failed.length} 条', isError: true);
|
||||
}
|
||||
}
|
||||
|
||||
void _vibrateSuccess() {
|
||||
Vibration.vibrate(duration: 200);
|
||||
_soundService.playSuccess();
|
||||
}
|
||||
|
||||
void _vibrateError() {
|
||||
Vibration.vibrate(duration: 1000);
|
||||
_soundService.playFailure();
|
||||
}
|
||||
|
||||
void _showDuplicateDialog(String zongpaiNo, Map<String, dynamic>? info) {
|
||||
showDialog(
|
||||
context: context,
|
||||
@@ -266,8 +303,11 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
return KeyboardListener(
|
||||
focusNode: _focusNode,
|
||||
onKeyEvent: _onKeyEvent,
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('上架登记'),
|
||||
actions: [
|
||||
Padding(
|
||||
@@ -551,7 +591,7 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
: Text(
|
||||
_isLocked && _zongpaiNos.length > 1
|
||||
? '批量上架(${_zongpaiNos.length} 条)'
|
||||
: '确 认 上 架',
|
||||
: '确认上架(P1)',
|
||||
style: const TextStyle(fontSize: 18),
|
||||
),
|
||||
),
|
||||
@@ -593,6 +633,7 @@ class _RegistrationPageState extends State<RegistrationPage> {
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user