7
7
using System . Windows . Controls ;
8
8
using System . Net . Http ;
9
9
using System . Text . Json ;
10
-
11
10
using Flow . Launcher . Plugin ;
12
11
using Flow . Launcher . Plugin . SharedCommands ;
13
12
14
13
namespace Flow . Launcher . Plugin . Weather
15
14
{
15
+ /// <summary>
16
+ /// Represents the main class of the Weather plugin.
17
+ /// </summary>
16
18
public class Main : IAsyncPlugin , ISettingProvider , IContextMenu
17
19
{
18
- private string ClassName => GetType ( ) . Name ;
19
- private PluginInitContext _context ;
20
- private Settings _settings ;
21
- private bool UseFahrenheit => _settings . useFahrenheit ;
22
-
23
- // OLD client
24
- // private readonly OpenMeteoClient _client;
25
-
26
- // NEW client
27
- private readonly OpenMeteoApiClient _weather_client ;
28
-
29
- private readonly CityLookupService cityService ;
30
-
31
- public Main ( )
20
+ private PluginInitContext context ;
21
+ private Settings settings ;
22
+ private bool UseFahrenheit => settings . useFahrenheit ;
23
+ private OpenMeteoApiClient weatherClient ;
24
+ private CityLookupService cityService ;
25
+ public Task InitAsync ( PluginInitContext context )
32
26
{
33
- // OLD client
34
- // _client = new OpenMeteoClient();
35
- // NEW client
36
- _weather_client = new OpenMeteoApiClient ( ) ;
37
- cityService = new CityLookupService ( ) ;
38
- }
39
-
40
- // Initialise query url
41
- public async Task InitAsync ( PluginInitContext context )
42
- {
43
- _context = context ;
44
- _settings = _context . API . LoadSettingJsonStorage < Settings > ( ) ;
45
-
46
-
27
+ this . context = context ;
28
+ settings = context . API . LoadSettingJsonStorage < Settings > ( ) ;
29
+ weatherClient = new OpenMeteoApiClient ( context ) ;
30
+ cityService = new CityLookupService ( context ) ;
31
+ return Task . CompletedTask ;
47
32
}
48
33
49
34
public async Task < List < Result > > QueryAsync ( Query query , CancellationToken token )
@@ -52,16 +37,15 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
52
37
53
38
if ( string . IsNullOrWhiteSpace ( searchTerm ) )
54
39
{
55
- if ( ! string . IsNullOrWhiteSpace ( _settings . defaultLocation ) )
40
+ if ( ! string . IsNullOrWhiteSpace ( settings . defaultLocation ) )
56
41
{
57
- searchTerm = _settings . defaultLocation ;
42
+ searchTerm = settings . defaultLocation ;
58
43
}
59
44
else
60
45
{
61
46
return new List < Result >
62
47
{
63
- new Result
64
- {
48
+ new ( ) {
65
49
Title = "Please enter a city name" ,
66
50
IcoPath = "Images\\ weather-icon.png"
67
51
}
@@ -71,21 +55,13 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
71
55
try
72
56
{
73
57
token . ThrowIfCancellationRequested ( ) ;
74
-
75
- // Get city data
76
- // OLD
77
- // GeocodingOptions geocodingData = new GeocodingOptions(searchTerm);
78
- // GeocodingApiResponse geocodingResult = await _client.GetLocationDataAsync(geocodingData);
79
-
80
- // NEW
81
58
var cityDetails = await cityService . GetCityDetailsAsync ( searchTerm ) ;
82
59
83
60
if ( cityDetails == null || cityDetails ? . Latitude == null || cityDetails ? . Longitude == null )
84
61
{
85
62
return new List < Result >
86
63
{
87
- new Result
88
- {
64
+ new ( ) {
89
65
Title = "City not found" ,
90
66
SubTitle = "Please check the city name and try again" ,
91
67
IcoPath = "Images\\ weather-icon.png" ,
@@ -94,19 +70,17 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
94
70
} ;
95
71
}
96
72
97
-
98
73
token . ThrowIfCancellationRequested ( ) ;
99
74
100
- WeatherForecast weatherData = await _weather_client . GetForecastAsync ( cityDetails . Latitude , cityDetails . Longitude ) ;
75
+ WeatherForecast weatherData = await weatherClient . GetForecastAsync ( cityDetails . Latitude , cityDetails . Longitude ) ;
101
76
102
77
token . ThrowIfCancellationRequested ( ) ;
103
78
104
79
if ( weatherData == null )
105
80
{
106
81
return new List < Result >
107
82
{
108
- new Result
109
- {
83
+ new ( ) {
110
84
Title = $ "Weather data not found for { cityDetails . Name } ",
111
85
SubTitle = $ "Please try again later",
112
86
IcoPath = "Images\\ weather-icon.png" ,
@@ -128,9 +102,9 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
128
102
129
103
// Set glyph (if enabled)
130
104
GlyphInfo glyph = null ;
131
- if ( _settings . useGlyphs )
105
+ if ( settings . useGlyphs )
132
106
{
133
- string fontPath = Path . Combine ( _context . CurrentPluginMetadata . PluginDirectory , "Resources" , "easy.ttf" ) ;
107
+ string fontPath = Path . Combine ( context . CurrentPluginMetadata . PluginDirectory , "Resources" , "easy.ttf" ) ;
134
108
PrivateFontCollection privateFonts = new PrivateFontCollection ( ) ;
135
109
privateFonts . AddFontFile ( fontPath ) ;
136
110
glyph = new GlyphInfo (
@@ -150,11 +124,9 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
150
124
// Result
151
125
return new List < Result >
152
126
{
153
- new Result
154
- {
127
+ new ( ) {
155
128
Title = $ "{ temp } { ( UseFahrenheit ? "°F" : "°C" ) } ",
156
129
SubTitle = subTitle ,
157
- // SubTitle = $"{_client.WeathercodeToString((int)(weatherData?.Current?.Weathercode))} ({weatherData?.Current?.Weathercode}) ({dayOrNight}) | {cityData.Name}, {cityData.Country}",
158
130
IcoPath = $ "Images\\ { GetWeatherIcon ( ( int ) ( weatherData ? . Current ? . WeatherCode ) , isNight ) } .png",
159
131
Glyph = glyph ,
160
132
}
@@ -177,27 +149,22 @@ public async Task<List<Result>> QueryAsync(Query query, CancellationToken token)
177
149
}
178
150
} ;
179
151
}
180
- return new List < Result > ( ) ;
181
152
}
182
153
183
154
public void Dispose ( )
184
155
{
185
156
// _httpClient.Dispose();
186
157
}
187
- public Control CreateSettingPanel ( ) => new SettingsControl ( _settings ) ;
158
+ public Control CreateSettingPanel ( ) => new SettingsControl ( settings ) ;
188
159
189
160
public List < Result > LoadContextMenus ( Result selectedResult )
190
161
{
191
- var results = new List < Result >
192
- {
193
-
194
- } ;
195
-
162
+ var results = new List < Result > { } ;
196
163
return results ;
197
164
}
198
165
199
166
// celsius to fahrenheit
200
- private double CelsiusToFahrenheit ( double celsius )
167
+ private static double CelsiusToFahrenheit ( double celsius )
201
168
{
202
169
return celsius * 9 / 5 + 32 ;
203
170
}
@@ -254,7 +221,7 @@ public string GetWeatherIcon(int wmoCode, bool isNight = false)
254
221
}
255
222
256
223
257
- private string GetDayIcon ( int wmoCode )
224
+ private static string GetDayIcon ( int wmoCode )
258
225
{
259
226
return wmoCode switch
260
227
{
@@ -311,24 +278,38 @@ public static string GetWeatherIconUnicode(int wmoCode, bool isNight = false)
311
278
312
279
}
313
280
314
-
315
281
public class CityDetails
316
282
{
317
283
public string DisplayName { get ; set ; }
318
284
public string Name { get ; set ; }
319
- public double Latitude { get ; set ; }
320
- public double Longitude { get ; set ; }
285
+ public string Latitude { get ; set ; }
286
+ public string Longitude { get ; set ; }
321
287
}
322
288
289
+
290
+ /// <summary>
291
+ /// Service for looking up city details using the OpenStreetMap Nominatim API.
292
+ /// </summary>
323
293
public class CityLookupService
324
294
{
325
- private static readonly HttpClient client = new HttpClient ( ) ;
326
-
327
- public CityLookupService ( )
295
+ private static readonly HttpClient client = new ( ) ;
296
+ private readonly PluginInitContext context ;
297
+
298
+ /// <summary>
299
+ /// Initializes a new instance of the <see cref="CityLookupService"/> class.
300
+ /// </summary>
301
+ /// <param name="context">The plugin initialization context.</param>
302
+ public CityLookupService ( PluginInitContext context )
328
303
{
304
+ this . context = context ;
329
305
client . DefaultRequestHeaders . Add ( "User-Agent" , "Flow.Launcher.Plugin.Weather" ) ;
330
306
}
331
307
308
+ /// <summary>
309
+ /// Gets the details of a city asynchronously.
310
+ /// </summary>
311
+ /// <param name="cityName">The name of the city to look up.</param>
312
+ /// <returns>A task that represents the asynchronous operation. The task result contains the city details.</returns>
332
313
public async Task < CityDetails > GetCityDetailsAsync ( string cityName )
333
314
{
334
315
string url = $ "https://nominatim.openstreetmap.org/search?q={ Uri . EscapeDataString ( cityName ) } &format=json&limit=1&accept-language=en";
@@ -352,8 +333,8 @@ public async Task<CityDetails> GetCityDetailsAsync(string cityName)
352
333
{
353
334
DisplayName = cityInfo . GetProperty ( "display_name" ) . GetString ( ) ,
354
335
Name = cityInfo . GetProperty ( "name" ) . GetString ( ) ,
355
- Latitude = double . Parse ( cityInfo . GetProperty ( "lat" ) . GetString ( ) ) ,
356
- Longitude = double . Parse ( cityInfo . GetProperty ( "lon" ) . GetString ( ) )
336
+ Latitude = cityInfo . GetProperty ( "lat" ) . GetString ( ) ,
337
+ Longitude = cityInfo . GetProperty ( "lon" ) . GetString ( )
357
338
} ;
358
339
}
359
340
0 commit comments