Skip to content

About

Offline-first personal to-do app: Flutter widget for Windows (frameless, tray, always-on-top) and Android, with Drift/SQLite local storage, transactional outbox sync via Firestore, and Google sign-in on both platforms.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

To Do Widget

To Do Widget is a personal, offline-first task list for Android and Windows. Android runs as a normal mobile application. Windows runs as a compact, frameless widget that can remain above other windows, hide to the system tray, remember its size and position, and start when the user signs in.

The same Google account owns one private task list on both platforms. Drift and SQLite remain the local source of truth, while Firebase Authentication and Cloud Firestore provide identity and cross-device synchronization.

Features

  • Create, edit, complete, restore, reorder, and delete tasks.
  • Add private notes and subtask checklists inside the task editor. Notes and subtasks are intentionally hidden from the main task cards.
  • Assign an optional deadline. Deadline tasks appear first and are ordered by the earliest deadline.
  • Keep tasks without deadlines in a manually reorderable ANYTIME section.
  • Keep completed tasks visible with a strike-through for 48 hours, then move them to searchable History.
  • Work offline using a transactional local mutation outbox.
  • Sync automatically when connectivity returns.
  • Authenticate with Google on Android and through a browser-assisted flow on Windows.
  • Pin, unpin, resize, move, hide, restore, and launch the Windows widget at sign-in.
  • Temporarily enlarge a small Windows widget while date and time dialogs are open, then restore its previous bounds.

Platforms and services

Area Implementation
UI Flutter and Material 3
State management Riverpod
Local database Drift over SQLite
Cloud database Cloud Firestore
Authentication Firebase Authentication with Google
Android background work WorkManager
Windows shell integration window_manager, tray_manager, and launch_at_startup
Windows browser authentication Firebase Hosting plus a localhost callback

Firebase client configuration is generated locally and is not tracked in this repository. Use your own Firebase project and identifiers before distributing a fork.

Project structure

lib/
  core/
    platform/                 Windows window, tray, and startup behavior
    theme/                    Palette and typography
  features/
    auth/                     Android and Windows Google sign-in
    tasks/
      application/            Riverpod providers
      data/                   Drift repository, outbox, and Firestore sync
      domain/                 Task, subtask, feed, and repository contracts
      presentation/           Task list, history, editor, and task tiles
  firebase_options.dart       Local FlutterFire configuration (ignored by Git)
  main.dart                   Firebase and platform initialization
firebase_hosting/
  desktop-auth.html           Windows browser sign-in bridge
test/
  features/tasks/             Sorting, lifecycle, repository, and subtask tests

Quick start

1. Install prerequisites

Install Flutter (3.41.9 or newer), Git, and the toolchain for the platform you will run:

  • Windows: Visual Studio 2022 with Desktop development with C++, CMake, and a Windows SDK.
  • Android: Android Studio or the Android SDK, platform tools, and JDK 17.

Confirm that Flutter recognizes the required tooling:

flutter doctor -v

2. Get the project ready

Clone the repository, open a PowerShell window in its root, then install packages and generate Drift's database code:

git clone <your-repository-url>
Set-Location to_do_widget
flutter pub get
dart run build_runner build

3. Connect Firebase

This app needs Firebase Authentication, Cloud Firestore, and Firebase Hosting for Windows Google sign-in. Create or select your own Firebase project, then generate its local configuration:

npm install -g firebase-tools
dart pub global activate flutterfire_cli
Copy-Item firebase.json.example firebase.json
flutterfire configure --project=<firebase-project-id> --platforms=android,windows --android-package-name=com.pohbo.todo_widget
firebase deploy --only firestore:rules,firestore:indexes,hosting

In Firebase Console, create Firestore and enable the Google sign-in provider. Android also requires the SHA-1 and SHA-256 fingerprints for each APK-signing key. Keep the Firebase Hosting deployment current whenever firebase_hosting/desktop-auth.html changes.

About Firebase client configuration

android/app/google-services.json and lib/firebase_options.dart are intentionally ignored by Git. They are required to build the app, so generate them locally with the command above. They are not private credentials: the compiled Android and Windows apps embed equivalent client configuration for Firebase to use. Protect data with Firebase Authentication, Firestore Security Rules, App Check where appropriate, and restricted API keys; never commit service-account files, OAuth client secrets, signing keys, or passwords.

4. Run it

flutter run -d windows

Or run on an Android device/emulator:

flutter devices
flutter run -d <android-device-id>

Before submitting changes, run:

dart format --output=none --set-exit-if-changed lib test
flutter analyze
flutter test

For the complete Firebase provisioning, signing, deployment, and troubleshooting guide, see SETUP.md.

Release builds

flutter build windows --release
flutter build apk --release

Outputs:

  • Windows: build/windows/x64/runner/Release/to_do_widget.exe
  • Android: build/app/outputs/flutter-apk/app-release.apk

An MSIX is not required to run or test the Windows release. Create one only when an installer is needed:

dart run msix:create

The Android release configuration currently uses the debug signing key for local testing. Configure a private release keystore before distribution.

Data and synchronization model

The UI watches Drift, never Firestore directly. Every local mutation updates the local task and appends an outbox entry in the same SQLite transaction. The sync service commits those mutations to Firestore using revisioned, field-level merge transactions. This allows an offline reorder to avoid overwriting unrelated task text.

Task deletions are tombstones rather than immediate local removal, preventing an offline device from recreating a deleted task. Dates are stored in UTC and rendered in the device's local timezone. Subtasks are stored as one checklist field, so concurrent edits to the same checklist use last-committed-write semantics.

The local schema is versioned. Any change to a Drift table must increment schemaVersion, add a migration, and regenerate app_database.g.dart.

Authentication note

Windows must not call Firebase's native signInWithProvider(GoogleAuthProvider()); that operation is unsupported on non-mobile Firebase C++ targets. The application instead opens the hosted bridge, completes Google authentication in the default browser, validates a random state value, and returns the short-lived credential through an ephemeral 127.0.0.1 HTTP callback.

The bridge is initially opened on web.app and moves authentication onto the matching firebaseapp.com domain. Keep this same-domain behavior: changing it can cause an endless Google account-selection loop in browsers that isolate third-party storage.

Documentation map

  • README.md: product overview, architecture summary, and common commands for people working with the repository.
  • SETUP.md: detailed environment, Firebase, authentication, signing, build, deployment, and troubleshooting guide.
  • CLAUDE.md: concise project memory and instructions specifically for Claude-based coding sessions.
  • AGENTS.md: implementation invariants, validation requirements, and operating rules for any coding agent.

Current verification baseline

The expected pre-handoff checks are:

dart format --output=none --set-exit-if-changed lib test
flutter analyze
flutter test
flutter build windows --release
flutter build apk --release

If the Windows executable is running, close it before rebuilding; otherwise the linker can fail with LNK1104 because the output file is locked.

About

Offline-first personal to-do app: Flutter widget for Windows (frameless, tray, always-on-top) and Android, with Drift/SQLite local storage, transactional outbox sync via Firestore, and Google sign-in on both platforms.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages