Compare commits
17 Commits
feat/inser
...
release/v2
| Author | SHA1 | Date | |
|---|---|---|---|
| cf3b897305 | |||
| 87a78ca924 | |||
| 13debac340 | |||
| 76846420a2 | |||
| 1a3e4f501f | |||
| 974d65f619 | |||
|
|
721ca0d7e0 | ||
|
|
2556eba84b | ||
|
|
fc1ff97d22 | ||
|
|
b7f3d421ef | ||
|
|
2722b3427a | ||
|
|
e28c293d27 | ||
|
|
5cb2a836ab | ||
|
|
b5978e7a61 | ||
| c4a048adee | |||
|
|
2746ca5784 | ||
| fc9bd33992 |
28
CHANGELOG.md
28
CHANGELOG.md
@@ -5,6 +5,31 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [2.13.1] — 2026-07-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- Create events from other apps and widgets. Calendula now registers the
|
||||||
|
standard "insert event" intent (`ACTION_INSERT` on the calendar events type),
|
||||||
|
so other apps and home-screen widgets — such as the Todo Agenda widget — can
|
||||||
|
hand off to Calendula to create a new event. It opens the new-event form
|
||||||
|
prefilled with whatever they passed (title, start/end time, all-day, location,
|
||||||
|
description, recurrence), and picks your last-used or first writable calendar.
|
||||||
|
Thanks to @dschuermann for the suggestion ([#30]).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Some recurring events could not be opened. Events in a series that started
|
||||||
|
before 1970 — for example yearly birthdays or anniversaries synced over CalDAV
|
||||||
|
— showed "Something went wrong" instead of opening, because their stored start
|
||||||
|
time is a negative value that was wrongly treated as invalid. They now open
|
||||||
|
normally and appear in search again. A related case (an event whose stored end
|
||||||
|
precedes its start) is now kept and openable instead of failing the same way.
|
||||||
|
Thanks to @dschuermann for the report ([#34]).
|
||||||
|
- The time picker now follows your 24-hour setting. With Calendula set to
|
||||||
|
24-hour time, the clock dial for choosing an event's start and end time still
|
||||||
|
showed AM/PM instead of a 24-hour dial; it now matches your setting (and the
|
||||||
|
same fix applies to the all-day reminder time in Settings). Thanks to
|
||||||
|
@abrossimow for the report ([#27]).
|
||||||
|
|
||||||
## [2.13.0] — 2026-07-03
|
## [2.13.0] — 2026-07-03
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
@@ -809,4 +834,7 @@ automatically, with zero telemetry and no internet permission.
|
|||||||
[#19]: https://codeberg.org/jlmakiola/calendula/issues/19
|
[#19]: https://codeberg.org/jlmakiola/calendula/issues/19
|
||||||
[#20]: https://codeberg.org/jlmakiola/calendula/issues/20
|
[#20]: https://codeberg.org/jlmakiola/calendula/issues/20
|
||||||
[#24]: https://codeberg.org/jlmakiola/calendula/issues/24
|
[#24]: https://codeberg.org/jlmakiola/calendula/issues/24
|
||||||
|
[#27]: https://codeberg.org/jlmakiola/calendula/issues/27
|
||||||
[#29]: https://codeberg.org/jlmakiola/calendula/issues/29
|
[#29]: https://codeberg.org/jlmakiola/calendula/issues/29
|
||||||
|
[#30]: https://codeberg.org/jlmakiola/calendula/issues/30
|
||||||
|
[#34]: https://codeberg.org/jlmakiola/calendula/issues/34
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ android {
|
|||||||
// which builds this version and then creates the matching vX.Y.Z tag +
|
// which builds this version and then creates the matching vX.Y.Z tag +
|
||||||
// release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 +
|
// release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 +
|
||||||
// PATCH from versionName, e.g. 2.7.2 -> 20702). See docs/RELEASING.md.
|
// PATCH from versionName, e.g. 2.7.2 -> 20702). See docs/RELEASING.md.
|
||||||
versionCode = 21300
|
versionCode = 21301
|
||||||
versionName = "2.13.0"
|
versionName = "2.13.1"
|
||||||
|
|
||||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,26 +23,29 @@ internal fun ColumnReader.toEventDetailCore(
|
|||||||
attendees: List<Attendee>,
|
attendees: List<Attendee>,
|
||||||
reminders: List<Reminder>,
|
reminders: List<Reminder>,
|
||||||
): EventDetail? {
|
): EventDetail? {
|
||||||
val begin = getLong(EventDetailProjection.IDX_DTSTART)
|
// DTSTART is epoch millis in UTC, so a series anchored before 1970 (common
|
||||||
|
// for yearly birthdays/anniversaries synced over CalDAV) is legitimately
|
||||||
if (begin < 0L) {
|
// negative — only an *absent* DTSTART marks a malformed row worth dropping.
|
||||||
Log.w(TAG, "Dropping event with negative dtstart=$begin")
|
// Dropping negatives made every occurrence of such a series un-openable
|
||||||
|
// (the detail loads the ancient series-master DTSTART), see issue #34.
|
||||||
|
if (isNull(EventDetailProjection.IDX_DTSTART)) {
|
||||||
|
Log.w(TAG, "Dropping event with missing dtstart")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
val begin = getLong(EventDetailProjection.IDX_DTSTART)
|
||||||
|
|
||||||
// Recurring events store DURATION instead of DTEND, so the series row's
|
// Recurring events store DURATION instead of DTEND, so the series row's
|
||||||
// DTEND is null. Keep the event (end == begin); callers that opened a
|
// DTEND is null. Keep the event (end == begin); callers that opened a
|
||||||
// specific occurrence supply the real per-occurrence times from
|
// specific occurrence supply the real per-occurrence times from
|
||||||
// CalendarContract.Instances. Only a present-but-backwards DTEND is malformed.
|
// CalendarContract.Instances. A present-but-backwards DTEND is malformed,
|
||||||
|
// but dropping the row would make the event un-openable — the same trap as
|
||||||
|
// the pre-1970 DTSTART bug above (issue #34): it would surface as the
|
||||||
|
// generic error screen with no way to open the event and fix it. Clamp to a
|
||||||
|
// zero-length event instead (matching SearchMapper's coerceAtLeast).
|
||||||
val end = if (isNull(EventDetailProjection.IDX_DTEND)) {
|
val end = if (isNull(EventDetailProjection.IDX_DTEND)) {
|
||||||
begin
|
begin
|
||||||
} else {
|
} else {
|
||||||
val rawEnd = getLong(EventDetailProjection.IDX_DTEND)
|
getLong(EventDetailProjection.IDX_DTEND).coerceAtLeast(begin)
|
||||||
if (rawEnd < begin) {
|
|
||||||
Log.w(TAG, "Dropping event with dtend=$rawEnd < dtstart=$begin")
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
rawEnd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kept raw (no untitled fallback): the detail screen substitutes its own
|
// Kept raw (no untitled fallback): the detail screen substitutes its own
|
||||||
|
|||||||
@@ -10,8 +10,11 @@ import de.jeanlucmakiola.calendula.domain.ics.parseRfc2445DurationMillis
|
|||||||
* of DTEND — reconstruct the end the same way the `.ics` export does.
|
* of DTEND — reconstruct the end the same way the `.ics` export does.
|
||||||
*/
|
*/
|
||||||
internal fun ColumnReader.toSearchResult(): EventInstance? {
|
internal fun ColumnReader.toSearchResult(): EventInstance? {
|
||||||
|
// A pre-1970 series anchor is a legitimately negative epoch-millis DTSTART
|
||||||
|
// (see EventDetailMapper / issue #34); drop only a genuinely absent one, so
|
||||||
|
// long-running birthdays/anniversaries still surface in search.
|
||||||
|
if (isNull(SearchProjection.IDX_DTSTART)) return null
|
||||||
val dtStart = getLong(SearchProjection.IDX_DTSTART)
|
val dtStart = getLong(SearchProjection.IDX_DTSTART)
|
||||||
if (dtStart < 0L) return null
|
|
||||||
val end = when {
|
val end = when {
|
||||||
!isNull(SearchProjection.IDX_DTEND) -> getLong(SearchProjection.IDX_DTEND)
|
!isNull(SearchProjection.IDX_DTEND) -> getLong(SearchProjection.IDX_DTEND)
|
||||||
else -> dtStart + parseRfc2445DurationMillis(getString(SearchProjection.IDX_DURATION))
|
else -> dtStart + parseRfc2445DurationMillis(getString(SearchProjection.IDX_DURATION))
|
||||||
|
|||||||
@@ -4,14 +4,9 @@ import androidx.compose.material3.AlertDialog
|
|||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import android.content.Context
|
|
||||||
import android.content.res.Resources
|
|
||||||
import android.provider.Settings
|
|
||||||
import android.text.format.DateFormat
|
|
||||||
import androidx.compose.material3.TimePicker
|
import androidx.compose.material3.TimePicker
|
||||||
import androidx.compose.material3.rememberTimePickerState
|
import androidx.compose.material3.rememberTimePickerState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.platform.LocalContext
|
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import de.jeanlucmakiola.calendula.R
|
import de.jeanlucmakiola.calendula.R
|
||||||
import kotlinx.datetime.LocalTime
|
import kotlinx.datetime.LocalTime
|
||||||
@@ -27,10 +22,13 @@ fun TimePickerAlert(
|
|||||||
onConfirm: (LocalTime) -> Unit,
|
onConfirm: (LocalTime) -> Unit,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
) {
|
) {
|
||||||
|
// Honour the app's own time-format preference (the value every time label
|
||||||
|
// reads), not the system/locale clock — otherwise an explicit 24h setting
|
||||||
|
// still showed an AM/PM dial (issue #27).
|
||||||
val state = rememberTimePickerState(
|
val state = rememberTimePickerState(
|
||||||
initialHour = initial.hour,
|
initialHour = initial.hour,
|
||||||
initialMinute = initial.minute,
|
initialMinute = initial.minute,
|
||||||
is24Hour = deviceUses24HourClock(LocalContext.current),
|
is24Hour = LocalUse24HourFormat.current,
|
||||||
)
|
)
|
||||||
AlertDialog(
|
AlertDialog(
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
@@ -45,24 +43,3 @@ fun TimePickerAlert(
|
|||||||
text = { TimePicker(state = state) },
|
text = { TimePicker(state = state) },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the clock should read 24-hour, matching the rest of the device.
|
|
||||||
*
|
|
||||||
* [DateFormat.is24HourFormat] resolves a "locale default" system setting against
|
|
||||||
* the *app's* context locale — and this app applies a per-app language
|
|
||||||
* (AppCompatDelegate), so an English UI on a German-region phone would wrongly
|
|
||||||
* read 12-hour while the system clock shows 24-hour. So we honour an explicit
|
|
||||||
* system 12/24 override, and otherwise fall back to the **device** locale
|
|
||||||
* (Resources.getSystem), not the app's.
|
|
||||||
*/
|
|
||||||
private fun deviceUses24HourClock(context: Context): Boolean =
|
|
||||||
when (Settings.System.getString(context.contentResolver, Settings.System.TIME_12_24)) {
|
|
||||||
"24" -> true
|
|
||||||
"12" -> false
|
|
||||||
// 'a' is the AM/PM marker; a best-fit pattern without it is 24-hour.
|
|
||||||
else -> {
|
|
||||||
val deviceLocale = Resources.getSystem().configuration.locales[0]
|
|
||||||
!DateFormat.getBestDateTimePattern(deviceLocale, "jm").contains('a')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
<string name="state_failure_provider">Kalender konnte nicht gelesen werden.</string>
|
<string name="state_failure_provider">Kalender konnte nicht gelesen werden.</string>
|
||||||
<!-- Permission-Flow (F1) -->
|
<!-- Permission-Flow (F1) -->
|
||||||
<string name="permission_rationale_title">Alle Termine, schön im Blick</string>
|
<string name="permission_rationale_title">Alle Termine, schön im Blick</string>
|
||||||
<string name="permission_rationale_body">Calendula braucht Zugriff auf deinen Kalender, um deine Termine zu zeigen und zu verwalten. Mehr verlangt die App nie.</string>
|
<string name="permission_rationale_body">Calendula braucht Zugriff auf deinen Kalender, um deine Termine zu zeigen und zu verwalten. Mehr braucht sie nicht um zu funktionieren — und nichts verlässt dein Gerät.</string>
|
||||||
<string name="permission_request_button">Kalender-Zugriff erlauben</string>
|
<string name="permission_request_button">Kalender-Zugriff erlauben</string>
|
||||||
<string name="permission_denied_title">Kalender-Zugriff abgelehnt</string>
|
<string name="permission_denied_title">Kalender-Zugriff abgelehnt</string>
|
||||||
<string name="permission_denied_body">Ohne Kalender-Zugriff kann Calendula keine Termine anzeigen. Du kannst den Zugriff in den System-Einstellungen wieder erlauben.</string>
|
<string name="permission_denied_body">Ohne Kalender-Zugriff kann Calendula keine Termine anzeigen. Du kannst den Zugriff in den System-Einstellungen wieder erlauben.</string>
|
||||||
@@ -309,7 +309,7 @@
|
|||||||
<string name="settings_language">App-Sprache</string>
|
<string name="settings_language">App-Sprache</string>
|
||||||
<string name="settings_language_auto">Systemstandard</string>
|
<string name="settings_language_auto">Systemstandard</string>
|
||||||
<!-- Hub category subtitles -->
|
<!-- Hub category subtitles -->
|
||||||
<string name="settings_appearance_subtitle">Design, dynamische Farben, Wochenstart</string>
|
<string name="settings_appearance_subtitle">Design, Standartansicht, Wochenstart</string>
|
||||||
<string name="settings_event_form_subtitle">Standardfelder für neue Termine</string>
|
<string name="settings_event_form_subtitle">Standardfelder für neue Termine</string>
|
||||||
<string name="settings_notifications_subtitle">Termin-Erinnerungen</string>
|
<string name="settings_notifications_subtitle">Termin-Erinnerungen</string>
|
||||||
<string name="settings_section_about">Über</string>
|
<string name="settings_section_about">Über</string>
|
||||||
@@ -387,4 +387,27 @@
|
|||||||
<string name="crash_report_open_failed">Der Issue-Tracker konnte nicht geöffnet werden. Der Bericht ist in deiner Zwischenablage.</string>
|
<string name="crash_report_open_failed">Der Issue-Tracker konnte nicht geöffnet werden. Der Bericht ist in deiner Zwischenablage.</string>
|
||||||
<string name="crash_report_body_template">Danke, dass du einen Absturz in Calendula meldest. Bitte ergänze, was du gerade getan hast, und sende dann ab.\n\n### Was ist passiert\n\n\n### Absturzbericht\n%1$s\n</string>
|
<string name="crash_report_body_template">Danke, dass du einen Absturz in Calendula meldest. Bitte ergänze, was du gerade getan hast, und sende dann ab.\n\n### Was ist passiert\n\n\n### Absturzbericht\n%1$s\n</string>
|
||||||
<string name="crash_report_body_paste">_(Der Bericht war zu lang für diesen Link — füge ihn aus deiner Zwischenablage hier ein.)_</string>
|
<string name="crash_report_body_paste">_(Der Bericht war zu lang für diesen Link — füge ihn aus deiner Zwischenablage hier ein.)_</string>
|
||||||
|
<string name="event_edit_managed_hint">Verwaltet durch “%1$s” — der Titel, das Datum und Wiederholungen werden synchron mit deinen Kontakten gehalten. Erinnerungen, Ort und Beschreibung kannst du frei bearbeiten.</string>
|
||||||
|
<plurals name="duration_days">
|
||||||
|
<item quantity="one">%d Tag</item>
|
||||||
|
<item quantity="other">%d Tage</item>
|
||||||
|
</plurals>
|
||||||
|
<plurals name="duration_weeks">
|
||||||
|
<item quantity="one">Woche</item>
|
||||||
|
<item quantity="other">Wochen</item>
|
||||||
|
</plurals>
|
||||||
|
<string name="settings_default_view">Standartansicht</string>
|
||||||
|
<string name="settings_font_headings">Überschriften Schriftart</string>
|
||||||
|
<string name="settings_font_system">Systemstandard</string>
|
||||||
|
<string name="font_jetbrains_mono">JetBrains Mono</string>
|
||||||
|
<string name="settings_font_choose_file">Datei auswählen…</string>
|
||||||
|
<string name="settings_font_import_failed">Die Datei konnte nicht als Schriftart gelesen werden</string>
|
||||||
|
<string name="settings_dim_completed">Vergangene Ereignisse abdunkeln</string>
|
||||||
|
<string name="settings_dim_completed_summary">Vergangene Termine in der Monats- und Wochenansicht abdunkeln</string>
|
||||||
|
<string name="settings_past_events">Vergangene Termine</string>
|
||||||
|
<string name="settings_past_events_show">Zeigen</string>
|
||||||
|
<string name="settings_past_events_dim">Abdunkeln</string>
|
||||||
|
<string name="settings_past_events_hide">Ausblenden</string>
|
||||||
|
<string name="settings_agenda_header">Agenda</string>
|
||||||
|
<string name="settings_special_dates_reminders">Erinnerungen</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<string name="state_failure_no_calendars_action">Abrir los ajustes del calendario del sistema</string>
|
<string name="state_failure_no_calendars_action">Abrir los ajustes del calendario del sistema</string>
|
||||||
<string name="state_failure_provider">No se pudo leer el calendario.</string>
|
<string name="state_failure_provider">No se pudo leer el calendario.</string>
|
||||||
<string name="permission_rationale_title">Mira todos sus eventos, a la perfección</string>
|
<string name="permission_rationale_title">Mira todos sus eventos, a la perfección</string>
|
||||||
<string name="permission_rationale_body">Calendula necesita acceso a tu calendario para mostrarte y administrar eventos. Ese es el único permiso que pedirá.</string>
|
<string name="permission_rationale_body">Calendula necesita acceso a tu calendario para mostrarte y administrar eventos. Ese es el único permiso que pedirá para comenzar a funcionar. Y nada de información sale de tu dispositivo.</string>
|
||||||
<string name="permission_request_button">Conceder el acceso al calendario</string>
|
<string name="permission_request_button">Conceder el acceso al calendario</string>
|
||||||
<string name="permission_denied_title">Acceso a calendario denegado</string>
|
<string name="permission_denied_title">Acceso a calendario denegado</string>
|
||||||
<string name="permission_denied_body">Calendula no puede mostrar eventos sin acceso al calendario. Puedes concederlo en ajustes del sistema.</string>
|
<string name="permission_denied_body">Calendula no puede mostrar eventos sin acceso al calendario. Puedes concederlo en ajustes del sistema.</string>
|
||||||
@@ -287,7 +287,7 @@
|
|||||||
<item quantity="many">%d dias</item>
|
<item quantity="many">%d dias</item>
|
||||||
<item quantity="other">%d dias</item>
|
<item quantity="other">%d dias</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="settings_section_event_form">Nueva formulario de evento</string>
|
<string name="settings_section_event_form">Formulario de nuevo evento</string>
|
||||||
<string name="settings_form_fields_hint">Campos mostrados por defecto — todo lo demás se encuentra bajo \"mas campos\"</string>
|
<string name="settings_form_fields_hint">Campos mostrados por defecto — todo lo demás se encuentra bajo \"mas campos\"</string>
|
||||||
<string name="settings_autofocus_title">Enfocar titulo en nuevos eventos</string>
|
<string name="settings_autofocus_title">Enfocar titulo en nuevos eventos</string>
|
||||||
<string name="settings_autofocus_title_hint">Cuando comienzas un nuevo evento, coloca el cursor en el titulo y abre el teclado inmediatamente.</string>
|
<string name="settings_autofocus_title_hint">Cuando comienzas un nuevo evento, coloca el cursor en el titulo y abre el teclado inmediatamente.</string>
|
||||||
@@ -418,4 +418,52 @@
|
|||||||
<string name="recurrence_with_count">%1$s, %2$d veces</string>
|
<string name="recurrence_with_count">%1$s, %2$d veces</string>
|
||||||
<string name="recurrence_with_until">%1$s hasta %2$s</string>
|
<string name="recurrence_with_until">%1$s hasta %2$s</string>
|
||||||
<string name="recurrence_on_days">%1$s los %2$s</string>
|
<string name="recurrence_on_days">%1$s los %2$s</string>
|
||||||
|
<string name="event_edit_managed_hint">Administrado por “%1$s” — el titulo, fecha y recurrencia se mantienen sincronizados con la inflación de tus contactos. Puedes editar los recordatorios, ubicacion y notas.</string>
|
||||||
|
<string name="settings_font_headings">Fuente de los títulos</string>
|
||||||
|
<string name="settings_font_body">Fuente del cuerpo del texto</string>
|
||||||
|
<string name="font_atkinson_hyperlegible">Atkinson Hyperlegible</string>
|
||||||
|
<string name="font_lora">Lora</string>
|
||||||
|
<string name="font_jetbrains_mono">JetBrains Mono</string>
|
||||||
|
<string name="settings_font_choose_file">Escoger desde archivo…</string>
|
||||||
|
<string name="settings_font_custom_selected">Fuente personalizada</string>
|
||||||
|
<string name="settings_font_import_failed">No se pude leer el archivo como fuente</string>
|
||||||
|
<string name="settings_section_views">Vistas</string>
|
||||||
|
<string name="settings_quick_switch_header">Botón de cambio rápido</string>
|
||||||
|
<string name="settings_quick_switch_hint">Escoge que vistas muestra el botón superior derecho y arrastralas para reordenalas. Las vistas deshabitadas permanecen accesibles desde el menú de navegación.</string>
|
||||||
|
<string name="settings_drawer_order_header">Menú de navegación</string>
|
||||||
|
<string name="settings_drawer_order_hint">Arrastra para cambiar el orden de las vistas que aparecen en el menú de navegación.</string>
|
||||||
|
<string name="reorder_drag_handle">Arrastra para reordenar</string>
|
||||||
|
<string name="settings_views_subtitle">Orden del botón de cambio rápido y menú</string>
|
||||||
|
<string name="settings_special_dates_subtitle">Aniversarios y cumpleaños de los contactos</string>
|
||||||
|
<string name="settings_section_special_dates">Fechas especiales de contactos</string>
|
||||||
|
<string name="settings_special_dates_enable">Mostrar fechas de contactos</string>
|
||||||
|
<string name="settings_special_dates_enable_hint">Refleja los cumpleaños y otras fechas de tus contactos en calendarios locales. Solo puede leer los contactos de este dispositivo — nada es compartido ni editado.</string>
|
||||||
|
<string name="settings_special_dates_type_birthday">Cumpleaños</string>
|
||||||
|
<string name="settings_special_dates_type_anniversary">Aniversarios</string>
|
||||||
|
<string name="settings_special_dates_type_custom">Otras fechas</string>
|
||||||
|
<string name="settings_special_dates_template">Formato de titulo</string>
|
||||||
|
<string name="settings_special_dates_template_hint">Usa {name} para el contacto y {year} para el año (el año de nacimiento u origen del aniversario; oculto cuando es desconocido).</string>
|
||||||
|
<string name="settings_special_dates_reminders">Recordatorios</string>
|
||||||
|
<string name="settings_special_dates_show_year">Mostrar año</string>
|
||||||
|
<string name="settings_special_dates_show_year_hint">Incluye {year} en títulos cuando se conoce el año</string>
|
||||||
|
<string name="settings_special_dates_sync_now">Sincronizar ahora</string>
|
||||||
|
<string name="settings_special_dates_never_synced">No se ha sincronizado todavía</string>
|
||||||
|
<string name="settings_special_dates_last_synced">Sincronizado por ultima vez %1$s</string>
|
||||||
|
<string name="settings_special_dates_calendar_hint">Cambia el color y visibilidad de cada calendario en ajustes de calendarios.</string>
|
||||||
|
<string name="settings_calendar_reminders_managed_hint">Establecido en Fechas especiales de contactos</string>
|
||||||
|
<string name="settings_special_dates_paused_hint">Calendula ya no puede leer tus contactos, por lo que estos calendarios ya no se estan actualizando.</string>
|
||||||
|
<string name="settings_special_dates_disable_title">¿Desactivar las fechas de contactos?</string>
|
||||||
|
<string name="settings_special_dates_disable_all_message">Esto eliminara los calendarios de fechas de contactos y sus eventos. Se perderán todos los recordatorios o notas agregadas.</string>
|
||||||
|
<string name="settings_special_dates_paused_title">Pausado</string>
|
||||||
|
<string name="settings_special_dates_disable_type_message">Esto eliminara el calendario “%1$s” y sus eventos. Se perderán todos los recordatorios o notas agregadas.</string>
|
||||||
|
<string name="settings_special_dates_disable_confirm">Desactivar</string>
|
||||||
|
<string name="special_dates_calendar_birthday">Cumpleaños</string>
|
||||||
|
<string name="special_dates_calendar_anniversary">Aniversarios</string>
|
||||||
|
<string name="special_dates_calendar_custom">Fechas especiales</string>
|
||||||
|
<string name="special_dates_default_title_birthday">Cumpleaños de {name} ({year})</string>
|
||||||
|
<string name="special_dates_default_title_anniversary">Aniversario de {name} ({year})</string>
|
||||||
|
<string name="special_dates_default_title_custom">{name}</string>
|
||||||
|
<string name="settings_special_dates_grant">Permitir acceso</string>
|
||||||
|
<string name="dialog_save">Guardar</string>
|
||||||
|
<string name="settings_font_system">Igual que el sistema</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -418,4 +418,42 @@
|
|||||||
<string name="settings_default_reminder">Promemoria standard</string>
|
<string name="settings_default_reminder">Promemoria standard</string>
|
||||||
<string name="settings_notifications_subtitle">Promemoria evento</string>
|
<string name="settings_notifications_subtitle">Promemoria evento</string>
|
||||||
<string name="shortcut_new_event_short">Nuovo evento</string>
|
<string name="shortcut_new_event_short">Nuovo evento</string>
|
||||||
|
<string name="event_edit_managed_hint">Gestito da “%1$s” - titolo, data e ripetizioni sono sincronizzate dai tuoi contatti. Promemoria e note sono modificabili dall\'utente</string>
|
||||||
|
<string name="settings_font_headings">Carattere dell\'intestazione</string>
|
||||||
|
<string name="settings_font_body">Carattere del corpo</string>
|
||||||
|
<string name="settings_font_system">Predefinito di sistema</string>
|
||||||
|
<string name="settings_font_choose_file">Scegli file…</string>
|
||||||
|
<string name="settings_font_custom_selected">Carattere personalizzato</string>
|
||||||
|
<string name="settings_font_import_failed">Impossibile leggere il file come font</string>
|
||||||
|
<string name="settings_section_views">Viste</string>
|
||||||
|
<string name="settings_quick_switch_header">Pulsante di cambio rapido</string>
|
||||||
|
<string name="settings_quick_switch_hint">Scegli attraverso quali viste scorrere mediante il pulsante in alto a destra, trascinale per riordinarle. Le viste disattivate rimangono raggiungibili dal menù di navigazione.</string>
|
||||||
|
<string name="settings_drawer_order_header">Menù di navigazione</string>
|
||||||
|
<string name="settings_drawer_order_hint">Trascina per riordinare le viste elencate nel menù di navigazione.</string>
|
||||||
|
<string name="reorder_drag_handle">Trascina per riordinare</string>
|
||||||
|
<string name="settings_views_subtitle">Ordine del pulsante di cambio rapido e del menù</string>
|
||||||
|
<string name="settings_special_dates_subtitle">Compleanni e anniversari dei contatti</string>
|
||||||
|
<string name="settings_section_special_dates">Date speciali dei contatti</string>
|
||||||
|
<string name="settings_special_dates_enable">Mostra date dei contatti</string>
|
||||||
|
<string name="settings_special_dates_enable_hint">Riporta compleanni ed altre date dei tuoi contatti nei calendari locali. Legge i contatti solo su questo dispositivo - niente viene caricato in rete ed i tuoi contatti non vengono mai modificati.</string>
|
||||||
|
<string name="settings_special_dates_type_birthday">Compleanni</string>
|
||||||
|
<string name="settings_special_dates_type_anniversary">Anniversari</string>
|
||||||
|
<string name="settings_special_dates_type_custom">Altre date</string>
|
||||||
|
<string name="settings_special_dates_template">Formato del titolo</string>
|
||||||
|
<string name="settings_special_dates_template_hint">Usa {name} per il contatto e {year} per l\'anno (l\'anno di nascita, o l\'anno di inizio di un anniversario; nascosto se sconosciuto).</string>
|
||||||
|
<string name="settings_special_dates_reminders">Promemoria</string>
|
||||||
|
<string name="settings_special_dates_show_year">Mostra anno</string>
|
||||||
|
<string name="settings_special_dates_show_year_hint">Include {year} nei titoli quando è noto</string>
|
||||||
|
<string name="settings_special_dates_sync_now">Sincronizza adesso</string>
|
||||||
|
<string name="settings_special_dates_never_synced">Ancora non sincronizzato</string>
|
||||||
|
<string name="settings_special_dates_last_synced">%1$s è un tempo relativo, per esempio \"5 minuti fa\"</string>
|
||||||
|
<string name="settings_special_dates_calendar_hint">Imposta colore e visibilità di ogni calendario nelle impostazioni dei calendari.</string>
|
||||||
|
<string name="settings_special_dates_paused_title">In pausa</string>
|
||||||
|
<string name="settings_special_dates_paused_hint">Calendula non può più leggere i tuoi contatti, quindi questi calendari non vengono aggiornati.</string>
|
||||||
|
<string name="settings_special_dates_grant">Concedi accesso</string>
|
||||||
|
<string name="settings_special_dates_disable_title">Disattivare date dei contatti?</string>
|
||||||
|
<string name="settings_special_dates_disable_all_message">Questo cancella i calendari delle date dei contatti ed i loro eventi. Ogni promemoria o note che erano stati aggiunti saranno persi.</string>
|
||||||
|
<string name="settings_special_dates_disable_type_message">Questo cancella il calendario “%1$s” ed i suoi eventi. Ogni promemoria o note che erano stati aggiunti saranno persi.</string>
|
||||||
|
<string name="settings_special_dates_disable_confirm">Spegni</string>
|
||||||
|
<string name="dialog_save">Salva</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
122
app/src/main/res/values-zh-rCN/strings.xml
Normal file
122
app/src/main/res/values-zh-rCN/strings.xml
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<string-array name="backup_interval_units">
|
||||||
|
<item>Minutes</item>
|
||||||
|
<item>Hours</item>
|
||||||
|
<item>Days</item>
|
||||||
|
<item>Weeks</item>
|
||||||
|
</string-array>
|
||||||
|
<string name="app_name">Calendula</string>
|
||||||
|
<string name="app_tagline">一个现代化的日历应用</string>
|
||||||
|
<string name="state_loading">加载中…</string>
|
||||||
|
<string name="state_retry">推迟</string>
|
||||||
|
<string name="state_failure_unknown">错误!</string>
|
||||||
|
<string name="state_failure_permission">需要日历权限</string>
|
||||||
|
<string name="state_failure_permission_action">授予访问权限</string>
|
||||||
|
<string name="state_failure_no_calendars">无已设置的日历</string>
|
||||||
|
<string name="state_failure_no_calendars_action">打开系统日历设置</string>
|
||||||
|
<string name="state_failure_provider">无法读取日历</string>
|
||||||
|
<string name="permission_rationale_title">优雅地查看你的所有活动</string>
|
||||||
|
<string name="permission_rationale_body">Calendula需要获取权限来访问您的日历来展示和管理您的活动。所有权限均会在使用前申请——不必担心隐私泄露。</string>
|
||||||
|
<string name="permission_request_button">授予日历权限</string>
|
||||||
|
<string name="permission_denied_title">日历权限不可用</string>
|
||||||
|
<string name="permission_denied_body">Calendula 无法显示没有日历访问权限的事件。你可以在系统设置里再次授予它。</string>
|
||||||
|
<string name="permission_open_settings_button">打开系统设置</string>
|
||||||
|
<string name="permission_retry_button">重试</string>
|
||||||
|
<string name="permission_benefit_private_title">保留在设备</string>
|
||||||
|
<string name="permission_benefit_private_body">您的日历数据将会在本地读取,而不会被上传。</string>
|
||||||
|
<string name="permission_benefit_sync_title">所有日历</string>
|
||||||
|
<string name="permission_benefit_sync_body">Google、CalDAV、本地设备——任何同步到设备的东西都会直接显示出来。</string>
|
||||||
|
<string name="permission_benefit_privacy_title">无追踪器</string>
|
||||||
|
<string name="permission_benefit_privacy_body">零遥测,零分析,没有广告。</string>
|
||||||
|
<string name="permission_privacy_footnote">数据仅保留在本地设备 ·无网络权限</string>
|
||||||
|
<string name="month_prev">上个月</string>
|
||||||
|
<string name="month_next">下个月</string>
|
||||||
|
<string name="month_today_action">今天</string>
|
||||||
|
<string name="month_more_actions">更多选项</string>
|
||||||
|
<string name="month_open_menu">打开菜单</string>
|
||||||
|
<string name="month_action_settings">设置</string>
|
||||||
|
<string name="month_a11y_today_prefix">今天</string>
|
||||||
|
<string name="week_today_action">本周</string>
|
||||||
|
<string name="day_today_action">今天</string>
|
||||||
|
<string name="event_detail_back">返回</string>
|
||||||
|
<string name="event_detail_edit">编辑</string>
|
||||||
|
<string name="event_detail_delete">删除</string>
|
||||||
|
<string name="event_detail_share">分享</string>
|
||||||
|
<string name="event_share_chooser_title">分享活动</string>
|
||||||
|
<string name="event_share_failed">无法分享该活动。</string>
|
||||||
|
<string name="event_delete_title">删除活动?</string>
|
||||||
|
<string name="event_delete_body">该活动将从你的日历以及所有同步设备中移除。</string>
|
||||||
|
<string name="event_delete_recurring_title">删除重复活动</string>
|
||||||
|
<string name="event_delete_option_occurrence">仅该活动</string>
|
||||||
|
<string name="event_delete_option_following">当前及接下来的所有活动</string>
|
||||||
|
<string name="event_delete_option_series">系列中的所有活动</string>
|
||||||
|
<string name="event_edit_recurring_title">编辑重复活动</string>
|
||||||
|
<string name="event_delete_failed">无法删除该活动</string>
|
||||||
|
<string name="event_delete_write_denied">Calendula需要权限读取或删除活动</string>
|
||||||
|
<string name="dialog_cancel">取消</string>
|
||||||
|
<string name="dialog_ok">确认</string>
|
||||||
|
<string name="event_edit_new_title">新活动</string>
|
||||||
|
<string name="event_edit_close">关闭</string>
|
||||||
|
<string name="event_edit_save">保存</string>
|
||||||
|
<string name="event_edit_title_hint">增加标题</string>
|
||||||
|
<string name="event_edit_managed_hint">由“%1$s”管理——标题、日期和重复内容会与你的联系人保持同步。提醒、位置和笔记由你自行编辑。</string>
|
||||||
|
<string name="event_edit_starts">开始</string>
|
||||||
|
<string name="event_edit_ends">结束</string>
|
||||||
|
<string name="event_edit_error_end_before_start">报错:结束时间早于起始时间</string>
|
||||||
|
<string name="event_edit_error_no_calendar">无可写入的日历</string>
|
||||||
|
<string name="event_edit_save_failed">无法保存该活动</string>
|
||||||
|
<string name="event_edit_write_denied">Calendula需要写入权限来创建活动</string>
|
||||||
|
<string name="event_edit_more_fields">其他领域</string>
|
||||||
|
<string name="event_edit_add">新增</string>
|
||||||
|
<string name="event_edit_add_reminder">新建提醒</string>
|
||||||
|
<string name="event_edit_remove_reminder">移除提醒</string>
|
||||||
|
<string name="event_edit_attendees">访问者</string>
|
||||||
|
<string name="event_edit_add_guest">新增访问者</string>
|
||||||
|
<string name="event_edit_add_guest_hint">通过 Email 新增一个访问者…</string>
|
||||||
|
<string name="event_edit_add_guest_from_contacts">从联系人中添加访问者</string>
|
||||||
|
<string name="event_edit_location_from_contacts">从联系人中添加地址</string>
|
||||||
|
<string name="event_edit_remove_guest">移除访问者</string>
|
||||||
|
<string name="event_edit_attendee_required">必填</string>
|
||||||
|
<string name="event_edit_attendee_optional">可选项</string>
|
||||||
|
<string name="event_edit_attendees_note_synced">Calendula 不发送邀请函。你的日历账户同步时可能会给访客发邮件。</string>
|
||||||
|
<string name="event_edit_attendees_note_local">保存在本设备,其他访客不会被提醒。</string>
|
||||||
|
<string name="event_edit_reminder_custom">自定义</string>
|
||||||
|
<string name="reminder_unit_minutes">分钟</string>
|
||||||
|
<string name="reminder_unit_hours">小时</string>
|
||||||
|
<string name="reminder_unit_days">天</string>
|
||||||
|
<string name="reminder_unit_weeks">周</string>
|
||||||
|
<string name="event_edit_availability">空闲</string>
|
||||||
|
<string name="event_edit_visibility">隐私设置</string>
|
||||||
|
<string name="event_edit_color">色彩</string>
|
||||||
|
<string name="event_edit_color_default">日历颜色</string>
|
||||||
|
<string name="event_edit_color_custom">自定义颜色</string>
|
||||||
|
<string name="event_edit_color_reset">重置</string>
|
||||||
|
<string name="event_edit_color_unsupported">该日历不可用</string>
|
||||||
|
<string name="event_edit_color_unsupported_hint">此日历未设置任何颜色集。您可以在“设置”中为此类日历启用自定义颜色。</string>
|
||||||
|
<string name="event_edit_color_sync_warning">该日历在下一次同步时可能会删除或覆盖该颜色。</string>
|
||||||
|
<string name="event_edit_conflict_title">其他设备的活动已更改</string>
|
||||||
|
<string name="event_edit_conflict_body">您在编辑时,该事件已被同步或其他应用修改。您的修改要怎么处理?</string>
|
||||||
|
<string name="event_edit_conflict_overwrite">保存我的更改</string>
|
||||||
|
<string name="event_edit_conflict_overwrite_hint">仅您编辑的字段会覆盖外部更改</string>
|
||||||
|
<string name="event_edit_conflict_discard">丢弃我的更改</string>
|
||||||
|
<string name="event_edit_conflict_discard_hint">该活动保持现状</string>
|
||||||
|
<string name="event_edit_gone_title">活动被删除</string>
|
||||||
|
<string name="event_edit_gone_body">这个事件在您编辑期间已被删除了(比如在另一台设备上)。您的修改现在无法保存。</string>
|
||||||
|
<string name="event_edit_recurrence_none">确认无需重复</string>
|
||||||
|
<string name="event_edit_recurrence_custom">自定义</string>
|
||||||
|
<string name="event_edit_recurrence_every">每</string>
|
||||||
|
<string name="recurrence_unit_days">天</string>
|
||||||
|
<string name="recurrence_unit_weeks">周</string>
|
||||||
|
<string name="recurrence_unit_months">月</string>
|
||||||
|
<string name="recurrence_unit_years">年</string>
|
||||||
|
<string name="event_edit_recurrence_ends">结束时间</string>
|
||||||
|
<string name="event_edit_recurrence_end_never">从不</string>
|
||||||
|
<string name="event_edit_recurrence_end_until">于指定日期</string>
|
||||||
|
<string name="event_edit_recurrence_end_count">重复几次后</string>
|
||||||
|
<string name="event_edit_recurrence_times">次</string>
|
||||||
|
<string name="event_edit_error_recurrence_ends_before_start">报错:结束日期早于开始日期</string>
|
||||||
|
<string name="event_availability_busy">占用中</string>
|
||||||
|
<string name="event_access_default">默认</string>
|
||||||
|
<string name="event_access_public">公开</string>
|
||||||
|
</resources>
|
||||||
@@ -22,8 +22,8 @@ class EventDetailMapperTest {
|
|||||||
eventColor: Any? = null,
|
eventColor: Any? = null,
|
||||||
eventColorKey: String? = null,
|
eventColorKey: String? = null,
|
||||||
calendarColor: Int = 0xFFAABBCC.toInt(),
|
calendarColor: Int = 0xFFAABBCC.toInt(),
|
||||||
dtstart: Long = 1_000_000_000L,
|
dtstart: Long? = 1_000_000_000L,
|
||||||
dtend: Long = 1_000_003_600L,
|
dtend: Long? = 1_000_003_600L,
|
||||||
allDay: Int = 0,
|
allDay: Int = 0,
|
||||||
location: String? = "Berlin",
|
location: String? = "Berlin",
|
||||||
calendarId: Long = 7L,
|
calendarId: Long = 7L,
|
||||||
@@ -120,9 +120,31 @@ class EventDetailMapperTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `dtend before dtstart drops detail`() {
|
fun `dtend before dtstart is clamped to a zero-length event, not dropped`() {
|
||||||
|
// A backwards DTEND is malformed, but dropping it would make the event
|
||||||
|
// un-openable (the "Something went wrong" trap, same as issue #34); keep
|
||||||
|
// it as a zero-length event so the user can still open and fix it.
|
||||||
val detail = detailReader(dtstart = 2000L, dtend = 1000L).toDetail()
|
val detail = detailReader(dtstart = 2000L, dtend = 1000L).toDetail()
|
||||||
assertThat(detail).isNull()
|
assertThat(detail).isNotNull()
|
||||||
|
assertThat(detail!!.instance.start.toEpochMilliseconds()).isEqualTo(2000L)
|
||||||
|
assertThat(detail.instance.end.toEpochMilliseconds()).isEqualTo(2000L)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `pre-1970 negative dtstart is kept, not dropped (issue #34)`() {
|
||||||
|
// A yearly birthday/anniversary anchored before the epoch has a
|
||||||
|
// legitimately negative UTC epoch-millis DTSTART; recurring rows carry
|
||||||
|
// no DTEND (they use DURATION), so it stays end == begin.
|
||||||
|
val begin = -157_766_400_000L // 1965-01-01T00:00:00Z
|
||||||
|
val detail = detailReader(dtstart = begin, dtend = null).toDetail()
|
||||||
|
assertThat(detail).isNotNull()
|
||||||
|
assertThat(detail!!.instance.start.toEpochMilliseconds()).isEqualTo(begin)
|
||||||
|
assertThat(detail.instance.end.toEpochMilliseconds()).isEqualTo(begin)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `absent dtstart drops detail`() {
|
||||||
|
assertThat(detailReader(dtstart = null).toDetail()).isNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
package de.jeanlucmakiola.calendula.data.calendar
|
||||||
|
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import org.junit.jupiter.api.Test
|
||||||
|
|
||||||
|
class SearchMapperTest {
|
||||||
|
|
||||||
|
private fun searchReader(
|
||||||
|
id: Long = 1L,
|
||||||
|
calendarId: Long = 7L,
|
||||||
|
title: String? = "Birthday",
|
||||||
|
dtstart: Long? = 1_000_000_000L,
|
||||||
|
dtend: Long? = null,
|
||||||
|
duration: String? = "P1D",
|
||||||
|
allDay: Int = 1,
|
||||||
|
eventColor: Any? = null,
|
||||||
|
calendarColor: Int = 0xFFAABBCC.toInt(),
|
||||||
|
location: String? = null,
|
||||||
|
): MapColumnReader = MapColumnReader(
|
||||||
|
SearchProjection.IDX_ID to id,
|
||||||
|
SearchProjection.IDX_CALENDAR_ID to calendarId,
|
||||||
|
SearchProjection.IDX_TITLE to title,
|
||||||
|
SearchProjection.IDX_DTSTART to dtstart,
|
||||||
|
SearchProjection.IDX_DTEND to dtend,
|
||||||
|
SearchProjection.IDX_DURATION to duration,
|
||||||
|
SearchProjection.IDX_ALL_DAY to allDay,
|
||||||
|
SearchProjection.IDX_EVENT_COLOR to eventColor,
|
||||||
|
SearchProjection.IDX_CALENDAR_COLOR to calendarColor,
|
||||||
|
SearchProjection.IDX_LOCATION to location,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `pre-1970 negative dtstart still surfaces in search (issue #34)`() {
|
||||||
|
val begin = -157_766_400_000L // 1965-01-01T00:00:00Z
|
||||||
|
val result = searchReader(dtstart = begin, dtend = null, duration = "P1D").toSearchResult()
|
||||||
|
assertThat(result).isNotNull()
|
||||||
|
assertThat(result!!.start.toEpochMilliseconds()).isEqualTo(begin)
|
||||||
|
assertThat(result.title).isEqualTo("Birthday")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `absent dtstart drops the search hit`() {
|
||||||
|
assertThat(searchReader(dtstart = null).toSearchResult()).isNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
16
fastlane/metadata/android/en-US/changelogs/21301.txt
Normal file
16
fastlane/metadata/android/en-US/changelogs/21301.txt
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
### Added
|
||||||
|
- Create events from other apps and widgets. Calendula now registers the
|
||||||
|
standard "insert event" intent, so other apps and home-screen widgets (such as
|
||||||
|
the Todo Agenda widget) can hand off to Calendula to create a new event — it
|
||||||
|
opens the new-event form prefilled with whatever they passed (title, time,
|
||||||
|
location, description). Thanks to @dschuermann for the suggestion ([#30]).
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- Some recurring events could not be opened. Events in a series that started
|
||||||
|
before 1970 — for example yearly birthdays or anniversaries synced over CalDAV
|
||||||
|
— showed "Something went wrong" instead of opening. They now open normally, and
|
||||||
|
show up in search again. Thanks to @dschuermann for the report ([#34]).
|
||||||
|
- The time picker now follows your 24-hour setting. With Calendula set to
|
||||||
|
24-hour time, the dial for choosing an event's start and end time still showed
|
||||||
|
AM/PM; it now matches your setting. Thanks to @abrossimow for the report
|
||||||
|
([#27]).
|
||||||
Reference in New Issue
Block a user