Record voice before selecting place
All checks were successful
Build and deploy Flutter Web / build (push) Successful in 1m46s

This commit is contained in:
Ruslan Bakiev
2026-05-09 16:56:15 +07:00
parent b93f7ec4ec
commit 35ccfe2368

View File

@@ -726,7 +726,7 @@ class _AddExperienceFlowState extends ConsumerState<AddExperienceFlow> {
final _recorder = AudioRecorder();
final _waveSamples = List<double>.filled(64, 0.04);
late final Future<List<PlaceRecommendation>> _nearbyPlacesFuture;
Future<List<PlaceRecommendation>>? _nearbyPlacesFuture;
Timer? _timer;
StreamSubscription<Uint8List>? _audioStreamSub;
var _step = 0;
@@ -734,12 +734,10 @@ class _AddExperienceFlowState extends ConsumerState<AddExperienceFlow> {
var _recording = false;
var _submitting = false;
var _micAllowed = true;
PlaceRecommendation? _selectedPlace;
@override
void initState() {
super.initState();
_nearbyPlacesFuture = _loadNearbyPlaces();
}
@override
@@ -851,19 +849,8 @@ class _AddExperienceFlowState extends ConsumerState<AddExperienceFlow> {
final controller = ref.read(placeControllerProvider.notifier);
final content = switch (_step) {
0 => _IntroStep(onNext: () => setState(() => _step = 1)),
1 => _PlaceStep(
placesFuture: _nearbyPlacesFuture,
radiusMeters: _nearbyPlaceRadiusMeters,
onSelect: (place) {
setState(() {
_selectedPlace = place;
_step = 2;
});
controller.setReviewPlace(place.name);
},
),
_ => _VoiceStep(
placeName: _selectedPlace?.name ?? '',
1 => _VoiceStep(
placeName: '',
hasTelegramAuth: widget.hasTelegramAuth,
seconds: _seconds,
minimumSeconds: _minimumVoiceSeconds,
@@ -875,16 +862,23 @@ class _AddExperienceFlowState extends ConsumerState<AddExperienceFlow> {
canContinue: widget.hasTelegramAuth && _seconds >= _minimumVoiceSeconds,
onToggleRecording: _toggleRecording,
onNext: () async {
final selectedPlace = _selectedPlace;
if (selectedPlace == null) {
return;
}
if (_recording) {
await _stopRecording();
}
setState(() {
_nearbyPlacesFuture = _loadNearbyPlaces();
_step = 2;
});
},
),
_ => _PlaceStep(
placesFuture: _nearbyPlacesFuture,
radiusMeters: _nearbyPlaceRadiusMeters,
isSubmitting: _submitting,
onSelect: (place) async {
setState(() => _submitting = true);
controller.setReviewPlace(selectedPlace.name);
await controller.publishReview(place: selectedPlace);
controller.setReviewPlace(place.name);
await controller.publishReview(place: place);
if (!context.mounted) {
return;
}
@@ -967,12 +961,14 @@ class _PlaceStep extends StatelessWidget {
const _PlaceStep({
required this.placesFuture,
required this.radiusMeters,
required this.isSubmitting,
required this.onSelect,
});
final Future<List<PlaceRecommendation>> placesFuture;
final Future<List<PlaceRecommendation>>? placesFuture;
final int radiusMeters;
final ValueChanged<PlaceRecommendation> onSelect;
final bool isSubmitting;
final Future<void> Function(PlaceRecommendation) onSelect;
@override
Widget build(BuildContext context) {
@@ -1021,7 +1017,7 @@ class _PlaceStep extends StatelessWidget {
itemBuilder: (context, index) {
final place = places[index];
return ListTile(
onTap: () => onSelect(place),
onTap: isSubmitting ? null : () => onSelect(place),
contentPadding: const EdgeInsets.symmetric(
horizontal: 14,
vertical: 8,
@@ -1083,16 +1079,18 @@ class _VoiceStep extends StatelessWidget {
return Column(
children: [
Text(
placeName.trim().isEmpty ? 'Место' : placeName.trim(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: Theme.of(
context,
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w900),
),
const SizedBox(height: 10),
if (placeName.trim().isNotEmpty) ...[
Text(
placeName.trim(),
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: Theme.of(
context,
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.w900),
),
const SizedBox(height: 10),
],
Expanded(
child: Center(
child: _VoiceWave(