Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 39 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

BusyMax is a Linux desktop calendar and task manager built with Flutter.

It brings calendar events and tasks into a native-feeling Linux desktop interface, with support for `Google Calendar`, `Google Tasks`, `Microsoft Calendar`, and `Microsoft To Do`.
It brings calendar events and tasks into a native-feeling Linux desktop
interface. BusyMax connects directly to Google, Microsoft, Apple iCloud
Calendar, and Nextcloud. Apple Reminders is not supported.

[![busymax](https://snapcraft.io/busymax/badge.svg)](https://snapcraft.io/busymax)

Expand All @@ -20,10 +22,18 @@ It brings calendar events and tasks into a native-feeling Linux desktop interfac

- Linux desktop app built with Flutter.
- Calendar views for day, week, month, year, and agenda planning.
- Task creation with lists, due dates, reminders, and repeat options.
- Event editing with calendar selection, time controls, repeat rules, and reminders.
- Task creation with lists, start/due dates, reminders, repeat options,
subtasks, status, progress, priority, categories, location, and URL.
- Nextcloud task-list creation/rename/delete, recursive task duplicate/delete,
raw iCalendar export, clear-completed, and cross-list subtree moves.
- Event editing with calendar selection, time controls, repeat rules, and
reminders.
- Tray shortcut for opening the main Agenda view.
- Integrations with Google Calendar, Google Tasks, Microsoft Calendar, and Microsoft To Do.
- Direct integrations with Google Calendar, Google Tasks, Microsoft Calendar,
Microsoft To Do, Apple iCloud Calendar, Nextcloud Calendar, and Nextcloud
Tasks.
- Offline-first local cache, conditional DAV writes, recurrence exceptions,
alarms, and explicit conflict handling for CalDAV accounts.

## Screenshots

Expand Down Expand Up @@ -59,6 +69,12 @@ It brings calendar events and tasks into a native-feeling Linux desktop interfac

<br>

<p>
<img src="docs/screenshots/account_provider_selection.png"
alt="BusyMax account provider selection"
width="700">
</p>

<p>
<img src="docs/screenshots/main_window_year.png" alt="BusyMax year view" width="700">
</p>
Expand All @@ -71,12 +87,20 @@ It brings calendar events and tasks into a native-feeling Linux desktop interfac

## Prerequisites

- Flutter: https://docs.flutter.dev/install
- [Flutter SDK](https://docs.flutter.dev/install)
- GTK 3 and libhandy development packages (`libgtk-3-dev` and
`libhandy-1-dev` on Ubuntu/Debian)
- `GOOGLE_OAUTH_CLIENT_ID` and `GOOGLE_OAUTH_CLIENT_SECRET`, see [Google Setup](docs/google_setup.md)
- `GOOGLE_OAUTH_CLIENT_ID` and `GOOGLE_OAUTH_CLIENT_SECRET`; see
[Google setup](docs/google_setup.md)
- `MICROSOFT_OAUTH_CLIENT_ID`, see [Microsoft Setup](docs/microsoft_setup.md)

Apple and Nextcloud do not require compile-time client credentials:

- [Apple iCloud Calendar setup](docs/apple_icloud_setup.md) requires two-factor
authentication and an Apple app-specific password.
- [Nextcloud setup](docs/nextcloud_setup.md) requires an HTTPS server and
completes authorization in the default browser.

## Run locally

Register the development launcher once so GNOME can associate BusyMax's native
Expand Down Expand Up @@ -127,7 +151,15 @@ flutter run -d linux \

The local Snap helper accepts the same value with
`--dart-define BUSYSTACK_FEEDBACK_ENDPOINT=http://127.0.0.1:8090/api/feedback`.
No API, CAPTCHA, or other private server credential is used by the desktop application.
No API, CAPTCHA, or other private server credential is used by the desktop
application.

## Provider support

The [provider capability matrix](docs/provider_support_matrix.md) lists the
features and limitations of each integration. Maintainers can use the
[live-provider test guide](docs/live_provider_testing.md) for opt-in Nextcloud
and iCloud integration tests.

## Build and publish the Snap

Expand Down
67 changes: 67 additions & 0 deletions docs/apple_icloud_setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Apple iCloud Calendar setup

BusyMax connects directly to Apple iCloud Calendar over CalDAV. This profile
synchronizes calendar collections and `VEVENT` resources only. It does not
connect to Apple Reminders.

## Before connecting

You need:

- an Apple Account with two-factor authentication enabled;
- the email address used by that Apple Account; and
- a dedicated app-specific password for BusyMax.

Do not enter your primary Apple Account password in BusyMax. Apple documents
app-specific passwords as the fallback for third-party apps that cannot use
Apple's account-authorization contract. BusyMax's Linux client does not use an
undocumented Apple authorization flow.

## Create the password and connect

1. Sign in at [account.apple.com](https://account.apple.com/).
2. Open **Sign-In and Security**, then **App-Specific Passwords**.
3. Generate a password with a recognizable label such as `BusyMax Linux`.
4. In BusyMax, open **Add account** and choose **Apple iCloud Calendar**.
5. Enter the Apple Account email and the complete generated password. BusyMax
trims accidental whitespace but otherwise treats the password as opaque.
6. Select **Connect**. BusyMax validates the credential and discovers the
account's calendars before saving it.

BusyMax starts discovery at `https://caldav.icloud.com/`, follows only
validated Apple iCloud CalDAV destinations, and requires normal platform TLS
certificate validation. There is no invalid-certificate, HTTP, or custom
iCloud-server option.

## Calendars and editing

BusyMax shows discovered event calendars and derives whether each one is
writable from DAV privileges. Shared or subscribed read-only calendars remain
visible but their edit controls are disabled. Event content is cached locally
for offline viewing; offline edits to writable calendars are queued and later
sent with conditional ETag checks.

Calendar collection creation, deletion, rename, color, and ordering are not
supported for iCloud. Invitations and scheduling changes are also not
supported.

## Reconnect, revoke, or remove

- If Apple rejects the credential, existing cached data and pending work stay
local. Generate a replacement app-specific password, then use **Reconnect**.
- To revoke access remotely, remove the BusyMax password at
[account.apple.com](https://account.apple.com/) under **App-Specific
Passwords**. BusyMax cannot revoke an Apple password through CalDAV.
- Removing the account from BusyMax removes its local credential, cached DAV
objects, projections, cursors, conflicts, and pending operations. It does
not revoke the remote Apple password; revoke it manually as well.
- Apple states that changing or resetting the primary Apple Account password
automatically revokes all app-specific passwords.

Apple's current instructions are [Sign in to apps with your Apple Account
using app-specific passwords](https://support.apple.com/en-gb/102654) and
[Access your iCloud Mail, Calendar and Contacts in third-party
apps](https://support.apple.com/en-ie/121539).

This setup is specific to Apple iCloud and cannot be used for arbitrary CalDAV
servers.
31 changes: 31 additions & 0 deletions docs/beta_snap_release.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ See [Google Setup](google_setup.md) and
and can be extracted, so use only native Desktop/public-client credentials.
Never use server credentials or commit the JSON or generated `.snap` files.

Apple iCloud Calendar and Nextcloud do not use compile-time client secrets.
Read [Apple iCloud setup](apple_icloud_setup.md) and [Nextcloud
setup](nextcloud_setup.md). Apple requires a per-user app-specific password;
Nextcloud creates a per-client app password through Login Flow v2 in the
default browser. Never put either credential in the defines file.

## Build

From the repository root:
Expand Down Expand Up @@ -117,11 +123,32 @@ Before upload, verify:
- Desktop search shows one BusyMax launcher; the tray Agenda action opens the
Agenda view in the main window.
- Google and Microsoft sign-in complete successfully.
- Apple iCloud setup accepts only an Apple Account email and app-specific
password, discovers calendars over verified TLS, and reconnects after a
controlled app-password revocation.
- Nextcloud Login Flow v2 opens the system default browser, completes after the
user returns to BusyMax, preserves an installation path, and uses the
server-returned canonical credentials.
- Tasks and events can be created, edited, completed, and deleted; a task
created in Agenda appears immediately without manual refresh.
- Accounts, settings, and data survive restart.
- The XDG Secret portal-backed encrypted credential file works while strictly
confined: connect, quit, restart the desktop session if practical, reopen,
sync, reconnect, then remove the account and confirm its local credential is
gone.
- Revoked Apple/Nextcloud credentials pause synchronization while cached data
and pending work remain visible.
- Read-only/shared DAV collections remain visible but do not expose mutation
controls; a server ACL change is enforced after refresh.
- Network, DNS, platform TLS rejection, recurrence/alarm projection, and
notifications work under confinement.
- Notifications and tray actions, including opening Agenda in the main window
and Quit, work.
- Upgrade a copy of data from the last released package and verify schema-5 to
schema-8 migration, existing provider credentials/cursors/pending
operations, DAV projections, and account removal/local cleanup.
- `snap/snapcraft.yaml`, metainfo, and screenshots describe exactly the tested
providers. Apple wording says iCloud Calendar, not Apple Reminders.

## Upload To Beta

Expand Down Expand Up @@ -178,6 +205,10 @@ snap info busymax

Repeat the local smoke checks against the Store-delivered revision.

Record the downloaded revision, channel, checksum, test machine, and smoke-test
result in the release record. Do not include account identities, credentials,
DAV resource paths, or calendar and task content.

Official references: [build environments](https://documentation.ubuntu.com/snapcraft/stable/reference/build-environment-options/),
[upload](https://documentation.ubuntu.com/snapcraft/stable/reference/commands/upload/),
and [revision management](https://documentation.ubuntu.com/snapcraft/stable/how-to/publishing/manage-revisions-and-releases/).
101 changes: 33 additions & 68 deletions docs/google_setup.md
Original file line number Diff line number Diff line change
@@ -1,78 +1,43 @@
# Google Setup
# Google OAuth setup

This setup is required to get `GOOGLE_OAUTH_CLIENT_ID` and `GOOGLE_OAUTH_CLIENT_SECRET`
BusyMax requires a Google desktop OAuth client. Its client ID and client secret
are supplied as `GOOGLE_OAUTH_CLIENT_ID` and
`GOOGLE_OAUTH_CLIENT_SECRET` at build time.

## 1 Enable APIs
## Create a Google Cloud project

### 1.1 Create New Project
1. Open the [Google Cloud Console](https://console.cloud.google.com/).
2. Create or select a project.
3. Enable the Google Tasks API and Google Calendar API.

Go to `Google Cloud Console`: https://console.cloud.google.com
## Configure the consent screen

Click `Open project picker` (top-left corner) and create a new project. Then, select it.
1. Open [Google Auth Platform](https://console.cloud.google.com/auth/).
2. Complete the initial setup with the application name, support email,
audience, and contact email.
3. Under **Audience**, add development accounts as test users while the app is
in testing mode.
4. Under **Data access**, add these scopes:

### 1.1 Enable Task and Calendar API
```text
openid
https://www.googleapis.com/auth/userinfo.email
https://www.googleapis.com/auth/userinfo.profile
https://www.googleapis.com/auth/tasks
https://www.googleapis.com/auth/calendar
```

Search and enable the following:
The identity scopes provide the stable account identity and display label. The
Tasks and Calendar scopes allow BusyMax to synchronize and edit the
corresponding data.

- Google Tasks API
- Google Calendar API
## Create the desktop client

## 2 Google Auth Platform
1. Open **Clients** and select **Create client**.
2. Choose **Desktop app** as the application type.
3. Give the client a recognizable name.
4. Store the client ID and client secret securely and provide them to the build
as `GOOGLE_OAUTH_CLIENT_ID` and `GOOGLE_OAUTH_CLIENT_SECRET`.

### 2.1 Initial Setup

Go to `Google Auth Platform`: https://console.cloud.google.com/auth/

Click `Get Started`.

Enter:

- App name: <APP NAME>
- User support email: <YOUR EMAIL>
- Audience: `External`
- Contact Information: <YOUR EMAIL>

Click `Save`.

### 2.2 Branding

Click `Branding` to provide additional information if needed.

### 2.3 Audience

Click `Audience` to add test users. While publishing status is set to "Testing", only test users are
able to access the app.

### 2.4 Clients

Click `Clients` -> `Create Client` and enter:

- Application type: Desktop app
- Name: <APP NAME>

!!! **Important**: copy and save `Client ID` and `Client secret`. **You will no longer be able to
view or download the client secret once you close this dialog. Make sure you have copied or
downloaded the information below and securely stored it.** Use it as `GOOGLE_OAUTH_CLIENT_ID` and
`GOOGLE_OAUTH_CLIENT_SECRET`.

#### 2.5 Data Access

Click `Add or remove scopes`

Check the following:

- openid
- https://www.googleapis.com/auth/userinfo.email
- https://www.googleapis.com/auth/userinfo.profile
- https://www.googleapis.com/auth/tasks
- https://www.googleapis.com/auth/calendar

Click `Update` and `Save`.

Rationale:

```text
openid/email/profile -> stable account identity and display label
tasks -> Google Tasks create/edit/delete/sync
calendar -> CalendarList, Calendars, Events, Colors, Freebusy support
```
Use only credentials created for this desktop application. Do not commit them
to the repository.
Loading
Loading