From 3bad2b50187f55463588a2d4e74fa9df4beb35b8 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sat, 10 Oct 2026 14:52:57 +0200 Subject: feat(android): back the calendars up as an iCalendar file A Calendar section sends every calendar the person can edit, as a dated .ics, into /-calendar once a day when it changed. Co-Authored-By: Claude Opus 5.5 --- docs/MESHBAY_DESIGN.md | 24 ++- docs/USERGUIDE.md | 13 +- .../app/src/main/AndroidManifest.xml | 2 + .../app/src/main/assets/bridge/meshbay-bridge.js | 12 ++ .../main/kotlin/org/meshbay/client/MainActivity.kt | 4 + .../org/meshbay/client/phonesync/CalendarSource.kt | 89 +++++++++++ .../kotlin/org/meshbay/client/phonesync/Ics.kt | 176 +++++++++++++++++++++ .../src/test/kotlin/org/meshbay/client/IcsTest.kt | 117 ++++++++++++++ packages/meshbay-hub/src/meshbay_hub/static/app.js | 7 +- .../src/meshbay_hub/static/locales/de.js | 3 + .../src/meshbay_hub/static/locales/en.js | 3 + .../src/meshbay_hub/static/locales/es.js | 3 + .../src/meshbay_hub/static/locales/fr.js | 3 + .../src/meshbay_hub/static/locales/it.js | 3 + .../src/meshbay_hub/static/locales/ja.js | 3 + .../src/meshbay_hub/static/locales/nl.js | 3 + .../src/meshbay_hub/static/locales/pl.js | 3 + .../src/meshbay_hub/static/locales/pt-BR.js | 3 + .../src/meshbay_hub/static/locales/zh-CN.js | 3 + .../src/meshbay_hub/static/phone-sync-settings.js | 10 +- .../src/meshbay_hub/static/phone-sync.js | 10 +- .../meshbay-hub/src/meshbay_hub/static/platform.js | 3 +- .../meshbay-hub/tests/harness/photo_sync_probe.py | 9 ++ packages/meshbay-hub/tests/test_android_shell.py | 4 +- packages/meshbay-hub/tests/test_photo_sync_ui.py | 6 +- 25 files changed, 495 insertions(+), 21 deletions(-) create mode 100644 packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/phonesync/CalendarSource.kt create mode 100644 packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/phonesync/Ics.kt create mode 100644 packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/IcsTest.kt diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md index 29b31a2..a30215d 100644 --- a/docs/MESHBAY_DESIGN.md +++ b/docs/MESHBAY_DESIGN.md @@ -3431,10 +3431,10 @@ foreground service (`BackupService`) and the WebView reported visible, like a cast (§11.3). Android 15 limits that type to six hours a day; the service stops when told and the run carries on at the next opening. -### 9.13 Contacts and messages backup (Android) +### 9.13 Contacts, calendar and messages backup (Android) -The Android application sends a copy of the phone's **contacts** and its **text -messages** to a folder of a group, on the photo backup's terms (§9.12): a client +The Android application sends a copy of the phone's **contacts**, its +**calendars** and its **text messages** to a folder of a group, on the photo backup's terms (§9.12): a client feature over the upload path, additive, once a day, the page doing the sending and the phone handing one file over by token (`/phonesync/`, `phonesync/` in the Android package, `phone-sync.js` on the page). Each kind is @@ -3452,6 +3452,18 @@ contact through `ContactsContract.Contacts.CONTENT_VCARD_URI`, the format any phone imports. It is sent only when its SHA-256 differs from the last copy the node took; a day with no change sends nothing. +**Calendar.** `/-calendar/calendar-2026-10-10-0900.ics`: one +iCalendar file (RFC 5545, `Ics.kt`) of every calendar the person can write to +(`CALENDAR_ACCESS_LEVEL` contributor or above); the ones they only subscribe +to, public holidays or birthdays from contacts, are someone else's and come +back by subscribing again. Timed events keep their Olson zone (`TZID`), so a +weekly 9:00 stays 9:00 across summer time; recurrences keep their RRULE, +RDATE and EXDATE, Android's `P3600S` durations become RFC's `PT3600S`, and a +changed instance carries its series' UID and a RECURRENCE-ID. Reminders, +organizer and attendees come along; each event names its calendar in +`X-MESHBAY-CALENDAR`, which importers ignore. Like contacts it is sent when +its SHA-256, taken without the DTSTAMP lines, differs from the last copy. + **Messages.** `/-messages/YYYY/sms-2026-10-10-0900.xml`: the SMS added since the last file the node took (the marker is the highest provider `_id` sent; ids only grow, so a message restored onto the phone later @@ -3470,10 +3482,10 @@ answers null in `src/play`). The bridge offers `messageSync` only where the shell has a message source (`MESSAGES` in its prelude), so the Play build shows no Messages section rather than one that refuses. -**Unlike photos**, both run on any network: a contacts file is small, and a +**Unlike photos**, these run on any network: a contacts or calendar file is small, and a history of text messages is megabytes, not the gigabytes of a camera roll. -`READ_CONTACTS` and `READ_SMS` are asked for when the person turns each on, -never at start. +`READ_CONTACTS`, `READ_CALENDAR` and `READ_SMS` are asked for when the person +turns each on, never at start. ## 10. Filesystem portability diff --git a/docs/USERGUIDE.md b/docs/USERGUIDE.md index e0c29da..1587160 100644 --- a/docs/USERGUIDE.md +++ b/docs/USERGUIDE.md @@ -385,7 +385,7 @@ that matters to you. ### Backing up your phone On the Android application, **Phone → Android Sync** in the side menu backs up -your phone's photos, contacts and text messages to a group. +your phone's photos, contacts, calendar and text messages to a group. Only your **personal profile** is backed up. If your phone has a work profile, nothing in it is sent, and MeshBay installed inside the work profile offers no @@ -434,6 +434,17 @@ backup at all. - It runs on any connection, since a copy is small. **Back up now** sends one at once if your contacts changed since the last copy. +#### Calendar + +- **Turn on** asks for access to your calendars, then sends a copy once a day + when they have changed. +- It holds every calendar you can edit: your own, local ones and those of the + accounts on the phone. Calendars you only subscribe to (public holidays, + birthdays) are left out. +- Each copy is an `.ics` file with the date in its name + (`calendar-2026-10-10-0900.ics`). Any calendar application can import it; + repeating events, their exceptions and reminders come along. + #### Text messages - **Turn on** asks for access to your text messages. The first copy holds them diff --git a/packages/meshbay-android/app/src/main/AndroidManifest.xml b/packages/meshbay-android/app/src/main/AndroidManifest.xml index 48a69ea..f52c06f 100644 --- a/packages/meshbay-android/app/src/main/AndroidManifest.xml +++ b/packages/meshbay-android/app/src/main/AndroidManifest.xml @@ -23,6 +23,8 @@ + +