|
|
|
|
@ -1,9 +1,12 @@
|
|
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
|
import 'package:flutter_svg/svg.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/api/dashboard_api_client.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/app_state/app_state.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/classes/colors.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/classes/utils.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/extensions/widget_extensions.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/generated/locale_keys.g.dart';
|
|
|
|
|
import 'package:mohem_flutter_app/models/generic_response_model.dart';
|
|
|
|
|
import 'package:speech_to_text/speech_recognition_result.dart';
|
|
|
|
|
import 'package:speech_to_text/speech_to_text.dart';
|
|
|
|
|
@ -53,7 +56,10 @@ class _ChatBotScreenState extends State<ChatBotScreen> {
|
|
|
|
|
|
|
|
|
|
/// Start listening for speech
|
|
|
|
|
void _startListening() async {
|
|
|
|
|
await _speechToText.listen(onResult: _onSpeechResult);
|
|
|
|
|
await _speechToText.listen(
|
|
|
|
|
onResult: _onSpeechResult,
|
|
|
|
|
localeId: AppState().isArabic(context) ? 'ar_SA' : 'en_US',
|
|
|
|
|
);
|
|
|
|
|
setState(() {});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -133,7 +139,7 @@ class _ChatBotScreenState extends State<ChatBotScreen> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void _scrollToBottom() {
|
|
|
|
|
Future.delayed(const Duration(milliseconds: 100), () {
|
|
|
|
|
Future<void>.delayed(const Duration(milliseconds: 100), () {
|
|
|
|
|
if (_scrollController.hasClients) {
|
|
|
|
|
_scrollController.animateTo(_scrollController.position.maxScrollExtent, duration: const Duration(milliseconds: 300), curve: Curves.easeOut);
|
|
|
|
|
}
|
|
|
|
|
@ -142,7 +148,7 @@ class _ChatBotScreenState extends State<ChatBotScreen> {
|
|
|
|
|
|
|
|
|
|
void _sendSuggestion(String text) {
|
|
|
|
|
if (atlasChatTokenResponse == null) {
|
|
|
|
|
Utils.showToast("Please wait, initializing chat...");
|
|
|
|
|
Utils.showToast(LocaleKeys.initializingChatPleaseWait.tr());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
_sendMessage(suggestionText: text);
|
|
|
|
|
@ -153,7 +159,7 @@ class _ChatBotScreenState extends State<ChatBotScreen> {
|
|
|
|
|
return Scaffold(
|
|
|
|
|
backgroundColor: MyColors.backgroundColor,
|
|
|
|
|
appBar: AppBar(
|
|
|
|
|
title: const Text("ChatBot", style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2B353E))),
|
|
|
|
|
title: Text(LocaleKeys.chatBot.tr(), style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2B353E))),
|
|
|
|
|
backgroundColor: MyColors.backgroundColor,
|
|
|
|
|
centerTitle: false,
|
|
|
|
|
),
|
|
|
|
|
@ -169,18 +175,18 @@ class _ChatBotScreenState extends State<ChatBotScreen> {
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
const Text("Hello, ask me", textAlign: TextAlign.center, style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2E303A))),
|
|
|
|
|
const Text("anything...", textAlign: TextAlign.center, style: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2E303A))),
|
|
|
|
|
Text(LocaleKeys.helloAskMe.tr(), textAlign: TextAlign.center, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2E303A))),
|
|
|
|
|
Text(LocaleKeys.anything.tr(), textAlign: TextAlign.center, style: const TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: Color(0xFF2E303A))),
|
|
|
|
|
const SizedBox(height: 50),
|
|
|
|
|
Wrap(
|
|
|
|
|
const Wrap(
|
|
|
|
|
alignment: WrapAlignment.center,
|
|
|
|
|
spacing: 8,
|
|
|
|
|
runSpacing: 12,
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
_buildSuggestionChip("Nostalgia Perfume", () => _sendSuggestion("Nostalgia Perfume")),
|
|
|
|
|
_buildSuggestionChip("Al Nafoura", () => _sendSuggestion("Al Nafoura")),
|
|
|
|
|
_buildSuggestionChip("Al Nafoura", () => _sendSuggestion("Al Nafoura")),
|
|
|
|
|
_buildSuggestionChip("Al Jadi", () => _sendSuggestion("Al Jadi")),
|
|
|
|
|
// _buildSuggestionChip("Nostalgia Perfume", () => _sendSuggestion("Nostalgia Perfume")),
|
|
|
|
|
// _buildSuggestionChip("Al Nafoura", () => _sendSuggestion("Al Nafoura")),
|
|
|
|
|
// _buildSuggestionChip("Al Nafoura", () => _sendSuggestion("Al Nafoura")),
|
|
|
|
|
// _buildSuggestionChip("Al Jadi", () => _sendSuggestion("Al Jadi")),
|
|
|
|
|
],
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
@ -275,12 +281,16 @@ class _ChatBotScreenState extends State<ChatBotScreen> {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
String _formatTimestamp(DateTime timestamp) {
|
|
|
|
|
String hour = timestamp.hour.toString().padLeft(2, '0');
|
|
|
|
|
String minute = timestamp.minute.toString().padLeft(2, '0');
|
|
|
|
|
int hourInt = timestamp.hour;
|
|
|
|
|
int minute = timestamp.minute;
|
|
|
|
|
String period = hourInt >= 12 ? LocaleKeys.pm.tr() : LocaleKeys.am.tr();
|
|
|
|
|
int formattedHour = hourInt % 12 == 0 ? 12 : hourInt % 12;
|
|
|
|
|
String hour = formattedHour.toString().padLeft(2, '0');
|
|
|
|
|
String min = minute.toString().padLeft(2, '0');
|
|
|
|
|
String month = timestamp.month.toString().padLeft(2, '0');
|
|
|
|
|
String day = timestamp.day.toString().padLeft(2, '0');
|
|
|
|
|
int year = timestamp.year;
|
|
|
|
|
return "$month/$day/$year $hour:$minute AM";
|
|
|
|
|
return "$month/$day/$year $hour:$min $period";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Widget _buildSuggestionChip(String label, VoidCallback onTap) {
|
|
|
|
|
@ -326,7 +336,7 @@ class _ChatBotScreenState extends State<ChatBotScreen> {
|
|
|
|
|
maxLines: 1,
|
|
|
|
|
textAlignVertical: TextAlignVertical.center,
|
|
|
|
|
decoration: InputDecoration(
|
|
|
|
|
hintText: _isThinking ? 'Waiting for response...' : 'Type a message..',
|
|
|
|
|
hintText: _isThinking ? LocaleKeys.waitingForResponse.tr() : LocaleKeys.typeAMessage.tr(),
|
|
|
|
|
hintStyle: const TextStyle(color: MyColors.hintTextColor, fontSize: 14, fontWeight: FontWeight.normal),
|
|
|
|
|
border: InputBorder.none,
|
|
|
|
|
isDense: true,
|
|
|
|
|
@ -353,7 +363,13 @@ class _ChatBotScreenState extends State<ChatBotScreen> {
|
|
|
|
|
width: 48,
|
|
|
|
|
height: 48,
|
|
|
|
|
decoration: BoxDecoration(color: _isThinking ? MyColors.hintTextColor.withValues(alpha: 0.3) : MyColors.white, shape: BoxShape.circle),
|
|
|
|
|
child: Center(child: SvgPicture.asset("assets/icons/send.svg", colorFilter: _isThinking ? const ColorFilter.mode(MyColors.hintTextColor, BlendMode.srcIn) : null)),
|
|
|
|
|
child: Center(
|
|
|
|
|
child: SvgPicture.asset(
|
|
|
|
|
"assets/icons/send.svg",
|
|
|
|
|
matchTextDirection: true,
|
|
|
|
|
colorFilter: _isThinking ? const ColorFilter.mode(MyColors.hintTextColor, BlendMode.srcIn) : null,
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
),
|
|
|
|
|
],
|
|
|
|
|
@ -390,7 +406,7 @@ class _ThinkingDotsAnimationState extends State<ThinkingDotsAnimation> with Sing
|
|
|
|
|
return Row(
|
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
|
children: <Widget>[
|
|
|
|
|
const Text("Thinking", style: TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white)),
|
|
|
|
|
Text(LocaleKeys.thinking.tr(), style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Colors.white)),
|
|
|
|
|
const SizedBox(width: 2),
|
|
|
|
|
AnimatedBuilder(
|
|
|
|
|
animation: _controller,
|
|
|
|
|
|