From 9a6215246e544c438ea99c27f5833f62fd0d060a Mon Sep 17 00:00:00 2001 From: Udhay-Adithya Date: Fri, 5 Sep 2025 03:02:00 +0530 Subject: [PATCH] feat: integrate dashbot tab for desktop devices --- .../core/model/dashbot_window_model.dart | 2 +- .../providers/dashbot_window_notifier.dart | 4 ++ lib/dashbot/core/utils/show_dashbot.dart | 22 ++++----- lib/dashbot/dashbot_dashboard.dart | 24 ++++++++++ lib/dashbot/dashbot_tab.dart | 45 +++++++++++++++++++ .../details_card/details_card.dart | 9 +++- 6 files changed, 94 insertions(+), 12 deletions(-) diff --git a/lib/dashbot/core/model/dashbot_window_model.dart b/lib/dashbot/core/model/dashbot_window_model.dart index be46e948..38987d72 100644 --- a/lib/dashbot/core/model/dashbot_window_model.dart +++ b/lib/dashbot/core/model/dashbot_window_model.dart @@ -12,7 +12,7 @@ class DashbotWindowModel { this.right = 50, this.bottom = 100, this.isActive = false, - this.isPopped = false, + this.isPopped = true, }); DashbotWindowModel copyWith({ diff --git a/lib/dashbot/core/providers/dashbot_window_notifier.dart b/lib/dashbot/core/providers/dashbot_window_notifier.dart index 628f8689..7f209fce 100644 --- a/lib/dashbot/core/providers/dashbot_window_notifier.dart +++ b/lib/dashbot/core/providers/dashbot_window_notifier.dart @@ -27,6 +27,10 @@ class DashbotWindowNotifier extends StateNotifier { void toggleActive() { state = state.copyWith(isActive: !state.isActive); } + + void togglePopped() { + state = state.copyWith(isPopped: !state.isPopped); + } } final dashbotWindowNotifierProvider = diff --git a/lib/dashbot/core/utils/show_dashbot.dart b/lib/dashbot/core/utils/show_dashbot.dart index db90e88d..3590afe1 100644 --- a/lib/dashbot/core/utils/show_dashbot.dart +++ b/lib/dashbot/core/utils/show_dashbot.dart @@ -12,23 +12,25 @@ void showDashbotWindow( List? overrides, }) { final isDashbotActive = ref.read(dashbotWindowNotifierProvider).isActive; + final isDashbotPopped = ref.read(dashbotWindowNotifierProvider).isPopped; final windowNotifier = ref.read(dashbotWindowNotifierProvider.notifier); if (isDashbotActive) return; + if (!isDashbotPopped) return; final overlay = Overlay.of(context); OverlayEntry? entry; entry = OverlayEntry( - builder: - (context) => ProviderScope( - overrides: overrides ?? const [], - child: DashbotWindow( - onClose: () { - entry?.remove(); - windowNotifier.toggleActive(); - }, - ), - ), + builder: (context) => ProviderScope( + overrides: overrides ?? const [], + child: DashbotWindow( + onClose: () { + entry?.remove(); + windowNotifier.toggleActive(); + }, + ), + ), ); + // Mark active and insert overlay windowNotifier.toggleActive(); overlay.insert(entry); } diff --git a/lib/dashbot/dashbot_dashboard.dart b/lib/dashbot/dashbot_dashboard.dart index 04dab940..66c5472f 100644 --- a/lib/dashbot/dashbot_dashboard.dart +++ b/lib/dashbot/dashbot_dashboard.dart @@ -25,6 +25,16 @@ class DashbotWindow extends ConsumerWidget { final settings = ref.watch(settingsProvider); final currentRequest = ref.watch(selectedRequestModelProvider); + // Close the overlay when the window is not popped anymore + ref.listen( + dashbotWindowNotifierProvider.select((s) => s.isPopped), + (prev, next) { + if (prev == true && next == false) { + onClose(); + } + }, + ); + ref.listen( selectedRequestModelProvider, (current, next) { @@ -108,6 +118,20 @@ class DashbotWindow extends ConsumerWidget { ), ], ), + Spacer(), + IconButton( + icon: Icon( + Icons.open_in_new, + color: + Theme.of(context).colorScheme.onPrimary, + ), + onPressed: () { + ref + .read(dashbotWindowNotifierProvider + .notifier) + .togglePopped(); + }, + ), IconButton( icon: Icon( Icons.close, diff --git a/lib/dashbot/dashbot_tab.dart b/lib/dashbot/dashbot_tab.dart index f80413f4..e9fe6ab3 100644 --- a/lib/dashbot/dashbot_tab.dart +++ b/lib/dashbot/dashbot_tab.dart @@ -4,6 +4,8 @@ import 'core/routes/dashbot_router.dart'; import 'core/routes/dashbot_routes.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'core/providers/dashbot_window_notifier.dart'; +import 'core/utils/show_dashbot.dart'; class DashbotTab extends ConsumerStatefulWidget { const DashbotTab({super.key}); @@ -54,6 +56,49 @@ class _DashbotTabState extends ConsumerState ), child: Column( children: [ + Padding( + padding: kP8, + child: Align( + alignment: AlignmentGeometry.centerRight, + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + IconButton( + icon: Icon( + Icons.close_fullscreen, + ), + onPressed: () { + ref + .read(dashbotWindowNotifierProvider.notifier) + .togglePopped(); + + final newState = + ref.read(dashbotWindowNotifierProvider); + if (newState.isPopped) { + showDashbotWindow(context, ref); + } + }, + ), + IconButton( + onPressed: () { + final isActive = + ref.read(dashbotWindowNotifierProvider).isActive; + + ref + .read(dashbotWindowNotifierProvider.notifier) + .togglePopped(); + if (isActive) { + ref + .read(dashbotWindowNotifierProvider.notifier) + .toggleActive(); + } + }, + icon: Icon(Icons.close), + ), + ], + ), + ), + ), Expanded( child: Navigator( key: _navKey, diff --git a/lib/screens/home_page/editor_pane/details_card/details_card.dart b/lib/screens/home_page/editor_pane/details_card/details_card.dart index 739f7475..072ffea5 100644 --- a/lib/screens/home_page/editor_pane/details_card/details_card.dart +++ b/lib/screens/home_page/editor_pane/details_card/details_card.dart @@ -1,3 +1,5 @@ +import 'package:apidash/dashbot/core/providers/dashbot_window_notifier.dart'; +import 'package:apidash/dashbot/dashbot_tab.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:apidash/providers/providers.dart'; @@ -12,10 +14,15 @@ class EditorPaneRequestDetailsCard extends ConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { final codePaneVisible = ref.watch(codePaneVisibleStateProvider); + final isDashbotPopped = ref.watch(dashbotWindowNotifierProvider).isPopped; return RequestDetailsCard( child: EqualSplitView( leftWidget: const EditRequestPane(), - rightWidget: codePaneVisible ? const CodePane() : const ResponsePane(), + rightWidget: !isDashbotPopped + ? DashbotTab() + : codePaneVisible + ? const CodePane() + : const ResponsePane(), ), ); }