aboutsummaryrefslogtreecommitdiffstats
path: root/lib/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'lib/widgets')
-rw-r--r--lib/widgets/assistant_mode_choice.dart202
-rw-r--r--lib/widgets/chat_section.dart128
-rw-r--r--lib/widgets/listen_wake_word_section.dart66
-rw-r--r--lib/widgets/nlu_engine_choice.dart200
-rw-r--r--lib/widgets/record_command_button.dart66
5 files changed, 662 insertions, 0 deletions
diff --git a/lib/widgets/assistant_mode_choice.dart b/lib/widgets/assistant_mode_choice.dart
new file mode 100644
index 0000000..ec17534
--- /dev/null
+++ b/lib/widgets/assistant_mode_choice.dart
@@ -0,0 +1,202 @@
+// import 'package:flutter/material.dart';
+// import 'package:provider/provider.dart';
+// import '../models/app_state.dart';
+
+// enum AssistantMode { wakeWord, manual }
+
+// class AssistantModeChoice extends StatefulWidget {
+// final Function(AssistantMode) onModeChanged;
+
+// const AssistantModeChoice({Key? key, required this.onModeChanged})
+// : super(key: key);
+
+// @override
+// AssistantModeChoiceState createState() => AssistantModeChoiceState();
+// }
+
+// class AssistantModeChoiceState extends State<AssistantModeChoice> {
+// @override
+// Widget build(BuildContext context) {
+// final appState = context.watch<AppState>(); // Watch the app state
+
+// return SegmentedButton<AssistantMode>(
+// segments: const <ButtonSegment<AssistantMode>>[
+// ButtonSegment<AssistantMode>(
+// value: AssistantMode.wakeWord,
+// label: Text('Wake Word'),
+// icon: Icon(Icons.graphic_eq)),
+// ButtonSegment<AssistantMode>(
+// value: AssistantMode.manual,
+// label: Text('Manual'),
+// icon: Icon(Icons.graphic_eq)),
+// ],
+// selected: <AssistantMode>{
+// appState.isWakeWordMode ? AssistantMode.wakeWord : AssistantMode.manual
+// }, // Use app state
+// onSelectionChanged: (Set<AssistantMode> newSelection) {
+// final newMode = newSelection.first;
+// setState(() {
+// // Update the app state when the mode changes
+// appState.isWakeWordMode = newMode == AssistantMode.wakeWord;
+// });
+// // Call the callback function to notify the mode change
+// widget.onModeChanged(newMode);
+// },
+// style: ButtonStyle(
+// side: MaterialStateProperty.all<BorderSide>(
+// BorderSide(
+// width: 0, // Remove border width
+// color: Colors.transparent, // Make border transparent
+// ),
+// ),
+// backgroundColor: MaterialStateProperty.resolveWith<Color>(
+// (states) {
+// if (states.contains(MaterialState.selected)) {
+// return Colors.green; // Color when pressed
+// }
+// // Add more conditions for other states as needed
+// return Colors.white; // Default color
+// },
+// ),
+// foregroundColor: MaterialStateProperty.resolveWith<Color>((states) {
+// if (states.contains(MaterialState.selected)) {
+// return Colors.white; // Color when pressed
+// }
+// // Add more conditions for other states as needed
+// return Colors.green;
+// })),
+// );
+// }
+// }
+
+import 'package:flutter/material.dart';
+
+enum AssistantMode { wakeWord, manual }
+
+class AssistantModeChoice extends StatefulWidget {
+ final Function(AssistantMode) onModeChanged;
+
+ const AssistantModeChoice({Key? key, required this.onModeChanged})
+ : super(key: key);
+
+ @override
+ AssistantModeChoiceState createState() => AssistantModeChoiceState();
+}
+
+class AssistantModeChoiceState extends State<AssistantModeChoice> {
+ late AssistantMode _selectedMode;
+
+ @override
+ void initState() {
+ super.initState();
+ _selectedMode = AssistantMode.manual; // Initialize the selection
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: <Widget>[
+ InkWell(
+ onTap: () => _onModeChanged(AssistantMode.wakeWord),
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ bottomLeft: Radius.circular(20.0),
+ ),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 17.5, vertical: 5.0),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ bottomLeft: Radius.circular(20.0),
+ ),
+ color: _selectedMode == AssistantMode.wakeWord
+ ? Colors.green
+ : Colors.white,
+ border: Border.all(
+ color: Colors.transparent,
+ ),
+ ),
+ child: Row(
+ children: [
+ Icon(
+ _selectedMode == AssistantMode.wakeWord
+ ? Icons.check
+ : Icons.graphic_eq,
+ color: _selectedMode == AssistantMode.wakeWord
+ ? Colors.white
+ : Colors.green,
+ ),
+ SizedBox(width: 8),
+ Text(
+ 'Wake Word',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 18,
+ color: _selectedMode == AssistantMode.wakeWord
+ ? Colors.white
+ : Colors.green,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ InkWell(
+ onTap: () => _onModeChanged(AssistantMode.manual),
+ borderRadius: BorderRadius.only(
+ topRight: Radius.circular(20.0),
+ bottomRight: Radius.circular(20.0),
+ ),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 17.5, vertical: 5.0),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topRight: Radius.circular(20.0),
+ bottomRight: Radius.circular(20.0),
+ ),
+ color: _selectedMode == AssistantMode.manual
+ ? Colors.green
+ : Colors.white,
+ border: Border.all(
+ color: Colors.transparent,
+ ),
+ ),
+ child: Row(
+ children: [
+ Icon(
+ _selectedMode == AssistantMode.manual
+ ? Icons.check
+ : Icons.graphic_eq,
+ color: _selectedMode == AssistantMode.manual
+ ? Colors.white
+ : Colors.green,
+ ),
+ SizedBox(width: 8),
+ Text(
+ 'Manual',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 18,
+ color: _selectedMode == AssistantMode.manual
+ ? Colors.white
+ : Colors.green,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+
+ void _onModeChanged(AssistantMode newMode) {
+ setState(() {
+ _selectedMode = newMode;
+ });
+
+ // Call the callback function to notify the mode change
+ widget.onModeChanged(newMode);
+ }
+}
diff --git a/lib/widgets/chat_section.dart b/lib/widgets/chat_section.dart
new file mode 100644
index 0000000..596b9f3
--- /dev/null
+++ b/lib/widgets/chat_section.dart
@@ -0,0 +1,128 @@
+import 'package:flutter/material.dart';
+
+class ChatSection extends StatelessWidget {
+ final ScrollController scrollController;
+ final List<ChatMessage> chatMessages;
+ final Function(String text, {bool isUserMessage}) addChatMessage;
+
+ ChatSection({
+ required this.scrollController,
+ required this.chatMessages,
+ required this.addChatMessage,
+ });
+
+ @override
+ @override
+ Widget build(BuildContext context) {
+ return Card(
+ elevation: 4, // Add a subtle shadow
+ shape: RoundedRectangleBorder(
+ borderRadius: BorderRadius.circular(12),
+ ),
+ child: Column(
+ children: [
+ // Chat heading
+ Container(
+ padding: EdgeInsets.all(6),
+ alignment: Alignment.center,
+ child: Text(
+ 'Command Logs',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 20,
+ ),
+ ),
+ ),
+ // Chat messages with fixed height
+ Container(
+ padding: EdgeInsets.all(12),
+ height: 180, // Adjust the height as needed
+ child: ListView.builder(
+ controller: scrollController,
+ itemCount: chatMessages.length,
+ itemBuilder: (context, index) {
+ final message = chatMessages[index];
+ return ChatMessageTile(message: message);
+ },
+ ),
+ ),
+ // User input field (if needed)
+ // ...
+ ],
+ ),
+ );
+ }
+}
+
+class ChatMessage {
+ final String text;
+ final bool isUserMessage;
+
+ ChatMessage({required this.text, this.isUserMessage = false});
+}
+
+class ChatMessageTile extends StatelessWidget {
+ final ChatMessage message;
+
+ ChatMessageTile({required this.message});
+
+ @override
+ Widget build(BuildContext context) {
+ return ListTile(
+ contentPadding: EdgeInsets.all(0),
+ title: Container(
+ alignment:
+ message.isUserMessage ? Alignment.topRight : Alignment.topLeft,
+ child: Row(
+ mainAxisAlignment: message.isUserMessage
+ ? MainAxisAlignment.end
+ : MainAxisAlignment.start,
+ children: [
+ if (!message.isUserMessage)
+ CircleAvatar(
+ backgroundColor: Colors.green[400],
+ child: Icon(
+ Icons.smart_toy_outlined,
+ color: Colors.white,
+ ),
+ ),
+ SizedBox(width: 8),
+ Flexible(
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 16, vertical: 8),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(16),
+ topRight: Radius.circular(16),
+ bottomLeft: message.isUserMessage
+ ? Radius.circular(16)
+ : Radius.circular(0),
+ bottomRight: message.isUserMessage
+ ? Radius.circular(0)
+ : Radius.circular(16),
+ ),
+ color:
+ message.isUserMessage ? Colors.blue : Colors.green[400],
+ ),
+ child: Text(
+ message.text,
+ style: TextStyle(color: Colors.white, fontSize: 18),
+ maxLines: null,
+ ),
+ ),
+ ),
+ SizedBox(width: 8),
+ if (message.isUserMessage)
+ CircleAvatar(
+ backgroundColor: Colors.blue,
+ child: Icon(
+ Icons.person,
+ color: Colors.white,
+ ),
+ ),
+ ],
+ ),
+ ),
+ );
+ }
+}
diff --git a/lib/widgets/listen_wake_word_section.dart b/lib/widgets/listen_wake_word_section.dart
new file mode 100644
index 0000000..61abcd0
--- /dev/null
+++ b/lib/widgets/listen_wake_word_section.dart
@@ -0,0 +1,66 @@
+import 'package:flutter/material.dart';
+
+class ListeningForWakeWordSection extends StatefulWidget {
+ @override
+ ListeningForWakeWordSectionState createState() =>
+ ListeningForWakeWordSectionState();
+}
+
+class ListeningForWakeWordSectionState
+ extends State<ListeningForWakeWordSection>
+ with SingleTickerProviderStateMixin {
+ late AnimationController _controller;
+ late Animation<Color?> _colorAnimation;
+
+ @override
+ void initState() {
+ super.initState();
+
+ // Create an animation controller
+ _controller = AnimationController(
+ vsync: this,
+ duration: Duration(milliseconds: 1500), // Adjust the duration as needed
+ );
+
+ // Create a color change animation
+ _colorAnimation = ColorTween(
+ begin: Colors.orangeAccent, // Use your desired initial color
+ end: Colors.redAccent, // Use your desired final color
+ ).animate(_controller);
+
+ // Start both animations
+ _controller.repeat(reverse: true);
+ }
+
+ @override
+ void dispose() {
+ _controller.dispose(); // Dispose of the animation controller
+ super.dispose();
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ AnimatedBuilder(
+ animation: _controller,
+ builder: (context, child) {
+ return Icon(
+ Icons.album, // Replace with your listening icon
+ size: 60,
+ color: _colorAnimation.value,
+ );
+ },
+ ),
+ SizedBox(height: 8),
+ Text(
+ 'Listening for wake word...',
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/widgets/nlu_engine_choice.dart b/lib/widgets/nlu_engine_choice.dart
new file mode 100644
index 0000000..1e8ca52
--- /dev/null
+++ b/lib/widgets/nlu_engine_choice.dart
@@ -0,0 +1,200 @@
+// import 'package:flutter/material.dart';
+
+// enum NLUEngine { snips, rasa }
+
+// class NLUEngineChoice extends StatefulWidget {
+// final Function(NLUEngine) onEngineChanged;
+
+// const NLUEngineChoice({Key? key, required this.onEngineChanged})
+// : super(key: key);
+
+// @override
+// State<NLUEngineChoice> createState() => _NLUEngineChoiceState();
+// }
+
+// class _NLUEngineChoiceState extends State<NLUEngineChoice> {
+// NLUEngine nluView = NLUEngine.snips;
+
+// @override
+// Widget build(BuildContext context) {
+// return SegmentedButton<NLUEngine>(
+// segments: const <ButtonSegment<NLUEngine>>[
+// ButtonSegment<NLUEngine>(
+// value: NLUEngine.snips,
+// label: Text('Snips'),
+// icon: Icon(Icons.settings_suggest)),
+// ButtonSegment<NLUEngine>(
+// value: NLUEngine.rasa,
+// label: Text('RASA'),
+// icon: Icon(Icons.settings_suggest)),
+// ],
+// selected: <NLUEngine>{nluView},
+// onSelectionChanged: (Set<NLUEngine> newSelection) {
+// final newEngine = newSelection.first;
+// setState(() {
+// // By default there is only a single segment that can be
+// // selected at one time, so its value is always the first
+// // item in the selected set.
+// nluView = newEngine;
+// });
+// // Call the callback function to notify the mode change
+// widget.onEngineChanged(newEngine);
+// },
+// style: ButtonStyle(
+// side: MaterialStateProperty.all<BorderSide>(
+// BorderSide(
+// width: 0, // Remove border width
+// color: Colors.transparent, // Make border transparent
+// ),
+// ),
+// backgroundColor: MaterialStateProperty.resolveWith<Color>(
+// (states) {
+// if (states.contains(MaterialState.selected)) {
+// return Colors.green; // Color when pressed
+// }
+// // Add more conditions for other states as needed
+// return Colors.white; // Default color
+// },
+// ),
+// foregroundColor: MaterialStateProperty.resolveWith<Color>((states) {
+// if (states.contains(MaterialState.selected)) {
+// return Colors.white; // Color when pressed
+// }
+// // Add more conditions for other states as needed
+// return Colors.green;
+// })),
+// );
+// }
+// }
+
+import 'package:flutter/material.dart';
+
+enum NLUEngine { snips, rasa }
+
+class NLUEngineChoice extends StatefulWidget {
+ final Function(NLUEngine) onEngineChanged;
+
+ const NLUEngineChoice({Key? key, required this.onEngineChanged})
+ : super(key: key);
+
+ @override
+ State<NLUEngineChoice> createState() => _NLUEngineChoiceState();
+}
+
+class _NLUEngineChoiceState extends State<NLUEngineChoice> {
+ late NLUEngine _selectedEngine;
+
+ @override
+ void initState() {
+ super.initState();
+ _selectedEngine = NLUEngine.snips; // Initialize the selection
+ }
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisAlignment: MainAxisAlignment.center,
+ children: <Widget>[
+ InkWell(
+ onTap: () => _onEngineChanged(NLUEngine.snips),
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ bottomLeft: Radius.circular(20.0),
+ ),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 17.5, vertical: 5.0),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topLeft: Radius.circular(20.0),
+ bottomLeft: Radius.circular(20.0),
+ ),
+ color: _selectedEngine == NLUEngine.snips
+ ? Colors.green
+ : Colors.white,
+ border: Border.all(
+ color: Colors.transparent,
+ ),
+ ),
+ child: Row(
+ children: [
+ Icon(
+ _selectedEngine == NLUEngine.snips
+ ? Icons.check
+ : Icons.settings_suggest,
+ color: _selectedEngine == NLUEngine.snips
+ ? Colors.white
+ : Colors.green,
+ ),
+ SizedBox(width: 8),
+ Text(
+ 'Snips',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 18,
+ color: _selectedEngine == NLUEngine.snips
+ ? Colors.white
+ : Colors.green,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ InkWell(
+ onTap: () => _onEngineChanged(NLUEngine.rasa),
+ borderRadius: BorderRadius.only(
+ topRight: Radius.circular(20.0),
+ bottomRight: Radius.circular(20.0),
+ ),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: 17.5, vertical: 5.0),
+ decoration: BoxDecoration(
+ borderRadius: BorderRadius.only(
+ topRight: Radius.circular(20.0),
+ bottomRight: Radius.circular(20.0),
+ ),
+ color: _selectedEngine == NLUEngine.rasa
+ ? Colors.green
+ : Colors.white,
+ border: Border.all(
+ color: Colors.transparent,
+ ),
+ ),
+ child: Row(
+ children: [
+ Icon(
+ _selectedEngine == NLUEngine.rasa
+ ? Icons.check
+ : Icons.settings_suggest,
+ color: _selectedEngine == NLUEngine.rasa
+ ? Colors.white
+ : Colors.green,
+ ),
+ SizedBox(width: 8),
+ Text(
+ 'RASA',
+ style: TextStyle(
+ fontWeight: FontWeight.bold,
+ fontSize: 18,
+ color: _selectedEngine == NLUEngine.rasa
+ ? Colors.white
+ : Colors.green,
+ ),
+ ),
+ ],
+ ),
+ ),
+ ),
+ ],
+ );
+ }
+
+ void _onEngineChanged(NLUEngine newEngine) {
+ setState(() {
+ _selectedEngine = newEngine;
+ });
+
+ // Call the callback function to notify the engine change
+ widget.onEngineChanged(newEngine);
+ }
+}
diff --git a/lib/widgets/record_command_button.dart b/lib/widgets/record_command_button.dart
new file mode 100644
index 0000000..fdff772
--- /dev/null
+++ b/lib/widgets/record_command_button.dart
@@ -0,0 +1,66 @@
+import 'package:flutter/material.dart';
+
+class RecordCommandButton extends StatefulWidget {
+ final ValueChanged<bool> onRecordingStateChanged;
+
+ RecordCommandButton({required this.onRecordingStateChanged});
+
+ @override
+ RecordCommandButtonState createState() => RecordCommandButtonState();
+}
+
+class RecordCommandButtonState extends State<RecordCommandButton> {
+ bool isRecording = false;
+
+ @override
+ Widget build(BuildContext context) {
+ return Column(
+ children: [
+ AnimatedContainer(
+ duration: Duration(seconds: 1),
+ curve: Curves.easeInOut,
+ width: 60, // Adjust the button size as needed
+ height: 60, // Adjust the button size as needed
+ decoration: BoxDecoration(
+ shape: BoxShape.circle,
+ color: isRecording
+ ? Colors.red
+ : Colors.green, // Green when recording, red when not recording
+ boxShadow: [
+ BoxShadow(
+ color: Colors.black.withOpacity(0.5),
+ blurRadius: 5,
+ spreadRadius: 1,
+ ),
+ ],
+ ),
+ child: InkWell(
+ onTap: () {
+ // Toggle recording state
+ setState(() {
+ isRecording = !isRecording;
+ });
+ // Call the callback function with the recording state
+ widget.onRecordingStateChanged(isRecording);
+ },
+ child: Center(
+ child: Icon(
+ Icons.mic, // Microphone icon
+ size: 36, // Icon size
+ color: Colors.white, // Icon color
+ ),
+ ),
+ ),
+ ),
+ SizedBox(height: 8), // Add spacing between the button and text
+ Text(
+ isRecording ? 'Recording...' : 'Record Command',
+ style: TextStyle(
+ fontSize: 18, // Text size
+ fontWeight: FontWeight.bold,
+ ),
+ ),
+ ],
+ );
+ }
+}