Knopf zum Nachsehen bei Calendarr
Onyx holt sich nichts, es liest den Schnappschuss und erfährt neue über eine Darwin-Nachricht. Wer Calendarr gerade erst gestartet hat, will aber nicht auf den nächsten Blick warten, sondern jetzt nachsehen. Der Knopf steht in jedem Zustand, nicht nur wenn Termine da sind: gerade wenn „noch nichts geschrieben" oder „bitte anmelden" dasteht, will man es nach dem Beheben sofort noch einmal versuchen. Beim Laden zeigt er einen Kreisel, in fester Breite — sonst zuckt die Zeile, weil der Kreisel schmaler ist als der Pfeil. Dabei aufgefallen: die Statustexte für „noch nichts geschrieben", „abgemeldet" und „zu neues Format" standen ohne Übersetzung im Katalog. Wer in einen dieser Zustände geriet, las den rohen Schlüssel. Jetzt übersetzt, dazu die zwei Zustände, die gar nicht behandelt waren — kein Kalenderzugriff und „wird gelesen". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -19,24 +19,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"%@ °C" : {
|
|
||||||
"comment" : "A label showing the temperature of the hottest fan in the report, in degrees Celsius. The argument is the temperature in degrees Celsius.",
|
|
||||||
"isCommentAutoGenerated" : true,
|
|
||||||
"localizations" : {
|
|
||||||
"de" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "%@ °C"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"en" : {
|
|
||||||
"stringUnit" : {
|
|
||||||
"state" : "translated",
|
|
||||||
"value" : "%@ °C"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"%@ U/min": {
|
"%@ U/min": {
|
||||||
"comment": "A label that shows the current speed of a fan. The argument is the current speed of the fan.",
|
"comment": "A label that shows the current speed of a fan. The argument is the current speed of the fan.",
|
||||||
"isCommentAutoGenerated": true,
|
"isCommentAutoGenerated": true,
|
||||||
@@ -55,6 +37,24 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"%@ °C": {
|
||||||
|
"comment": "A label showing the temperature of the hottest fan in the report, in degrees Celsius. The argument is the temperature in degrees Celsius.",
|
||||||
|
"isCommentAutoGenerated": true,
|
||||||
|
"localizations": {
|
||||||
|
"de": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "%@ °C"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "%@ °C"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"%@°": {
|
"%@°": {
|
||||||
"comment": "A temperature in °C.",
|
"comment": "A temperature in °C.",
|
||||||
"isCommentAutoGenerated": true,
|
"isCommentAutoGenerated": true,
|
||||||
@@ -73,16 +73,89 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"calendar.source.status.denied": {
|
||||||
|
"localizations": {
|
||||||
|
"de": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Kein Zugriff auf die Kalender."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "No access to calendars."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"calendar.source.status.incompatible": {
|
"calendar.source.status.incompatible": {
|
||||||
|
"localizations": {
|
||||||
|
"de": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Calendarr schreibt ein neueres Format — bitte Onyx aktualisieren."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Calendarr writes a newer format — please update Onyx."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"calendar.source.status.loading": {
|
||||||
|
"localizations": {
|
||||||
|
"de": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Wird gelesen …"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Reading …"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"calendar.source.status.loggedOut": {
|
"calendar.source.status.loggedOut": {
|
||||||
"comment": "A message that is displayed when the user is logged out of their calendar.",
|
"comment": "A message that is displayed when the user is logged out of their calendar.",
|
||||||
"isCommentAutoGenerated" : true
|
"isCommentAutoGenerated": true,
|
||||||
|
"localizations": {
|
||||||
|
"de": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "In Calendarr anmelden."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Sign in to Calendarr."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"calendar.source.status.neverWritten": {
|
"calendar.source.status.neverWritten": {
|
||||||
"comment": "A message that is displayed when the user has not",
|
"comment": "A message that is displayed when the user has not",
|
||||||
"isCommentAutoGenerated" : true
|
"isCommentAutoGenerated": true,
|
||||||
|
"localizations": {
|
||||||
|
"de": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Calendarr hat noch nichts geschrieben — einmal öffnen."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Calendarr hasn’t written anything yet — open it once."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"charge.limit": {
|
"charge.limit": {
|
||||||
"extractionState": "stale",
|
"extractionState": "stale",
|
||||||
@@ -1547,6 +1620,22 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"options.calendar.reload": {
|
||||||
|
"localizations": {
|
||||||
|
"de": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Neu einlesen"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"en": {
|
||||||
|
"stringUnit": {
|
||||||
|
"state": "translated",
|
||||||
|
"value": "Reload"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"options.calendar.source": {
|
"options.calendar.source": {
|
||||||
"localizations": {
|
"localizations": {
|
||||||
"de": {
|
"de": {
|
||||||
|
|||||||
@@ -90,7 +90,9 @@ private struct CalendarOptions: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if model.kind != .appleCalendar {
|
if model.kind != .appleCalendar {
|
||||||
CalendarrStatus(state: calendarrState)
|
CalendarrStatus(state: calendarrState,
|
||||||
|
isLoading: model.isLoading,
|
||||||
|
onRefresh: { model.refresh() })
|
||||||
.task(id: model.kind) {
|
.task(id: model.kind) {
|
||||||
guard model.kind != .appleCalendar else { return }
|
guard model.kind != .appleCalendar else { return }
|
||||||
let now = Date()
|
let now = Date()
|
||||||
@@ -103,30 +105,67 @@ private struct CalendarOptions: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Was Calendarr gerade liefert. Bleibt das Widget leer, steht hier das Warum.
|
/// Was Calendarr gerade liefert. Bleibt das Widget leer, steht hier das Warum.
|
||||||
|
///
|
||||||
|
/// Mit einem Knopf zum Nachsehen. Onyx holt sich nichts — es liest den
|
||||||
|
/// Schnappschuss, den Calendarr schreibt, und erfährt neue über eine
|
||||||
|
/// Darwin-Nachricht. Die ist flüchtig: wer Calendarr gerade erst gestartet hat,
|
||||||
|
/// will nicht auf den nächsten Blick warten, sondern jetzt nachsehen.
|
||||||
private struct CalendarrStatus: View {
|
private struct CalendarrStatus: View {
|
||||||
let state: CalendarSourceState?
|
let state: CalendarSourceState?
|
||||||
|
let isLoading: Bool
|
||||||
|
let onRefresh: () -> Void
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
switch state {
|
HStack(spacing: 8) {
|
||||||
case .ready(let window):
|
message
|
||||||
LabeledContent {
|
Spacer(minLength: 8)
|
||||||
|
if case .ready(let window) = state {
|
||||||
Text(window.asOf?.formatted(date: .abbreviated, time: .shortened) ?? "–")
|
Text(window.asOf?.formatted(date: .abbreviated, time: .shortened) ?? "–")
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
} label: {
|
|
||||||
Text("options.calendar.calendarrEvents \(window.events.count)")
|
|
||||||
}
|
}
|
||||||
|
reloadButton
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var message: some View {
|
||||||
|
switch state {
|
||||||
|
case .ready(let window):
|
||||||
|
Text("options.calendar.calendarrEvents \(window.events.count)")
|
||||||
case .neverWritten:
|
case .neverWritten:
|
||||||
Text("calendar.source.status.neverWritten").font(.callout).foregroundStyle(.secondary)
|
Text("calendar.source.status.neverWritten").font(.callout).foregroundStyle(.secondary)
|
||||||
case .loggedOut:
|
case .loggedOut:
|
||||||
Text("calendar.source.status.loggedOut").font(.callout).foregroundStyle(.secondary)
|
Text("calendar.source.status.loggedOut").font(.callout).foregroundStyle(.secondary)
|
||||||
case .incompatible:
|
case .incompatible:
|
||||||
Text("calendar.source.status.incompatible").font(.callout).foregroundStyle(Onyx.Color.warning)
|
Text("calendar.source.status.incompatible").font(.callout)
|
||||||
|
.foregroundStyle(Onyx.Color.warning)
|
||||||
case .unreadable(let reason):
|
case .unreadable(let reason):
|
||||||
Text(reason).font(.callout).foregroundStyle(Onyx.Color.warning)
|
Text(reason).font(.callout).foregroundStyle(Onyx.Color.warning)
|
||||||
case .denied, .none:
|
case .denied:
|
||||||
ProgressView().controlSize(.small)
|
Text("calendar.source.status.denied").font(.callout)
|
||||||
|
.foregroundStyle(Onyx.Color.warning)
|
||||||
|
case .none:
|
||||||
|
Text("calendar.source.status.loading").font(.callout).foregroundStyle(.secondary)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Feste Breite, damit die Zeile beim Laden nicht zuckt: der Kreisel ist
|
||||||
|
/// nicht so breit wie der Pfeil.
|
||||||
|
private var reloadButton: some View {
|
||||||
|
Button(action: onRefresh) {
|
||||||
|
Group {
|
||||||
|
if isLoading {
|
||||||
|
ProgressView().controlSize(.small)
|
||||||
|
} else {
|
||||||
|
Image(systemName: "arrow.clockwise")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(width: 16, height: 16)
|
||||||
|
}
|
||||||
|
.buttonStyle(.borderless)
|
||||||
|
.disabled(isLoading)
|
||||||
|
.help(Text("options.calendar.reload"))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Wetter
|
// MARK: - Wetter
|
||||||
|
|||||||
Reference in New Issue
Block a user