Commit Graph
10 Commits
Author SHA1 Message Date
Linus Rath f2aedd2948 chore: merge contacts and files into the settings branch 2026-11-03 09:22:04 +01:00
Linus Rath a7c3c5b9a6 feat: prune kept mail at once when the scope tightens and fetch it back when it widens
The store took a scope only when it opened and acted on it only at a full
sync, so a lower cap left old mail on the device until something else
forced a resync. Now the engine applies a changed scope first, without the
network, and once a day as the window moves on.

Also tell the page whether an account's file was there when it opened, so
it can notice a store the browser deleted.

- `calendar-sync.test.ts` now syncs with `days: null`: its old events test
  checks the calendar's own two years, and the calendar follows the scope now
- `page-side.test.ts`: the fake worker answers an open with what it found,
  as the real one does
2026-11-03 08:56:24 +01:00
Linus Rath 20b2e7054e chore: merge search, notification actions and calendar into the mail branch 2026-11-03 07:02:39 +01:00
Linus Rath 9fbe33004b fix: send contact edits that remove entries and stop reading own edits as conflicts
An edit that removed an entry was dropped at flush, because a server
value with more keys counted as already applied. Other fixes in the same
path:

- the local copy after a flush is the server's read-back, never what was
  sent, since Stalwart 1.0 stores a data: URI as a blob
- a delete or a newer edit after a lost response no longer reads as a
  change on the server, and an edit made during a refused send stays
- a create only becomes a card with its uid if that card holds what was
  sent, otherwise it is a refused conflict
- a refused or failed flush no longer stops contacts syncing
- request limits come from the session
- answers wait for the first full pass
- paging goes by anchor, so a deleted card doesn't make the next one
  get skipped and swept

contacts.test.ts: "continues a stopped full sync" now checks the anchor
instead of position 2000, because the cursor no longer pages by position.
2026-11-03 06:20:39 +01:00
Linus Rath f6db7ea53a fix: keep pinned and unread-first lists off a full sort, and stop syncing when the disk is full 2026-11-03 06:02:10 +01:00
Linus Rath 79ae1d51f8 feat: keep contacts on the device, search them offline and queue edits 2026-11-03 05:46:59 +01:00
Linus Rath 877a7a93b2 feat: keep calendars on the device and queue calendar changes while offline
Adds a `calendar` area to the local store. It syncs calendars, participant
identities, events and tasks as masters, through CalendarEvent/changes,
and answers Calendar/get, CalendarEvent/query, /get and /set from SQLite
when the server can't be reached.

- A range query gets series in both client modes, with their overrides,
  and the calendar store expands them as it does for an older server.
- The synthetic-id probe gets the verdict from the last sync, so a client
  started offline behaves the same once the server is back.
- Create, edit, delete and RSVP queue in `calendar_pending`, one merged
  row per event, and go out through `calendar.flush` or the next sync.
  A create finds itself by uid after a lost response.
- A write the server refuses, or one on a value the server changed, goes
  to `calendar.conflicts`.
- `lib/store/calendar/reminders.ts` lists upcoming alerts with keys that
  don't depend on synthetic ids.
2026-11-03 05:42:01 +01:00
Linus Rath 51ccac02ca feat: answer every mail read from the local store, including header forms, identities and quotas, and keep attachments 2026-11-03 05:30:09 +01:00
Linus Rath bad156eaed refactor: let each part of the local store expose its own calls to the page 2026-11-03 04:59:39 +01:00
Linus Rath 6da9a6a6f5 feat: add an encrypted local mail store that syncs in a worker 2026-11-03 04:57:20 +01:00