Skip to content

Commit 848b76f

Browse files
authored
feat: flutter upgrade and add location autocomplete (#15)
1 parent dfee70b commit 848b76f

19 files changed

+388
-182
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
branches: [master]
66

77
env:
8-
FLUTTER_VERSION: '3.27.4'
8+
FLUTTER_VERSION: '3.29.0'
99

1010
jobs:
1111
analyze:

.github/workflows/release.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
branches:
6+
- master
7+
workflow_dispatch:
8+
9+
jobs:
10+
release:
11+
permissions:
12+
contents: write
13+
pull-requests: write
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: googleapis/release-please-action@v4
17+
with:
18+
release-type: dart

.github/workflows/snap.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ on:
77
workflow_dispatch:
88

99
env:
10-
FLUTTER_VERSION: "3.27.4"
10+
FLUTTER_VERSION: "3.29.0"
1111

1212
jobs:
1313
build_and_release_linux_snap_edge_amd64:

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
*.swp
66
.DS_Store
77
.atom/
8+
.build/
89
.buildlog/
910
.history
1011
.svn/
12+
.swiftpm/
1113
migrate_working_dir/
1214

1315
# IntelliJ related

devtools_options.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
description: This file stores settings for Dart & Flutter DevTools.
2+
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
3+
extensions:

lib/app/side_bar.dart

Lines changed: 86 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,41 @@ import '../extensions/build_context_x.dart';
77
import '../weather/view/city_search_field.dart';
88
import '../weather/weather_model.dart';
99

10-
class SideBar extends StatelessWidget with WatchItMixin {
10+
class SideBar extends StatefulWidget with WatchItStatefulWidgetMixin {
1111
const SideBar({super.key, this.onSelected});
1212

1313
final VoidCallback? onSelected;
1414

15+
@override
16+
State<SideBar> createState() => _SideBarState();
17+
}
18+
19+
class _SideBarState extends State<SideBar> {
1520
@override
1621
Widget build(BuildContext context) {
1722
final theme = context.theme;
1823

19-
final model = di<WeatherModel>();
20-
2124
final favLocationsLength =
2225
watchPropertyValue((WeatherModel m) => m.favLocations.length);
2326
final favLocations = watchPropertyValue((WeatherModel m) => m.favLocations);
24-
final lastLocation = watchPropertyValue((WeatherModel m) => m.lastLocation);
27+
final currentLocation =
28+
watchPropertyValue((WeatherModel m) => m.lastLocation);
2529

2630
final listView = ListView.builder(
2731
itemCount: favLocationsLength,
2832
itemBuilder: (context, index) {
29-
final location = favLocations.elementAt(index);
30-
return Stack(
31-
alignment: Alignment.centerRight,
32-
children: [
33-
YaruMasterTile(
34-
onTap: () {
35-
model.loadWeather(cityName: location);
36-
onSelected?.call();
37-
},
38-
selected: lastLocation == location,
39-
title: Text(
40-
favLocations.elementAt(index),
41-
),
42-
),
43-
if (favLocationsLength > 1 && lastLocation == location)
44-
Positioned(
45-
right: 20,
46-
child: SizedBox.square(
47-
dimension: 30,
48-
child: IconButton(
49-
padding: EdgeInsets.zero,
50-
onPressed: () {
51-
model.removeFavLocation(location).then(
52-
(value) => model.loadWeather(
53-
cityName: favLocations.lastOrNull,
54-
),
55-
);
56-
},
57-
icon: const Icon(
58-
YaruIcons.window_close,
59-
),
60-
),
61-
),
62-
),
63-
],
33+
final selected = currentLocation == favLocations.elementAt(index);
34+
return Tile(
35+
selected: selected,
36+
location: favLocations.elementAt(index),
37+
onClear: favLocationsLength > 1
38+
? () => di<WeatherModel>().loadWeather(
39+
cityName: selected
40+
? favLocations.elementAtOrNull(index - 1)
41+
: currentLocation,
42+
)
43+
: null,
44+
onSelected: widget.onSelected,
6445
);
6546
},
6647
);
@@ -89,3 +70,69 @@ class SideBar extends StatelessWidget with WatchItMixin {
8970
);
9071
}
9172
}
73+
74+
class Tile extends StatefulWidget {
75+
const Tile({
76+
super.key,
77+
required this.location,
78+
required this.onSelected,
79+
required this.onClear,
80+
required this.selected,
81+
});
82+
83+
final String location;
84+
final VoidCallback? onSelected;
85+
final bool selected;
86+
final Function()? onClear;
87+
88+
@override
89+
State<Tile> createState() => _TileState();
90+
}
91+
92+
class _TileState extends State<Tile> {
93+
bool _hovered = false;
94+
95+
@override
96+
Widget build(BuildContext context) {
97+
return MouseRegion(
98+
onEnter: (_) => setState(() => _hovered = true),
99+
onExit: (_) => setState(() => _hovered = false),
100+
child: Stack(
101+
alignment: Alignment.centerRight,
102+
children: [
103+
Tooltip(
104+
message: widget.location,
105+
child: YaruMasterTile(
106+
onTap: () {
107+
di<WeatherModel>().loadWeather(cityName: widget.location);
108+
widget.onSelected?.call();
109+
},
110+
selected: widget.selected,
111+
title: Text(
112+
widget.location,
113+
),
114+
),
115+
),
116+
if (widget.onClear != null && (_hovered || widget.selected))
117+
Positioned(
118+
right: 20,
119+
child: SizedBox.square(
120+
dimension: 30,
121+
child: IconButton(
122+
padding: EdgeInsets.zero,
123+
onPressed: () {
124+
di<WeatherModel>().removeFavLocation(widget.location).then(
125+
(_) => widget.onClear?.call(),
126+
);
127+
},
128+
icon: const Icon(
129+
YaruIcons.window_close,
130+
),
131+
),
132+
),
133+
),
134+
],
135+
),
136+
);
137+
}
138+
}

0 commit comments

Comments
 (0)