@@ -3,6 +3,8 @@ import 'package:flutter/material.dart';
33import '../widgets/control_panel.dart' ;
44import '../widgets/name_display.dart' ;
55import '../widgets/nav_rail.dart' ;
6+ import '../widgets/slide_panel.dart' ;
7+ import '../utils/device_size_helper.dart' ;
68import 'history_screen.dart' ;
79import 'lottery_screen.dart' ;
810import 'settings_screen.dart' ;
@@ -25,6 +27,13 @@ class _HomeScreenState extends State<HomeScreen> {
2527
2628 int _selectedIndex = 0 ;
2729
30+ void _openSlidePanel (Widget panelContent) {
31+ SlidePanelOverlay .show (
32+ context: context,
33+ child: panelContent,
34+ );
35+ }
36+
2837 @override
2938 Widget build (BuildContext context) {
3039 return LayoutBuilder (
@@ -37,13 +46,18 @@ class _HomeScreenState extends State<HomeScreen> {
3746 shortestSide <= _kPhoneMaxShortestSide;
3847 final bool isWideScreen = constraints.maxWidth > 800 || isLandscapePhone;
3948 final bool isRailVisible = constraints.maxWidth >= _kRailMinWidth;
49+ final bool isSmallDevice = DeviceSizeHelper .isSmallDevice (constraints);
4050
4151 return Scaffold (
4252 bottomNavigationBar: ! isRailVisible
4353 ? NavigationBar (
4454 selectedIndex: _selectedIndex,
45- onDestinationSelected: (index) =>
46- setState (() => _selectedIndex = index),
55+ onDestinationSelected: (index) {
56+ if (SlidePanelOverlay .isShowing) {
57+ SlidePanelOverlay .hide ();
58+ }
59+ setState (() => _selectedIndex = index);
60+ },
4761 destinations: const [
4862 NavigationDestination (
4963 icon: Icon (Icons .people_outline),
@@ -70,91 +84,27 @@ class _HomeScreenState extends State<HomeScreen> {
7084 NavRail (
7185 selectedIndex: _selectedIndex,
7286 onDestinationSelected: (int index) {
87+ if (SlidePanelOverlay .isShowing) {
88+ SlidePanelOverlay .hide ();
89+ }
7390 setState (() {
7491 _selectedIndex = index;
7592 });
7693 },
7794 ),
7895 if (isRailVisible) const VerticalDivider (thickness: 1 , width: 1 ),
79- Expanded (child: _buildBody (isWideScreen, constraints)),
96+ Expanded (child: _buildBody (isWideScreen, isSmallDevice, constraints)),
8097 ],
8198 ),
8299 );
83100 },
84101 );
85102 }
86103
87- Widget _buildBody (bool isWideScreen, BoxConstraints viewportConstraints) {
104+ Widget _buildBody (bool isWideScreen, bool isSmallDevice, BoxConstraints viewportConstraints) {
88105 switch (_selectedIndex) {
89106 case 0 :
90- if (isWideScreen) {
91- final normalPanelAvailableHeight =
92- viewportConstraints.maxHeight - (_kPanelGap * 2 );
93- const rightPanelReservedWidth = _kPanelWidth + _kPanelGap;
94-
95- return Container (
96- color: Theme .of (context).colorScheme.surfaceContainer,
97- child: Stack (
98- children: [
99- const Positioned (
100- left: 0 ,
101- right: rightPanelReservedWidth,
102- top: 0 ,
103- bottom: 0 ,
104- child: Padding (
105- padding: EdgeInsets .all (24 ),
106- child: NameDisplay (isWideScreen: true ),
107- ),
108- ),
109- Positioned (
110- right: _kPanelGap,
111- bottom: _kPanelGap,
112- child: SizedBox (
113- width: _kPanelWidth,
114- child: ControlPanel (
115- layoutMode: ControlPanelLayoutMode .autoFit,
116- availableHeight: normalPanelAvailableHeight,
117- ),
118- ),
119- ),
120- ],
121- ),
122- );
123- } else {
124- return Container (
125- color: Theme .of (context).colorScheme.surfaceContainer,
126- child: Column (
127- children: [
128- const Expanded (
129- child: Padding (
130- padding: EdgeInsets .all (16 ),
131- child: NameDisplay (isWideScreen: false ),
132- ),
133- ),
134- Container (
135- padding: const EdgeInsets .symmetric (
136- horizontal: 8 ,
137- vertical: 6 ,
138- ),
139- decoration: BoxDecoration (
140- color: Theme .of (context).cardColor,
141- boxShadow: [
142- BoxShadow (
143- color: Colors .black.withValues (alpha: 0.1 ),
144- blurRadius: 4 ,
145- offset: const Offset (0 , - 2 ),
146- ),
147- ],
148- ),
149- child: const SizedBox (
150- height: _kNarrowPanelHeight,
151- child: ControlPanel (),
152- ),
153- ),
154- ],
155- ),
156- );
157- }
107+ return _buildRollCallScreen (isWideScreen, isSmallDevice, viewportConstraints);
158108 case 1 :
159109 return const LotteryScreen ();
160110 case 2 :
@@ -165,4 +115,108 @@ class _HomeScreenState extends State<HomeScreen> {
165115 return const SizedBox .shrink ();
166116 }
167117 }
118+
119+ Widget _buildRollCallScreen (bool isWideScreen, bool isSmallDevice, BoxConstraints viewportConstraints) {
120+ if (isSmallDevice) {
121+ return Stack (
122+ children: [
123+ Container (
124+ color: Theme .of (context).colorScheme.surfaceContainer,
125+ child: const Padding (
126+ padding: EdgeInsets .all (16 ),
127+ child: NameDisplay (isWideScreen: false ),
128+ ),
129+ ),
130+ Positioned (
131+ right: 8 ,
132+ bottom: 8 ,
133+ child: FloatingActionButton .small (
134+ heroTag: 'rollcall_panel_fab' ,
135+ onPressed: () {
136+ _openSlidePanel (
137+ const ControlPanel (
138+ layoutMode: ControlPanelLayoutMode .compact,
139+ fillHeight: false ,
140+ ),
141+ );
142+ },
143+ backgroundColor: Theme .of (context).colorScheme.primary,
144+ foregroundColor: Colors .white,
145+ child: const Icon (Icons .tune, size: 20 ),
146+ ),
147+ ),
148+ ],
149+ );
150+ }
151+
152+ if (isWideScreen) {
153+ final normalPanelAvailableHeight =
154+ viewportConstraints.maxHeight - (_kPanelGap * 2 );
155+ const rightPanelReservedWidth = _kPanelWidth + _kPanelGap;
156+
157+ return Container (
158+ color: Theme .of (context).colorScheme.surfaceContainer,
159+ child: Stack (
160+ children: [
161+ const Positioned (
162+ left: 0 ,
163+ right: rightPanelReservedWidth,
164+ top: 0 ,
165+ bottom: 0 ,
166+ child: Padding (
167+ padding: EdgeInsets .all (24 ),
168+ child: NameDisplay (isWideScreen: true ),
169+ ),
170+ ),
171+ Positioned (
172+ right: _kPanelGap,
173+ bottom: _kPanelGap,
174+ child: SizedBox (
175+ width: _kPanelWidth,
176+ child: ControlPanel (
177+ layoutMode: ControlPanelLayoutMode .autoFit,
178+ availableHeight: normalPanelAvailableHeight,
179+ ),
180+ ),
181+ ),
182+ ],
183+ ),
184+ );
185+ } else {
186+ return Container (
187+ color: Theme .of (context).colorScheme.surfaceContainer,
188+ child: SafeArea (
189+ child: Column (
190+ children: [
191+ const Expanded (
192+ child: Padding (
193+ padding: EdgeInsets .all (16 ),
194+ child: NameDisplay (isWideScreen: false ),
195+ ),
196+ ),
197+ Container (
198+ decoration: BoxDecoration (
199+ color: Theme .of (context).cardColor,
200+ boxShadow: [
201+ BoxShadow (
202+ color: Colors .black.withValues (alpha: 0.1 ),
203+ blurRadius: 4 ,
204+ offset: const Offset (0 , - 2 ),
205+ ),
206+ ],
207+ ),
208+ constraints: BoxConstraints (
209+ maxHeight: _kNarrowPanelHeight,
210+ ),
211+ child: const Padding (
212+ padding: EdgeInsets .all (8 ),
213+ child: ControlPanel (),
214+ ),
215+ ),
216+ ],
217+ ),
218+ ),
219+ );
220+ }
221+ }
168222}
0 commit comments