unical

One resilient API over device calendars and CalDAV for events and tasks with progress. unical prefers native VTODO / invisible X- properties and degrades gracefully so task metadata (percent-complete, tags) is never lost, even on servers that cannot store tasks.

The core is pure Dart with no plugin dependencies. Backends are pluggable:

  • unical_caldav — CalDAV, via the caldav package (native VTODO with PERCENT-COMPLETE).
  • unical_flutter — device calendars (Android Calendar Provider / iOS EventKit), via device_calendar_plus.
  • InMemoryBackend — ships in this package for tests and ephemeral use.

The fail-safe ladder

A task's extra metadata (percent, tags, identity) is carried by the best channel the backend can honor:

Strategy When Where metadata lives
nativeVtodo server stores VTODO native PERCENT-COMPLETE
xProps events-only but keeps X- props invisible X-STABILITAS-*
descriptionBlock opt-in only a delimited block in the description
driftOnly Google CalDAV / device calendars your own store; the event is a clean projection

The description block is off by default because it is user-visible; the ladder is MetadataStrategy.select(capabilities, allowDescriptionFallback:).

Note: Google Calendar over CalDAV is events-only and strips X- properties, and device calendars have no tasks at all — under both, unical runs the driftOnly strategy: your local store remains the source of truth for percent/tags and the calendar shows a clean event.

Usage

import 'package:unical/unical.dart';

final engine = SyncEngine(
  backend: myBackend,               // from unical_caldav / unical_flutter
  mappings: InMemoryMappingStore(), // or a Drift-backed MappingStore
);
final client = UnicalClient(engine);
await client.ensureReady();

await client.pushTask(
  UnicalTask(id: 'goal-42', title: 'Write the chapter', percent: 60),
);

final tasks = await client.pullTasks(); // Outcome<List<UnicalTask>>

UnicalClient never throws: every call returns an Outcome and is time-bounded.

Libraries

unical
unical — one resilient API over device calendars and CalDAV for events and tasks with progress.