Skip to content

Commit 888427f

Browse files
committed
style: optimize imports
1 parent 4838a76 commit 888427f

6 files changed

Lines changed: 168 additions & 130 deletions

File tree

lib/api/exptech.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ import 'package:option_result/result.dart';
3131
import 'package:zstandard/zstandard.dart';
3232

3333
part '_client.dart';
34+
part 'endpoints/app.dart';
35+
part 'endpoints/device.dart';
3436
part 'endpoints/earthquake.dart';
35-
part 'endpoints/weather.dart';
36-
part 'endpoints/tsunami.dart';
3737
part 'endpoints/history.dart';
3838
part 'endpoints/station.dart';
39-
part 'endpoints/device.dart';
40-
part 'endpoints/app.dart';
39+
part 'endpoints/tsunami.dart';
40+
part 'endpoints/weather.dart';
4141

4242
/// Client for the ExpTech API.
4343
class ExpTech

lib/app.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import 'dart:async';
22
import 'dart:io';
33

4-
import 'package:dpip/app/welcome/4-permissions/page.dart';
54
import 'package:dpip/app/map/_lib/utils.dart';
65
import 'package:dpip/app/map/page.dart';
6+
import 'package:dpip/app/welcome/4-permissions/page.dart';
77
import 'package:dpip/core/notify.dart';
88
import 'package:dpip/core/preference.dart';
99
import 'package:dpip/core/providers.dart';

lib/app/home/_widgets/location_button.dart

Lines changed: 153 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
1-
import 'package:dpip/app/home/_models/home_location.dart';
21
import 'package:dpip/api/model/location/location.dart';
3-
import 'package:dpip/app/home/_widgets/blurred_button.dart';
2+
import 'package:dpip/app/home/_models/home_red_button.dart';
43
import 'package:dpip/core/i18n.dart';
54
import 'package:dpip/global.dart';
65
import 'package:dpip/models/settings/location.dart';
76
import 'package:dpip/router.dart';
87
import 'package:dpip/utils/extensions/build_context.dart';
9-
import 'package:dpip/widgets/list/segmented_list.dart';
108
import 'package:flutter/material.dart';
119
import 'package:material_symbols_icons/symbols.dart';
1210
import 'package:provider/provider.dart';
1311

1412
class LocationButton extends StatelessWidget {
15-
const LocationButton({super.key});
13+
final String? temporaryCode;
14+
final ValueChanged<String?>? onLocationChanged;
15+
16+
const LocationButton({
17+
super.key,
18+
this.temporaryCode,
19+
this.onLocationChanged,
20+
});
1621

1722
@override
1823
Widget build(BuildContext context) {
19-
return Consumer2<HomeLocationModel, SettingsLocationModel>(
20-
builder: (context, homeLocation, settingsLocation, child) {
21-
final savedCode = settingsLocation.code;
22-
final favorited = settingsLocation.favorited;
23-
final temporaryCode = homeLocation.temporaryCode;
24+
return Selector<SettingsLocationModel, (String?, Set<String>)>(
25+
selector: (context, model) => (model.code, model.favorited),
26+
builder: (context, data, child) {
27+
final (savedCode, favorited) = data;
2428
final displayCode = temporaryCode ?? savedCode;
2529
final location = Global.location[displayCode];
2630

@@ -56,27 +60,22 @@ class LocationButton extends StatelessWidget {
5660

5761
showModalBottomSheet<String?>(
5862
context: context,
59-
constraints: context.bottomSheetConstraints,
63+
backgroundColor: Colors.transparent,
6064
isScrollControlled: true,
61-
builder: (context) => _LocationMenuSheet(
65+
builder: (sheetContext) => _LocationMenuSheet(
6266
savedCode: savedCode,
6367
favorited: favorited,
6468
currentCode: currentCode,
6569
onLocationSelected: (code) {
66-
Navigator.of(context).pop();
67-
final model = context.read<HomeLocationModel>();
70+
Navigator.of(sheetContext).pop();
6871
if (code == savedCode) {
69-
model.setTemporaryCode(null);
72+
onLocationChanged?.call(null);
7073
} else {
71-
model.setTemporaryCode(code);
74+
onLocationChanged?.call(code);
7275
}
7376
},
74-
onAddLocationPressed: () {
75-
Navigator.of(context).pop();
76-
SettingsLocationSelectRoute().push(context);
77-
},
7877
onSettingsPressed: () {
79-
Navigator.of(context).pop();
78+
Navigator.of(sheetContext).pop();
8079
SettingsLocationRoute().push(context);
8180
},
8281
),
@@ -89,15 +88,13 @@ class _LocationMenuSheet extends StatefulWidget {
8988
final Set<String> favorited;
9089
final String? currentCode;
9190
final ValueChanged<String> onLocationSelected;
92-
final VoidCallback onAddLocationPressed;
9391
final VoidCallback onSettingsPressed;
9492

9593
const _LocationMenuSheet({
9694
required this.savedCode,
9795
required this.favorited,
9896
required this.currentCode,
9997
required this.onLocationSelected,
100-
required this.onAddLocationPressed,
10198
required this.onSettingsPressed,
10299
});
103100

@@ -125,32 +122,57 @@ class _LocationMenuSheetState extends State<_LocationMenuSheet> {
125122

126123
@override
127124
Widget build(BuildContext context) {
128-
return Material(
129-
borderRadius: const .vertical(top: .circular(16)),
130-
clipBehavior: .antiAlias,
131-
child: Scaffold(
132-
appBar: AppBar(
133-
leading: BackButton(
134-
onPressed: _selectedCity != null
135-
? () => setState(() => _selectedCity = null)
136-
: null,
125+
return Container(
126+
margin: const EdgeInsets.all(16),
127+
constraints: BoxConstraints(
128+
maxHeight: MediaQuery.of(context).size.height * 0.7,
129+
),
130+
decoration: BoxDecoration(
131+
color: context.colors.surfaceContainer,
132+
borderRadius: BorderRadius.circular(16),
133+
),
134+
child: Column(
135+
mainAxisSize: MainAxisSize.min,
136+
children: [
137+
_buildHeader(context),
138+
Flexible(
139+
child: _selectedCity == null
140+
? _buildCityList(context)
141+
: _buildTownList(context),
137142
),
138-
title: Text('切換區域'.i18n),
139-
centerTitle: true,
140-
actions: [
143+
],
144+
),
145+
);
146+
}
147+
148+
Widget _buildHeader(BuildContext context) {
149+
return Padding(
150+
padding: const EdgeInsets.fromLTRB(8, 8, 8, 0),
151+
child: Row(
152+
children: [
153+
if (_selectedCity != null)
141154
IconButton(
142-
icon: const Icon(Symbols.settings_rounded),
143-
onPressed: widget.onSettingsPressed,
144-
tooltip: '位置設定'.i18n,
155+
onPressed: () => setState(() => _selectedCity = null),
156+
icon: const Icon(Symbols.arrow_back_rounded, size: 20),
157+
tooltip: '返回'.i18n,
158+
)
159+
else
160+
const SizedBox(width: 48),
161+
Expanded(
162+
child: Text(
163+
_selectedCity ?? '切換區域'.i18n,
164+
style: context.theme.textTheme.titleMedium?.copyWith(
165+
fontWeight: FontWeight.w600,
166+
),
167+
textAlign: TextAlign.center,
145168
),
146-
],
147-
),
148-
body: SingleChildScrollView(
149-
padding: .only(bottom: context.padding.bottom + 16),
150-
child: _selectedCity == null
151-
? _buildCityList(context)
152-
: _buildTownList(context),
153-
),
169+
),
170+
IconButton(
171+
onPressed: widget.onSettingsPressed,
172+
icon: const Icon(Symbols.settings_rounded, size: 20),
173+
tooltip: '位置設定'.i18n,
174+
),
175+
],
154176
),
155177
);
156178
}
@@ -188,92 +210,111 @@ class _LocationMenuSheetState extends State<_LocationMenuSheet> {
188210
}
189211
}
190212

191-
return Column(
192-
crossAxisAlignment: .start,
213+
return ListView(
214+
shrinkWrap: true,
215+
padding: const EdgeInsets.only(bottom: 16),
193216
children: [
194-
SegmentedList(
195-
label: Text('快速切換'.i18n),
196-
children: [
197-
for (var i = 0; i < quickItems.length; i++)
198-
SegmentedListTile(
199-
isFirst: i == 0,
200-
tileColor: quickItems[i].isSelected
201-
? context.colors.secondaryContainer
202-
: null,
203-
leading: Icon(
204-
quickItems[i].icon,
205-
fill: 1,
206-
color: quickItems[i].isSelected
217+
if (quickItems.isNotEmpty) ...[
218+
Padding(
219+
padding: const EdgeInsets.fromLTRB(16, 8, 16, 4),
220+
child: Text(
221+
'快速切換'.i18n,
222+
style: context.theme.textTheme.labelMedium?.copyWith(
223+
color: context.colors.onSurfaceVariant,
224+
),
225+
),
226+
),
227+
for (final item in quickItems)
228+
ListTile(
229+
dense: true,
230+
leading: Icon(
231+
item.icon,
232+
size: 20,
233+
color: item.isSelected
234+
? context.colors.primary
235+
: context.colors.onSurfaceVariant,
236+
),
237+
title: Text(
238+
item.name,
239+
style: TextStyle(
240+
color: item.isSelected
207241
? context.colors.primary
208-
: context.colors.onSurfaceVariant,
242+
: context.colors.onSurface,
243+
fontWeight: item.isSelected
244+
? FontWeight.w600
245+
: FontWeight.normal,
209246
),
210-
title: Text(
211-
quickItems[i].name,
212-
style: TextStyle(
213-
color: quickItems[i].isSelected
214-
? context.colors.primary
215-
: context.colors.onSurface,
216-
fontWeight: quickItems[i].isSelected
217-
? FontWeight.w600
218-
: FontWeight.normal,
219-
),
220-
),
221-
trailing: quickItems[i].isSelected
222-
? Icon(
223-
Symbols.check_rounded,
224-
color: context.colors.primary,
225-
)
226-
: null,
227-
onTap: () => widget.onLocationSelected(quickItems[i].code),
228247
),
229-
SegmentedListTile(
230-
isFirst: quickItems.isEmpty,
231-
isLast: true,
232-
leading: const Icon(Symbols.add_circle_rounded),
233-
title: Text('新增地點'.i18n),
234-
onTap: widget.onAddLocationPressed,
235-
),
236-
],
237-
),
238-
239-
SegmentedList.builder(
240-
label: Text('選擇縣市'.i18n),
241-
itemCount: cities.length,
242-
itemBuilder: (context, index) {
243-
final city = cities[index];
244-
245-
return SegmentedListTile(
246-
isFirst: index == 0,
247-
isLast: index == cities.length - 1,
248-
title: Text(city.cityWithLevel),
249-
subtitle: currentLocation?.cityWithLevel == city.cityWithLevel
250-
? Text('目前選擇'.i18n)
248+
trailing: item.isSelected
249+
? Icon(
250+
Symbols.check_rounded,
251+
size: 20,
252+
color: context.colors.primary,
253+
)
251254
: null,
252-
trailing: const Icon(Symbols.chevron_right_rounded),
253-
onTap: () => setState(() => _selectedCity = city.cityWithLevel),
254-
);
255-
},
255+
onTap: () => widget.onLocationSelected(item.code),
256+
),
257+
const Divider(height: 16),
258+
],
259+
Padding(
260+
padding: const EdgeInsets.fromLTRB(16, 8, 16, 4),
261+
child: Text(
262+
'選擇縣市'.i18n,
263+
style: context.theme.textTheme.labelMedium?.copyWith(
264+
color: context.colors.onSurfaceVariant,
265+
),
266+
),
256267
),
268+
for (final city in cities)
269+
ListTile(
270+
dense: true,
271+
title: Text(city.cityWithLevel),
272+
subtitle: currentLocation?.cityWithLevel == city.cityWithLevel
273+
? Text(
274+
'目前選擇'.i18n,
275+
style: TextStyle(
276+
color: context.colors.primary,
277+
fontSize: 12,
278+
),
279+
)
280+
: null,
281+
trailing: const Icon(Symbols.chevron_right_rounded, size: 20),
282+
onTap: () => setState(() => _selectedCity = city.cityWithLevel),
283+
),
257284
],
258285
);
259286
}
260287

261288
Widget _buildTownList(BuildContext context) {
262289
final towns = _towns;
263290

264-
return SegmentedList.builder(
265-
label: Text(_selectedCity!),
291+
return ListView.builder(
292+
shrinkWrap: true,
293+
padding: const EdgeInsets.only(bottom: 16),
266294
itemCount: towns.length,
267295
itemBuilder: (context, index) {
268296
final entry = towns[index];
269297
final code = entry.key;
270298
final town = entry.value;
271299
final isSelected = widget.currentCode == code;
300+
final isSaved = widget.savedCode == code;
301+
final isFavorited = widget.favorited.contains(code);
272302

273-
return SegmentedListTile(
274-
isFirst: index == 0,
275-
isLast: index == towns.length - 1,
276-
tileColor: isSelected ? context.colors.secondaryContainer : null,
303+
return ListTile(
304+
dense: true,
305+
leading: isSaved
306+
? Icon(
307+
Symbols.home_rounded,
308+
size: 20,
309+
color: context.colors.onSurfaceVariant,
310+
)
311+
: isFavorited
312+
? Icon(
313+
Symbols.star_rounded,
314+
size: 20,
315+
color: context.colors.onSurfaceVariant,
316+
)
317+
: const SizedBox(width: 20),
277318
title: Text(
278319
town.townWithLevel,
279320
style: TextStyle(
@@ -286,6 +327,7 @@ class _LocationMenuSheetState extends State<_LocationMenuSheet> {
286327
trailing: isSelected
287328
? Icon(
288329
Symbols.check_rounded,
330+
size: 20,
289331
color: context.colors.primary,
290332
)
291333
: null,

0 commit comments

Comments
 (0)