Skip to content

Commit fe684e0

Browse files
authored
Merge pull request #408 from DenserMeerkat/add-feat-desktop-responsiveness
feat: desktop responsiveness
2 parents a49bcec + 126de74 commit fe684e0

21 files changed

+525
-557
lines changed

lib/app.dart

+18-19
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
55
import 'package:window_manager/window_manager.dart' hide WindowCaption;
66
import 'widgets/widgets.dart' show WindowCaption;
77
import 'providers/providers.dart';
8-
import 'screens/screens.dart';
98
import 'extensions/extensions.dart';
9+
import 'screens/screens.dart';
1010
import 'consts.dart';
1111

1212
class App extends ConsumerStatefulWidget {
@@ -95,7 +95,7 @@ class _AppState extends ConsumerState<App> with WindowListener {
9595

9696
@override
9797
Widget build(BuildContext context) {
98-
return const Dashboard();
98+
return context.isMediumWindow ? const MobileDashboard() : const Dashboard();
9999
}
100100
}
101101

@@ -125,24 +125,23 @@ class DashApp extends ConsumerWidget {
125125
visualDensity: VisualDensity.adaptivePlatformDensity,
126126
),
127127
themeMode: isDarkMode ? ThemeMode.dark : ThemeMode.light,
128-
home: kIsMobile
129-
? context.isLargeWidth
130-
? const Dashboard()
131-
: const MobileDashboard()
132-
: Stack(
133-
children: [
134-
kIsLinux ? const Dashboard() : const App(),
135-
if (kIsWindows)
136-
SizedBox(
137-
height: 29,
138-
child: WindowCaption(
139-
backgroundColor: Colors.transparent,
140-
brightness:
141-
isDarkMode ? Brightness.dark : Brightness.light,
142-
),
143-
),
144-
],
128+
home: Stack(
129+
children: [
130+
!kIsLinux && !kIsMobile
131+
? const App()
132+
: context.isMediumWindow
133+
? const MobileDashboard()
134+
: const Dashboard(),
135+
if (kIsWindows)
136+
SizedBox(
137+
height: 29,
138+
child: WindowCaption(
139+
backgroundColor: Colors.transparent,
140+
brightness: isDarkMode ? Brightness.dark : Brightness.light,
141+
),
145142
),
143+
],
144+
),
146145
);
147146
}
148147
}

lib/consts.dart

+14-2
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,14 @@ final kColorLightDanger = Colors.red.withOpacity(0.9);
3535
const kColorDarkDanger = Color(0xffcf6679);
3636

3737
const kWindowTitle = "API Dash";
38-
const kMinWindowSize = Size(900, 600);
38+
const kMinWindowSize = Size(320, 600);
3939
const kMinInitialWindowWidth = 1200.0;
4040
const kMinInitialWindowHeight = 800.0;
4141
const kMinRequestEditorDetailsCardPaneSize = 300.0;
42-
const kLargeMobileWidth = 600.0;
42+
const kCompactWindowWidth = 600.0;
43+
const kMediumWindowWidth = 840.0;
44+
const kExpandedWindowWidth = 1200.0;
45+
const kLargeWindowWidth = 1600.0;
4346

4447
const kColorSchemeSeed = Colors.blue;
4548
final kFontFamily = GoogleFonts.openSans().fontFamily;
@@ -106,12 +109,21 @@ const kP8CollectionPane = EdgeInsets.only(
106109
//right: 4.0,
107110
// bottom: 8.0,
108111
);
112+
const kPt28 = EdgeInsets.only(
113+
top: 28,
114+
);
115+
const kPt32 = EdgeInsets.only(
116+
top: 32,
117+
);
109118
const kPb10 = EdgeInsets.only(
110119
bottom: 10,
111120
);
112121
const kPb15 = EdgeInsets.only(
113122
bottom: 15,
114123
);
124+
const kPb70 = EdgeInsets.only(
125+
bottom: 70,
126+
);
115127
const kHSpacer4 = SizedBox(width: 4);
116128
const kHSpacer5 = SizedBox(width: 5);
117129
const kHSpacer10 = SizedBox(width: 10);

lib/extensions/context_extensions.dart

+16-4
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,21 @@ import 'package:apidash/consts.dart';
22
import 'package:flutter/material.dart';
33

44
extension MediaQueryExtension on BuildContext {
5-
bool get isLargeWidth =>
6-
MediaQuery.of(this).size.width > kMinWindowSize.width;
5+
bool get isCompactWindow =>
6+
MediaQuery.of(this).size.width < kCompactWindowWidth;
77

8-
bool get isMobile =>
9-
kIsMobile && MediaQuery.of(this).size.width < kMinWindowSize.width;
8+
bool get isMediumWindow =>
9+
MediaQuery.of(this).size.width < kMediumWindowWidth;
10+
11+
bool get isExpandedWindow =>
12+
MediaQuery.of(this).size.width < kExpandedWindowWidth;
13+
14+
bool get isLargeWindow => MediaQuery.of(this).size.width < kLargeWindowWidth;
15+
16+
bool get isExtraLargeWindow =>
17+
MediaQuery.of(this).size.width > kLargeWindowWidth;
18+
19+
double get width => MediaQuery.of(this).size.width;
20+
21+
double get height => MediaQuery.of(this).size.height;
1022
}

lib/providers/ui_providers.dart

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import 'package:flutter/widgets.dart';
1+
import 'package:flutter/material.dart';
22
import 'package:flutter_riverpod/flutter_riverpod.dart';
3-
import 'package:inner_drawer/inner_drawer.dart';
43

5-
final mobileDrawerKeyProvider = StateProvider<GlobalKey<InnerDrawerState>>(
6-
(ref) => GlobalKey<InnerDrawerState>());
4+
final mobileScaffoldKeyStateProvider = StateProvider<GlobalKey<ScaffoldState>>(
5+
(ref) => GlobalKey<ScaffoldState>());
6+
final leftDrawerStateProvider = StateProvider<bool>((ref) => false);
77
final navRailIndexStateProvider = StateProvider<int>((ref) => 0);
88
final selectedIdEditStateProvider = StateProvider<String?>((ref) => null);
99
final codePaneVisibleStateProvider = StateProvider<bool>((ref) => false);

lib/screens/dashboard.dart

+16-2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,19 @@ class Dashboard extends ConsumerWidget {
3737
'Requests',
3838
style: Theme.of(context).textTheme.labelSmall,
3939
),
40+
kVSpacer10,
41+
IconButton(
42+
isSelected: railIdx == 1,
43+
onPressed: () {
44+
ref.read(navRailIndexStateProvider.notifier).state = 1;
45+
},
46+
icon: const Icon(Icons.computer_outlined),
47+
selectedIcon: const Icon(Icons.computer_rounded),
48+
),
49+
Text(
50+
'Variables',
51+
style: Theme.of(context).textTheme.labelSmall,
52+
),
4053
],
4154
),
4255
Expanded(
@@ -45,12 +58,12 @@ class Dashboard extends ConsumerWidget {
4558
children: [
4659
Padding(
4760
padding: const EdgeInsets.only(bottom: 16.0),
48-
child: bottomButton(context, ref, railIdx, 1,
61+
child: bottomButton(context, ref, railIdx, 2,
4962
Icons.help, Icons.help_outline),
5063
),
5164
Padding(
5265
padding: const EdgeInsets.only(bottom: 16.0),
53-
child: bottomButton(context, ref, railIdx, 2,
66+
child: bottomButton(context, ref, railIdx, 3,
5467
Icons.settings, Icons.settings_outlined),
5568
),
5669
],
@@ -81,6 +94,7 @@ class Dashboard extends ConsumerWidget {
8194
index: railIdx,
8295
children: const [
8396
HomePage(),
97+
SizedBox(),
8498
IntroPage(),
8599
SettingsPage(),
86100
],

lib/screens/home_page/collection_pane.dart

+90-81
Original file line numberDiff line numberDiff line change
@@ -22,91 +22,101 @@ class CollectionPane extends ConsumerWidget {
2222
child: CircularProgressIndicator(),
2323
);
2424
}
25-
return Padding(
26-
padding: kIsMacOS ? kP24CollectionPane : kP8CollectionPane,
27-
child: Column(
28-
crossAxisAlignment: CrossAxisAlignment.stretch,
29-
children: [
30-
Padding(
31-
padding: kPe8,
32-
child: Wrap(
33-
alignment: WrapAlignment.spaceBetween,
34-
children: [
35-
TextButton.icon(
36-
onPressed: (savingData || !hasUnsavedChanges)
37-
? null
38-
: () async {
39-
overlayWidget.show(
40-
widget:
41-
const SavingOverlay(saveCompleted: false));
25+
return Drawer(
26+
shape: const ContinuousRectangleBorder(),
27+
backgroundColor: Theme.of(context).colorScheme.surface,
28+
surfaceTintColor: kColorTransparent,
29+
child: Padding(
30+
padding: (!context.isMediumWindow && kIsMacOS
31+
? kP24CollectionPane
32+
: kP8CollectionPane) +
33+
(context.isMediumWindow ? kPb70 : EdgeInsets.zero),
34+
child: Column(
35+
crossAxisAlignment: CrossAxisAlignment.stretch,
36+
children: [
37+
Padding(
38+
padding: kPe8,
39+
child: Wrap(
40+
alignment: WrapAlignment.spaceBetween,
41+
children: [
42+
TextButton.icon(
43+
onPressed: (savingData || !hasUnsavedChanges)
44+
? null
45+
: () async {
46+
overlayWidget.show(
47+
widget:
48+
const SavingOverlay(saveCompleted: false));
4249

43-
await ref
44-
.read(collectionStateNotifierProvider.notifier)
45-
.saveData();
46-
overlayWidget.hide();
47-
overlayWidget.show(
48-
widget: const SavingOverlay(saveCompleted: true));
49-
await Future.delayed(const Duration(seconds: 1));
50-
overlayWidget.hide();
51-
},
52-
icon: const Icon(
53-
Icons.save,
54-
size: 20,
55-
),
56-
label: const Text(
57-
kLabelSave,
58-
style: kTextStyleButton,
50+
await ref
51+
.read(collectionStateNotifierProvider.notifier)
52+
.saveData();
53+
overlayWidget.hide();
54+
overlayWidget.show(
55+
widget:
56+
const SavingOverlay(saveCompleted: true));
57+
await Future.delayed(const Duration(seconds: 1));
58+
overlayWidget.hide();
59+
},
60+
icon: const Icon(
61+
Icons.save,
62+
size: 20,
63+
),
64+
label: const Text(
65+
kLabelSave,
66+
style: kTextStyleButton,
67+
),
5968
),
60-
),
61-
//const Spacer(),
62-
ElevatedButton(
63-
onPressed: () {
64-
ref.read(collectionStateNotifierProvider.notifier).add();
65-
},
66-
child: const Text(
67-
kLabelPlusNew,
68-
style: kTextStyleButton,
69+
//const Spacer(),
70+
ElevatedButton(
71+
onPressed: () {
72+
ref.read(collectionStateNotifierProvider.notifier).add();
73+
},
74+
child: const Text(
75+
kLabelPlusNew,
76+
style: kTextStyleButton,
77+
),
6978
),
70-
),
71-
],
72-
),
73-
),
74-
kVSpacer10,
75-
Container(
76-
margin: const EdgeInsets.only(right: 8),
77-
decoration: BoxDecoration(
78-
borderRadius: kBorderRadius8,
79-
border: Border.all(
80-
color: Theme.of(context).colorScheme.surfaceVariant,
79+
],
8180
),
8281
),
83-
child: Row(
84-
children: [
85-
kHSpacer5,
86-
Icon(
87-
Icons.filter_alt,
88-
size: 18,
89-
color: Theme.of(context).colorScheme.secondary,
82+
kVSpacer10,
83+
Container(
84+
margin: const EdgeInsets.only(right: 8),
85+
decoration: BoxDecoration(
86+
borderRadius: kBorderRadius8,
87+
border: Border.all(
88+
color: Theme.of(context).colorScheme.surfaceVariant,
9089
),
91-
kHSpacer5,
92-
Expanded(
93-
child: RawTextField(
94-
style: Theme.of(context).textTheme.bodyMedium,
95-
hintText: "Filter by name or URL",
96-
onChanged: (value) {
97-
ref.read(searchQueryProvider.notifier).state =
98-
value.toLowerCase();
99-
},
90+
),
91+
child: Row(
92+
children: [
93+
kHSpacer5,
94+
Icon(
95+
Icons.filter_alt,
96+
size: 18,
97+
color: Theme.of(context).colorScheme.secondary,
10098
),
101-
),
102-
],
99+
kHSpacer5,
100+
Expanded(
101+
child: RawTextField(
102+
style: Theme.of(context).textTheme.bodyMedium,
103+
hintText: "Filter by name or URL",
104+
onChanged: (value) {
105+
ref.read(searchQueryProvider.notifier).state =
106+
value.toLowerCase();
107+
},
108+
),
109+
),
110+
],
111+
),
112+
),
113+
kVSpacer10,
114+
const Expanded(
115+
child: RequestList(),
103116
),
104-
),
105-
kVSpacer10,
106-
const Expanded(
107-
child: RequestList(),
108-
),
109-
],
117+
kVSpacer5
118+
],
119+
),
110120
),
111121
);
112122
}
@@ -150,7 +160,7 @@ class _RequestListState extends ConsumerState<RequestList> {
150160
radius: const Radius.circular(12),
151161
child: filterQuery.isEmpty
152162
? ReorderableListView.builder(
153-
padding: context.isMobile
163+
padding: context.isMediumWindow
154164
? EdgeInsets.only(
155165
bottom: MediaQuery.paddingOf(context).bottom,
156166
right: 8,
@@ -198,7 +208,7 @@ class _RequestListState extends ConsumerState<RequestList> {
198208
},
199209
)
200210
: ListView(
201-
padding: kIsMobile
211+
padding: context.isMediumWindow
202212
? EdgeInsets.only(
203213
bottom: MediaQuery.paddingOf(context).bottom,
204214
right: 8,
@@ -240,7 +250,6 @@ class RequestItem extends ConsumerWidget {
240250
Widget build(BuildContext context, WidgetRef ref) {
241251
final selectedId = ref.watch(selectedIdStateProvider);
242252
final editRequestId = ref.watch(selectedIdEditStateProvider);
243-
final mobileDrawerKey = ref.watch(mobileDrawerKeyProvider);
244253

245254
return SidebarRequestCard(
246255
id: id,
@@ -250,7 +259,7 @@ class RequestItem extends ConsumerWidget {
250259
selectedId: selectedId,
251260
editRequestId: editRequestId,
252261
onTap: () {
253-
mobileDrawerKey.currentState?.close();
262+
ref.read(mobileScaffoldKeyStateProvider).currentState?.closeDrawer();
254263
ref.read(selectedIdStateProvider.notifier).state = id;
255264
},
256265
// onDoubleTap: () {

0 commit comments

Comments
 (0)