Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Speech Profile Page Improvements #971

Merged
merged 11 commits into from
Oct 8, 2024
258 changes: 136 additions & 122 deletions app/lib/pages/onboarding/speech_profile_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_provider_utilities/flutter_provider_utilities.dart';
import 'package:friend_private/backend/preferences.dart';
import 'package:friend_private/pages/speech_profile/percentage_bar_progress.dart';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The import of percentage_bar_progress.dart is new. Ensure that this file exists and is accessible from the current file's location. If it doesn't exist or isn't accessible, it will cause a compilation error.

+ import 'package:friend_private/pages/speech_profile/percentage_bar_progress.dart';

import 'package:friend_private/providers/capture_provider.dart';
import 'package:friend_private/providers/speech_profile_provider.dart';
import 'package:friend_private/widgets/dialog.dart';
Expand Down Expand Up @@ -138,6 +139,23 @@ class _SpeechProfileWidgetState extends State<SpeechProfileWidget> with TickerPr
),
barrierDismissible: false,
);
} else if (error == "NO_SPEECH") {
showDialog(
context: context,
builder: (c) => getDialog(
context,
() {
Navigator.pop(context);
// Navigator.pop(context);
},
() {},
'Are you there?',
'We could not detect any speech. Please make sure to speak for at least 10 seconds and not more than 3 minutes.',
okButtonText: 'Ok',
singleButton: true,
),
barrierDismissible: false,
);
Comment on lines +142 to +158
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The error handling for "NO_SPEECH" has been improved. The new dialog provides a clearer message to the user about what went wrong and how to fix it. However, consider using a constant or enum for the error string "NO_SPEECH" to avoid potential typos and improve maintainability.

- } else if (error == "NO_SPEECH") {
+ } else if (error == SpeechErrors.NO_SPEECH) {

}
},
child: Container(
Expand All @@ -148,17 +166,23 @@ class _SpeechProfileWidgetState extends State<SpeechProfileWidget> with TickerPr
height: 10,
),
Padding(
padding: const EdgeInsets.fromLTRB(40, 20, 40, 20),
padding: EdgeInsets.fromLTRB(40, !provider.startedRecording ? 20 : 0, 40, 20),
child: !provider.startedRecording
? const Text(
'Now, Omi needs to learn your voice to be able to recognise you.',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 20,
height: 1.4,
fontWeight: FontWeight.w400,
),
? const Column(
children: [
Text(
'Omi needs to learn your voice to recognize you',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 20,
height: 1.4,
fontWeight: FontWeight.w400,
),
),
SizedBox(height: 14),
Text("Note: This only works in English", style: TextStyle(color: Colors.white)),
],
Comment on lines +169 to +185
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The padding and text have been updated to provide more information to the user before they start recording. This is a good change as it improves the user experience by setting clear expectations. However, consider extracting the Column widget into a separate stateless widget for better readability and maintainability.

)
: LayoutBuilder(
builder: (context, constraints) {
Expand Down Expand Up @@ -200,128 +224,118 @@ class _SpeechProfileWidgetState extends State<SpeechProfileWidget> with TickerPr
},
),
),
Padding(
padding: const EdgeInsets.fromLTRB(24, 0, 24, 0),
child: !provider.startedRecording
? (provider.isInitialising
? const CircularProgressIndicator(
color: Colors.white,
)
: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(height: 20),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 0),
decoration: BoxDecoration(
border: const GradientBoxBorder(
gradient: LinearGradient(colors: [
Color.fromARGB(127, 208, 208, 208),
Color.fromARGB(127, 188, 99, 121),
Color.fromARGB(127, 86, 101, 182),
Color.fromARGB(127, 126, 190, 236)
]),
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
child: TextButton(
onPressed: () async {
await stopDeviceRecording();
await provider.initialise(finalizedCallback: restartDeviceRecording);
provider.forceCompletionTimer =
Timer(Duration(seconds: provider.maxDuration), () async {
provider.finalize();
});
provider.updateStartedRecording(true);
},
child: const Text(
'Get Started',
style: TextStyle(color: Colors.white, fontSize: 16),
),
!provider.startedRecording
? (provider.isInitialising
? const CircularProgressIndicator(
color: Colors.white,
)
: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(height: 20),
Container(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 0),
decoration: BoxDecoration(
border: const GradientBoxBorder(
gradient: LinearGradient(colors: [
Color.fromARGB(127, 208, 208, 208),
Color.fromARGB(127, 188, 99, 121),
Color.fromARGB(127, 86, 101, 182),
Color.fromARGB(127, 126, 190, 236)
]),
width: 2,
),
borderRadius: BorderRadius.circular(12),
),
const SizedBox(height: 10),
],
))
: provider.profileCompleted
? Container(
margin: const EdgeInsets.only(top: 40),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0),
decoration: BoxDecoration(
border: const GradientBoxBorder(
gradient: LinearGradient(colors: [
Color.fromARGB(127, 208, 208, 208),
Color.fromARGB(127, 188, 99, 121),
Color.fromARGB(127, 86, 101, 182),
Color.fromARGB(127, 126, 190, 236)
]),
width: 2,
child: TextButton(
onPressed: () async {
await stopDeviceRecording();
await provider.initialise(finalizedCallback: restartDeviceRecording);
provider.forceCompletionTimer =
Timer(Duration(seconds: provider.maxDuration), () async {
provider.finalize();
});
provider.updateStartedRecording(true);
},
child: const Text(
'Get Started',
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
borderRadius: BorderRadius.circular(12),
),
child: TextButton(
onPressed: () {
provider.close();
widget.goNext();
},
child: const Text(
"All done!",
style: TextStyle(color: Colors.white, fontSize: 16),
),
const SizedBox(height: 10),
],
))
: provider.profileCompleted
? Container(
margin: const EdgeInsets.only(top: 40),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 0),
decoration: BoxDecoration(
border: const GradientBoxBorder(
gradient: LinearGradient(colors: [
Color.fromARGB(127, 208, 208, 208),
Color.fromARGB(127, 188, 99, 121),
Color.fromARGB(127, 86, 101, 182),
Color.fromARGB(127, 126, 190, 236)
]),
width: 2,
),
)
: provider.uploadingProfile
? Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(
height: 24,
width: 24,
child: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
),
),
const SizedBox(width: 24),
Text(provider.loadingText,
style: const TextStyle(color: Colors.white, fontSize: 18)),
],
),
)
: Column(
mainAxisSize: MainAxisSize.min,
borderRadius: BorderRadius.circular(12),
),
child: TextButton(
onPressed: () {
widget.goNext();
},
child: const Text(
"All done!",
style: TextStyle(color: Colors.white, fontSize: 16),
),
),
)
: provider.uploadingProfile
? Padding(
padding: const EdgeInsets.only(top: 40.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 30),
Text(
provider.message,
style: TextStyle(color: Colors.grey.shade300, fontSize: 14, height: 1.4),
textAlign: TextAlign.center,
),
const SizedBox(height: 18),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Stack(
children: [
LinearProgressIndicator(
value: provider.percentageCompleted,
backgroundColor: Colors.grey.shade300,
valueColor: const AlwaysStoppedAnimation<Color>(Colors.deepPurple),
),
],
const SizedBox(
height: 24,
width: 24,
child: Center(
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
),
),
),
const SizedBox(height: 12),
Text(
'${(provider.percentageCompleted * 100).toInt()}%',
style: const TextStyle(color: Colors.white),
),
const SizedBox(width: 24),
Text(provider.loadingText,
style: const TextStyle(color: Colors.white, fontSize: 18)),
],
),
),
)
: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 20),
provider.percentageCompleted > 0
? const SizedBox()
: const Text(
"Introduce\nyourself",
style: TextStyle(color: Colors.white, fontSize: 24, height: 1.4),
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
SizedBox(
width: MediaQuery.sizeOf(context).width * 0.9,
child: ProgressBarWithPercentage(progressValue: provider.percentageCompleted)),
const SizedBox(height: 14),
Text(
provider.message,
style: TextStyle(color: Colors.grey.shade300, fontSize: 14, height: 1.4),
textAlign: TextAlign.center,
),
],
),
Comment on lines +227 to +338
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description Entelligence.AI

The logic for displaying different UI elements based on the state of the speech profile provider has been significantly refactored. The changes appear to be mostly related to UI layout and styling, with some minor adjustments to the logic. It's important to ensure that all possible states are handled correctly to avoid unexpected behavior. Consider breaking down this large block of code into smaller, more manageable functions or widgets to improve readability and maintainability.

(!provider.startedRecording)
? TextButton(
onPressed: () {
Expand Down
15 changes: 7 additions & 8 deletions app/lib/pages/onboarding/wrapper.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import 'package:friend_private/backend/schema/bt_device/bt_device.dart';
import 'package:friend_private/pages/home/page.dart';
import 'package:friend_private/pages/onboarding/auth.dart';
import 'package:friend_private/pages/onboarding/find_device/page.dart';
import 'package:friend_private/pages/onboarding/memory_created_widget.dart';
import 'package:friend_private/pages/onboarding/name/name_widget.dart';
import 'package:friend_private/pages/onboarding/permissions/permissions_widget.dart';
import 'package:friend_private/pages/onboarding/speech_profile_widget.dart';
Expand Down Expand Up @@ -36,7 +35,7 @@ class _OnboardingWrapperState extends State<OnboardingWrapper> with TickerProvid
@override
void initState() {
//TODO: Change from tab controller to default controller and use provider (part of instabug cleanup) @mdmohsin7
_controller = TabController(length: hasSpeechProfile ? 5 : 7, vsync: this);
_controller = TabController(length: hasSpeechProfile ? 5 : 6, vsync: this);
_controller!.addListener(() => setState(() {}));
WidgetsBinding.instance.addPostFrameCallback((_) async {
if (isSignedIn()) {
Expand Down Expand Up @@ -158,12 +157,12 @@ class _OnboardingWrapperState extends State<OnboardingWrapper> with TickerProvid
routeToPage(context, const HomePageWrapper(), replace: true);
},
),
MemoryCreatedWidget(
goNext: () {
// _goNext();
MixpanelManager().onboardingStepCompleted('Memory Created');
},
),
// MemoryCreatedWidget(
// goNext: () {
// // _goNext();
// MixpanelManager().onboardingStepCompleted('Memory Created');
// },
// ),
]);
}

Expand Down
Loading
Loading