mirror of
https://github.com/foss42/apidash.git
synced 2025-06-10 07:09:41 +08:00
fix: page navigation
This commit is contained in:
@ -4,6 +4,7 @@ import 'package:inner_drawer/inner_drawer.dart';
|
|||||||
|
|
||||||
final mobileDrawerKeyProvider = StateProvider<GlobalKey<InnerDrawerState>>(
|
final mobileDrawerKeyProvider = StateProvider<GlobalKey<InnerDrawerState>>(
|
||||||
(ref) => GlobalKey<InnerDrawerState>());
|
(ref) => GlobalKey<InnerDrawerState>());
|
||||||
|
final leftDrawerStateProvider = StateProvider<bool>((ref) => false);
|
||||||
final navRailIndexStateProvider = StateProvider<int>((ref) => 0);
|
final navRailIndexStateProvider = StateProvider<int>((ref) => 0);
|
||||||
final selectedIdEditStateProvider = StateProvider<String?>((ref) => null);
|
final selectedIdEditStateProvider = StateProvider<String?>((ref) => null);
|
||||||
final codePaneVisibleStateProvider = StateProvider<bool>((ref) => false);
|
final codePaneVisibleStateProvider = StateProvider<bool>((ref) => false);
|
||||||
@ -29,4 +30,5 @@ final nameTextFieldFocusNodeProvider =
|
|||||||
return focusNode;
|
return focusNode;
|
||||||
});
|
});
|
||||||
|
|
||||||
final searchQueryProvider = StateProvider<String>((ref) => '');
|
final collectionSearchQueryProvider = StateProvider<String>((ref) => '');
|
||||||
|
final environmentSearchQueryProvider = StateProvider<String>((ref) => '');
|
||||||
|
@ -58,11 +58,13 @@ class Dashboard extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 16.0),
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
child: bottomButton(context, ref, railIdx, 2,
|
||||||
child: bottomButton(context, ref, railIdx, 2,
|
child: bottomButton(context, ref, railIdx, 2,
|
||||||
Icons.help, Icons.help_outline),
|
Icons.help, Icons.help_outline),
|
||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 16.0),
|
padding: const EdgeInsets.only(bottom: 16.0),
|
||||||
|
child: bottomButton(context, ref, railIdx, 3,
|
||||||
child: bottomButton(context, ref, railIdx, 3,
|
child: bottomButton(context, ref, railIdx, 3,
|
||||||
Icons.settings, Icons.settings_outlined),
|
Icons.settings, Icons.settings_outlined),
|
||||||
),
|
),
|
||||||
@ -95,6 +97,7 @@ class Dashboard extends ConsumerWidget {
|
|||||||
children: const [
|
children: const [
|
||||||
HomePage(),
|
HomePage(),
|
||||||
SizedBox(),
|
SizedBox(),
|
||||||
|
SizedBox(),
|
||||||
IntroPage(),
|
IntroPage(),
|
||||||
SettingsPage(),
|
SettingsPage(),
|
||||||
],
|
],
|
||||||
|
0
lib/screens/envvar/environment_page.dart
Normal file
0
lib/screens/envvar/environment_page.dart
Normal file
129
lib/screens/envvar/environments_pane.dart
Normal file
129
lib/screens/envvar/environments_pane.dart
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
import 'package:apidash/consts.dart';
|
||||||
|
import 'package:apidash/extensions/extensions.dart';
|
||||||
|
import 'package:apidash/models/environment_model.dart';
|
||||||
|
import 'package:apidash/providers/providers.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
|
||||||
|
class EnvironmentsPane extends ConsumerWidget {
|
||||||
|
const EnvironmentsPane({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EnvironmentsList extends HookConsumerWidget {
|
||||||
|
const EnvironmentsList({
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final environmentSequence = ref.watch(environmentSequenceProvider);
|
||||||
|
final environmentItems = ref.watch(environmentsStateNotifierProvider)!;
|
||||||
|
final alwaysShowEnvironmentsPaneScrollbar = ref.watch(settingsProvider
|
||||||
|
.select((value) => value.alwaysShowCollectionPaneScrollbar));
|
||||||
|
final filterQuery = ref.watch(environmentSearchQueryProvider).trim();
|
||||||
|
|
||||||
|
ScrollController scrollController = useScrollController();
|
||||||
|
return Scrollbar(
|
||||||
|
controller: scrollController,
|
||||||
|
thumbVisibility: alwaysShowEnvironmentsPaneScrollbar,
|
||||||
|
radius: const Radius.circular(12),
|
||||||
|
child: filterQuery.isEmpty
|
||||||
|
? ReorderableListView.builder(
|
||||||
|
padding: context.isMediumWindow
|
||||||
|
? EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom,
|
||||||
|
right: 8,
|
||||||
|
)
|
||||||
|
: kPe8,
|
||||||
|
scrollController: scrollController,
|
||||||
|
buildDefaultDragHandles: false,
|
||||||
|
itemCount: environmentSequence.length,
|
||||||
|
onReorder: (int oldIndex, int newIndex) {
|
||||||
|
if (oldIndex < newIndex) {
|
||||||
|
newIndex -= 1;
|
||||||
|
}
|
||||||
|
if (oldIndex != newIndex) {
|
||||||
|
ref
|
||||||
|
.read(collectionStateNotifierProvider.notifier)
|
||||||
|
.reorder(oldIndex, newIndex);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
var id = environmentSequence[index];
|
||||||
|
if (kIsMobile) {
|
||||||
|
return ReorderableDelayedDragStartListener(
|
||||||
|
key: ValueKey(id),
|
||||||
|
index: index,
|
||||||
|
child: Padding(
|
||||||
|
padding: kP1,
|
||||||
|
child: EnvironmentItem(
|
||||||
|
id: id,
|
||||||
|
environmentModel: environmentItems[id]!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ReorderableDragStartListener(
|
||||||
|
key: ValueKey(id),
|
||||||
|
index: index,
|
||||||
|
child: Padding(
|
||||||
|
padding: kP1,
|
||||||
|
child: EnvironmentItem(
|
||||||
|
id: id,
|
||||||
|
environmentModel: environmentItems[id]!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
: ListView(
|
||||||
|
padding: context.isMediumWindow
|
||||||
|
? EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.paddingOf(context).bottom,
|
||||||
|
right: 8,
|
||||||
|
)
|
||||||
|
: kPe8,
|
||||||
|
controller: scrollController,
|
||||||
|
children: environmentSequence.map((id) {
|
||||||
|
var item = environmentItems[id]!;
|
||||||
|
if (item.name.toLowerCase().contains(filterQuery)) {
|
||||||
|
return Padding(
|
||||||
|
padding: kP1,
|
||||||
|
child: EnvironmentItem(
|
||||||
|
id: id,
|
||||||
|
environmentModel: item,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return const SizedBox();
|
||||||
|
}).toList(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EnvironmentItem extends ConsumerWidget {
|
||||||
|
const EnvironmentItem({
|
||||||
|
super.key,
|
||||||
|
required this.id,
|
||||||
|
required this.environmentModel,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String id;
|
||||||
|
final EnvironmentModel environmentModel;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final selectedId = ref.watch(selectedEnvironmentIdProvider);
|
||||||
|
|
||||||
|
return Text(environmentModel.name);
|
||||||
|
}
|
||||||
|
}
|
@ -94,7 +94,7 @@ class CollectionPane extends ConsumerWidget {
|
|||||||
style: Theme.of(context).textTheme.bodyMedium,
|
style: Theme.of(context).textTheme.bodyMedium,
|
||||||
hintText: "Filter by name or URL",
|
hintText: "Filter by name or URL",
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
ref.read(searchQueryProvider.notifier).state =
|
ref.read(collectionSearchQueryProvider.notifier).state =
|
||||||
value.toLowerCase();
|
value.toLowerCase();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@ -142,7 +142,7 @@ class _RequestListState extends ConsumerState<RequestList> {
|
|||||||
final requestItems = ref.watch(collectionStateNotifierProvider)!;
|
final requestItems = ref.watch(collectionStateNotifierProvider)!;
|
||||||
final alwaysShowCollectionPaneScrollbar = ref.watch(settingsProvider
|
final alwaysShowCollectionPaneScrollbar = ref.watch(settingsProvider
|
||||||
.select((value) => value.alwaysShowCollectionPaneScrollbar));
|
.select((value) => value.alwaysShowCollectionPaneScrollbar));
|
||||||
final filterQuery = ref.watch(searchQueryProvider).trim();
|
final filterQuery = ref.watch(collectionSearchQueryProvider).trim();
|
||||||
|
|
||||||
return Scrollbar(
|
return Scrollbar(
|
||||||
controller: controller,
|
controller: controller,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import 'package:apidash/consts.dart';
|
import 'package:apidash/widgets/splitviews.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@ -6,11 +6,13 @@ import 'package:inner_drawer/inner_drawer.dart';
|
|||||||
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
import 'package:flex_color_scheme/flex_color_scheme.dart';
|
||||||
import 'package:apidash/extensions/extensions.dart';
|
import 'package:apidash/extensions/extensions.dart';
|
||||||
import 'package:apidash/providers/providers.dart';
|
import 'package:apidash/providers/providers.dart';
|
||||||
|
import '../intro_page.dart';
|
||||||
|
import '../settings_page.dart';
|
||||||
import 'navbar.dart';
|
import 'navbar.dart';
|
||||||
import 'widgets/left_drawer.dart';
|
|
||||||
import 'requests_page.dart';
|
import 'requests_page.dart';
|
||||||
import 'response_drawer.dart';
|
import 'response_drawer.dart';
|
||||||
import '../home_page/collection_pane.dart';
|
import '../home_page/collection_pane.dart';
|
||||||
|
import 'widgets/page_base.dart';
|
||||||
|
|
||||||
class MobileDashboard extends ConsumerStatefulWidget {
|
class MobileDashboard extends ConsumerStatefulWidget {
|
||||||
const MobileDashboard({super.key});
|
const MobileDashboard({super.key});
|
||||||
@ -20,31 +22,14 @@ class MobileDashboard extends ConsumerStatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _MobileDashboardState extends ConsumerState<MobileDashboard> {
|
class _MobileDashboardState extends ConsumerState<MobileDashboard> {
|
||||||
late Color backgroundColor;
|
|
||||||
bool isLeftDrawerOpen = false;
|
|
||||||
ValueNotifier<double> dragPosition = ValueNotifier(0);
|
|
||||||
ValueNotifier<InnerDrawerDirection?> drawerDirection =
|
|
||||||
ValueNotifier(InnerDrawerDirection.start);
|
|
||||||
|
|
||||||
Color calculateBackgroundColor(double dragPosition) {
|
|
||||||
Color start = Theme.of(context).colorScheme.surface;
|
|
||||||
Color end = Theme.of(context).colorScheme.onInverseSurface;
|
|
||||||
return dragPosition == 0 ? start : end;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
super.dispose();
|
|
||||||
dragPosition.dispose();
|
|
||||||
drawerDirection.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(
|
Widget build(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
) {
|
) {
|
||||||
|
final railIdx = ref.watch(navRailIndexStateProvider);
|
||||||
final GlobalKey<InnerDrawerState> innerDrawerKey =
|
final GlobalKey<InnerDrawerState> innerDrawerKey =
|
||||||
ref.watch(mobileDrawerKeyProvider);
|
ref.watch(mobileDrawerKeyProvider);
|
||||||
|
final isLeftDrawerOpen = ref.watch(leftDrawerStateProvider);
|
||||||
return AnnotatedRegion<SystemUiOverlayStyle>(
|
return AnnotatedRegion<SystemUiOverlayStyle>(
|
||||||
value: FlexColorScheme.themedSystemNavigationBar(
|
value: FlexColorScheme.themedSystemNavigationBar(
|
||||||
context,
|
context,
|
||||||
@ -54,66 +39,10 @@ class _MobileDashboardState extends ConsumerState<MobileDashboard> {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: AlignmentDirectional.bottomCenter,
|
alignment: AlignmentDirectional.bottomCenter,
|
||||||
children: [
|
children: [
|
||||||
InnerDrawer(
|
PageBranch(
|
||||||
key: innerDrawerKey,
|
pageIndex: railIdx,
|
||||||
swipe: true,
|
|
||||||
swipeChild: true,
|
|
||||||
onTapClose: true,
|
|
||||||
offset: !context.isCompactWindow
|
|
||||||
? const IDOffset.only(left: 0.1, right: 1)
|
|
||||||
: const IDOffset.only(left: 0.7, right: 1),
|
|
||||||
boxShadow: [
|
|
||||||
BoxShadow(
|
|
||||||
offset: const Offset(1, 0),
|
|
||||||
color: Theme.of(context).colorScheme.onInverseSurface,
|
|
||||||
blurRadius: 0,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
colorTransitionChild: Colors.transparent,
|
|
||||||
colorTransitionScaffold: Colors.transparent,
|
|
||||||
rightAnimationType: InnerDrawerAnimation.linear,
|
|
||||||
backgroundDecoration: BoxDecoration(
|
|
||||||
color: Theme.of(context).colorScheme.onInverseSurface),
|
|
||||||
onDragUpdate: (value, direction) {
|
|
||||||
drawerDirection.value = direction;
|
|
||||||
if (value > 0.98 && direction == InnerDrawerDirection.start) {
|
|
||||||
dragPosition.value = 1;
|
|
||||||
} else {
|
|
||||||
dragPosition.value = 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
innerDrawerCallback: (isOpened) {
|
|
||||||
if (drawerDirection.value == InnerDrawerDirection.start) {
|
|
||||||
setState(() {
|
|
||||||
isLeftDrawerOpen = isOpened;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
leftChild: const LeftDrawer(
|
|
||||||
drawerContent: CollectionPane(),
|
|
||||||
),
|
|
||||||
rightChild: const ResponseDrawer(),
|
|
||||||
scaffold: ValueListenableBuilder<double>(
|
|
||||||
valueListenable: dragPosition,
|
|
||||||
builder: (context, value, child) {
|
|
||||||
return Container(
|
|
||||||
color: calculateBackgroundColor(value),
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius:
|
|
||||||
const BorderRadius.only(topLeft: Radius.circular(8)),
|
|
||||||
child: SafeArea(
|
|
||||||
minimum: kIsWindows || kIsMacOS ? kPt28 : EdgeInsets.zero,
|
|
||||||
bottom: false,
|
|
||||||
child: RequestsPage(
|
|
||||||
innerDrawerKey: innerDrawerKey,
|
innerDrawerKey: innerDrawerKey,
|
||||||
),
|
),
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (context.isCompactWindow)
|
if (context.isCompactWindow)
|
||||||
AnimatedPositioned(
|
AnimatedPositioned(
|
||||||
bottom: isLeftDrawerOpen
|
bottom: isLeftDrawerOpen
|
||||||
@ -131,3 +60,53 @@ class _MobileDashboardState extends ConsumerState<MobileDashboard> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class PageBranch extends StatelessWidget {
|
||||||
|
const PageBranch({
|
||||||
|
super.key,
|
||||||
|
required this.pageIndex,
|
||||||
|
required this.innerDrawerKey,
|
||||||
|
});
|
||||||
|
|
||||||
|
final int pageIndex;
|
||||||
|
final GlobalKey<InnerDrawerState> innerDrawerKey;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
switch (pageIndex) {
|
||||||
|
case 1:
|
||||||
|
return TwoDrawerSplitView(
|
||||||
|
key: const ValueKey('env'),
|
||||||
|
innerDrawerKey: innerDrawerKey,
|
||||||
|
offset: !context.isCompactWindow
|
||||||
|
? const IDOffset.only(left: 0.1)
|
||||||
|
: const IDOffset.only(left: 0.7),
|
||||||
|
leftDrawerContent: const SizedBox(),
|
||||||
|
mainContent: const SizedBox(),
|
||||||
|
);
|
||||||
|
case 2:
|
||||||
|
return const PageBase(
|
||||||
|
title: 'About',
|
||||||
|
scaffoldBody: IntroPage(),
|
||||||
|
);
|
||||||
|
case 3:
|
||||||
|
return const PageBase(
|
||||||
|
title: 'Settings',
|
||||||
|
scaffoldBody: SettingsPage(),
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
return TwoDrawerSplitView(
|
||||||
|
key: const ValueKey('home'),
|
||||||
|
innerDrawerKey: innerDrawerKey,
|
||||||
|
offset: !context.isCompactWindow
|
||||||
|
? const IDOffset.only(left: 0.1, right: 1)
|
||||||
|
: const IDOffset.only(left: 0.7, right: 1),
|
||||||
|
leftDrawerContent: const CollectionPane(),
|
||||||
|
rightDrawerContent: const ResponseDrawer(),
|
||||||
|
mainContent: RequestsPage(
|
||||||
|
innerDrawerKey: innerDrawerKey,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,9 +2,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:apidash/extensions/context_extensions.dart';
|
import 'package:apidash/extensions/context_extensions.dart';
|
||||||
import 'package:apidash/providers/ui_providers.dart';
|
import 'package:apidash/providers/ui_providers.dart';
|
||||||
import 'package:apidash/screens/mobile/widgets/page_base.dart';
|
|
||||||
import '../settings_page.dart';
|
|
||||||
import '../intro_page.dart';
|
|
||||||
|
|
||||||
class BottomNavBar extends ConsumerWidget {
|
class BottomNavBar extends ConsumerWidget {
|
||||||
const BottomNavBar({super.key});
|
const BottomNavBar({super.key});
|
||||||
@ -48,30 +45,26 @@ class BottomNavBar extends ConsumerWidget {
|
|||||||
'Variables'),
|
'Variables'),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: customNavigationDestination(context, ref, railIdx, 2,
|
child: customNavigationDestination(
|
||||||
Icons.help, Icons.help_outline, 'About',
|
context,
|
||||||
isNavigator: true, onTap: () {
|
ref,
|
||||||
Navigator.of(context).push(
|
railIdx,
|
||||||
MaterialPageRoute(
|
2,
|
||||||
builder: (context) => const PageBase(
|
Icons.help,
|
||||||
title: 'About',
|
Icons.help_outline,
|
||||||
scaffoldBody: IntroPage(),
|
'About',
|
||||||
)),
|
),
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: customNavigationDestination(context, ref, railIdx, 3,
|
child: customNavigationDestination(
|
||||||
Icons.settings, Icons.settings_outlined, 'Settings',
|
context,
|
||||||
isNavigator: true, onTap: () {
|
ref,
|
||||||
Navigator.of(context).push(
|
railIdx,
|
||||||
MaterialPageRoute(
|
3,
|
||||||
builder: (context) => const PageBase(
|
Icons.settings,
|
||||||
title: 'Settings',
|
Icons.settings_outlined,
|
||||||
scaffoldBody: SettingsPage(),
|
'Settings',
|
||||||
)),
|
),
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -131,17 +124,6 @@ class NavRail extends ConsumerWidget {
|
|||||||
Icons.help,
|
Icons.help,
|
||||||
Icons.help_outline,
|
Icons.help_outline,
|
||||||
'About',
|
'About',
|
||||||
isNavigator: true,
|
|
||||||
showLabel: false,
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).push(
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const PageBase(
|
|
||||||
title: 'About',
|
|
||||||
scaffoldBody: IntroPage(),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
customNavigationDestination(
|
customNavigationDestination(
|
||||||
@ -152,17 +134,6 @@ class NavRail extends ConsumerWidget {
|
|||||||
Icons.settings,
|
Icons.settings,
|
||||||
Icons.settings_outlined,
|
Icons.settings_outlined,
|
||||||
'Settings',
|
'Settings',
|
||||||
isNavigator: true,
|
|
||||||
showLabel: false,
|
|
||||||
onTap: () {
|
|
||||||
Navigator.of(context).push(
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const PageBase(
|
|
||||||
title: 'Settings',
|
|
||||||
scaffoldBody: SettingsPage(),
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -179,7 +150,6 @@ Widget customNavigationDestination(
|
|||||||
IconData selectedIcon,
|
IconData selectedIcon,
|
||||||
IconData icon,
|
IconData icon,
|
||||||
String label, {
|
String label, {
|
||||||
bool isNavigator = false,
|
|
||||||
bool showLabel = true,
|
bool showLabel = true,
|
||||||
Function()? onTap,
|
Function()? onTap,
|
||||||
}) {
|
}) {
|
||||||
@ -195,9 +165,9 @@ Widget customNavigationDestination(
|
|||||||
onTap: isSelected
|
onTap: isSelected
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
if (!isNavigator) {
|
ref.read(navRailIndexStateProvider.notifier).state = buttonIdx;
|
||||||
ref.read(navRailIndexStateProvider.notifier).state =
|
if (railIdx > 1 && buttonIdx <= 1) {
|
||||||
buttonIdx;
|
ref.read(leftDrawerStateProvider.notifier).state = false;
|
||||||
}
|
}
|
||||||
onTap?.call();
|
onTap?.call();
|
||||||
},
|
},
|
||||||
@ -218,9 +188,11 @@ Widget customNavigationDestination(
|
|||||||
onTap: isSelected
|
onTap: isSelected
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
if (!isNavigator) {
|
|
||||||
ref.read(navRailIndexStateProvider.notifier).state =
|
ref.read(navRailIndexStateProvider.notifier).state =
|
||||||
buttonIdx;
|
buttonIdx;
|
||||||
|
if (railIdx > 1 && buttonIdx <= 1) {
|
||||||
|
ref.read(leftDrawerStateProvider.notifier).state =
|
||||||
|
false;
|
||||||
}
|
}
|
||||||
onTap?.call();
|
onTap?.call();
|
||||||
},
|
},
|
||||||
|
@ -16,7 +16,8 @@ class PageBase extends ConsumerWidget {
|
|||||||
return Stack(
|
return Stack(
|
||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
padding: kIsWindows || kIsMacOS ? kPt28 : EdgeInsets.zero,
|
padding: const EdgeInsets.only(bottom: 70) +
|
||||||
|
(kIsWindows || kIsMacOS ? kPt28 : EdgeInsets.zero),
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
backgroundColor: Theme.of(context).colorScheme.background,
|
backgroundColor: Theme.of(context).colorScheme.background,
|
||||||
|
@ -152,3 +152,41 @@ class RequestDetailsCard extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SidebarEnvironmentCard extends StatelessWidget {
|
||||||
|
const SidebarEnvironmentCard({
|
||||||
|
super.key,
|
||||||
|
required this.id,
|
||||||
|
this.isGlobal = false,
|
||||||
|
this.isSelected = false,
|
||||||
|
this.isActive = false,
|
||||||
|
this.name,
|
||||||
|
this.editRequestId,
|
||||||
|
this.onTap,
|
||||||
|
this.onDoubleTap,
|
||||||
|
this.onSecondaryTap,
|
||||||
|
this.onChangedNameEditor,
|
||||||
|
this.focusNode,
|
||||||
|
this.onTapOutsideNameEditor,
|
||||||
|
this.onMenuSelected,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String id;
|
||||||
|
final bool isGlobal;
|
||||||
|
final bool isSelected;
|
||||||
|
final bool isActive;
|
||||||
|
final String? name;
|
||||||
|
final String? editRequestId;
|
||||||
|
final void Function()? onTap;
|
||||||
|
final void Function()? onDoubleTap;
|
||||||
|
final void Function()? onSecondaryTap;
|
||||||
|
final Function(String)? onChangedNameEditor;
|
||||||
|
final FocusNode? focusNode;
|
||||||
|
final Function()? onTapOutsideNameEditor;
|
||||||
|
final Function(RequestItemMenuOption)? onMenuSelected;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return const SizedBox();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
|
import 'package:apidash/screens/mobile/widgets/left_drawer.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:inner_drawer/inner_drawer.dart';
|
||||||
import 'package:multi_split_view/multi_split_view.dart';
|
import 'package:multi_split_view/multi_split_view.dart';
|
||||||
import 'package:apidash/consts.dart';
|
import 'package:apidash/consts.dart';
|
||||||
|
import 'package:apidash/providers/ui_providers.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
|
||||||
class DashboardSplitView extends StatefulWidget {
|
class DashboardSplitView extends StatefulWidget {
|
||||||
const DashboardSplitView({
|
const DashboardSplitView({
|
||||||
@ -110,3 +115,85 @@ class _EqualSplitViewState extends State<EqualSplitView> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TwoDrawerSplitView extends HookConsumerWidget {
|
||||||
|
const TwoDrawerSplitView({
|
||||||
|
super.key,
|
||||||
|
required this.innerDrawerKey,
|
||||||
|
required this.offset,
|
||||||
|
required this.mainContent,
|
||||||
|
required this.leftDrawerContent,
|
||||||
|
this.rightDrawerContent,
|
||||||
|
});
|
||||||
|
|
||||||
|
final GlobalKey<InnerDrawerState> innerDrawerKey;
|
||||||
|
final IDOffset offset;
|
||||||
|
final Widget mainContent;
|
||||||
|
final Widget leftDrawerContent;
|
||||||
|
final Widget? rightDrawerContent;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
ValueNotifier<double> dragPosition = useState(0.0);
|
||||||
|
ValueNotifier<InnerDrawerDirection?> drawerDirection =
|
||||||
|
ValueNotifier(InnerDrawerDirection.start);
|
||||||
|
|
||||||
|
Color calculateBackgroundColor(double dragPosition) {
|
||||||
|
Color start = Theme.of(context).colorScheme.surface;
|
||||||
|
Color end = Theme.of(context).colorScheme.onInverseSurface;
|
||||||
|
return dragPosition == 0 ? start : end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return InnerDrawer(
|
||||||
|
key: innerDrawerKey,
|
||||||
|
swipe: true,
|
||||||
|
swipeChild: true,
|
||||||
|
onTapClose: true,
|
||||||
|
offset: offset,
|
||||||
|
boxShadow: [
|
||||||
|
BoxShadow(
|
||||||
|
offset: const Offset(1, 0),
|
||||||
|
color: Theme.of(context).colorScheme.onInverseSurface,
|
||||||
|
blurRadius: 0,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
colorTransitionChild: Colors.transparent,
|
||||||
|
colorTransitionScaffold: Colors.transparent,
|
||||||
|
rightAnimationType: InnerDrawerAnimation.linear,
|
||||||
|
backgroundDecoration:
|
||||||
|
BoxDecoration(color: Theme.of(context).colorScheme.onInverseSurface),
|
||||||
|
onDragUpdate: (value, direction) {
|
||||||
|
drawerDirection.value = direction;
|
||||||
|
if (value > 0.98 && direction == InnerDrawerDirection.start) {
|
||||||
|
dragPosition.value = 1;
|
||||||
|
} else {
|
||||||
|
dragPosition.value = 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
innerDrawerCallback: (isOpened) {
|
||||||
|
if (drawerDirection.value == InnerDrawerDirection.start) {
|
||||||
|
ref.read(leftDrawerStateProvider.notifier).state = isOpened;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
leftChild: LeftDrawer(drawerContent: leftDrawerContent),
|
||||||
|
rightChild: rightDrawerContent,
|
||||||
|
scaffold: ValueListenableBuilder<double>(
|
||||||
|
valueListenable: dragPosition,
|
||||||
|
builder: (context, value, child) {
|
||||||
|
return Container(
|
||||||
|
color: calculateBackgroundColor(value),
|
||||||
|
child: child,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: const BorderRadius.only(topLeft: Radius.circular(8)),
|
||||||
|
child: SafeArea(
|
||||||
|
minimum: kIsWindows || kIsMacOS ? kPt28 : EdgeInsets.zero,
|
||||||
|
bottom: false,
|
||||||
|
child: mainContent,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
16
pubspec.lock
16
pubspec.lock
@ -390,6 +390,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_hooks:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_hooks
|
||||||
|
sha256: cde36b12f7188c85286fba9b38cc5a902e7279f36dd676967106c041dc9dde70
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.20.5"
|
||||||
flutter_keyboard_visibility:
|
flutter_keyboard_visibility:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@ -576,6 +584,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
hooks_riverpod:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: hooks_riverpod
|
||||||
|
sha256: "45b2030a18bcd6dbd680c2c91bc3b33e3fe7c323e3acb5ecec93a613e2fbaa8a"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.5.1"
|
||||||
html:
|
html:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -61,6 +61,8 @@ dependencies:
|
|||||||
flex_color_scheme: ^7.3.1
|
flex_color_scheme: ^7.3.1
|
||||||
data_table_2: ^2.5.11
|
data_table_2: ^2.5.11
|
||||||
file_selector: ^1.0.3
|
file_selector: ^1.0.3
|
||||||
|
hooks_riverpod: ^2.5.1
|
||||||
|
flutter_hooks: ^0.20.5
|
||||||
|
|
||||||
dependency_overrides:
|
dependency_overrides:
|
||||||
web: ^0.5.0
|
web: ^0.5.0
|
||||||
|
Reference in New Issue
Block a user