A native Android app for tracking manga and light novel reading progress
Features • Architecture • Google Drive Backup • Build • Testing
What-Manga is a personal production app that I actively develop and use. The Android application in this repository is the primary platform. The original web application remains maintained as a separate project and deployed independently.
What-Manga is a personal manga and light novel tracking application built as a native Android app. It allows users to maintain a comprehensive collection of reading progress with offline-first storage and optional cloud backup via Google Drive.
This project originated as a Next.js web application. The Android version was built to bring the same functionality to mobile with a truly native experience:
- Offline-first local storage using Room database
- Native Material 3 UI with Jetpack Compose
- Google Drive backup for data portability
- Smooth animations and haptic feedback
Tracking hundreds of manga and light novel entries across multiple platforms is cumbersome. What-Manga provides a unified, personal tracker with:
- Custom indexing — Maintain your personal ordering
- Progress tracking — Track manga chapters and novel volumes separately
- CSV import/export — Portable data format for backup and migration
- Cloud sync — Optional Google Drive backup for cross-device access
The pre-built APK is available in the Releases section.
The samples/ folder contains an example CSV (demo_data.csv) showing the expected data format for importing entries into the app.
If your data is in a different format, you can use the original web application to import and convert it:
The original full-stack Next.js web application. It features a Smart Import System that can parse a custom
.txtnotation format (e.g.,1- Naruto (*72 vol.). {10}) and import it into the database. You can fork this project, adapt the.txtparser to accept your specific notation, import your data, then export it as a CSV compatible with this Android APK.
- Real-time search across all entries
- Filter by status (Reading, Completed, Dropped/Hiatus, etc.)
- Sort by index, score, or title
- Swipe-to-delete with undo support
- Create new manga/novel entries
- Track manga and novel progress separately
- Score entries on a 0-10 scale
- Add personal review notes
- CSV import with anti-duplication logic
- CSV export for backup
- Automatic backup detection (distinguishes backup files from user CSVs)
- Google Drive integration using OAuth 2.0
- Automatic backup on data changes (debounced)
- Manual backup and restore options
- Local backup history
- Material 3 design with custom color palette
- Dark and light mode support
- Glassmorphism effects
- Smooth spring animations
- Haptic feedback on interactions
What-Manga follows a clean architecture pattern with clear separation of concerns.
flowchart TB
subgraph UI["UI Layer (Compose)"]
Screens[Screens]
Components[Components]
Theme[Theme System]
end
subgraph ViewModel["ViewModel Layer"]
WVM[WorkListViewModel]
StateFlow[StateFlow + combine]
end
subgraph Repository["Repository Layer"]
WR[WorkRepository]
DCN[DataChangeNotifier]
end
subgraph Data["Data Layer"]
Room[(Room Database)]
DAO[WorkDao]
end
subgraph Backup["Backup Layer"]
BM[BackupManager]
GDB[GoogleDriveBackup]
CSV[CsvUtils]
end
UI --> ViewModel
ViewModel --> Repository
Repository --> Data
Repository --> DCN
DCN --> Backup
BM --> GDB
BM --> CSV
sequenceDiagram
participant UI as UI
participant VM as ViewModel
participant Repo as Repository
participant DB as Room DB
participant Notifier as DataChangeNotifier
participant Backup as BackupManager
participant Drive as Google Drive
UI->>VM: User action (create/edit/delete)
VM->>Repo: Data mutation
Repo->>DB: Write to Room
Repo->>Notifier: Emit DataChangeEvent
Notifier->>Backup: onDataChanged()
alt Source in allowlist
Backup->>Backup: Debounce (3s)
Backup->>Drive: Upload CSV backup
else Source not in allowlist
Note over Backup: No backup triggered
end
DB-->>Repo: Flow<List<Work>>
Repo-->>VM: StateFlow<List<Work>>
VM-->>UI: Recompose with new data
| Layer | Technology |
|---|---|
| UI | Jetpack Compose, Material 3 |
| State | StateFlow, ViewModel |
| Database | Room (SQLite) |
| Async | Kotlin Coroutines, Flow |
| Backup | Google Drive REST API v3 |
| Auth | Google Sign-In SDK |
android/app/src/main/java/com/whatmanga/app/
├── MainActivity.kt # Entry point, theme management
├── WhatMangaApp.kt # Application class, dependency init
├── backup/
│ ├── BackupManager.kt # Orchestrates backup operations
│ ├── GoogleDriveBackup.kt # Drive API integration
│ ├── CsvUtils.kt # CSV parsing/generation
│ └── DataChangeNotifier.kt # Event bus for data mutations
├── data/
│ ├── Work.kt # Room entity
│ ├── WorkDao.kt # Data access object
│ ├── WorkRepository.kt # Repository with mutation tracking
│ └── import/ # Import row models
├── ui/
│ ├── components/ # Reusable UI components
│ ├── screens/ # Full-screen composables
│ └── theme/ # Colors, typography, effects
├── util/ # Utility functions
└── viewmodel/
└── WorkListViewModel.kt # Main screen ViewModel
Google Drive backup is a core architectural feature that ensures data durability and cross-device access.
- User-owned storage — Data lives in the user's own Drive
- No backend required — App is fully offline-capable
- Familiar UX — Users already trust Google with their data
drive.filescope — App can only access files it creates
The backup file is a CSV export of all entries containing:
| Field | Description |
|---|---|
| userIndex | User's custom ordering |
| title | Entry title |
| status | Reading status |
| score | User rating (0-10) |
| mangaProgress | Manga chapter progress |
| novelProgress | Novel volume/chapter progress |
| reviewNote | Personal notes |
| timestamps | Created/updated times |
Backups are triggered by user-initiated data changes, controlled by a MutationSource allowlist:
flowchart LR
subgraph Triggers["✅ Triggers Backup"]
A[CREATE_MANUAL]
B[EDIT_SAVE]
C[DELETE_SINGLE]
D[CREATE_IMPORT_USER_CSV]
end
subgraph NoTrigger["❌ No Backup"]
E[DELETE_CLEAR_ALL]
F[RESTORE_BACKUP]
G[IMPORT_BACKUP_CSV]
end
Triggers --> Debounce[3-second debounce]
Debounce --> Upload[Upload to Drive]
This design prevents:
- Backup loops (restore → backup → restore)
- Accidental backup of empty state after "Clear All"
- Duplicate backups during bulk imports
sequenceDiagram
participant User
participant Settings as Settings Screen
participant BM as BackupManager
participant Drive as Google Drive
participant Repo as Repository
User->>Settings: Tap "Restore from Drive"
Settings->>BM: restoreFromDrive()
BM->>Drive: List backup files
Drive-->>BM: Latest backup info
BM->>Drive: Download CSV
BM->>BM: Parse CSV to Works
BM->>Repo: restoreFromBackup(works)
Note over Repo: Uses RESTORE_BACKUP source<br/>(no new backup triggered)
Repo-->>Settings: Success count
Settings-->>User: "Restored X entries"
Important
Google Sign-In requires SHA-1 fingerprint registration in Google Cloud Console.
| Build Type | SHA-1 Source | Notes |
|---|---|---|
| Debug | ~/.android/debug.keystore |
Auto-generated by Android Studio |
| Release | Your signing keystore | Must register separately |
To get your debug SHA-1:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass androidOAuth Setup Checklist:
- Create OAuth consent screen in Google Cloud Console
- Add
https://www.googleapis.com/auth/drive.filescope - Create Android OAuth client with:
- Package name:
com.whatmanga.app - SHA-1 fingerprint (debug AND release)
- Package name:
- Android Studio Hedgehog (2023.1.1) or newer
- JDK 17
- Android SDK 34
cd android
./gradlew assembleDebugAPK location: app/build/outputs/apk/debug/app-debug.apk
cd android
./gradlew assembleReleaseCaution
Release builds require a signing configuration. Do not commit keystores or passwords.
-
Create a keystore (if you don't have one):
keytool -genkey -v -keystore whatmanga-release.jks -keyalias whatmanga -keyalg RSA -keysize 2048 -validity 10000
-
Create
keystore.properties(gitignored):storeFile=../whatmanga-release.jks storePassword=your_store_password keyAlias=whatmanga keyPassword=your_key_password
-
Reference in
app/build.gradle.kts:signingConfigs { create("release") { // Load from keystore.properties } }
The app includes unit tests for critical business logic:
cd android
./gradlew test| Test File | Coverage |
|---|---|
BackupTriggerRulesTest.kt |
Validates MutationSource allowlist logic |
CsvBackupDetectionTest.kt |
Verifies backup file detection |
CsvImportAntiDuplicationTest.kt |
Tests import deduplication |
TitleNormalizerTest.kt |
Tests title matching normalization |
For pre-release verification:
-
CRUD Operations
- Create new entry → appears in list
- Edit entry → changes persist after restart
- Delete entry → removed with undo option
-
Import/Export
- Export CSV → valid format
- Import CSV → no duplicates, progress-forward merge
-
Backup/Restore
- Sign in to Google
- Make changes → backup triggers (check Drive)
- Restore from Drive → data restored correctly
- LazyColumn with
keyparameter for efficient recomposition - StateFlow.combine for derived state (avoids redundant computation)
- Debounced backup (3-second window) to prevent API spam
- Stable references for Compose optimizations
WhatsApp.Video.2025-12-19.at.15.29.11.mp4 |
202512191547.mp4 |
GPLv2 © DeguShi




