From a0793dd37030f7213ecb07a018b11e6a8adf9238 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Sat, 10 Oct 2026 12:56:26 +0200 Subject: feat(android): back the phone's contacts up to a group of one's own A Contacts backup section on the Android Sync page sends a dated .vcf into /-contacts once a day when the address book changed, only to a group the account is alone in, checked again at every run. Co-Authored-By: Claude Opus 5.5 --- docs/MESHBAY_DESIGN.md | 31 +++ docs/USERGUIDE.md | 19 +- .../app/src/main/AndroidManifest.xml | 2 + .../app/src/main/assets/bridge/meshbay-bridge.js | 13 + .../main/kotlin/org/meshbay/client/MainActivity.kt | 15 +- .../kotlin/org/meshbay/client/bridge/Channels.kt | 5 +- .../org/meshbay/client/phonesync/ContactSource.kt | 51 ++++ .../org/meshbay/client/phonesync/DocChannels.kt | 179 ++++++++++++++ .../kotlin/org/meshbay/client/phonesync/DocPlan.kt | 91 +++++++ .../org/meshbay/client/photos/PhotoChannels.kt | 36 +-- .../test/kotlin/org/meshbay/client/DocSyncTest.kt | 55 +++++ .../src/meshbay_hub/static/android-sync-page.js | 11 +- packages/meshbay-hub/src/meshbay_hub/static/app.js | 31 ++- .../src/meshbay_hub/static/locales/de.js | 21 ++ .../src/meshbay_hub/static/locales/en.js | 21 ++ .../src/meshbay_hub/static/locales/es.js | 21 ++ .../src/meshbay_hub/static/locales/fr.js | 21 ++ .../src/meshbay_hub/static/locales/it.js | 21 ++ .../src/meshbay_hub/static/locales/ja.js | 21 ++ .../src/meshbay_hub/static/locales/nl.js | 21 ++ .../src/meshbay_hub/static/locales/pl.js | 21 ++ .../src/meshbay_hub/static/locales/pt-BR.js | 21 ++ .../src/meshbay_hub/static/locales/zh-CN.js | 21 ++ .../src/meshbay_hub/static/phone-sync-settings.js | 210 ++++++++++++++++ .../src/meshbay_hub/static/phone-sync.js | 249 +++++++++++++++++++ .../src/meshbay_hub/static/photo-sync.js | 13 +- .../meshbay-hub/src/meshbay_hub/static/platform.js | 27 +++ packages/meshbay-hub/tests/test_android_shell.py | 10 +- .../meshbay-hub/tests/test_first_load_is_lean.py | 3 +- packages/meshbay-hub/tests/test_hook_ordering.py | 3 +- packages/meshbay-hub/tests/test_phone_sync.py | 266 +++++++++++++++++++++ 31 files changed, 1492 insertions(+), 38 deletions(-) create mode 100644 packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/phonesync/ContactSource.kt create mode 100644 packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/phonesync/DocChannels.kt create mode 100644 packages/meshbay-android/app/src/main/kotlin/org/meshbay/client/phonesync/DocPlan.kt create mode 100644 packages/meshbay-android/app/src/test/kotlin/org/meshbay/client/DocSyncTest.kt create mode 100644 packages/meshbay-hub/src/meshbay_hub/static/phone-sync-settings.js create mode 100644 packages/meshbay-hub/src/meshbay_hub/static/phone-sync.js create mode 100644 packages/meshbay-hub/tests/test_phone_sync.py diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md index 0714e7e..44592d2 100644 --- a/docs/MESHBAY_DESIGN.md +++ b/docs/MESHBAY_DESIGN.md @@ -3411,6 +3411,37 @@ 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) + +The Android application sends a copy of the phone's **contacts** 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 +bytes over by token (`/phonesync/`, `phonesync/` in the Android +package, `phone-sync.js` on the page). Messages follow the same design. + +**Only a group the person is alone in.** What a group's folder holds every +member can read, and an address book is not the group's. The set-up offers +only groups whose member list is this account and nobody invited, and every +run asks the hub again before reading anything: somebody who joins later stops +the backup (`not_private`, a lasting refusal said once) rather than reading +every copy from then on. Any writable folder of that group is offered, not +only the ones the Photos tab shows. + +**Where.** `/-contacts/`, made if missing. Each copy is a new +file named for when it was taken (`contacts-2026-10-10-0900.vcf`), never a +replacement: restoring is importing the newest one, and an older one is there +if a phone sync went wrong. + +**What.** The whole address book as the platform exports it, one vCard per +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. The marker moves only on the +node's acknowledgement, so a copy cut short is written again whole. + +**Unlike photos**, it runs on any network: a vCard file is small, and there is +no first run of gigabytes to keep off mobile data. `READ_CONTACTS` is asked for +when the person sets it up, never at start. + ## 10. Filesystem portability **exFAT and NTFS on Windows are the common case, not an edge case.** Most users are diff --git a/docs/USERGUIDE.md b/docs/USERGUIDE.md index ebcf152..9daf71b 100644 --- a/docs/USERGUIDE.md +++ b/docs/USERGUIDE.md @@ -408,7 +408,24 @@ of your groups, once a day. - **Where a photo was taken is removed** from the copy that is sent. - If the backup cannot go on — the node's disk is full, the folder no longer accepts files, you left the group — it stops, says why once in a - notification and in Settings, and tries again the next day. + notification and on the Android Sync page, and tries again the next day. + +### Backing up your phone's contacts + +**Contacts backup**, on the same **Android Sync** page, sends a copy of your +phone's contacts to a group, once a day when they have changed. + +- **Only a group you are the only member of** can receive it: your address + book is not something to share. If you have none, create a group just for + yourself first. If somebody joins that group later, the backup stops and + tells you. +- You choose any folder of that group you may add to; the copies go into a + folder named after you inside it, such as `Backups/alice-contacts`. +- Each copy is a `.vcf` file with the date in its name + (`contacts-2026-10-10-0900.vcf`). Any phone can import it. Older copies are + kept, nothing is ever replaced. +- 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. ### Search diff --git a/packages/meshbay-android/app/src/main/AndroidManifest.xml b/packages/meshbay-android/app/src/main/AndroidManifest.xml index 37c18c7..48a69ea 100644 --- a/packages/meshbay-android/app/src/main/AndroidManifest.xml +++ b/packages/meshbay-android/app/src/main/AndroidManifest.xml @@ -21,6 +21,8 @@ + +