89 lines
2.7 KiB
Dart
89 lines
2.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:nhance_app_pwa/config/environment.dart';
|
|
import 'package:nhance_app_pwa/customAppBar/responsive.dart';
|
|
import 'package:nhance_app_pwa/features/chatbot/application/chatbot_controller.dart';
|
|
import 'package:nhance_app_pwa/features/chatbot/presentation/widgets/chatbot_fab.dart';
|
|
import 'package:nhance_app_pwa/features/chatbot/presentation/widgets/chatbot_window.dart';
|
|
|
|
class ChatbotHost extends ConsumerStatefulWidget {
|
|
final Widget child;
|
|
final bool triggerIntroOnHome;
|
|
|
|
const ChatbotHost({
|
|
super.key,
|
|
required this.child,
|
|
this.triggerIntroOnHome = false,
|
|
});
|
|
|
|
@override
|
|
ConsumerState<ChatbotHost> createState() => _ChatbotHostState();
|
|
}
|
|
|
|
class _ChatbotHostState extends ConsumerState<ChatbotHost> {
|
|
bool _didFireIntro = false;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
if (!widget.triggerIntroOnHome) return;
|
|
if (_didFireIntro) return;
|
|
_didFireIntro = true;
|
|
ref.read(chatbotControllerProvider.notifier).triggerHomeIntroAnimation();
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (!Environment.chatbotEnabled) {
|
|
return widget.child;
|
|
}
|
|
|
|
final state = ref.watch(chatbotControllerProvider);
|
|
final controller = ref.read(chatbotControllerProvider.notifier);
|
|
|
|
final isMobile = Responsive.isMobile(context);
|
|
final isTablet = Responsive.isTablet(context);
|
|
|
|
final mobileBottomInset =
|
|
MediaQuery.of(context).padding.bottom + kBottomNavigationBarHeight + 10;
|
|
final edgeInsets = isMobile
|
|
? EdgeInsets.only(right: 12, bottom: mobileBottomInset)
|
|
: isTablet
|
|
? const EdgeInsets.only(right: 18, bottom: 22)
|
|
: const EdgeInsets.only(right: 24, bottom: 24);
|
|
|
|
return Stack(
|
|
children: [
|
|
widget.child,
|
|
if (!(isMobile && state.isOpen))
|
|
Positioned(
|
|
right: edgeInsets.right,
|
|
bottom: edgeInsets.bottom,
|
|
child: AnimatedScale(
|
|
scale: state.isIntroAnimating ? 1.14 : 1.0,
|
|
duration: const Duration(milliseconds: 250),
|
|
curve: Curves.easeOut,
|
|
child: ChatbotFab(
|
|
isOpen: state.isOpen,
|
|
onTap: controller.toggleOpen,
|
|
),
|
|
),
|
|
),
|
|
if (state.isOpen)
|
|
isMobile
|
|
? const Positioned.fill(
|
|
child: ChatbotWindow(),
|
|
)
|
|
: Positioned(
|
|
right: edgeInsets.right,
|
|
bottom: edgeInsets.bottom + 70,
|
|
child: const ChatbotWindow(),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|