feat: integrate chat state management for dynamic navigation in dashbot

This commit is contained in:
Udhay-Adithya
2025-09-26 23:49:17 +05:30
parent 7fd7bb1306
commit 8cd9923690
2 changed files with 94 additions and 53 deletions

View File

@@ -9,6 +9,8 @@ import 'core/routes/dashbot_router.dart';
import 'core/routes/dashbot_routes.dart'; import 'core/routes/dashbot_routes.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
// Removed navigation persistence provider.
import 'features/chat/viewmodel/chat_viewmodel.dart';
class DashbotWindow extends ConsumerWidget { class DashbotWindow extends ConsumerWidget {
final VoidCallback onClose; final VoidCallback onClose;
@@ -24,6 +26,7 @@ class DashbotWindow extends ConsumerWidget {
final windowNotifier = ref.read(dashbotWindowNotifierProvider.notifier); final windowNotifier = ref.read(dashbotWindowNotifierProvider.notifier);
final settings = ref.watch(settingsProvider); final settings = ref.watch(settingsProvider);
final currentRequest = ref.watch(selectedRequestModelProvider); final currentRequest = ref.watch(selectedRequestModelProvider);
final chatState = ref.watch(chatViewmodelProvider);
// Close the overlay when the window is not popped anymore // Close the overlay when the window is not popped anymore
ref.listen( ref.listen(
@@ -35,32 +38,43 @@ class DashbotWindow extends ConsumerWidget {
}, },
); );
// Listen to changes in response status and navigate accordingly void _maybeNavigate() {
ref.listen( final req = ref.read(selectedRequestModelProvider);
selectedRequestModelProvider final hasResponse = (req?.httpResponseModel?.statusCode != null) ||
.select((request) => request?.httpResponseModel?.statusCode != null), (req?.responseStatus != null);
(prev, hasResponse) { final requestId = req?.id ?? 'global';
if (prev == hasResponse) return; final messages = chatState.chatSessions[requestId] ?? const [];
final isChatActive = messages.isNotEmpty;
final navigator = _dashbotNavigatorKey.currentState;
if (navigator == null) return;
final canPop = navigator.canPop();
final currentRoute = final desired = isChatActive
_dashbotNavigatorKey.currentState?.widget.initialRoute; ? DashbotRoutes.dashbotChat
final canPop = _dashbotNavigatorKey.currentState?.canPop() ?? false; : hasResponse
? DashbotRoutes.dashbotHome
: DashbotRoutes.dashbotDefault;
bool isOn(String r) {
Route? top;
navigator.popUntil((route) {
top = route;
return true;
});
return top?.settings.name == r;
}
if (hasResponse) { if (isOn(desired)) return;
// Response available - navigate to home if not already there if (desired == DashbotRoutes.dashbotDefault && canPop) {
if (currentRoute == DashbotRoutes.dashbotDefault && !canPop) { navigator.popUntil((route) => route.isFirst);
_dashbotNavigatorKey.currentState return;
?.pushNamed(DashbotRoutes.dashbotHome); }
} if (desired != DashbotRoutes.dashbotDefault) {
} else { navigator.pushNamed(desired);
// No response - navigate back to default if we're in home }
if (canPop) { }
_dashbotNavigatorKey.currentState
?.popUntil((route) => route.isFirst); ref.listen(chatViewmodelProvider, (_, __) => _maybeNavigate());
} ref.listen(selectedRequestModelProvider, (_, __) => _maybeNavigate());
}
},
);
return Stack( return Stack(
children: [ children: [
@@ -174,11 +188,17 @@ class DashbotWindow extends ConsumerWidget {
Expanded( Expanded(
child: Navigator( child: Navigator(
key: _dashbotNavigatorKey, key: _dashbotNavigatorKey,
initialRoute: (currentRequest initialRoute: (chatState
?.httpResponseModel?.statusCode != .chatSessions[
null) (currentRequest?.id ?? 'global')]
? DashbotRoutes.dashbotHome ?.isNotEmpty ??
: DashbotRoutes.dashbotDefault, false)
? DashbotRoutes.dashbotChat
: (currentRequest
?.httpResponseModel?.statusCode !=
null)
? DashbotRoutes.dashbotHome
: DashbotRoutes.dashbotDefault,
onGenerateRoute: generateRoute, onGenerateRoute: generateRoute,
), ),
), ),

View File

@@ -7,6 +7,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'core/providers/dashbot_window_notifier.dart'; import 'core/providers/dashbot_window_notifier.dart';
import 'core/utils/show_dashbot.dart'; import 'core/utils/show_dashbot.dart';
import 'package:apidash/consts.dart'; import 'package:apidash/consts.dart';
import 'features/chat/viewmodel/chat_viewmodel.dart';
class DashbotTab extends ConsumerStatefulWidget { class DashbotTab extends ConsumerStatefulWidget {
const DashbotTab({super.key}); const DashbotTab({super.key});
@@ -26,31 +27,46 @@ class _DashbotTabState extends ConsumerState<DashbotTab>
Widget build(BuildContext context) { Widget build(BuildContext context) {
super.build(context); super.build(context);
final currentRequest = ref.watch(selectedRequestModelProvider); final currentRequest = ref.watch(selectedRequestModelProvider);
final chatState = ref.watch(chatViewmodelProvider);
// Listen to changes in response status and navigate accordingly void maybeNavigate() {
ref.listen( final req = ref.read(selectedRequestModelProvider);
selectedRequestModelProvider.select((request) => final hasResponse = (req?.httpResponseModel?.statusCode != null) ||
request?.httpResponseModel?.statusCode != null || (req?.responseStatus != null);
request?.responseStatus != null), final requestId = req?.id ?? 'global';
(prev, hasResponse) { final messages = chatState.chatSessions[requestId] ?? const [];
if (prev == hasResponse) return; final isChatActive = messages.isNotEmpty;
final navigator = _navKey.currentState;
if (navigator == null) return;
final canPop = navigator.canPop();
final currentRoute = _navKey.currentState?.widget.initialRoute; final desired = isChatActive
final canPop = _navKey.currentState?.canPop() ?? false; ? DashbotRoutes.dashbotChat
: hasResponse
? DashbotRoutes.dashbotHome
: DashbotRoutes.dashbotDefault;
if (hasResponse) { bool isOn(String r) {
// Response available - navigate to home if not already there Route? top;
if (currentRoute == DashbotRoutes.dashbotDefault && !canPop) { navigator.popUntil((route) {
_navKey.currentState?.pushNamed(DashbotRoutes.dashbotHome); top = route;
} return true;
} else { });
// No response - navigate back to default if we're in home return top?.settings.name == r;
if (canPop) { }
_navKey.currentState?.popUntil((route) => route.isFirst);
} if (isOn(desired)) return;
} if (desired == DashbotRoutes.dashbotDefault && canPop) {
}, navigator.popUntil((route) => route.isFirst);
); return;
}
if (desired != DashbotRoutes.dashbotDefault) {
navigator.pushNamed(desired);
}
}
ref.listen(chatViewmodelProvider, (_, __) => maybeNavigate());
ref.listen(selectedRequestModelProvider, (_, __) => maybeNavigate());
return PopScope( return PopScope(
canPop: true, canPop: true,
@@ -119,8 +135,13 @@ class _DashbotTabState extends ConsumerState<DashbotTab>
Expanded( Expanded(
child: Navigator( child: Navigator(
key: _navKey, key: _navKey,
initialRoute: initialRoute: (chatState
(currentRequest?.httpResponseModel?.statusCode != null || .chatSessions[(currentRequest?.id ?? 'global')]
?.isNotEmpty ??
false)
? DashbotRoutes.dashbotChat
: (currentRequest?.httpResponseModel?.statusCode !=
null ||
currentRequest?.responseStatus != null) currentRequest?.responseStatus != null)
? DashbotRoutes.dashbotHome ? DashbotRoutes.dashbotHome
: DashbotRoutes.dashbotDefault, : DashbotRoutes.dashbotDefault,