Spaces:
Build error
Build error
File size: 6,249 Bytes
3382f47 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
import 'package:auto_gpt_flutter_client/viewmodels/chat_viewmodel.dart';
import 'package:auto_gpt_flutter_client/views/chat/continuous_mode_dialog.dart';
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
class ChatInputField extends StatefulWidget {
// Callback to be triggered when the send button is pressed
final Function(String) onSendPressed;
final Function() onContinuousModePressed;
final bool isContinuousMode;
// TODO: Create a view model for this class and remove the ChatViewModel
final ChatViewModel viewModel;
const ChatInputField({
Key? key,
required this.onSendPressed,
required this.onContinuousModePressed,
this.isContinuousMode = false,
required this.viewModel,
}) : super(key: key);
@override
_ChatInputFieldState createState() => _ChatInputFieldState();
}
class _ChatInputFieldState extends State<ChatInputField> {
// Controller for the TextField to manage its content
final TextEditingController _controller = TextEditingController();
final FocusNode _focusNode = FocusNode();
final FocusNode _throwawayFocusNode = FocusNode();
@override
void initState() {
super.initState();
_focusNode.addListener(() {
if (_focusNode.hasFocus && widget.isContinuousMode) {
widget.onContinuousModePressed();
}
});
}
@override
void dispose() {
_focusNode.dispose(); // Dispose of the FocusNode when you're done.
super.dispose();
}
Future<void> _presentContinuousModeDialogIfNeeded() async {
final showContinuousModeDialog = await widget.viewModel.prefsService
.getBool('showContinuousModeDialog') ??
true;
FocusScope.of(context).requestFocus(_throwawayFocusNode);
if (showContinuousModeDialog) {
showDialog(
context: context,
builder: (BuildContext context) {
return ContinuousModeDialog(
onProceed: () {
Navigator.of(context).pop();
_executeContinuousMode();
},
onCheckboxChanged: (bool value) async {
await widget.viewModel.prefsService
.setBool('showContinuousModeDialog', !value);
},
);
},
);
} else {
_executeContinuousMode();
}
}
void _executeContinuousMode() {
if (!widget.isContinuousMode) {
widget.onSendPressed(_controller.text);
_controller.clear();
_focusNode.unfocus();
}
widget.onContinuousModePressed();
}
@override
Widget build(BuildContext context) {
// Using LayoutBuilder to provide the current constraints of the widget,
// ensuring it rebuilds when the window size changes
return LayoutBuilder(
builder: (context, constraints) {
// Calculate the width of the chat view based on the constraints provided
double chatViewWidth = constraints.maxWidth;
// Determine the width of the input field based on the chat view width.
// If the chat view width is 1000 or more, the input width will be 900.
// Otherwise, the input width will be the chat view width minus 40.
double inputWidth = (chatViewWidth >= 1000) ? 900 : chatViewWidth - 40;
return Container(
width: inputWidth,
// Defining the minimum and maximum height for the TextField container
constraints: const BoxConstraints(
minHeight: 50,
maxHeight: 400,
),
// Styling the container with a border and rounded corners
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.black, width: 0.5),
borderRadius: BorderRadius.circular(8),
),
padding: const EdgeInsets.symmetric(horizontal: 8),
// Using SingleChildScrollView to ensure the TextField can scroll
// when the content exceeds its maximum height
child: SingleChildScrollView(
reverse: true,
child: TextField(
controller: _controller,
focusNode: _focusNode,
// Enable enter key stroke to send the message
onSubmitted: (_) {
widget.onSendPressed(_controller.text);
_controller.clear();
},
// Allowing the TextField to expand vertically and accommodate multiple lines
maxLines: null,
decoration: InputDecoration(
hintText: 'Type a message...',
border: InputBorder.none,
suffixIcon: Row(
mainAxisSize: MainAxisSize.min, // Set to minimum space
children: [
if (!widget.isContinuousMode)
Tooltip(
message: 'Send a single message',
child: IconButton(
splashRadius: 0.1,
icon: const Icon(Icons.send),
onPressed: () {
widget.onSendPressed(_controller.text);
_controller.clear();
},
),
),
Tooltip(
message: widget.isContinuousMode
? ''
: 'Enable continuous mode',
child: IconButton(
splashRadius: 0.1,
icon: Icon(widget.isContinuousMode
? Icons.pause
: Icons.fast_forward),
onPressed: () {
// TODO: All of this logic should be handled at a higher level in the widget tree. Temporary
if (!widget.isContinuousMode) {
_presentContinuousModeDialogIfNeeded();
} else {
widget.onContinuousModePressed();
}
},
),
)
],
),
),
),
),
);
},
);
}
}
|