50fe9a9d36
App móvil para validar pases QR contra base-admin-web con login Cognito, escáner en tiempo real, feedback auditivo/háptico y README completo.
72 lines
1.8 KiB
Dart
72 lines
1.8 KiB
Dart
import 'package:audioplayers/audioplayers.dart';
|
|
import 'package:flutter/services.dart';
|
|
import 'package:vibration/vibration.dart';
|
|
|
|
class FeedbackService {
|
|
FeedbackService() : _player = AudioPlayer() {
|
|
_player.setReleaseMode(ReleaseMode.stop);
|
|
}
|
|
|
|
final AudioPlayer _player;
|
|
|
|
Future<void> onCodeDetected() async {
|
|
await Future.wait([
|
|
_play('sounds/scan.wav'),
|
|
_vibratePattern(const [0, 40]),
|
|
]);
|
|
}
|
|
|
|
Future<void> onSuccess() async {
|
|
await Future.wait([
|
|
_play('sounds/success.wav'),
|
|
_vibratePattern(const [0, 90, 70, 140]),
|
|
]);
|
|
await HapticFeedback.heavyImpact();
|
|
}
|
|
|
|
Future<void> onWarning() async {
|
|
await Future.wait([
|
|
_play('sounds/warning.wav'),
|
|
_vibratePattern(const [0, 120, 80, 120, 80, 120]),
|
|
]);
|
|
await HapticFeedback.mediumImpact();
|
|
}
|
|
|
|
Future<void> _play(String asset) async {
|
|
try {
|
|
await _player.stop();
|
|
await _player.play(AssetSource(asset));
|
|
} catch (_) {
|
|
// Ignore audio errors on devices without speaker routing.
|
|
}
|
|
}
|
|
|
|
Future<void> _vibratePattern(List<int> pattern) async {
|
|
try {
|
|
final hasVibrator = await Vibration.hasVibrator();
|
|
if (hasVibrator != true) return;
|
|
|
|
final hasAmplitude = await Vibration.hasAmplitudeControl();
|
|
if (hasAmplitude == true) {
|
|
final intensities = pattern
|
|
.asMap()
|
|
.entries
|
|
.map((entry) => entry.key.isOdd ? 180 : 0)
|
|
.toList();
|
|
await Vibration.vibrate(
|
|
pattern: pattern,
|
|
intensities: intensities,
|
|
);
|
|
return;
|
|
}
|
|
|
|
await Vibration.vibrate(pattern: pattern);
|
|
} catch (_) {
|
|
await HapticFeedback.selectionClick();
|
|
}
|
|
}
|
|
|
|
Future<void> dispose() async {
|
|
await _player.dispose();
|
|
}
|
|
} |