mirror of
https://github.com/glanceapp/glance.git
synced 2025-06-22 02:41:23 +02:00
Allow specifying state in weather location
This commit is contained in:
parent
ad06146784
commit
d8d6625478
@ -579,6 +579,15 @@ Example:
|
|||||||
location: London, United Kingdom
|
location: London, United Kingdom
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
>
|
||||||
|
> US cities which have common names can have their state specified as the second parameter like such:
|
||||||
|
>
|
||||||
|
> * Greenville, North Carolina, United States
|
||||||
|
> * Greenville, South Carolina, United States
|
||||||
|
> * Greenville, Mississippi, United States
|
||||||
|
|
||||||
|
|
||||||
Preview:
|
Preview:
|
||||||
|
|
||||||

|

|
||||||
@ -592,6 +601,7 @@ Each bar represents a 2 hour interval. The yellow background represents sunrise
|
|||||||
| location | string | yes | |
|
| location | string | yes | |
|
||||||
| units | string | no | metric |
|
| units | string | no | metric |
|
||||||
| hide-location | boolean | no | false |
|
| hide-location | boolean | no | false |
|
||||||
|
| show-area-name | boolean | no | false |
|
||||||
|
|
||||||
##### `location`
|
##### `location`
|
||||||
The name of the city and country to fetch weather information for. Attempting to launch the applcation with an invalid location will result in an error. You can use the [gecoding API page](https://open-meteo.com/en/docs/geocoding-api) to search for your specific location. Glance will use the first result from the list if there are multiple.
|
The name of the city and country to fetch weather information for. Attempting to launch the applcation with an invalid location will result in an error. You can use the [gecoding API page](https://open-meteo.com/en/docs/geocoding-api) to search for your specific location. Glance will use the first result from the list if there are multiple.
|
||||||
@ -602,6 +612,19 @@ Whether to show the temperature in celsius or fahrenheit, possible values are `m
|
|||||||
##### `hide-location`
|
##### `hide-location`
|
||||||
Optionally don't display the location name on the widget.
|
Optionally don't display the location name on the widget.
|
||||||
|
|
||||||
|
##### `show-area-name`
|
||||||
|
Whether to display the state/administrative area in the location name. If set to `true` the location will be displayed as:
|
||||||
|
|
||||||
|
```
|
||||||
|
Greenville, North Carolina, United States
|
||||||
|
```
|
||||||
|
|
||||||
|
Otherwise, if set to `false` (which is the default) it'll be displayed as:
|
||||||
|
|
||||||
|
```
|
||||||
|
Greenville, United States
|
||||||
|
```
|
||||||
|
|
||||||
### Monitor
|
### Monitor
|
||||||
Display a list of sites and whether they are reachable (online) or not. This is determined by sending a HEAD request to the specified URL, if the response is 200 then the site is OK. The time it took to receive a response is also shown in milliseconds.
|
Display a list of sites and whether they are reachable (online) or not. This is determined by sending a HEAD request to the specified URL, if the response is 200 then the site is OK. The time it took to receive a response is also shown in milliseconds.
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
{{ if not .HideLocation }}
|
{{ if not .HideLocation }}
|
||||||
<div class="flex items-center justify-center margin-top-15 gap-7 size-h5">
|
<div class="flex items-center justify-center margin-top-15 gap-7 size-h5">
|
||||||
<div class="location-icon"></div>
|
<div class="location-icon"></div>
|
||||||
<div class="text-truncate">{{ .Place.Name }}, {{ .Place.Country }}</div>
|
<div class="text-truncate">{{ .Place.Name }},{{ if .ShowAreaName }} {{ .Place.Area }},{{ end }} {{ .Place.Country }}</div>
|
||||||
</div>
|
</div>
|
||||||
{{ end }}
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"slices"
|
"slices"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "time/tzdata"
|
_ "time/tzdata"
|
||||||
@ -17,6 +18,7 @@ type PlacesResponseJson struct {
|
|||||||
|
|
||||||
type PlaceJson struct {
|
type PlaceJson struct {
|
||||||
Name string
|
Name string
|
||||||
|
Area string `json:"admin1"`
|
||||||
Latitude float64
|
Latitude float64
|
||||||
Longitude float64
|
Longitude float64
|
||||||
Timezone string
|
Timezone string
|
||||||
@ -48,8 +50,41 @@ type weatherColumn struct {
|
|||||||
HasPrecipitation bool
|
HasPrecipitation bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var commonCountryAbbreviations = map[string]string{
|
||||||
|
"US": "United States",
|
||||||
|
"USA": "United States",
|
||||||
|
"UK": "United Kingdom",
|
||||||
|
}
|
||||||
|
|
||||||
|
func expandCountryAbbreviations(name string) string {
|
||||||
|
if expanded, ok := commonCountryAbbreviations[strings.TrimSpace(name)]; ok {
|
||||||
|
return expanded
|
||||||
|
}
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separates the location that Open Meteo accepts from the administrative area
|
||||||
|
// which can then be used to filter to the correct place after the list of places
|
||||||
|
// has been retrieved. Also expands abbreviations since Open Meteo does not accept
|
||||||
|
// country names like "US", "USA" and "UK"
|
||||||
|
func parsePlaceName(name string) (string, string) {
|
||||||
|
parts := strings.Split(name, ",")
|
||||||
|
|
||||||
|
if len(parts) == 1 {
|
||||||
|
return name, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(parts) == 2 {
|
||||||
|
return parts[0] + ", " + expandCountryAbbreviations(parts[1]), ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts[0] + ", " + expandCountryAbbreviations(parts[2]), strings.TrimSpace(parts[1])
|
||||||
|
}
|
||||||
|
|
||||||
func FetchPlaceFromName(location string) (*PlaceJson, error) {
|
func FetchPlaceFromName(location string) (*PlaceJson, error) {
|
||||||
requestUrl := fmt.Sprintf("https://geocoding-api.open-meteo.com/v1/search?name=%s&count=1&language=en&format=json", url.QueryEscape(location))
|
location, area := parsePlaceName(location)
|
||||||
|
requestUrl := fmt.Sprintf("https://geocoding-api.open-meteo.com/v1/search?name=%s&count=10&language=en&format=json", url.QueryEscape(location))
|
||||||
request, _ := http.NewRequest("GET", requestUrl, nil)
|
request, _ := http.NewRequest("GET", requestUrl, nil)
|
||||||
responseJson, err := decodeJsonFromRequest[PlacesResponseJson](defaultClient, request)
|
responseJson, err := decodeJsonFromRequest[PlacesResponseJson](defaultClient, request)
|
||||||
|
|
||||||
@ -61,7 +96,24 @@ func FetchPlaceFromName(location string) (*PlaceJson, error) {
|
|||||||
return nil, fmt.Errorf("no places found for %s", location)
|
return nil, fmt.Errorf("no places found for %s", location)
|
||||||
}
|
}
|
||||||
|
|
||||||
place := &responseJson.Results[0]
|
var place *PlaceJson
|
||||||
|
|
||||||
|
if area != "" {
|
||||||
|
area = strings.ToLower(area)
|
||||||
|
|
||||||
|
for i := range responseJson.Results {
|
||||||
|
if strings.ToLower(responseJson.Results[i].Area) == area {
|
||||||
|
place = &responseJson.Results[i]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if place == nil {
|
||||||
|
return nil, fmt.Errorf("no place found for %s in %s", location, area)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
place = &responseJson.Results[0]
|
||||||
|
}
|
||||||
|
|
||||||
loc, err := time.LoadLocation(place.Timezone)
|
loc, err := time.LoadLocation(place.Timezone)
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
type Weather struct {
|
type Weather struct {
|
||||||
widgetBase `yaml:",inline"`
|
widgetBase `yaml:",inline"`
|
||||||
Location string `yaml:"location"`
|
Location string `yaml:"location"`
|
||||||
|
ShowAreaName bool `yaml:"show-area-name"`
|
||||||
HideLocation bool `yaml:"hide-location"`
|
HideLocation bool `yaml:"hide-location"`
|
||||||
Units string `yaml:"units"`
|
Units string `yaml:"units"`
|
||||||
Place *feed.PlaceJson `yaml:"-"`
|
Place *feed.PlaceJson `yaml:"-"`
|
||||||
|
Loading…
x
Reference in New Issue
Block a user