From 6a125b7c734c8293c687535922d4a672c1c8d0a7 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiolas Weblate Bot Date: Thu, 6 Aug 2026 19:40:09 +0200 Subject: [PATCH 1/7] Translations update from Weblate (#136) Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/136 --- app/src/main/res/values-es/strings.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3e41783..a429555 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -491,4 +491,5 @@ Importando %d eventos Importando %d eventos + Armoniza los colores del calendario From 66dbdc89133915d5cba9e28c8ce8de3352658706 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiola Date: Thu, 6 Aug 2026 20:09:50 +0200 Subject: [PATCH 2/7] =?UTF-8?q?2.18.1=20=E2=80=94=20create=20at=20the=20ta?= =?UTF-8?q?pped=20hour=20after=20a=20zoom=20(#155)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/155 --- CHANGELOG.md | 10 ++++++++++ app/build.gradle.kts | 4 ++-- .../calendula/ui/common/TimelineScale.kt | 12 +++++++++++ .../calendula/ui/day/DayScreen.kt | 14 +++++++++++-- .../calendula/ui/week/WeekScreen.kt | 14 +++++++++++-- .../calendula/ui/common/TimelineScaleTest.kt | 20 +++++++++++++++++++ .../metadata/android/ar/changelogs/21801.txt | 2 ++ .../android/de-DE/changelogs/21801.txt | 2 ++ .../android/en-GB/changelogs/21801.txt | 2 ++ .../android/en-US/changelogs/21801.txt | 2 ++ .../android/es-ES/changelogs/21801.txt | 2 ++ .../android/fr-FR/changelogs/21801.txt | 2 ++ .../android/it-IT/changelogs/21801.txt | 2 ++ .../android/pl-PL/changelogs/21801.txt | 2 ++ .../android/pt-PT/changelogs/21801.txt | 2 ++ .../android/ru-RU/changelogs/21801.txt | 2 ++ .../android/zh-CN/changelogs/21801.txt | 2 ++ 17 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 fastlane/metadata/android/ar/changelogs/21801.txt create mode 100644 fastlane/metadata/android/de-DE/changelogs/21801.txt create mode 100644 fastlane/metadata/android/en-GB/changelogs/21801.txt create mode 100644 fastlane/metadata/android/en-US/changelogs/21801.txt create mode 100644 fastlane/metadata/android/es-ES/changelogs/21801.txt create mode 100644 fastlane/metadata/android/fr-FR/changelogs/21801.txt create mode 100644 fastlane/metadata/android/it-IT/changelogs/21801.txt create mode 100644 fastlane/metadata/android/pl-PL/changelogs/21801.txt create mode 100644 fastlane/metadata/android/pt-PT/changelogs/21801.txt create mode 100644 fastlane/metadata/android/ru-RU/changelogs/21801.txt create mode 100644 fastlane/metadata/android/zh-CN/changelogs/21801.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index 19e5eeb..0d68afe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [2.18.1] — 2026-08-06 + +### Fixed +- Tapping an empty slot in week or day view creates the event at the hour you + tapped, after the timeline has been zoomed. Pinching the day taller or shorter + — or changing **Hour height** in Settings — left the tap still being measured + against the old spacing, so the new event landed at some other hour entirely + ([#148]). + ## [2.18.0] — 2026-07-31 ### Added @@ -1323,3 +1332,4 @@ automatically, with zero telemetry and no internet permission. [#57]: https://codeberg.org/jlmakiola/calendula/issues/57 [#56]: https://codeberg.org/jlmakiola/calendula/issues/56 [#114]: https://codeberg.org/jlmakiola/calendula/issues/114 +[#148]: https://codeberg.org/jlmakiola/calendula/issues/148 diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 595c6ce..e4fd84a 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -28,8 +28,8 @@ android { // which builds this version and then creates the matching vX.Y.Z tag + // release itself (versionCode is pinned to MAJOR*10000 + MINOR*100 + // PATCH from versionName, e.g. 2.7.2 -> 20702). See docs/RELEASING.md. - versionCode = 21800 - versionName = "2.18.0" + versionCode = 21801 + versionName = "2.18.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/TimelineScale.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/TimelineScale.kt index d514029..b236aef 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/TimelineScale.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/common/TimelineScale.kt @@ -76,6 +76,18 @@ fun TimelineScale.hourHeight(viewportHeight: Dp): Dp = when (this) { .coerceAtLeast(fillHourHeight(viewportHeight)) } +/** + * The minute of the day a tap [offsetY] px down a timeline column means, snapped + * to the hour it landed in. + * + * [hourPx] must be the hour height the column is drawing at *now* — a tap + * detector that captured it when it was installed maps taps to a pre-pinch grid + * (#148). A zero or negative height (a viewport measured at nothing) has no grid + * to read, so it answers midnight rather than dividing by it. + */ +fun tappedMinuteOfDay(offsetY: Float, hourPx: Float): Int = + if (hourPx <= 0f) 0 else (offsetY / hourPx).toInt().coerceIn(0, 23) * 60 + /** * Shortest an event block may render, as a fraction of an hour. Blocks keep a * floor so a 15-minute event stays tappable, but the floor scales with the hour diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/day/DayScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/day/DayScreen.kt index 1027d13..a03b5fd 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/day/DayScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/day/DayScreen.kt @@ -45,6 +45,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -96,6 +97,7 @@ import de.jeanlucmakiola.calendula.ui.common.rememberTimelinePinchZoom import de.jeanlucmakiola.calendula.ui.common.formatHourLabel import de.jeanlucmakiola.calendula.ui.common.formatMinuteOfDay import de.jeanlucmakiola.calendula.ui.common.hourSeparatorLines +import de.jeanlucmakiola.calendula.ui.common.tappedMinuteOfDay import de.jeanlucmakiola.calendula.ui.week.TimedBlock import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch @@ -577,6 +579,12 @@ private fun DayColumnCard( val hourPx = with(LocalDensity.current) { hourHeight.toPx() } val showHourLines = LocalShowHourLines.current val hourLineColor = MaterialTheme.colorScheme.outlineVariant + // The tap detector outlives the composition that installed it — a pinch or a + // Settings change moves the hour height without restarting it — so it reads + // the height and the callback through state handles instead of capturing + // them, or taps land on the scale the column had before the zoom (#148). + val currentHourPx = rememberUpdatedState(hourPx) + val currentOnCreateAt = rememberUpdatedState(onCreateAt) Card( // Plain rectangular column — the soft corners come from the outer // rounded scroll viewport, so inner rounding would look odd at the edges. @@ -597,8 +605,10 @@ private fun DayColumnCard( // only fires on the column background. Snaps to the tapped hour. .pointerInput(date) { detectTapGestures { offset -> - val hour = (offset.y / hourPx).toInt().coerceIn(0, 23) - onCreateAt(date, hour * 60) + currentOnCreateAt.value( + date, + tappedMinuteOfDay(offset.y, currentHourPx.value), + ) } }, ) { diff --git a/app/src/main/java/de/jeanlucmakiola/calendula/ui/week/WeekScreen.kt b/app/src/main/java/de/jeanlucmakiola/calendula/ui/week/WeekScreen.kt index f4ff867..306bda5 100644 --- a/app/src/main/java/de/jeanlucmakiola/calendula/ui/week/WeekScreen.kt +++ b/app/src/main/java/de/jeanlucmakiola/calendula/ui/week/WeekScreen.kt @@ -51,6 +51,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableIntStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.rememberUpdatedState import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment @@ -107,6 +108,7 @@ import de.jeanlucmakiola.calendula.ui.common.rememberTimelinePinchZoom import de.jeanlucmakiola.calendula.ui.common.formatHourLabel import de.jeanlucmakiola.calendula.ui.common.formatMinuteOfDay import de.jeanlucmakiola.calendula.ui.common.hourSeparatorLines +import de.jeanlucmakiola.calendula.ui.common.tappedMinuteOfDay import de.jeanlucmakiola.calendula.ui.common.rememberCalendarSlideSpec import de.jeanlucmakiola.calendula.ui.common.next import de.jeanlucmakiola.floret.time.isoWeekNumber @@ -722,6 +724,12 @@ private fun DayColumnCard( val hourPx = with(LocalDensity.current) { hourHeight.toPx() } val showHourLines = LocalShowHourLines.current val hourLineColor = MaterialTheme.colorScheme.outlineVariant + // The tap detector outlives the composition that installed it — a pinch or a + // Settings change moves the hour height without restarting it — so it reads + // the height and the callback through state handles instead of capturing + // them, or taps land on the scale the column had before the zoom (#148). + val currentHourPx = rememberUpdatedState(hourPx) + val currentOnCreateAt = rememberUpdatedState(onCreateAt) Card( // Plain rectangular columns — the soft corners come from the outer // rounded scroll viewport, so inner rounding would look odd at the edges. @@ -741,8 +749,10 @@ private fun DayColumnCard( // blocks are consumed by their own handler first. Snaps to hour. .pointerInput(date) { detectTapGestures { offset -> - val hour = (offset.y / hourPx).toInt().coerceIn(0, 23) - onCreateAt(date, hour * 60) + currentOnCreateAt.value( + date, + tappedMinuteOfDay(offset.y, currentHourPx.value), + ) } }, ) { diff --git a/app/src/test/java/de/jeanlucmakiola/calendula/ui/common/TimelineScaleTest.kt b/app/src/test/java/de/jeanlucmakiola/calendula/ui/common/TimelineScaleTest.kt index c78bcd4..15b1e19 100644 --- a/app/src/test/java/de/jeanlucmakiola/calendula/ui/common/TimelineScaleTest.kt +++ b/app/src/test/java/de/jeanlucmakiola/calendula/ui/common/TimelineScaleTest.kt @@ -126,4 +126,24 @@ class TimelineScaleTest { assertThat(parseTimelineScale(stored)).isEqualTo(TimelineScale.Regular) } } + + @Test + fun `a tap creates at the hour it landed in, at whatever scale`() { + // Same point on the same column reads as a different hour once the + // timeline has been pinched — which is the whole of #148: the tap has to + // be measured against the height the column is drawing at now. + assertThat(tappedMinuteOfDay(offsetY = 500f, hourPx = 100f)).isEqualTo(5 * 60) + assertThat(tappedMinuteOfDay(offsetY = 500f, hourPx = 50f)).isEqualTo(10 * 60) + // Within an hour it snaps back to that hour's start. + assertThat(tappedMinuteOfDay(offsetY = 599f, hourPx = 100f)).isEqualTo(5 * 60) + } + + @Test + fun `a tap outside the day stays inside it`() { + assertThat(tappedMinuteOfDay(offsetY = -20f, hourPx = 56f)).isEqualTo(0) + assertThat(tappedMinuteOfDay(offsetY = 99_999f, hourPx = 56f)).isEqualTo(23 * 60) + // A viewport measured at nothing has no grid to read — midnight, not a + // division by zero. + assertThat(tappedMinuteOfDay(offsetY = 500f, hourPx = 0f)).isEqualTo(0) + } } diff --git a/fastlane/metadata/android/ar/changelogs/21801.txt b/fastlane/metadata/android/ar/changelogs/21801.txt new file mode 100644 index 0000000..9fb5c70 --- /dev/null +++ b/fastlane/metadata/android/ar/changelogs/21801.txt @@ -0,0 +1,2 @@ +إصلاحات +• عرض الأسبوع واليوم: النقر على مساحة فارغة يُنشئ الحدث في الساعة التي نقرت عليها، حتى بعد تكبير شريط الوقت أو تغيير ارتفاع الساعة. diff --git a/fastlane/metadata/android/de-DE/changelogs/21801.txt b/fastlane/metadata/android/de-DE/changelogs/21801.txt new file mode 100644 index 0000000..34add94 --- /dev/null +++ b/fastlane/metadata/android/de-DE/changelogs/21801.txt @@ -0,0 +1,2 @@ +Behoben +• Wochen- und Tagesansicht: Ein Tippen auf einen freien Bereich legt den Termin jetzt zur angetippten Uhrzeit an – auch nachdem die Zeitleiste gezoomt oder die Stundenhöhe geändert wurde. diff --git a/fastlane/metadata/android/en-GB/changelogs/21801.txt b/fastlane/metadata/android/en-GB/changelogs/21801.txt new file mode 100644 index 0000000..e8f6b85 --- /dev/null +++ b/fastlane/metadata/android/en-GB/changelogs/21801.txt @@ -0,0 +1,2 @@ +Fixed +• Week and day view: tapping an empty slot now creates the event at the hour you tapped, even after zooming the timeline or changing the hour height. diff --git a/fastlane/metadata/android/en-US/changelogs/21801.txt b/fastlane/metadata/android/en-US/changelogs/21801.txt new file mode 100644 index 0000000..e8f6b85 --- /dev/null +++ b/fastlane/metadata/android/en-US/changelogs/21801.txt @@ -0,0 +1,2 @@ +Fixed +• Week and day view: tapping an empty slot now creates the event at the hour you tapped, even after zooming the timeline or changing the hour height. diff --git a/fastlane/metadata/android/es-ES/changelogs/21801.txt b/fastlane/metadata/android/es-ES/changelogs/21801.txt new file mode 100644 index 0000000..516da95 --- /dev/null +++ b/fastlane/metadata/android/es-ES/changelogs/21801.txt @@ -0,0 +1,2 @@ +Corregido +• Vista de semana y día: al tocar un hueco libre, el evento se crea a la hora que has tocado, incluso después de ampliar la línea de tiempo o cambiar la altura de la hora. diff --git a/fastlane/metadata/android/fr-FR/changelogs/21801.txt b/fastlane/metadata/android/fr-FR/changelogs/21801.txt new file mode 100644 index 0000000..bf43334 --- /dev/null +++ b/fastlane/metadata/android/fr-FR/changelogs/21801.txt @@ -0,0 +1,2 @@ +Corrigé +• Vues Semaine et Jour : appuyer sur un créneau vide crée désormais l'événement à l'heure touchée, même après avoir zoomé sur la grille ou modifié la hauteur d'une heure. diff --git a/fastlane/metadata/android/it-IT/changelogs/21801.txt b/fastlane/metadata/android/it-IT/changelogs/21801.txt new file mode 100644 index 0000000..38ba36f --- /dev/null +++ b/fastlane/metadata/android/it-IT/changelogs/21801.txt @@ -0,0 +1,2 @@ +Corretto +• Vista settimana e giorno: toccando uno spazio libero l'evento viene creato all'ora toccata, anche dopo aver ingrandito la linea temporale o cambiato l'altezza dell'ora. diff --git a/fastlane/metadata/android/pl-PL/changelogs/21801.txt b/fastlane/metadata/android/pl-PL/changelogs/21801.txt new file mode 100644 index 0000000..359c9a2 --- /dev/null +++ b/fastlane/metadata/android/pl-PL/changelogs/21801.txt @@ -0,0 +1,2 @@ +Poprawki +• Widok tygodnia i dnia: dotknięcie pustego miejsca tworzy teraz wydarzenie o dotkniętej godzinie, także po powiększeniu osi czasu lub zmianie wysokości godziny. diff --git a/fastlane/metadata/android/pt-PT/changelogs/21801.txt b/fastlane/metadata/android/pt-PT/changelogs/21801.txt new file mode 100644 index 0000000..bfbb427 --- /dev/null +++ b/fastlane/metadata/android/pt-PT/changelogs/21801.txt @@ -0,0 +1,2 @@ +Corrigido +• Vista de semana e de dia: tocar num espaço livre cria o evento à hora tocada, mesmo depois de ampliar a linha temporal ou alterar a altura da hora. diff --git a/fastlane/metadata/android/ru-RU/changelogs/21801.txt b/fastlane/metadata/android/ru-RU/changelogs/21801.txt new file mode 100644 index 0000000..6dd2e26 --- /dev/null +++ b/fastlane/metadata/android/ru-RU/changelogs/21801.txt @@ -0,0 +1,2 @@ +Исправлено +• Вид недели и дня: нажатие на свободное место создаёт событие на выбранный час — в том числе после масштабирования шкалы времени или изменения высоты часа. diff --git a/fastlane/metadata/android/zh-CN/changelogs/21801.txt b/fastlane/metadata/android/zh-CN/changelogs/21801.txt new file mode 100644 index 0000000..c3ec928 --- /dev/null +++ b/fastlane/metadata/android/zh-CN/changelogs/21801.txt @@ -0,0 +1,2 @@ +修复 +• 周视图和日视图:点按空白处会在所点的时间创建事件,即使在缩放时间轴或更改小时高度之后也是如此。 From a6a6c0c71482975b5a29d18b20b126b4520047cf Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 8 Aug 2026 13:48:29 +0200 Subject: [PATCH 3/7] fix(deps): update documentfile to v1.1.0 (#157) Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/157 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aeb3573..bf1deca 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -27,7 +27,7 @@ androidxTestRules = "1.7.0" # Glance: 1.1.1 is the latest stable (1.2.0 is still rc, 1.3.0 alpha). glance = "1.1.1" work = "2.10.1" -documentfile = "1.0.1" +documentfile = "1.1.0" [libraries] # AndroidX core From 3c8c555b943a06d0ce7833230e472927d2d0151c Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 8 Aug 2026 13:50:15 +0200 Subject: [PATCH 4/7] fix(deps): update hiltnavigationcompose to v1.4.0 (#159) Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/159 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bf1deca..d688e8f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ espressoCore = "3.7.0" kotlinxDatetime = "0.7.0" kotlinxCoroutines = "1.10.2" turbine = "1.2.1" -hiltNavigationCompose = "1.3.0" +hiltNavigationCompose = "1.4.0" lifecycleCompose = "2.10.0" androidxTestRules = "1.7.0" # Glance: 1.1.1 is the latest stable (1.2.0 is still rc, 1.3.0 alpha). From 5b83b9da73a36b781616db2e93ad023548d4eead Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 8 Aug 2026 13:50:44 +0200 Subject: [PATCH 5/7] fix(deps): update kotlinx-coroutines monorepo to v1.11.0 (#160) Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/160 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d688e8f..1050c07 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ truth = "1.4.5" androidxJunit = "1.3.0" espressoCore = "3.7.0" kotlinxDatetime = "0.7.0" -kotlinxCoroutines = "1.10.2" +kotlinxCoroutines = "1.11.0" turbine = "1.2.1" hiltNavigationCompose = "1.4.0" lifecycleCompose = "2.10.0" From 3f85bac74e00f5fb00413008fb46deeb40345d8b Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 8 Aug 2026 13:51:11 +0200 Subject: [PATCH 6/7] chore(deps): update ksp monorepo to v2.3.10 (#137) Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/137 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1050c07..8eeeb9b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,7 @@ [versions] agp = "9.2.1" kotlin = "2.3.21" -ksp = "2.3.9" +ksp = "2.3.10" hilt = "2.59.2" coreKtx = "1.19.0" appcompat = "1.7.1" From 25e3640ba0024289c2482e2d4f74be75f32f7d97 Mon Sep 17 00:00:00 2001 From: Jean-Luc Makiolas Weblate Bot Date: Mon, 10 Aug 2026 18:04:24 +0200 Subject: [PATCH 7/7] Translations update from Weblate (#170) Translations update from [Weblate](https://weblate.dev.jeanlucmakiola.de) for [Calendula/Strings](https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/). Current translation status: ![Weblate translation status](https://weblate.dev.jeanlucmakiola.de/widget/calendula/strings/horizontal-auto.svg) Co-authored-by: Anonymous Co-authored-by: Admin Co-authored-by: Sup99999 Co-authored-by: Weblate Co-authored-by: Weblate Co-authored-by: Pedro Co-authored-by: Bernardo Krzysczak Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/170 --- app/src/main/res/values-pt-rBR/strings.xml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 app/src/main/res/values-pt-rBR/strings.xml diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml new file mode 100644 index 0000000..92a7f63 --- /dev/null +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -0,0 +1,9 @@ + + + + Minutes + Hours + Days + Weeks + +