Skip to content
 
 

Repository files navigation

YATA — Yet Another To-Do App

A Material 3 Expressive task manager for Android, built with Jetpack Compose, Room, and Hilt. yata-status-v5 yata-status-v4 yata-status-v3 yata-status-v2 yata-status-v1

Contents

Overview

YATA is a single-user, offline-first task manager. Tasks can optionally be organized under Projects, folder-style Lists, Tags, and People (for delegation) — each of those entity types can be hidden entirely via a feature flag if you don't need it. The whole app is backed by one Room database and one large MainViewModel; screens are Compose destinations that read from it via hiltViewModel().

Features

Task management

  • Natural-language quick add — type a task and it parses out due date/time, priority, and list
  • Recurrence rules, subtasks, Markdown-rendered notes, per-task comments
  • Recurring-task streaks (2+ consecutive on-time completions) shown on the task detail screen
  • Priority levels, flags, per-task reminders
  • Duplicate-task detection when adding a new task
  • Voice quick add, share-to-task (share text/links from other apps straight into a new task)
  • Manual drag-and-drop reordering
  • Bulk actions (complete / delete / tag / move / assign / duplicate) from a multiselect toolbar
  • Delete-with-undo everywhere — soft-deletes to Trash, 30-day retention before permanent purge

Organization

  • Projects, Lists, Tags, People — each independently toggleable via feature flags
  • Starring for quick access from the nav drawer
  • A shared accent-color system (16 accent slots) used consistently across custom color/icon pickers

Views & navigation

  • Today — due-today + overdue tasks; progress ring reflects tasks pending as of the start of today (a task completed on a previous day no longer inflates the ring — only tasks still open, or completed today, count)
  • Tappable hero stats (Overdue / High priority / Due today) on Today and every entity-detail hero (Project/List/Tag/Person) filter the visible task list in place — tap again to clear, with a dismissible "Showing: X" banner
  • Next 10 Days — a flat, date-grouped agenda across a rolling 10-day window (reachable from the drawer and a shortcut button on Today)
  • Upcoming — 7-day strip or full month calendar, with a per-day agenda
  • Projects / People / Tags tabs, each with its own detail screen
  • Scoped Search across all tasks
  • Analytics — completion trends, streaks, on-time rate, workload share, aging buckets, breakdowns by project/person/tag
  • Trash — restore or permanently delete
  • First-run welcome tour

Home-screen widgets (Glance)

  • Full agenda widget, Single List, Quick Add (with a lightweight config dialog instead of launching the full app), Progress/Stats ring, Upcoming, Team Overdue
  • Per-widget corner radius, opacity, Material You dynamic color, accent override, and custom label
  • One shared refresh signal keeps every placed widget in sync after any task write
  • A Quick Settings tile opens the quick-add dialog straight from the notification shade

Security

  • Optional App Lock — PIN + biometric, with a configurable auto-lock timeout

Notifications & reminders

  • Per-task reminders scheduled via AlarmManager, rescheduled automatically on device reboot
  • Inline notification actions (e.g. mark done) without opening the app
  • Scheduled theme window (auto light/dark on a schedule)

Team / People

  • Assignment and delegation, per-person workload trend (overdue count over the last 7 days), Team Overdue widget

Backup & export

  • Full JSON backup/restore, CSV export/import
  • Self-hosted sync and backup over SFTP/FTPS/FTP, periodic + debounced background sync via WorkManager
  • Client-only multi-device sync over a self-hosted SFTP/FTPS/FTP folder: three-way snapshot merge, deletion propagation, remote writer lease, foreground/periodic/debounced pulls, and rotated rollback backups; no custom server daemon required. Devices in one sync set use the same protocol, remote folder, and encryption passphrase.
  • .ics calendar export, Markdown export for clipboard/share
  • Branded PDF/image export for any Project, Tag, or Person — accent-colored letterhead, stat chips + progress bar, tasks grouped by project/list with tag chips and assignee names, via an options sheet (include/exclude completed with an optional "older than N days" cutoff, strike-off toggle, show tags/assignees, Compact/Relaxed layout). PDFs paginate cleanly (never mid-row) with real page numbers and document metadata (Title/Author/Subject)

Customization

  • Theme mode (light/dark/system) + dynamic color, scheduled theme window
  • App font, text scale, UI scale, FAB position, task-row density (compact/comfortable/spacious)
  • Haptics toggle, reduce-motion toggle, start-of-week (Sunday/Monday)
  • Independent visibility toggles per tab (Today/Upcoming/Projects/People/Tags)
  • Independent "hide completed" state persisted per screen (Today/Project/List/Person)

Tasker integration

  • A "Create Task" Tasker plugin action that writes directly to the repository, so it works outside the app's own running process

Tech stack

Layer Choice
Language Kotlin 2.0.21
UI Jetpack Compose, Material 3 Expressive (Compose BOM 2024.02.01)
DI Hilt 2.52
Persistence Room 2.6.1 (hand-written migrations) + DataStore Preferences
Navigation Navigation-Compose 2.7.7
Home-screen widgets Glance 1.1.1 (glance-appwidget, glance-material3)
Background work WorkManager + Hilt-Work (self-hosted and local backups)
Self-hosted sync Client-side SFTP/FTPS/FTP snapshot merge; no custom server daemon required
Markdown Markwon
PDF metadata pdfbox-android (Info-dictionary only — pages are rendered natively via android.graphics.pdf.PdfDocument)
Tasker plugin taskerpluginlibrary
Build AGP 8.7.2, KSP, JDK 17

Architecture

Two Gradle modules:

  • :app — the phone app, com.mj.yata, minSdk 26, compileSdk/targetSdk 35
  • :baselineprofile — generates the ART baseline profile packaged with the app

Layering is one-directional:

domain/model            plain Kotlin data classes, no Android/Room dependency
   ↓
data/local/db           Room entities + DAOs
   ↓
data/mapper             Entity ⇄ domain model conversion
   ↓
data/repository         YataRepositoryImpl (implements domain/repository/YataRepository, exposes Flows)
   ↓
ui/screen/main/MainViewModel   single ViewModel for the entire app (StateFlows + imperative methods)
   ↓
ui/screen/*             Compose screens, obtained via hiltViewModel()

There is one MainViewModel for the whole app, not one per screen — every screen reads from and calls methods on the same instance. Room schema changes are hand-written Migration objects (no auto-migration); a missing forward migration throws rather than silently wiping data.

Navigation is single-Activity via AppNavigation.kt / Screen.kt over a NavHost. Screen.Main is a 5-tab shell (Today, Projects, People, Tags, Upcoming) with its own drawer, FAB, and a shared SnackbarHostState for cross-tab bulk actions; detail screens (task/project/list/tag/person, search, settings, trash, analytics, next-10-days) are separate top-level destinations.

Project structure

app/src/main/java/com/mj/yata/
├── domain/model/          Task, Project, YataList, Person, Tag, ... (plain data classes)
├── data/
│   ├── local/db/          Room entities, DAOs, AppDatabase + migrations
│   ├── local/datastore/   UserPreferences (DataStore-backed settings)
│   ├── mapper/            Entity ⇄ domain model conversion
│   └── repository/        YataRepositoryImpl
├── ui/
│   ├── screen/            main/ (tab shell + MainViewModel), task/project/person/tag/list detail,
│   │                        search, settings, analytics, trash, welcome, nextdays
│   ├── navigation/        Screen routes + AppNavigation NavHost
│   ├── widgets/           Reusable Compose widgets (TaskRow, ProgressRing, pickers, ...)
│   ├── sheets/            Bottom sheets (new/edit task, bulk actions, ...)
│   └── theme/             M3 Expressive theme + accent system
├── widget/                Home-screen Glance widgets
├── notification/          Reminder scheduling + delivery
├── tasker/createtask/     Tasker plugin integration
└── util/                  Exporters, recurrence, NLP quick-add parser, analytics, ...
    └── export/            Branded PDF/image entity export (compose-to-bitmap render, pagination, PDF metadata)

Getting started

Prerequisites

  • Android Studio (recent stable) or a JDK 17 + Android SDK command-line setup
  • compileSdk/targetSdk 35; minSdk 26

Build & run

git clone https://github.com/rjwarrier/yata.git
cd yata

# Compile Kotlin only — fast correctness check, no packaging
./gradlew :app:compileDebugKotlin -q

# Full debug build
./gradlew :app:assembleDebug -q

# Install to a connected device/emulator
./gradlew :app:installDebug -q

On native Windows shells, use gradlew.bat in place of ./gradlew.

Testing

# Unit tests (JVM, no device)
./gradlew :app:testDebugUnitTest

# A single test class or method
./gradlew :app:testDebugUnitTest --tests "com.mj.yata.RecurrenceEvaluatorTest"
./gradlew :app:testDebugUnitTest --tests "com.mj.yata.NaturalLanguageParserTest"

# Instrumented tests — Room migrations — require a connected device/emulator
./gradlew :app:connectedDebugAndroidTest --tests "com.mj.yata.data.local.db.AppDatabaseMigrationTest"

There is no automated Compose UI test suite; UI-facing changes are verified manually on-device.

Design reference

design/ and design_handoff_yata/ contain the original HTML/JSX design tokens and handoff notes the M3 Expressive theme was built from. They're static references for design intent, not code imported into the build.

Status

Personal, actively-evolving project — schema and UI can change between commits. Current versionName (app/build.gradle.kts) is 0.5.

About

Yet Another To-Do App — a Material 3 Expressive task manager for Android. Projects, lists, tags, people, natural-language quick add, recurring tasks, start dates, home-screen widgets, and encrypted local + Github backup. Built with Jetpack Compose, Room, and Hilt.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages