Skip to content

Commit 15b2e49

Browse files
committed
Completed initial work on voice assistant
1 parent 3456c21 commit 15b2e49

File tree

9 files changed

+296
-83
lines changed

9 files changed

+296
-83
lines changed

lib/features/communities/screens/health_screen.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ class WellnessScreen extends StatelessWidget {
152152
children: [
153153
SizedBox(
154154
height: 48,
155-
child: const Icon(Icons.chat_bubble,
155+
child: const Icon(Icons.mic,
156156
size: 48, color: Colors.white),
157157
),
158158
SizedBox(height: 16),

lib/features/posts/screens/chat_screen.dart

Lines changed: 150 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
import 'package:animate_do/animate_do.dart';
12
import 'package:femunity/features/posts/screens/feature_box.dart';
3+
import 'package:femunity/features/posts/screens/openai_service.dart';
24
import 'package:femunity/theme/pallate.dart';
35
import 'package:flutter/material.dart';
6+
import 'package:flutter_tts/flutter_tts.dart';
47
import 'package:speech_to_text/speech_recognition_result.dart';
58
import 'package:speech_to_text/speech_to_text.dart';
69

@@ -14,11 +17,23 @@ class ChatScreen extends StatefulWidget {
1417
class _ChatScreenState extends State<ChatScreen> {
1518
final speechToText = SpeechToText();
1619
String lastWords = '';
20+
final OpenAIService openAIService = OpenAIService();
21+
final flutterTts = FlutterTts();
22+
String? generatedContent;
23+
String? generatedImageUrl;
24+
int start = 200;
25+
int delay = 200;
1726

1827
@override
1928
void initState() {
2029
super.initState();
2130
initSpeechToText();
31+
initTextToSpeech();
32+
}
33+
34+
Future<void> initTextToSpeech() async {
35+
await flutterTts.setSharedInstance(true);
36+
setState(() {});
2237
}
2338

2439
Future<void> initSpeechToText() async {
@@ -48,121 +63,175 @@ class _ChatScreenState extends State<ChatScreen> {
4863
});
4964
}
5065

66+
Future<void> systemSpeak(String content) async {
67+
await flutterTts.speak(content);
68+
}
69+
5170
@override
5271
void dispose() {
5372
super.dispose();
5473
speechToText.stop();
74+
flutterTts.stop();
5575
}
5676

5777
@override
5878
Widget build(BuildContext context) {
5979
return Scaffold(
6080
appBar: AppBar(
61-
title: const Text('Sakhi'),
81+
title: Text('Sakhi'),
6282
),
6383
body: SingleChildScrollView(
6484
child: Column(
6585
children: [
66-
Stack(
67-
children: [
68-
Center(
69-
child: Container(
70-
height: 120,
71-
width: 120,
72-
margin: const EdgeInsets.only(top: 4),
86+
ZoomIn(
87+
child: Stack(
88+
children: [
89+
Center(
90+
child: Container(
91+
height: 120,
92+
width: 120,
93+
margin: const EdgeInsets.only(top: 4),
94+
decoration: BoxDecoration(
95+
color: Colors.black,
96+
shape: BoxShape.circle,
97+
),
98+
),
99+
),
100+
Container(
101+
height: 140,
73102
decoration: BoxDecoration(
74-
color: Colors.black,
75103
shape: BoxShape.circle,
104+
image: DecorationImage(
105+
image: AssetImage(
106+
"assets/images/sakhi.png",
107+
),
108+
),
76109
),
77110
),
78-
),
79-
Container(
80-
height: 140,
111+
],
112+
),
113+
),
114+
FadeInRight(
115+
child: Visibility(
116+
visible: generatedImageUrl == null,
117+
child: Container(
118+
padding: const EdgeInsets.symmetric(
119+
horizontal: 20,
120+
vertical: 10,
121+
),
122+
margin: const EdgeInsets.symmetric(horizontal: 40)
123+
.copyWith(top: 30),
81124
decoration: BoxDecoration(
82-
shape: BoxShape.circle,
83-
image: DecorationImage(
84-
image: AssetImage(
85-
"assets/images/sakhi.png",
125+
border: Border.all(color: Colors.white),
126+
borderRadius: BorderRadius.circular(20)
127+
.copyWith(topLeft: const Radius.circular(0)),
128+
),
129+
child: Padding(
130+
padding: const EdgeInsets.symmetric(vertical: 10.0),
131+
child: Text(
132+
generatedContent == null
133+
? "Hey! What's on your mind?"
134+
: generatedContent!,
135+
style: TextStyle(
136+
fontSize: generatedContent == null ? 20 : 15,
137+
fontFamily: 'Times New Roman',
86138
),
87139
),
88140
),
89141
),
90-
],
91-
),
92-
Container(
93-
padding: const EdgeInsets.symmetric(
94-
horizontal: 20,
95-
vertical: 10,
96142
),
97-
margin:
98-
const EdgeInsets.symmetric(horizontal: 40).copyWith(top: 30),
99-
decoration: BoxDecoration(
100-
border: Border.all(color: Colors.white),
101-
borderRadius: BorderRadius.circular(20)
102-
.copyWith(topLeft: const Radius.circular(0)),
143+
),
144+
if (generatedImageUrl != null)
145+
Padding(
146+
padding: const EdgeInsets.all(10.0),
147+
child: ClipRRect(
148+
borderRadius: BorderRadius.circular(20),
149+
child: Image.network(generatedImageUrl!)),
103150
),
104-
child: const Padding(
105-
padding: const EdgeInsets.symmetric(vertical: 10.0),
106-
child: Text(
107-
"Hey! What's on your mind?",
108-
style: TextStyle(
109-
fontSize: 20,
110-
fontFamily: 'Times New Roman',
151+
Visibility(
152+
visible: generatedContent == null && generatedImageUrl == null,
153+
child: Container(
154+
padding: const EdgeInsets.all(10),
155+
alignment: Alignment.centerLeft,
156+
margin: const EdgeInsets.only(
157+
top: 8,
158+
left: 10,
159+
),
160+
child: SlideInLeft(
161+
child: Text(
162+
"Here are a few features",
163+
style: TextStyle(
164+
fontFamily: "Times New Roman",
165+
fontSize: 18,
166+
fontWeight: FontWeight.bold,
167+
),
111168
),
112169
),
113170
),
114171
),
115-
Container(
116-
padding: const EdgeInsets.all(10),
117-
alignment: Alignment.centerLeft,
118-
margin: const EdgeInsets.only(
119-
top: 8,
120-
left: 10,
121-
),
122-
child: const Text(
123-
"Here are a few features",
124-
style: TextStyle(
125-
fontFamily: "Times New Roman",
126-
fontSize: 18,
127-
fontWeight: FontWeight.bold,
128-
),
172+
Visibility(
173+
visible: generatedContent == null && generatedImageUrl == null,
174+
child: Column(
175+
children: [
176+
SlideInLeft(
177+
delay: Duration(milliseconds: start),
178+
child: FeatureBox(
179+
color: Pallete.firstSuggestionBoxColor,
180+
headerText: 'Share your feelings',
181+
descriptionText:
182+
"Talk and interact with non-judgmental ears.",
183+
),
184+
),
185+
SlideInRight(
186+
delay: Duration(milliseconds: start + delay),
187+
child: FeatureBox(
188+
color: Pallete.secondSuggestionBoxColor,
189+
headerText: "headerText",
190+
descriptionText: "descriptionText",
191+
),
192+
),
193+
SlideInLeft(
194+
delay: Duration(milliseconds: start + 2 * delay),
195+
child: FeatureBox(
196+
color: Pallete.thirdSuggestionBoxColor,
197+
headerText: "headerText",
198+
descriptionText: "descriptionText",
199+
),
200+
),
201+
],
129202
),
130203
),
131-
Column(
132-
children: [
133-
FeatureBox(
134-
color: Pallete.firstSuggestionBoxColor,
135-
headerText: 'Share your feelings',
136-
descriptionText:
137-
"Talk and interact with non-judgmental ears.",
138-
),
139-
FeatureBox(
140-
color: Pallete.secondSuggestionBoxColor,
141-
headerText: "headerText",
142-
descriptionText: "descriptionText",
143-
),
144-
FeatureBox(
145-
color: Pallete.thirdSuggestionBoxColor,
146-
headerText: "headerText",
147-
descriptionText: "descriptionText",
148-
),
149-
],
150-
),
151204
],
152205
),
153206
),
154-
floatingActionButton: FloatingActionButton(
155-
backgroundColor: Colors.yellow,
156-
onPressed: () async {
157-
if (await speechToText.hasPermission && speechToText.isNotListening) {
158-
await startListening();
159-
} else if (speechToText.isListening) {
160-
await stopListening();
161-
} else {
162-
initSpeechToText();
163-
}
164-
},
165-
child: const Icon(Icons.mic),
207+
floatingActionButton: ZoomIn(
208+
delay: Duration(milliseconds: start + 3 * delay),
209+
child: FloatingActionButton(
210+
backgroundColor: Colors.yellow,
211+
onPressed: () async {
212+
if (await speechToText.hasPermission &&
213+
speechToText.isNotListening) {
214+
await startListening();
215+
} else if (speechToText.isListening) {
216+
final speech = await openAIService.isArtPromptAPI(lastWords);
217+
if (speech.contains('https')) {
218+
generatedImageUrl = speech;
219+
generatedContent = null;
220+
setState(() {});
221+
} else {
222+
generatedContent = speech;
223+
generatedImageUrl = null;
224+
setState(() {});
225+
await systemSpeak(speech);
226+
}
227+
228+
await stopListening();
229+
} else {
230+
initSpeechToText();
231+
}
232+
},
233+
child: Icon(speechToText.isListening ? Icons.stop : Icons.mic),
234+
),
166235
),
167236
);
168237
}

0 commit comments

Comments
 (0)