Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea04aec0b4 | ||
|
|
b8e2717faf | ||
|
|
502950709c | ||
|
|
2c3e14d84c | ||
|
|
8e71afe158 | ||
|
|
03b616622e | ||
|
|
50e1da01fe |
@@ -958,6 +958,7 @@ Preview:
|
|||||||
| search-engine | string | no | duckduckgo |
|
| search-engine | string | no | duckduckgo |
|
||||||
| new-tab | boolean | no | false |
|
| new-tab | boolean | no | false |
|
||||||
| autofocus | boolean | no | false |
|
| autofocus | boolean | no | false |
|
||||||
|
| target | string | no | _blank |
|
||||||
| placeholder | string | no | Type here to search… |
|
| placeholder | string | no | Type here to search… |
|
||||||
| bangs | array | no | |
|
| bangs | array | no | |
|
||||||
|
|
||||||
@@ -975,6 +976,9 @@ When set to `true`, swaps the shortcuts for showing results in the same or new t
|
|||||||
##### `autofocus`
|
##### `autofocus`
|
||||||
When set to `true`, automatically focuses the search input on page load.
|
When set to `true`, automatically focuses the search input on page load.
|
||||||
|
|
||||||
|
##### `target`
|
||||||
|
The target to use when opening the search results in a new tab. Possible values are `_blank`, `_self`, `_parent` and `_top`.
|
||||||
|
|
||||||
##### `placeholder`
|
##### `placeholder`
|
||||||
When set, modifies the text displayed in the input field before typing.
|
When set, modifies the text displayed in the input field before typing.
|
||||||
|
|
||||||
|
|||||||
@@ -378,6 +378,7 @@ The following helper functions provided by Glance are available:
|
|||||||
- `offsetNow(offset string) time.Time`: Returns the current time with an offset. The offset can be positive or negative and must be in the format "3h" "-1h" or "2h30m10s".
|
- `offsetNow(offset string) time.Time`: Returns the current time with an offset. The offset can be positive or negative and must be in the format "3h" "-1h" or "2h30m10s".
|
||||||
- `duration(str string) time.Duration`: Parses a string such as `1h`, `24h`, `5h30m`, etc into a `time.Duration`.
|
- `duration(str string) time.Duration`: Parses a string such as `1h`, `24h`, `5h30m`, etc into a `time.Duration`.
|
||||||
- `parseTime(layout string, s string) time.Time`: Parses a string into time.Time. The layout must be provided in Go's [date format](https://pkg.go.dev/time#pkg-constants). You can alternatively use these values instead of the literal format: "unix", "RFC3339", "RFC3339Nano", "DateTime", "DateOnly".
|
- `parseTime(layout string, s string) time.Time`: Parses a string into time.Time. The layout must be provided in Go's [date format](https://pkg.go.dev/time#pkg-constants). You can alternatively use these values instead of the literal format: "unix", "RFC3339", "RFC3339Nano", "DateTime", "DateOnly".
|
||||||
|
- `parseLocalTime(layout string, s string) time.Time`: Same as the above, except in the absence of a timezone, it will use the local timezone instead of UTC.
|
||||||
- `parseRelativeTime(layout string, s string) time.Time`: A shorthand for `{{ .String "date" | parseTime "rfc3339" | toRelativeTime }}`.
|
- `parseRelativeTime(layout string, s string) time.Time`: A shorthand for `{{ .String "date" | parseTime "rfc3339" | toRelativeTime }}`.
|
||||||
- `add(a, b float) float`: Adds two numbers.
|
- `add(a, b float) float`: Adds two numbers.
|
||||||
- `sub(a, b float) float`: Subtracts two numbers.
|
- `sub(a, b float) float`: Subtracts two numbers.
|
||||||
|
|||||||
@@ -96,11 +96,15 @@ func parseCliOptions() (*cliOptions, error) {
|
|||||||
func cliSensorsPrint() int {
|
func cliSensorsPrint() int {
|
||||||
tempSensors, err := sensors.SensorsTemperatures()
|
tempSensors, err := sensors.SensorsTemperatures()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Failed to retrieve list of sensors: %v\n", err)
|
|
||||||
if warns, ok := err.(*sensors.Warnings); ok {
|
if warns, ok := err.(*sensors.Warnings); ok {
|
||||||
|
fmt.Printf("Could not retrieve information for some sensors (%v):\n", err)
|
||||||
for _, w := range warns.List {
|
for _, w := range warns.List {
|
||||||
fmt.Printf(" - %v\n", w)
|
fmt.Printf(" - %v\n", w)
|
||||||
}
|
}
|
||||||
|
fmt.Println()
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Failed to retrieve sensor information: %v\n", err)
|
||||||
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
@@ -111,8 +115,9 @@ func cliSensorsPrint() int {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Println("Sensors found:")
|
||||||
for _, sensor := range tempSensors {
|
for _, sensor := range tempSensors {
|
||||||
fmt.Printf("%s: %.1f°C\n", sensor.SensorKey, sensor.Temperature)
|
fmt.Printf(" %s: %.1f°C\n", sensor.SensorKey, sensor.Temperature)
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
@@ -133,7 +138,7 @@ func cliMountpointInfo(requestedPath string) int {
|
|||||||
|
|
||||||
fmt.Println("Path:", usage.Path)
|
fmt.Println("Path:", usage.Path)
|
||||||
fmt.Println("FS type:", ternary(usage.Fstype == "", "unknown", usage.Fstype))
|
fmt.Println("FS type:", ternary(usage.Fstype == "", "unknown", usage.Fstype))
|
||||||
fmt.Printf("Used percent: %.1f%%", usage.UsedPercent)
|
fmt.Printf("Used percent: %.1f%%\n", usage.UsedPercent)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -104,6 +104,7 @@ function setupSearchBoxes() {
|
|||||||
for (let i = 0; i < searchWidgets.length; i++) {
|
for (let i = 0; i < searchWidgets.length; i++) {
|
||||||
const widget = searchWidgets[i];
|
const widget = searchWidgets[i];
|
||||||
const defaultSearchUrl = widget.dataset.defaultSearchUrl;
|
const defaultSearchUrl = widget.dataset.defaultSearchUrl;
|
||||||
|
const target = widget.dataset.target || "_blank";
|
||||||
const newTab = widget.dataset.newTab === "true";
|
const newTab = widget.dataset.newTab === "true";
|
||||||
const inputElement = widget.getElementsByClassName("search-input")[0];
|
const inputElement = widget.getElementsByClassName("search-input")[0];
|
||||||
const bangElement = widget.getElementsByClassName("search-bang")[0];
|
const bangElement = widget.getElementsByClassName("search-bang")[0];
|
||||||
@@ -143,7 +144,7 @@ function setupSearchBoxes() {
|
|||||||
const url = searchUrlTemplate.replace("!QUERY!", encodeURIComponent(query));
|
const url = searchUrlTemplate.replace("!QUERY!", encodeURIComponent(query));
|
||||||
|
|
||||||
if (newTab && !event.ctrlKey || !newTab && event.ctrlKey) {
|
if (newTab && !event.ctrlKey || !newTab && event.ctrlKey) {
|
||||||
window.open(url, '_blank').focus();
|
window.open(url, target).focus();
|
||||||
} else {
|
} else {
|
||||||
window.location.href = url;
|
window.location.href = url;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
{{ define "widget-content-classes" }}widget-content-frameless{{ end }}
|
{{ define "widget-content-classes" }}widget-content-frameless{{ end }}
|
||||||
|
|
||||||
{{ define "widget-content" }}
|
{{ define "widget-content" }}
|
||||||
<div class="search widget-content-frame padding-inline-widget flex gap-15 items-center" data-default-search-url="{{ .SearchEngine }}" data-new-tab="{{ .NewTab }}">
|
<div class="search widget-content-frame padding-inline-widget flex gap-15 items-center" data-default-search-url="{{ .SearchEngine }}" data-new-tab="{{ .NewTab }}" data-target="{{ .Target }}">
|
||||||
<div class="search-bangs">
|
<div class="search-bangs">
|
||||||
{{ range .Bangs }}
|
{{ range .Bangs }}
|
||||||
<input type="hidden" data-shortcut="{{ .Shortcut }}" data-title="{{ .Title }}" data-url="{{ .URL }}">
|
<input type="hidden" data-shortcut="{{ .Shortcut }}" data-title="{{ .Title }}" data-url="{{ .URL }}">
|
||||||
|
|||||||
@@ -450,11 +450,16 @@ var customAPITemplateFuncs = func() template.FuncMap {
|
|||||||
|
|
||||||
return d
|
return d
|
||||||
},
|
},
|
||||||
"parseTime": customAPIFuncParseTime,
|
"parseTime": func(layout, value string) time.Time {
|
||||||
|
return customAPIFuncParseTimeInLocation(layout, value, time.UTC)
|
||||||
|
},
|
||||||
|
"parseLocalTime": func(layout, value string) time.Time {
|
||||||
|
return customAPIFuncParseTimeInLocation(layout, value, time.Local)
|
||||||
|
},
|
||||||
"toRelativeTime": dynamicRelativeTimeAttrs,
|
"toRelativeTime": dynamicRelativeTimeAttrs,
|
||||||
"parseRelativeTime": func(layout, value string) template.HTMLAttr {
|
"parseRelativeTime": func(layout, value string) template.HTMLAttr {
|
||||||
// Shorthand to do both of the above with a single function call
|
// Shorthand to do both of the above with a single function call
|
||||||
return dynamicRelativeTimeAttrs(customAPIFuncParseTime(layout, value))
|
return dynamicRelativeTimeAttrs(customAPIFuncParseTimeInLocation(layout, value, time.UTC))
|
||||||
},
|
},
|
||||||
// The reason we flip the parameter order is so that you can chain multiple calls together like this:
|
// The reason we flip the parameter order is so that you can chain multiple calls together like this:
|
||||||
// {{ .JSON.String "foo" | trimPrefix "bar" | doSomethingElse }}
|
// {{ .JSON.String "foo" | trimPrefix "bar" | doSomethingElse }}
|
||||||
@@ -528,8 +533,8 @@ var customAPITemplateFuncs = func() template.FuncMap {
|
|||||||
},
|
},
|
||||||
"sortByTime": func(key, layout, order string, results []decoratedGJSONResult) []decoratedGJSONResult {
|
"sortByTime": func(key, layout, order string, results []decoratedGJSONResult) []decoratedGJSONResult {
|
||||||
sort.Slice(results, func(a, b int) bool {
|
sort.Slice(results, func(a, b int) bool {
|
||||||
timeA := customAPIFuncParseTime(layout, results[a].String(key))
|
timeA := customAPIFuncParseTimeInLocation(layout, results[a].String(key), time.UTC)
|
||||||
timeB := customAPIFuncParseTime(layout, results[b].String(key))
|
timeB := customAPIFuncParseTimeInLocation(layout, results[b].String(key), time.UTC)
|
||||||
|
|
||||||
if order == "asc" {
|
if order == "asc" {
|
||||||
return timeA.Before(timeB)
|
return timeA.Before(timeB)
|
||||||
@@ -566,7 +571,7 @@ var customAPITemplateFuncs = func() template.FuncMap {
|
|||||||
return funcs
|
return funcs
|
||||||
}()
|
}()
|
||||||
|
|
||||||
func customAPIFuncParseTime(layout, value string) time.Time {
|
func customAPIFuncParseTimeInLocation(layout, value string, loc *time.Location) time.Time {
|
||||||
switch strings.ToLower(layout) {
|
switch strings.ToLower(layout) {
|
||||||
case "unix":
|
case "unix":
|
||||||
asInt, err := strconv.ParseInt(value, 10, 64)
|
asInt, err := strconv.ParseInt(value, 10, 64)
|
||||||
@@ -585,7 +590,7 @@ func customAPIFuncParseTime(layout, value string) time.Time {
|
|||||||
layout = time.DateOnly
|
layout = time.DateOnly
|
||||||
}
|
}
|
||||||
|
|
||||||
parsed, err := time.Parse(layout, value)
|
parsed, err := time.ParseInLocation(layout, value, loc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return time.Unix(0, 0)
|
return time.Unix(0, 0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -194,7 +194,7 @@ func fetchSubredditPosts(
|
|||||||
var client requestDoer = defaultHTTPClient
|
var client requestDoer = defaultHTTPClient
|
||||||
|
|
||||||
if requestUrlTemplate != "" {
|
if requestUrlTemplate != "" {
|
||||||
requestUrl = strings.ReplaceAll(requestUrlTemplate, "{REQUEST-URL}", requestUrl)
|
requestUrl = strings.ReplaceAll(requestUrlTemplate, "{REQUEST-URL}", url.QueryEscape(requestUrl))
|
||||||
} else if proxyClient != nil {
|
} else if proxyClient != nil {
|
||||||
client = proxyClient
|
client = proxyClient
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ type searchWidget struct {
|
|||||||
SearchEngine string `yaml:"search-engine"`
|
SearchEngine string `yaml:"search-engine"`
|
||||||
Bangs []SearchBang `yaml:"bangs"`
|
Bangs []SearchBang `yaml:"bangs"`
|
||||||
NewTab bool `yaml:"new-tab"`
|
NewTab bool `yaml:"new-tab"`
|
||||||
|
Target string `yaml:"target"`
|
||||||
Autofocus bool `yaml:"autofocus"`
|
Autofocus bool `yaml:"autofocus"`
|
||||||
Placeholder string `yaml:"placeholder"`
|
Placeholder string `yaml:"placeholder"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,8 +182,8 @@ func workerPoolDo[I any, O any](job *workerPoolJob[I, O]) ([]O, []error, error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(job.data) == 1 {
|
if len(job.data) == 1 {
|
||||||
output, err := job.task(job.data[0])
|
results[0], errs[0] = job.task(job.data[0])
|
||||||
return append(results, output), append(errs, err), nil
|
return results, errs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
tasksQueue := make(chan *workerPoolTask[I, O])
|
tasksQueue := make(chan *workerPoolTask[I, O])
|
||||||
|
|||||||
@@ -201,11 +201,12 @@ func Collect(req *SystemInfoRequest) (*SystemInfo, []error) {
|
|||||||
// currently disabled on Windows because it requires elevated privilidges, otherwise
|
// currently disabled on Windows because it requires elevated privilidges, otherwise
|
||||||
// keeps returning a single sensor with key "ACPI\\ThermalZone\\TZ00_0" which
|
// keeps returning a single sensor with key "ACPI\\ThermalZone\\TZ00_0" which
|
||||||
// doesn't seem to be the CPU sensor or correspond to anything useful when
|
// doesn't seem to be the CPU sensor or correspond to anything useful when
|
||||||
// compared against the temperatures Libre Hardware Monitor reports
|
// compared against the temperatures Libre Hardware Monitor reports.
|
||||||
// also disabled on openbsd because it's not implemented by go-psutil
|
// Also disabled on the bsd's because it's not implemented by go-psutil for them
|
||||||
if runtime.GOOS != "windows" && runtime.GOOS != "openbsd" {
|
if runtime.GOOS != "windows" && runtime.GOOS != "openbsd" && runtime.GOOS != "netbsd" && runtime.GOOS != "freebsd" {
|
||||||
sensorReadings, err := sensors.SensorsTemperatures()
|
sensorReadings, err := sensors.SensorsTemperatures()
|
||||||
if err == nil {
|
_, errIsWarning := err.(*sensors.Warnings)
|
||||||
|
if err == nil || errIsWarning {
|
||||||
if req.CPUTempSensor != "" {
|
if req.CPUTempSensor != "" {
|
||||||
for i := range sensorReadings {
|
for i := range sensorReadings {
|
||||||
if sensorReadings[i].SensorKey == req.CPUTempSensor {
|
if sensorReadings[i].SensorKey == req.CPUTempSensor {
|
||||||
|
|||||||
Reference in New Issue
Block a user