From f8de726959df8c60f37c3b304864eec4212cc7db Mon Sep 17 00:00:00 2001 From: Yasien Mac Mini Date: Mon, 10 Nov 2025 13:35:04 +0200 Subject: [PATCH] QOL: Mzansi AI Chat Look and Feel & Startup question pt4 --- .../mih_providers/mzansi_ai_provider.dart | 9 + .../mzansi_ai/package_tools/mih_ai_chat.dart | 163 ++++++++---------- 2 files changed, 79 insertions(+), 93 deletions(-) diff --git a/Frontend/lib/mih_components/mih_providers/mzansi_ai_provider.dart b/Frontend/lib/mih_components/mih_providers/mzansi_ai_provider.dart index 7f3e35e8..574977a0 100644 --- a/Frontend/lib/mih_components/mih_providers/mzansi_ai_provider.dart +++ b/Frontend/lib/mih_components/mih_providers/mzansi_ai_provider.dart @@ -8,12 +8,14 @@ import 'package:mzansi_innovation_hub/mih_config/mih_colors.dart'; import 'package:mzansi_innovation_hub/mih_config/mih_env.dart'; class MzansiAiProvider extends ChangeNotifier { + bool ttsOn; int toolIndex; String? startUpQuestion; late OllamaProvider ollamaProvider; MzansiAiProvider({ this.toolIndex = 0, + this.ttsOn = false, }) { ollamaProvider = OllamaProvider( baseUrl: "${AppEnviroment.baseAiUrl}/api", @@ -35,6 +37,7 @@ class MzansiAiProvider extends ChangeNotifier { "- Mzansi Directory: A place to search and find out more about the people and businesses across Mzansi.\n" + "- Calendar: Integrated calendar for managing personal and business appointments.\n" + "- Calculator: Simple calculator with tip and forex calculation functionality.\n" + + "- MIH Minesweeper: The first game from MIH! It's the classic brain-teaser ready to entertain you no matter where you are.\n" + "- MIH Access: Manage and view profile access security.\n" + "**Core Rules and Guidelines:**\n" + "- **Accuracy First:** Always prioritize providing correct information.\n" + @@ -59,6 +62,11 @@ class MzansiAiProvider extends ChangeNotifier { notifyListeners(); } + void setTTSstate(bool ttsOn) { + this.ttsOn = ttsOn; + notifyListeners(); + } + void setStartUpQuestion(String? question) { startUpQuestion = question; notifyListeners(); @@ -244,6 +252,7 @@ class MzansiAiProvider extends ChangeNotifier { ], ), textStyle: TextStyle( + fontSize: 16, color: MihColors.getPrimaryColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), ), diff --git a/Frontend/lib/mih_packages/mzansi_ai/package_tools/mih_ai_chat.dart b/Frontend/lib/mih_packages/mzansi_ai/package_tools/mih_ai_chat.dart index d4bfd9f6..e801bc46 100644 --- a/Frontend/lib/mih_packages/mzansi_ai/package_tools/mih_ai_chat.dart +++ b/Frontend/lib/mih_packages/mzansi_ai/package_tools/mih_ai_chat.dart @@ -4,6 +4,7 @@ import 'package:flutter_speed_dial/flutter_speed_dial.dart'; import 'package:flutter_tts/flutter_tts.dart'; import 'package:ken_logger/ken_logger.dart'; import 'package:mzansi_innovation_hub/main.dart'; +import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_button.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_floating_menu.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_package_components/mih_icons.dart'; import 'package:mzansi_innovation_hub/mih_components/mih_providers/mzansi_ai_provider.dart'; @@ -18,7 +19,6 @@ class MihAiChat extends StatefulWidget { } class _MihAiChatState extends State { - bool ttsOn = false; final FlutterTts _flutterTts = FlutterTts(); Widget noMessagescDisplay() { @@ -123,9 +123,9 @@ class _MihAiChatState extends State { _flutterTts.stop(); } - Future initTts() async { + Future initTts(MzansiAiProvider aiProvider) async { try { - await _flutterTts.setSpeechRate(1); + await _flutterTts.setSpeechRate(0.55); // await _flutterTts.setLanguage("en-US"); // Safer voice selection with error handling @@ -153,25 +153,19 @@ class _MihAiChatState extends State { _flutterTts.setStartHandler(() { if (mounted) { - setState(() { - ttsOn = true; - }); + aiProvider.setTTSstate(true); } }); _flutterTts.setCompletionHandler(() { if (mounted) { - setState(() { - ttsOn = false; - }); + aiProvider.setTTSstate(false); } }); _flutterTts.setErrorHandler((message) { if (mounted) { - setState(() { - ttsOn = false; - }); + aiProvider.setTTSstate(false); } }); } @@ -192,7 +186,8 @@ class _MihAiChatState extends State { @override void initState() { super.initState(); - initTts(); + MzansiAiProvider aiProvider = context.read(); + initTts(aiProvider); initStartQuestion(); } @@ -205,102 +200,84 @@ class _MihAiChatState extends State { @override Widget build(BuildContext context) { return Consumer( - builder: (BuildContext context, MzansiAiProvider mzansiAiProvider, - Widget? child) { - // final startupQuestion = mzansiAiProvider.startUpQuestion; - // if (startupQuestion != null) { - // WidgetsBinding.instance.addPostFrameCallback((_) { - // mzansiAiProvider.ollamaProvider.sendMessageStream(startupQuestion); - // mzansiAiProvider.setStartUpQuestion(null); - // }); - // } - bool hasHistory = mzansiAiProvider.ollamaProvider.history.isNotEmpty; - KenLogger.success("has history: $hasHistory"); - KenLogger.success( - "length: ${mzansiAiProvider.ollamaProvider.history.length}"); + builder: + (BuildContext context, MzansiAiProvider aiProvider, Widget? child) { + bool hasHistory = aiProvider.ollamaProvider.history.isNotEmpty; + return Stack( children: [ LlmChatView( - provider: mzansiAiProvider.ollamaProvider, - messageSender: mzansiAiProvider.ollamaProvider.sendMessageStream, + provider: aiProvider.ollamaProvider, + messageSender: aiProvider.ollamaProvider.sendMessageStream, // welcomeMessage: // "Mzansi AI is here to help. Send us a messahe and we'll try our best to assist you.", autofocus: false, enableAttachments: false, enableVoiceNotes: false, - style: mzansiAiProvider.getChatStyle(context), - // suggestions: [ - // "What is mih all about?", - // "What are the features of MIH?" - // ], + style: aiProvider.getChatStyle(context), + suggestions: [ + "What is mih all about?", + "What are the features of MIH?" + ], ), if (hasHistory) Positioned( - right: 10, bottom: 80, - child: MihFloatingMenu( - animatedIcon: AnimatedIcons.menu_close, - children: [ - SpeedDialChild( - child: Icon( - Icons.refresh, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - label: "New Chat", - labelBackgroundColor: MihColors.getGreenColor( + left: 10, + child: MihButton( + width: 35, + height: 35, + onPressed: () { + if (!aiProvider.ttsOn) { + speakLastMessage(aiProvider); + } else { + stopTTS(); + } + }, + buttonColor: !aiProvider.ttsOn + ? MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark") + : MihColors.getRedColor( MzansiInnovationHub.of(context)!.theme.mode == "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onTap: () { - resetChat(mzansiAiProvider); - }, - ), - SpeedDialChild( - child: Icon( - !ttsOn ? Icons.volume_up : Icons.volume_off, - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - ), - label: !ttsOn ? "Read last Message" : "Stop Reading", - labelBackgroundColor: MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - labelStyle: TextStyle( - color: MihColors.getPrimaryColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - fontWeight: FontWeight.bold, - ), - backgroundColor: !ttsOn - ? MihColors.getGreenColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark") - : MihColors.getRedColor( - MzansiInnovationHub.of(context)!.theme.mode == - "Dark"), - onTap: () { - KenLogger.success("Button pressed: TtsOn - $ttsOn"); - if (!ttsOn) { - speakLastMessage(mzansiAiProvider); - } else { - stopTTS(); - } - }, - ), - ], + child: Icon( + !aiProvider.ttsOn ? Icons.volume_up : Icons.volume_off, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + ), ), ), + Positioned( + right: 10, + bottom: 80, + child: MihFloatingMenu( + animatedIcon: AnimatedIcons.menu_close, + children: [ + SpeedDialChild( + child: Icon( + Icons.refresh, + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + ), + label: "New Chat", + labelBackgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + labelStyle: TextStyle( + color: MihColors.getPrimaryColor( + MzansiInnovationHub.of(context)!.theme.mode == + "Dark"), + fontWeight: FontWeight.bold, + ), + backgroundColor: MihColors.getGreenColor( + MzansiInnovationHub.of(context)!.theme.mode == "Dark"), + onTap: () { + resetChat(aiProvider); + }, + ), + ], + ), + ), if (!hasHistory) noMessagescDisplay(), ], );