added send functionality to icon.
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'package:app/theme.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'chat.dart';
|
||||
|
||||
@@ -26,9 +27,12 @@ class ChatBubbleWidget extends StatelessWidget{
|
||||
bottomRight: c.role ? const Radius.circular(12.0) : const Radius
|
||||
.circular(0.0),
|
||||
),
|
||||
color: c.role ? Colors.blue[200] : Colors.grey[200],
|
||||
color: c.role ? AppTheme.darkest : AppTheme.dark,
|
||||
),
|
||||
child: Text(
|
||||
c.content,
|
||||
style: AppTheme.bodyMedium,
|
||||
),
|
||||
child: Text(c.content),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -18,7 +18,7 @@ class Conversation with ChangeNotifier {
|
||||
}
|
||||
|
||||
void loadChats() {
|
||||
chats = Server.getChatsByConversationID(conversationID);
|
||||
chats = Backend.getChatsByConversationID(conversationID);
|
||||
}
|
||||
|
||||
void setLabel() {
|
||||
|
||||
@@ -20,7 +20,7 @@ class ConversationThreadModel extends FlutterFlowModel<ConversationThreadWidget>
|
||||
|
||||
@override
|
||||
void initState(BuildContext context) {
|
||||
conversation = Server.getLoadedConversation();
|
||||
conversation = Backend.getLoadedConversation();
|
||||
promptBoxModel = createModel(context, () => PromptBoxModel());
|
||||
}
|
||||
|
||||
|
||||
@@ -53,9 +53,7 @@ class _ConversationThreadWidgetState extends State<ConversationThreadWidget> {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
height: double.infinity,
|
||||
decoration: const BoxDecoration(
|
||||
color: AppTheme.primaryBackground,
|
||||
),
|
||||
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@@ -65,12 +63,12 @@ class _ConversationThreadWidgetState extends State<ConversationThreadWidget> {
|
||||
listenable: _model.conversation,
|
||||
builder: (BuildContext context, Widget? child) {
|
||||
return ListView.builder(
|
||||
itemCount: Server.getLoadedConversation().chats.length,
|
||||
itemCount: Backend.getLoadedConversation().chats.length,
|
||||
padding: const EdgeInsets.fromLTRB(0, 12, 0, 24,),
|
||||
reverse: false,
|
||||
scrollDirection: Axis.vertical,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return ChatBubbleWidget(c: Server.getLoadedConversation().chats[index]);
|
||||
return ChatBubbleWidget(c: Backend.getLoadedConversation().chats[index]);
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -79,7 +77,7 @@ class _ConversationThreadWidgetState extends State<ConversationThreadWidget> {
|
||||
Container(
|
||||
width: double.infinity,
|
||||
decoration: const BoxDecoration(
|
||||
color: AppTheme.secondaryBackground,
|
||||
color: AppTheme.medium,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 3,
|
||||
@@ -95,74 +93,74 @@ class _ConversationThreadWidgetState extends State<ConversationThreadWidget> {
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(0, 12, 0, 0),
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// FlutterFlowMediaDisplay(
|
||||
// path: '',
|
||||
// imageBuilder: (path) => ClipRRect(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// child: CachedNetworkImage(
|
||||
// fadeInDuration: const Duration(milliseconds: 500),
|
||||
// fadeOutDuration:
|
||||
// const Duration(milliseconds: 500),
|
||||
// imageUrl: path,
|
||||
// width: 120,
|
||||
// height: 100,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// ),
|
||||
// TODO
|
||||
// videoPlayerBuilder: (path) =>
|
||||
// FlutterFlowVideoPlayer(
|
||||
// path: path,
|
||||
// width: 300,
|
||||
// autoPlay: false,
|
||||
// looping: true,
|
||||
// showControls: true,
|
||||
// allowFullScreen: true,
|
||||
// allowPlaybackSpeedMenu: false,
|
||||
// ),
|
||||
// ),
|
||||
Align(
|
||||
alignment: const AlignmentDirectional(-1, -1),
|
||||
// TODO: Make the delete button conditional upon media upload.
|
||||
child: FlutterFlowIconButton(
|
||||
borderColor:
|
||||
AppTheme.error,
|
||||
borderRadius: 20,
|
||||
borderWidth: 2,
|
||||
buttonSize: 40,
|
||||
fillColor: AppTheme.primaryBackground,
|
||||
icon: const Icon(
|
||||
Icons.delete_outline_rounded,
|
||||
color: AppTheme.error,
|
||||
size: 24,
|
||||
),
|
||||
onPressed: () {
|
||||
print('IconButton pressed ...');
|
||||
},
|
||||
),
|
||||
),
|
||||
]
|
||||
.divide(const SizedBox(width: 8))
|
||||
.addToStart(const SizedBox(width: 16))
|
||||
.addToEnd(const SizedBox(width: 16)),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
// Row(
|
||||
// mainAxisSize: MainAxisSize.max,
|
||||
// children: [
|
||||
// Expanded(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsetsDirectional.fromSTEB(0, 12, 0, 0),
|
||||
// child: SingleChildScrollView(
|
||||
// scrollDirection: Axis.horizontal,
|
||||
// child: Row(
|
||||
// mainAxisSize: MainAxisSize.max,
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// FlutterFlowMediaDisplay(
|
||||
// path: '',
|
||||
// imageBuilder: (path) => ClipRRect(
|
||||
// borderRadius: BorderRadius.circular(8),
|
||||
// child: CachedNetworkImage(
|
||||
// fadeInDuration: const Duration(milliseconds: 500),
|
||||
// fadeOutDuration:
|
||||
// const Duration(milliseconds: 500),
|
||||
// imageUrl: path,
|
||||
// width: 120,
|
||||
// height: 100,
|
||||
// fit: BoxFit.cover,
|
||||
// ),
|
||||
// ),
|
||||
// // TODO
|
||||
// videoPlayerBuilder: (path) =>
|
||||
// FlutterFlowVideoPlayer(
|
||||
// path: path,
|
||||
// width: 300,
|
||||
// autoPlay: false,
|
||||
// looping: true,
|
||||
// showControls: true,
|
||||
// allowFullScreen: true,
|
||||
// allowPlaybackSpeedMenu: false,
|
||||
// ),
|
||||
// ),
|
||||
// Align(
|
||||
// alignment: const AlignmentDirectional(-1, -1),
|
||||
// // TODO: Make the delete button conditional upon media upload.
|
||||
// child: FlutterFlowIconButton(
|
||||
// borderColor:
|
||||
// AppTheme.error,
|
||||
// borderRadius: 20,
|
||||
// borderWidth: 2,
|
||||
// buttonSize: 40,
|
||||
// fillColor: AppTheme.primaryBackground,
|
||||
// icon: const Icon(
|
||||
// Icons.delete_outline_rounded,
|
||||
// color: AppTheme.error,
|
||||
// size: 24,
|
||||
// ),
|
||||
// onPressed: () {
|
||||
// print('IconButton pressed ...');
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ]
|
||||
// .divide(const SizedBox(width: 8))
|
||||
// .addToStart(const SizedBox(width: 16))
|
||||
// .addToEnd(const SizedBox(width: 16)),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
Form(
|
||||
key: _model.formKey,
|
||||
autovalidateMode: AutovalidateMode.disabled,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:app/components/conversation_thread/conversation.dart';
|
||||
import 'package:flutterflow_ui/flutterflow_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
@@ -9,14 +10,18 @@ import 'model_item_model.dart';
|
||||
export 'model_item_model.dart';
|
||||
|
||||
class ModelItemWidget extends StatefulWidget {
|
||||
const ModelItemWidget({super.key});
|
||||
final Conversation conversation;
|
||||
const ModelItemWidget({super.key, required this.conversation});
|
||||
|
||||
@override
|
||||
State<ModelItemWidget> createState() => _ModelItemWidgetState();
|
||||
State<ModelItemWidget> createState() => _ModelItemWidgetState(conversation);
|
||||
}
|
||||
|
||||
class _ModelItemWidgetState extends State<ModelItemWidget> {
|
||||
late ModelItemModel _model;
|
||||
late Conversation conversation;
|
||||
|
||||
_ModelItemWidgetState(this.conversation);
|
||||
|
||||
@override
|
||||
void setState(VoidCallback callback) {
|
||||
@@ -78,22 +83,22 @@ class _ModelItemWidgetState extends State<ModelItemWidget> {
|
||||
),
|
||||
),
|
||||
),
|
||||
const Expanded(
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(12, 0, 8, 0),
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(12, 0, 8, 0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.max,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Randy Peterson',
|
||||
Text( // Label
|
||||
conversation.conversationLabel,
|
||||
style: AppTheme.bodyMedium,
|
||||
),
|
||||
Padding(
|
||||
padding: EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0),
|
||||
child: Text(
|
||||
'name@domainname.com',
|
||||
padding: const EdgeInsetsDirectional.fromSTEB(0, 4, 0, 0),
|
||||
child: Text( // Sub-label
|
||||
conversation.conversationSubLabel,
|
||||
style: AppTheme.bodySmall,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -17,6 +17,7 @@ class PromptBoxWidget extends StatefulWidget {
|
||||
|
||||
class _PromptBoxWidgetState extends State<PromptBoxWidget> {
|
||||
late PromptBoxModel _model;
|
||||
late String entry_text;
|
||||
|
||||
@override
|
||||
void setState(VoidCallback callback) {
|
||||
@@ -69,7 +70,7 @@ class _PromptBoxWidgetState extends State<PromptBoxWidget> {
|
||||
buttonSize: 40,
|
||||
icon: const Icon(
|
||||
Icons.file_upload_outlined,
|
||||
color: AppTheme.secondaryText,
|
||||
color: AppTheme.darkest,
|
||||
size: 30,
|
||||
),
|
||||
onPressed: () {
|
||||
@@ -88,7 +89,7 @@ class _PromptBoxWidgetState extends State<PromptBoxWidget> {
|
||||
buttonSize: 40,
|
||||
icon: const Icon(
|
||||
Icons.photo_outlined,
|
||||
color: AppTheme.secondaryText,
|
||||
color: AppTheme.darkest,
|
||||
size: 30,
|
||||
),
|
||||
onPressed: () {
|
||||
@@ -105,13 +106,28 @@ class _PromptBoxWidgetState extends State<PromptBoxWidget> {
|
||||
borderRadius: 30,
|
||||
borderWidth: 1,
|
||||
buttonSize: 40,
|
||||
icon: const Icon(
|
||||
Icons.mic_none,
|
||||
color: AppTheme.secondaryText,
|
||||
icon: // Backend.stt.speechToText.isListening ?
|
||||
// const Icon(
|
||||
// Icons.mic_none,
|
||||
// color: AppTheme.error,
|
||||
// size: 30,
|
||||
// ) :
|
||||
const Icon(
|
||||
Icons.mic_off_outlined,
|
||||
color: AppTheme.darkest,
|
||||
size: 30,
|
||||
),
|
||||
onPressed: () {
|
||||
print('IconButton pressed ...');
|
||||
if(Backend.stt.isSpeechEnabled()) {
|
||||
if(Backend.stt.speechToText.isListening) {
|
||||
print('De-activating STT.');
|
||||
Backend.stt.stopListening();
|
||||
}
|
||||
print('Activating STT.');
|
||||
entry_text = Backend.stt.startListening() as String;
|
||||
} else {
|
||||
print('Microphone is unavailable for STT');
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -126,7 +142,7 @@ class _PromptBoxWidgetState extends State<PromptBoxWidget> {
|
||||
buttonSize: 40,
|
||||
icon: const Icon(
|
||||
Icons.videocam_outlined,
|
||||
color: AppTheme.secondaryText,
|
||||
color: AppTheme.darkest,
|
||||
size: 30,
|
||||
),
|
||||
onPressed: () {
|
||||
@@ -145,7 +161,7 @@ class _PromptBoxWidgetState extends State<PromptBoxWidget> {
|
||||
buttonSize: 40,
|
||||
icon: const Icon(
|
||||
Icons.camera_alt_outlined,
|
||||
color: AppTheme.secondaryText,
|
||||
color: AppTheme.darkest,
|
||||
size: 30,
|
||||
),
|
||||
onPressed: () {
|
||||
@@ -206,21 +222,28 @@ class _PromptBoxWidgetState extends State<PromptBoxWidget> {
|
||||
),
|
||||
filled: true,
|
||||
fillColor: AppTheme.alternate,
|
||||
suffixIcon: const Icon(
|
||||
Icons.send,
|
||||
color: AppTheme.primary,
|
||||
size: 30,
|
||||
suffixIcon: GestureDetector(
|
||||
onTap: () {
|
||||
// TODO: Connect with multimedia
|
||||
entry_text = _model.textController.text;
|
||||
Backend.respondWhenReady(entry_text);
|
||||
_model.textController?.clear(); // Clear the text field
|
||||
},
|
||||
child: const Icon(
|
||||
Icons.send,
|
||||
color: AppTheme.primary,
|
||||
size: 30,
|
||||
),
|
||||
),
|
||||
),
|
||||
style: AppTheme.bodyMedium,
|
||||
style: AppTheme.displayMedium,
|
||||
textAlign: TextAlign.start,
|
||||
maxLines: 5,
|
||||
minLines: 1,
|
||||
validator: _model.textControllerValidator.asValidator(context),
|
||||
textInputAction: TextInputAction.send, // "Send" on keyboard
|
||||
onFieldSubmitted: (text) {
|
||||
// TODO: Clear text box
|
||||
Server.respondWhenReady(text); // TODO: Connect with multimedia
|
||||
Backend.respondWhenReady(text); // TODO: Connect with multimedia
|
||||
_model.textController?.clear(); // Clear the text field
|
||||
},
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user