Commit Graph
563 Commits
Author SHA1 Message Date
makiolaj ce55b913cd Back clears the selected day in the split month view (#142)
Beta — Codeberg pre-release / detect (push) Successful in 5s
Beta — Codeberg pre-release / beta (push) Skipped
2026-11-06 17:16:27 +01:00
makiolaj 5dd522e4c6 Merge remote-tracking branch 'origin/release/2.24.0' into prep/2.24.0
Beta — Codeberg pre-release / detect (push) Successful in 6s
Beta — Codeberg pre-release / beta (push) Skipped
# Conflicts:
#	CHANGELOG.md
2026-11-06 16:44:56 +01:00
Tritra002andtritra002 7bdd0329bc Smoother split month expand and collapse, animated week numbers (#473) (#474)
Co-authored-by: tritra002 <tritra002@noreply.codeberg.org>
2026-11-06 16:44:30 +01:00
makiolaj 03138b8740 Merge main (v2.23.1) into release/2.24.0 2026-11-06 11:43:06 +01:00
Jean-Luc Makiola 4d3859490b Keep short events at the end of the day fully visible (#483) (#485)
Beta — Codeberg pre-release / detect (push) Successful in 7s
Beta — Codeberg pre-release / beta (push) Skipped
Short events near midnight keep their minimum height flush against midnight and get their own lane, and the timeline scrolls far enough past midnight to clear the + button.
2026-11-06 11:31:30 +01:00
Jean-Luc Makiola 2da892e34a Month view: setting to hide start times, per-chip title rule (#476) (#486)
Beta — Codeberg pre-release / detect (push) Successful in 6s
Beta — Codeberg pre-release / beta (push) Skipped
New Start times switch under Settings → Views → Month, and the time on a month chip now only shows when the whole title or its first 12 characters still fit beside it.
2026-11-06 11:11:37 +01:00
Jean-Luc Makiola edd4bf965a Follow-ups for whole-day events and event status (#296, #388) (#484)
Beta — Codeberg pre-release / detect (push) Successful in 6s
Beta — Codeberg pre-release / beta (push) Skipped
Drag all-day strip events between days or back into the grid, show cancelled one-off events, review fixes, floret-kit pinned to main.
2026-11-06 10:13:03 +01:00
Jean-Luc Makiolaandmakiolaj 90245b6893 Midnight-to-midnight events as all-day, and event status (#296, #388) (#472)
Beta — Codeberg pre-release / detect (push) Successful in 6s
Beta — Codeberg pre-release / beta (push) Skipped
Combines #470 and #471 into one PR.

## Midnight-to-midnight events (#296)

A timed event that starts and ends on local midnight now displays as an all-day event:

- Day/week: in the all-day strip instead of the time grid.
- Month and month widget: a bar with no start time.
- Agenda and agenda widget: "All day".
- Sorting: with the all-day events.
- Countdown widget: skipped in next-event mode like other all-day events, with the all-day label when pinned.
- Reminder notification: the text names the day(s) instead of 00:00 – 00:00.

The event itself stays timed. The detail sheet still shows 00:00 – 00:00, and reminders still fire at their own lead time before 00:00, since that is what the stored reminder says. Midnight is checked in the device zone, so a feed event stored as 22:00Z only counts as whole-day at UTC+2. Search results are left as they are.

Dragging or resizing a block in the timeline so it lands exactly on midnight to midnight moves it to the all-day strip. The floating copy and the selection are dropped right away. Display priority is now computed once per event, not on every sort comparison.

## Event status (#388)

The calendar views now use the event's own status (Events.STATUS), not just your reply to an invite:

- Cancelled events are struck through and sorted last, the same as declined invites. This applies to day/week, month, agenda, search and the widgets. The countdown widget skips them in both modes, and the week-strip widget leaves them out of its count and dots.
- Tentative events get the outline used for unanswered invites (in-app grids). An event that is both cancelled and an open invite is struck through, not outlined.
- Cancelled standalone events and cancelled series are no longer hidden. Cancelled exception rows (a single occurrence deleted from a series) are still filtered out, matched by ORIGINAL_ID or ORIGINAL_SYNC_ID.
- The editor has a new optional Status field after Availability, built on floret-kit's new `SegmentedChoiceCard` (Availability uses it too). A new event writes STATUS only when it isn't Confirmed, an edit writes it only when it changed.
- `isDeclined` was renamed to `isCrossedOut`, and a new `isOutlined` covers both cases.

Deviations from the issue:

- The editor offers Confirmed and Tentative only. Cancelled is offered only for an event that's already cancelled, so it can be put back. Google treats a cancelled event as deleted, so letting people pick it would silently delete Google events.
- A cancelled series can't be edited or moved one occurrence at a time. "Only this event" is left out of the scope prompts, because Android saves a cancelled single occurrence as a deleted one. A drag that could only move the single occurrence is refused.
- The widgets don't draw outlines for unanswered invites either, so tentative events look filled there.

Depends on jlmakiola/floret-kit#27. The submodule is pinned to its branch, so that PR has to land on floret-kit main and the pin has to be moved before release.

Closes #296
Closes #388

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/472
2026-11-03 14:13:35 +01:00
Jean-Luc Makiolaandmakiolaj 8987573295 Don't list a free first day in the split agenda (#142) (#469)
Beta — Codeberg pre-release / detect (push) Successful in 6s
Beta — Codeberg pre-release / beta (push) Skipped
With no day selected, the split agenda always added its start day, so in any month other than the current one an empty 1st showed a "Nothing scheduled" block above the first events.

The list now only holds days with events. A free today is kept only when the Agenda view's "show today" setting is on, using the same helper as the Agenda view. A month with nothing in it shows a single "Nothing scheduled this month" row instead of a date header ("Nothing else scheduled this month" for the rest of the current one); these are two new strings. A fixed first item keeps a newly added earlier day in view instead of above the scroll position.

Closes #142

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/469
2026-11-02 20:53:02 +01:00
Jean-Luc Makiolaandmakiolaj 1807f228e7 Share one date span across every view (#457) (#466)
Beta — Codeberg pre-release / detect (push) Successful in 8s
Beta — Codeberg pre-release / beta (push) Skipped
Switching back to month view after going before 1 Jan 1900 in day or week view crashed with `IndexOutOfBoundsException: index: -1, size: 12`. Each view had its own range: the month grid and the date picker covered 1900–2100, while the week and day pagers reached roughly 1808–2191. The month view took the date it was handed without checking it.

- A new `CalendarSpan` (1 Jan 1600 – 31 Dec 2399) is used by the month and dense-week grids, the week, multi-day and day pagers, and the date picker's `yearRange`. No view can hand another a date it can't show, and you can now go past 2100 and before 1900 everywhere.
- Every write to the month view's current month goes through one clamp, and `yearMonthForIndex` can't throw on any index. This is a safety net for dates arriving from outside, such as another app opening Calendula via the time intent.
- Tapping a greyed-out day past either end of the grid is ignored.

The timeline pagers now number pages from the span's first day rather than around a fixed middle page, so page numbers change once. `PageNumberingTest` pins the new numbering.

Closes #457

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/466
2026-11-02 20:31:21 +01:00
Jean-Luc Makiolaandmakiolaj b794c35d8e Keep month pages updating after a drag (#440, #454) (#467)
Beta — Codeberg pre-release / detect (push) Successful in 9s
Beta — Codeberg pre-release / beta (push) Skipped
A month page could stop updating for good. `PageStateCache` cancelled a month's query when the requested month moved far enough away, but the pager keeps pages composed further out than that window. Even a small drag that snaps back loads two months ahead (it prefetches), so the neighbouring month was dropped while still on screen. That page then never showed new or edited events until you swiped two months away and back.

This explains both reports. In split mode the day pane reads from the same stale page, and opening an event from it handed the editor the old start and end times.

`PageStateCache` now runs a page's query only while something collects it, stops it 5 s after the last collector leaves, and starts it again when it's collected again. Letting an entry go only removes it from the cache; it never stops a state a page still holds. A dropped entry nobody collects holds no coroutine. Week and day views use the same cache and get the same behaviour.

Widening the month window was tried first and wasn't enough, since how far the pager composes depends on drag and prefetch.

Closes #440
Closes #454

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/467
2026-11-02 20:30:58 +01:00
Jean-Luc Makiolaandmakiolaj 43ef4027f5 One reminder notification per event occurrence (#463) (#468)
Beta — Codeberg pre-release / detect (push) Successful in 7s
Beta — Codeberg pre-release / beta (push) Skipped
An event with several reminders posted a separate notification for each one. Each occurrence now has one notification, and every later reminder replaces the earlier one in place.

- The notification tag and the snooze alarm are keyed on the occurrence. Snooze, dismiss and open actions stay per reminder, so tapping them on an outdated notification can't remove the newer one.
- A different reminder alerts again; the same reminder posted twice stays silent.
- If several reminders of one occurrence are due in the same scan (e.g. after the phone was off), only the latest is posted.
- A newly due reminder cancels a pending snooze for its occurrence, and a snoozed reminder doesn't re-show over a newer one.
- Notifications posted before this change still dismiss and snooze, and a newer reminder for the same event replaces them.
- Reminder and occurrence keys share one hash in `ReminderPlan`.

Closes #463

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/468
2026-11-02 20:30:43 +01:00
Jean-Luc Makiolaandmakiolaj a5c4a73de1 Release v2.23.1 (#453)
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 8s
Renovate / renovate (push) Successful in 2m2s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Successful in 17m11s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Successful in 1m37s
Follow-up to the #142 feedback in the split month view:

- With a day selected, the filter chip now stands in for the day's header, so the date isn't shown twice. Tapping the chip opens the Day view; its ✕ clears the filter.
- The day headers in the agenda pane below the grid use less vertical space.
- Event dots no longer drop on days that show a "+N".

Closes #142

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/453
2026-10-28 20:11:10 +01:00
Jean-Luc Makiola 2a55bc3baa Fix widget review findings for 2.24 (#452)
Beta — Codeberg pre-release / detect (push) Successful in 6s
Beta — Codeberg pre-release / beta (push) Skipped
2026-10-28 18:45:19 +01:00
Jean-Luc Makiolaandmakiolaj f5e28eae8d Widget fixes and tweaks from the 2.24 beta feedback (#449)
Beta — Codeberg pre-release / detect (push) Successful in 5s
Beta — Codeberg pre-release / beta (push) Skipped
Feedback on 2.24.0-beta.1 from #90, #376 and #71. floret-kit is pinned to its main after floret-kit#24, which carries the shared parts.

- Transparent background: switching to or from it now shows right away on Date, Countdown, Week strip, Quick add, Upcoming and Today (and the Month and day grid). Their backings always set a fill, so a reapplied rendering can't keep the old one.
- App language: changing it in Settings redraws every widget, which now render in the app language. Below Android 13 the choice is mirrored for the widget process, since AppCompat only applies it inside an activity.
- Picker previews: Countdown and Week strip previews inflate on Android 14 and below (they used View/Space, which RemoteViews refuses).
- Month widget: days outside the month take a 40% lighter shade, in the widget and its XML preview.
- Add button: the filled header action is 44dp instead of 36dp wide (floret-kit).
- Tinted background: the tonal header and weekday pills had the same tone as the fill and disappeared; they now use inversePrimary there (floret-kit). Not in the issues, found while testing.
- Dimmed past events (Month and day, Today, Agenda): the fill fades to 30% and the text to 65% instead of both to 40%, so the title stays readable.
- Widget picker: names drop the Calendula prefix, and each widget gets its own description instead of repeating its name (#71).

The config screen stalling until touched (#90, item 2) is not addressed: it didn't reproduce on an Android 12 emulator.

Closes #376
Closes #71

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/449
2026-10-28 15:34:16 +01:00
makiolaj 3f81bb9ea5 Widget picker: generated previews on Android 15+, XML mock-ups redrawn to match the widgets 2026-10-26 20:08:18 +01:00
makiolaj a08ad15c4a Month and day widget: clear the fill of previously tapped days (#441) 2026-10-26 20:08:11 +01:00
makiolaj c9cc40ff60 Month and day widget: compact month grid beside the selected day's events (#441) 2026-10-23 18:51:49 +02:00
makiolaj 343a8904ea Countdown widget: next timed event or a chosen event/series, redrawn when its label changes (#439) 2026-10-23 18:51:49 +02:00
makiolaj 075940d29e Today list widget: today's events, then tomorrow's first ones once the day is done (#438) 2026-10-23 18:51:49 +02:00
makiolaj 670cdb226a Upcoming widget: today's date over the next events, rows fitted to the height (#437) 2026-10-23 18:51:49 +02:00
makiolaj a8da8bc7a3 Week strip widget: this week's days with event-colour dots, today filled (#436) 2026-10-23 18:51:49 +02:00
makiolaj cfcba283f1 Date widget: 1×1 weekday and day number on a cookie shape, opens today (#376) 2026-10-23 18:51:49 +02:00
makiolaj 85d4dc535c Quick add widget: 1×1 shaped + opening the editor on today (#435) 2026-10-23 18:51:49 +02:00
makiolaj edf80fe8b8 Widgets: one kind registry and receiver base, per-widget calendar choice (#292) 2026-10-23 18:51:49 +02:00
makiolaj 610409012f Month widget: day cells and weekday pills, shaded outside days, new-event button (#71) 2026-10-23 17:59:34 +02:00
makiolaj 94b04c1365 Month widget grid: palette-following colours, day ripples, bold today, strike via span, lane cap (#372) 2026-10-23 15:45:54 +02:00
makiolaj d1557825c6 Month widget: draw the weeks as plain RemoteViews, lanes from the widget's height (#372)
Glance's 499 view ids forced busy months down to one or two lanes. The week rows are now one embedded RemoteViews tree, so every event that fits the height gets its bar and only the rest folds into +N. The on-device test now checks the payload instead of the view count.
2026-10-23 15:16:28 +02:00
makiolaj d43a741c93 Agenda widget: format the month label outside the composable (#71) 2026-10-23 15:16:28 +02:00
makiolaj 6da0648b77 Widget redesign: agenda date pills and tinted day cards, month labels, pill headers, true-size config preview (#71, #90)
Drops the agenda refresh button (redraws are automatic since #420). Caps the config preview at Glance's 10-row Column limit, which made it fail with busy agendas (#292).
2026-10-23 14:51:29 +02:00
makiolaj 04a677dc10 Per-widget config screen: background, theme and agenda options (#292) 2026-10-23 11:12:18 +02:00
makiolaj 46ca2db63a Month widget: count Glance's real view ids per Android version, test the budget on device (#372) 2026-10-21 18:44:14 +02:00
makiolaj a87ebc33b6 Month widget: tap a day anywhere opens it, fit busy months into Glance's view limit (#386, #372) 2026-10-21 18:18:01 +02:00
makiolaj 35f5dc1666 Fix widget onUpdate crash, skip provider echoes, per-widget redraws (#420, #229) 2026-10-21 17:36:30 +02:00
makiolaj 225901ceee Share widget loads across sizes, redraw on own changes only (#420, #229) 2026-10-21 17:02:43 +02:00
makiolaj 77e103c66c Move widgets onto floret-kit glance, reload on every redraw (#420, #229) 2026-10-21 15:26:05 +02:00
dbd5ce6700 Release v2.23.0 (#433)
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 9s
Renovate / renovate (push) Successful in 1m28s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Successful in 18m17s
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Successful in 1m31s
Beta — Codeberg pre-release / detect (push) Successful in 5s
Beta — Codeberg pre-release / beta (push) Skipped
Stable 2.23.0 after four betas. It adds long-press select, move, resize and drafting in the timeline, tap-to-call phone numbers, formatted HTML descriptions, scrolling back in the agenda, events from shared text, the option to open the editor on tap, the black theme, Liberapay and more haptics. It also fixes the daylight saving and recurring-move bugs. CHANGELOG.md has the full list, and every store locale has its own What's New.

I merged main into the release branch to pick up Liberapay (#430) and Weblate #421. The Czech and Japanese string conflicts were lines added at the end of each file on both sides, so I kept main's.

Closes #116, closes #141, closes #153, closes #178, closes #181, closes #271, closes #306, closes #339, closes #367, closes #387, closes #413

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Co-authored-by: Tritra002 <tritratrulala002@outlook.com>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/433
2026-10-21 14:10:22 +02:00
James Trivette 7c522c5903 Translated using Weblate (Czech)
Currently translated at 100.0% (656 of 656 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/cs/
2026-10-21 08:16:14 +00:00
Sup99999 6ef516fe4d Translated using Weblate (Arabic)
Currently translated at 100.0% (651 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ar/
2026-10-21 02:38:13 +00:00
mirai yamada 9a7d65be6b Translated using Weblate (Japanese)
Currently translated at 17.6% (115 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ja/
2026-10-21 02:38:13 +00:00
mirai yamada c2aae1629f Translated using Weblate (Japanese)
Currently translated at 17.3% (113 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ja/
2026-10-21 02:38:13 +00:00
Weblate a697803e29 Translated using Weblate (Japanese)
Currently translated at 17.3% (113 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ja/
2026-10-21 02:38:13 +00:00
Weblate f4b6cb3acb Translated using Weblate (Japanese)
Currently translated at 16.4% (107 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ja/
2026-10-21 02:38:13 +00:00
mirai yamada c3f3eb83f2 Translated using Weblate (Japanese)
Currently translated at 16.4% (107 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ja/
2026-10-21 02:38:13 +00:00
Jean-Luc Makiolaandmakiolaj 5d10f773ca Add Liberapay alongside Ko-fi for donations (#430)
Release — F-Droid repo + Gitea/Codeberg release + Play / detect (push) Successful in 10s
Release — F-Droid repo + Gitea/Codeberg release + Play / release (push) Skipped
Release — F-Droid repo + Gitea/Codeberg release + Play / play (push) Skipped
Renovate / renovate (push) Successful in 2m1s
Adds Liberapay as a second donation option next to Ko-fi.

- Settings: "Support development" now opens a full-screen picker with Ko-fi (one-off tips) and Liberapay (recurring donations) instead of linking straight to Ko-fi.
- README: Liberapay badge next to the Ko-fi badge, plus a short Support section.

No issue for this one.

Co-authored-by: Jean-Luc Makiola <business@jeanlucmakiola.de>
Reviewed-on: https://codeberg.org/jlmakiola/calendula/pulls/430
2026-10-20 11:09:52 +02:00
mirai yamada 10414fcf05 Translated using Weblate (Japanese)
Currently translated at 13.2% (86 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ja/
2026-10-15 12:55:25 +00:00
Dmitri Gabinski 49f604bdc2 Translated using Weblate (Belarusian)
Currently translated at 92.6% (603 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/be/
2026-10-13 12:41:03 +00:00
Dmitri Gabinski 56763f58da Translated using Weblate (Russian)
Currently translated at 39.1% (255 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/ru/
2026-10-13 12:41:02 +00:00
Dmitri Gabinski af34f014a7 Translated using Weblate (Belarusian)
Currently translated at 90.6% (590 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/be/
2026-10-13 10:01:47 +00:00
Dmitri Gabinski 3280191309 Translated using Weblate (Belarusian)
Currently translated at 90.3% (588 of 651 strings)

Translation: Calendula/Strings
Translate-URL: https://weblate.dev.jeanlucmakiola.de/projects/calendula/strings/be/
2026-10-13 09:50:18 +00:00