Add ContinuousModeDialog and integrate with ChatInputField

- Introduced a new dialog, ContinuousModeDialog, to inform users about the repercussions of the continuous mode.
- Integrated ContinuousModeDialog with ChatInputField. The dialog is shown when the fast-forward icon is clicked, based on the user's shared preferences.
- Leveraged shared preferences to remember if the user has chosen not to see the dialog again.
- Enhanced the ChatInputField to handle different states and user interactions related to continuous mode.
This commit is contained in:
hunteraraujo
2023-09-26 14:25:20 -07:00
parent cf630e4f2c
commit 389131f2ab
2 changed files with 208 additions and 5 deletions

View File

@@ -1,4 +1,6 @@
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
@@ -38,6 +40,40 @@ class _ChatInputFieldState extends State<ChatInputField> {
super.dispose();
}
Future<void> _presentContinuousModeDialogIfNeeded() async {
final prefs = await SharedPreferences.getInstance();
final showContinuousModeDialog =
prefs.getBool('showContinuousModeDialog') ?? true;
if (showContinuousModeDialog) {
showDialog(
context: context,
builder: (BuildContext context) {
return ContinuousModeDialog(
onProceed: () {
Navigator.of(context).pop();
_executeContinuousMode();
},
onCheckboxChanged: (bool value) async {
await prefs.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,
@@ -93,7 +129,6 @@ class _ChatInputFieldState extends State<ChatInputField> {
},
),
),
// TODO: Include pop up to explain continuous mode reprecussions
Tooltip(
message: widget.isContinuousMode
? ''
@@ -104,12 +139,12 @@ class _ChatInputFieldState extends State<ChatInputField> {
? 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) {
widget.onSendPressed(_controller.text);
_controller.clear();
_focusNode.unfocus();
_presentContinuousModeDialogIfNeeded();
} else {
widget.onContinuousModePressed();
}
widget.onContinuousModePressed();
},
),
)

View File

@@ -0,0 +1,168 @@
import 'package:auto_gpt_flutter_client/constants/app_colors.dart';
import 'package:flutter/material.dart';
class ContinuousModeDialog extends StatefulWidget {
final VoidCallback? onProceed;
final ValueChanged<bool>? onCheckboxChanged;
const ContinuousModeDialog({
Key? key,
this.onProceed,
this.onCheckboxChanged,
}) : super(key: key);
@override
_ContinuousModeDialogState createState() => _ContinuousModeDialogState();
}
class _ContinuousModeDialogState extends State<ContinuousModeDialog> {
bool _attemptedToDismiss = false;
bool _checkboxValue = false;
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async {
setState(() {
_attemptedToDismiss = true;
});
return false;
},
child: Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
side: BorderSide(
color: _attemptedToDismiss
? AppColors.accentDeniedLight
: Colors.transparent,
width: 3.0,
),
),
child: Container(
width: 260,
height: 251,
padding: const EdgeInsets.all(16),
child: Column(
children: [
// Black circle exclamation icon
Icon(Icons.error_outline,
color: _attemptedToDismiss
? AppColors.accentDeniedLight
: Colors.black),
const SizedBox(height: 8),
// Title
const Text(
'Continuous Mode',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 16,
fontFamily: 'Archivo',
fontWeight: FontWeight.w600,
),
),
const SizedBox(height: 8),
// Block of text
const SizedBox(
width: 220,
child: Text(
'Agents operating in Continuous Mode will perform Actions without requesting authorization from the user. Configure the number of steps in the settings menu.',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.black,
fontSize: 12.50,
fontFamily: 'Archivo',
fontWeight: FontWeight.w400,
),
),
),
// Buttons
const SizedBox(height: 14),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Cancel Button
SizedBox(
width: 106,
height: 28,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
onPressed: () => Navigator.of(context).pop(),
child: const Text(
'Cancel',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 12.50,
fontFamily: 'Archivo',
fontWeight: FontWeight.w400,
),
),
),
),
const SizedBox(width: 8),
// Proceed Button
SizedBox(
width: 106,
height: 28,
child: ElevatedButton(
style: ElevatedButton.styleFrom(
backgroundColor: AppColors.primaryLight,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0),
),
),
onPressed: widget.onProceed, // Use the provided callback
child: const Text(
'Proceed',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontSize: 12.50,
fontFamily: 'Archivo',
fontWeight: FontWeight.w400,
),
),
),
),
],
),
const SizedBox(height: 11),
// Checkbox and text
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Checkbox(
value: _checkboxValue,
onChanged: (bool? newValue) {
setState(() {
_checkboxValue = newValue ?? false;
});
if (widget.onCheckboxChanged != null) {
widget.onCheckboxChanged!(_checkboxValue);
}
},
),
const Text(
"Don't ask again",
style: TextStyle(
color: Colors.black,
fontSize: 11,
fontFamily: 'Archivo',
fontWeight: FontWeight.w400,
),
),
],
),
],
),
),
),
);
}
}