@@ -7,60 +7,41 @@ import '../extensions/build_context_x.dart';
7
7
import '../weather/view/city_search_field.dart' ;
8
8
import '../weather/weather_model.dart' ;
9
9
10
- class SideBar extends StatelessWidget with WatchItMixin {
10
+ class SideBar extends StatefulWidget with WatchItStatefulWidgetMixin {
11
11
const SideBar ({super .key, this .onSelected});
12
12
13
13
final VoidCallback ? onSelected;
14
14
15
+ @override
16
+ State <SideBar > createState () => _SideBarState ();
17
+ }
18
+
19
+ class _SideBarState extends State <SideBar > {
15
20
@override
16
21
Widget build (BuildContext context) {
17
22
final theme = context.theme;
18
23
19
- final model = di <WeatherModel >();
20
-
21
24
final favLocationsLength =
22
25
watchPropertyValue ((WeatherModel m) => m.favLocations.length);
23
26
final favLocations = watchPropertyValue ((WeatherModel m) => m.favLocations);
24
- final lastLocation = watchPropertyValue ((WeatherModel m) => m.lastLocation);
27
+ final currentLocation =
28
+ watchPropertyValue ((WeatherModel m) => m.lastLocation);
25
29
26
30
final listView = ListView .builder (
27
31
itemCount: favLocationsLength,
28
32
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,
64
45
);
65
46
},
66
47
);
@@ -89,3 +70,69 @@ class SideBar extends StatelessWidget with WatchItMixin {
89
70
);
90
71
}
91
72
}
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