- Kotlin 100%
|
All checks were successful
Build APK / Build Android APK (push) Successful in 11m14s
|
||
|---|---|---|
| .forgejo/workflows | ||
| app | ||
| gradle | ||
| .gitignore | ||
| build.gradle.kts | ||
| gradle.properties | ||
| README.md | ||
| settings.gradle.kts | ||
TuxPlanner Android
Native Android client for the TuxPlanner self-hosted calendar & todo app.
Built with Kotlin + Jetpack Compose + Material 3
Features
| Feature | Status |
|---|---|
| Login / First-run setup | ✅ |
| Configurable backend URL | ✅ |
| Dashboard with live clock & greeting | ✅ |
| Today's events on dashboard | ✅ |
| Today's tasks (with toggle) on dashboard | ✅ |
| Work sessions summary on dashboard | ✅ |
| Events list (create, edit, delete) | ✅ |
| Event detail bottom sheet | ✅ |
| Full event form (title, desc, location, datetime, all-day, color, calendar) | ✅ |
| Calendar list management (create, edit, delete, visibility toggle) | ✅ |
| Filter events by calendar list | ✅ |
| Todos list (create, edit, toggle, delete) | ✅ |
| Todo detail bottom sheet | ✅ |
| Full todo form (title, desc, priority, due date, list) | ✅ |
| Filter todos by status (All / Pending / Completed) | ✅ |
| Filter todos by todo list | ✅ |
| Work session management per todo (add, delete) | ✅ |
| Todo list management (create, edit, delete) via API | ✅ |
| Material 3 UI + dark mode | ✅ |
| GitHub Actions release build | ✅ |
Stack
| Layer | Technology |
|---|---|
| Language | Kotlin |
| UI | Jetpack Compose + Material 3 |
| Networking | Retrofit 2 + OkHttp 4 |
| JSON | Gson |
| Auth | Cookie-based (HttpOnly JWT via OkHttp CookieJar) |
| Preferences | Jetpack DataStore |
| Navigation | Navigation Compose |
| Min SDK | 24 (Android 7.0) |
| Target SDK | 35 (Android 15) |
Running Locally
Prerequisites
- Android Studio Hedgehog (2023.1.1) or newer
- JDK 17
- Android SDK with API 35
Steps
-
Clone the repo
git clone https://github.com/jonasvanleeuwen19/tuxplanner-android.git cd tuxplanner-android -
Open in Android Studio Open the root folder (
tuxplanner-android/) as an Android Studio project. -
Set the backend URL (first launch)
- The app defaults to
http://10.0.2.2:8000which routes tolocalhost:8000on the host machine when using the Android Emulator. - If running a real device, use your machine's LAN IP (e.g.,
http://192.168.1.x:8000). - You can change the URL at any time in Settings → Backend URL.
- The app defaults to
-
Start the TuxPlanner backend
# In the TuxPlanner repo docker compose up --build -
Run the app via Android Studio (▶) or:
./gradlew installDebug
First-run setup
If no users exist on the backend yet, the app shows a "Create Account" screen instead of the login form. Enter a username and password (min 8 characters) to create the first admin account.
Project Structure
app/src/main/java/com/tuxplanner/app/
├── TuxPlannerApp.kt # Application class + AppContainer (service locator)
├── MainActivity.kt
├── data/
│ ├── model/
│ │ └── Models.kt # Data classes matching the API
│ ├── network/
│ │ ├── TuxPlannerApiService.kt # Retrofit interface
│ │ └── ApiClient.kt # OkHttp + Retrofit factory (cookie jar, dynamic URL)
│ ├── preferences/
│ │ └── AppPreferences.kt # DataStore wrapper (base URL, login state)
│ └── repository/
│ ├── AuthRepository.kt
│ ├── CalendarListRepository.kt
│ ├── EventRepository.kt
│ ├── TaskSessionRepository.kt
│ ├── TodoListRepository.kt
│ └── TodoRepository.kt
└── ui/
├── navigation/
│ ├── Screen.kt # Route constants
│ └── AppNavHost.kt # Root NavHost
├── screens/
│ ├── calendarlists/ # CalendarListsScreen + CalendarListsViewModel
│ ├── dashboard/ # DashboardScreen + DashboardViewModel
│ ├── events/ # EventsScreen + EventsViewModel + EventDetailSheet
│ ├── home/ # HomeScreen (bottom navigation host)
│ ├── login/ # LoginScreen + LoginViewModel
│ ├── serverconfig/ # ServerConfigScreen + ServerConfigViewModel
│ ├── settings/ # SettingsScreen + SettingsViewModel
│ └── todos/ # TodosScreen + TodosViewModel + TodoDetailSheet
└── theme/ # Material 3 colors, typography, theme
GitHub Actions – Release Build
The workflow file is at .github/workflows/android-release.yml.
What it does
| Trigger | Action |
|---|---|
Push to main |
Builds release APK, uploads as workflow artifact |
Pull request to main |
Same (build check) |
Tag v* (e.g., v1.0.0) |
Builds release APK + creates a GitHub Release with the APK attached |
Creating a release
git tag v1.0.0
git push origin v1.0.0
The workflow will automatically create a GitHub Release named "TuxPlanner Android v1.0.0" with:
- Auto-generated release notes
- The signed APK attached
Signing
By default the release APK is signed with the debug key (installable on any device for testing, but not suitable for Play Store).
To use a real signing key:
-
Generate a keystore:
keytool -genkey -v -keystore my-release-key.jks \ -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000 -
Base64-encode it:
base64 -i my-release-key.jks | tr -d '\n' -
Add these repository secrets (
Settings → Secrets → Actions):Secret Value KEYSTORE_BASE64base64 output from step 2 KEYSTORE_PASSWORDyour keystore password KEY_ALIASyour key alias KEY_PASSWORDyour key password
Backend API Summary
| Endpoint | Method | Description |
|---|---|---|
/api/auth/setup-status |
GET | Check if first-run setup is needed |
/api/auth/setup |
POST | Create first admin account |
/api/auth/login |
POST | Login (form-encoded) → sets httpOnly cookie |
/api/auth/logout |
POST | Clear auth cookie |
/api/auth/me |
GET | Get current user info |
/api/calendar-lists/ |
GET/POST | List or create calendar lists |
/api/calendar-lists/{id} |
PUT/DELETE | Update or delete calendar list |
/api/events/ |
GET/POST | List or create events |
/api/events/{id} |
GET/PUT/DELETE | Read, update, or delete event |
/api/todos/ |
GET/POST | List or create todos |
/api/todos/{id} |
GET/PUT/DELETE | Read, update, or delete todo |
/api/todo-lists/ |
GET/POST | List or create todo lists |
/api/todo-lists/{id} |
PUT/DELETE | Update or delete todo list |
/api/todos/{id}/sessions/ |
GET/POST | List or create work sessions |
/api/todos/{id}/sessions/{sid} |
PUT/DELETE | Update or delete work session |
Authentication uses an httpOnly JWT cookie (access_token). OkHttp's JavaNetCookieJar handles this transparently.
License
MIT