Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
F
flutter-chat
Project
Project
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
Graph
比较
统计图
议题
0
议题
0
列表
看板
标记
Milestones
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
songchuancai
flutter-chat
Commits
130ed14a
提交
130ed14a
authored
11月 07, 2024
作者:
songchuancai
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
优化语音输入和文本输入功能
上级
7c6edfa7
隐藏空白字符变更
内嵌
并排
正在显示
1 个修改的文件
包含
151 行增加
和
112 行删除
+151
-112
home_page.dart
lib/home_page.dart
+151
-112
没有找到文件。
lib/home_page.dart
浏览文件 @
130ed14a
...
...
@@ -39,6 +39,9 @@ class _HomePageState extends State<HomePage> {
String
currentStreamedContent
=
''
;
final
List
<
ChatMessage
>
messages
=
[];
bool
_isLoading
=
false
;
bool
_isVoiceMode
=
true
;
bool
_isListeningPressed
=
false
;
String
_currentVoiceText
=
''
;
@override
void
initState
()
{
...
...
@@ -72,17 +75,8 @@ class _HomePageState extends State<HomePage> {
Future
<
void
>
onSpeechResult
(
SpeechRecognitionResult
result
)
async
{
setState
(()
{
lastWords
=
result
.
recognizedWords
;
_
isLoading
=
true
;
_
currentVoiceText
=
result
.
recognizedWords
;
});
if
(
lastWords
.
isNotEmpty
)
{
setState
(()
{
messages
.
add
(
ChatMessage
(
text:
lastWords
,
isUserMessage:
true
,
));
});
}
}
Future
<
void
>
systemSpeak
(
String
content
)
async
{
...
...
@@ -148,6 +142,42 @@ class _HomePageState extends State<HomePage> {
}
}
Future
<
void
>
_processAIResponse
(
String
userInput
)
async
{
try
{
String
fullResponse
=
''
;
bool
isFirstChunk
=
true
;
await
for
(
final
chunk
in
openAIService
.
chatGPTAPI
(
userInput
))
{
setState
(()
{
fullResponse
+=
chunk
;
if
(
isFirstChunk
)
{
messages
.
add
(
ChatMessage
(
text:
fullResponse
,
isUserMessage:
false
,
));
isFirstChunk
=
false
;
}
else
{
messages
.
last
=
ChatMessage
(
text:
fullResponse
,
isUserMessage:
false
,
);
}
});
}
await
systemSpeak
(
fullResponse
);
}
catch
(
e
)
{
setState
(()
{
messages
.
add
(
ChatMessage
(
text:
'抱歉,出现了一些错误:
$e
'
,
isUserMessage:
false
,
));
});
}
finally
{
setState
(()
{
_isLoading
=
false
;
});
}
}
@override
void
dispose
()
{
super
.
dispose
();
...
...
@@ -156,6 +186,116 @@ class _HomePageState extends State<HomePage> {
_messageController
.
dispose
();
}
Widget
_buildBottomInput
()
{
return
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
boxShadow:
[
BoxShadow
(
color:
Colors
.
grey
.
withOpacity
(
0.1
),
spreadRadius:
1
,
blurRadius:
3
,
offset:
const
Offset
(
0
,
-
1
),
),
],
),
child:
Row
(
children:
[
Expanded
(
child:
_isVoiceMode
?
GestureDetector
(
onLongPressStart:
(
_
)
async
{
setState
(()
{
_isListeningPressed
=
true
;
_currentVoiceText
=
''
;
});
await
startListening
();
},
onLongPressEnd:
(
_
)
async
{
setState
(()
=>
_isListeningPressed
=
false
);
await
stopListening
();
final
finalVoiceText
=
_currentVoiceText
;
if
(
finalVoiceText
.
isNotEmpty
)
{
setState
(()
{
messages
.
add
(
ChatMessage
(
text:
finalVoiceText
,
isUserMessage:
true
,
));
_isLoading
=
true
;
});
await
_processAIResponse
(
finalVoiceText
);
}
setState
(()
{
_currentVoiceText
=
''
;
});
},
child:
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
vertical:
10
,
),
decoration:
BoxDecoration
(
color:
Colors
.
grey
[
100
],
borderRadius:
BorderRadius
.
circular
(
25
),
),
child:
Text
(
_isListeningPressed
?
(
_currentVoiceText
.
isEmpty
?
'正在聆听...'
:
_currentVoiceText
)
:
'按住说话'
,
textAlign:
TextAlign
.
center
,
style:
TextStyle
(
color:
_isListeningPressed
?
Pallete
.
firstSuggestionBoxColor
:
Colors
.
grey
[
600
],
),
),
),
)
:
TextField
(
controller:
_messageController
,
decoration:
InputDecoration
(
hintText:
'输入消息...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
25
),
borderSide:
BorderSide
.
none
,
),
filled:
true
,
fillColor:
Colors
.
grey
[
100
],
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
vertical:
10
,
),
),
),
),
const
SizedBox
(
width:
8
),
IconButton
(
icon:
Icon
(
_isVoiceMode
?
Icons
.
keyboard
:
Icons
.
mic
,
color:
Pallete
.
firstSuggestionBoxColor
,
),
onPressed:
()
{
setState
(()
=>
_isVoiceMode
=
!
_isVoiceMode
);
},
),
if
(!
_isVoiceMode
)
IconButton
(
icon:
const
Icon
(
Icons
.
send
,
color:
Pallete
.
firstSuggestionBoxColor
,
),
onPressed:
_sendMessage
,
),
],
),
);
}
@override
Widget
build
(
BuildContext
context
)
{
return
Scaffold
(
...
...
@@ -291,110 +431,9 @@ class _HomePageState extends State<HomePage> {
},
),
),
Container
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
16
,
vertical:
8
),
decoration:
BoxDecoration
(
color:
Colors
.
white
,
boxShadow:
[
BoxShadow
(
color:
Colors
.
grey
.
withOpacity
(
0.1
),
spreadRadius:
1
,
blurRadius:
3
,
offset:
const
Offset
(
0
,
-
1
),
),
],
),
child:
Row
(
children:
[
Expanded
(
child:
TextField
(
controller:
_messageController
,
decoration:
InputDecoration
(
hintText:
'输入消息...'
,
border:
OutlineInputBorder
(
borderRadius:
BorderRadius
.
circular
(
25
),
borderSide:
BorderSide
.
none
,
),
filled:
true
,
fillColor:
Colors
.
grey
[
100
],
contentPadding:
const
EdgeInsets
.
symmetric
(
horizontal:
20
,
vertical:
10
,
),
),
onSubmitted:
(
_
)
=>
_sendMessage
(),
),
),
const
SizedBox
(
width:
8
),
FloatingActionButton
(
onPressed:
_sendMessage
,
backgroundColor:
Pallete
.
firstSuggestionBoxColor
,
child:
const
Icon
(
Icons
.
send
),
mini:
true
,
),
],
),
),
_buildBottomInput
(),
],
),
floatingActionButton:
ZoomIn
(
delay:
Duration
(
milliseconds:
start
+
3
*
delay
),
child:
FloatingActionButton
(
backgroundColor:
Pallete
.
firstSuggestionBoxColor
,
onPressed:
()
async
{
if
(
await
speechToText
.
hasPermission
&&
speechToText
.
isNotListening
)
{
await
startListening
();
}
else
if
(
speechToText
.
isListening
)
{
setState
(()
{
currentStreamedContent
=
''
;
generatedContent
=
''
;
});
await
stopListening
();
try
{
String
fullResponse
=
''
;
bool
isFirstChunk
=
true
;
await
for
(
final
chunk
in
openAIService
.
chatGPTAPI
(
lastWords
))
{
setState
(()
{
fullResponse
+=
chunk
;
if
(
isFirstChunk
)
{
messages
.
add
(
ChatMessage
(
text:
fullResponse
,
isUserMessage:
false
,
));
isFirstChunk
=
false
;
}
else
{
messages
.
last
=
ChatMessage
(
text:
fullResponse
,
isUserMessage:
false
,
);
}
});
}
await
systemSpeak
(
fullResponse
);
}
catch
(
e
)
{
setState
(()
{
messages
.
add
(
ChatMessage
(
text:
'抱歉,出现了一些错误:
$e
'
,
isUserMessage:
false
,
));
});
}
finally
{
setState
(()
{
_isLoading
=
false
;
});
}
}
else
{
initSpeechToText
();
}
},
child:
Icon
(
speechToText
.
isListening
?
Icons
.
stop
:
Icons
.
mic
,
),
),
),
);
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论