No description
- Kotlin 100%
- Add the four -dontwarn rules R8 requires for Tink's compile-only errorprone annotations (pulled in by EncryptedSharedPreferences); release minification failed without them. - Debug-sign the release build type so it can be installed for on-device testing. Swap in a dedicated upload keystore before Play Store release. - Ignore *.log and /.vscode. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|---|---|---|
| app | ||
| gradle | ||
| .gitignore | ||
| build.gradle.kts | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| README.md | ||
| settings.gradle.kts | ||
| TODO.md | ||
Mobiflux — Kotlin / Jetpack Compose
A native Android rewrite of the Flutter Mobiflux client for Miniflux. Feature-for-feature port: unread/feed/category/starred/history browsing, a native HTML article reader, feed & category management, configurable swipe actions, and settings.
Tech stack
- Kotlin 2.0 + Jetpack Compose (Material 3), dark-only theme
- MVVM:
ViewModel+StateFlow, collected withcollectAsStateWithLifecycle - Navigation Compose (type-safe routes)
- Retrofit + OkHttp + kotlinx.serialization — Miniflux v1 REST API, HTTP Basic Auth
- EncryptedSharedPreferences for credentials, DataStore for settings
- Coil for feed-icon images
- Jsoup + a custom Compose renderer for article HTML (no WebView)
- Manual DI via a small
ServiceLocator(no Hilt)
Project layout
data/
model/ kotlinx.serialization models + request bodies
remote/ MinifluxApi (Retrofit) + ApiClient (Basic Auth interceptor, dynamic base URL)
repository/ MinifluxRepository — single entry point for all network ops
prefs/ CredentialStore (encrypted) + SettingsStore (DataStore)
ui/
theme/ AppColors, typography, Material3 theme (ported 1:1 from Flutter)
navigation/ Routes (type-safe) + NavCache (in-memory hand-off) + NavHost
components/ top bar, drawer, entry cards, swipe wrappers, list body, states
html/ HtmlContent — native Jsoup→Compose article renderer
login/ home/ feed/ category/ starred/ history/ entry/ settings/ managefeeds/
util/ DateUtils, BrowserLauncher (Chrome Custom Tabs / share)
Build & run
The repo has no gradle on PATH; use the wrapper with the JDK bundled in Android Studio:
export JAVA_HOME="/Applications/Android Studio.app/Contents/jbr/Contents/Home"
./gradlew assembleDebug # → app/build/outputs/apk/debug/app-debug.apk
# install to a connected device/emulator yourself:
# $ANDROID_HOME/platform-tools/adb install -r app/build/outputs/apk/debug/app-debug.apk
local.properties (git-ignored) points Gradle at the SDK: sdk.dir=/Users/sarat/Library/Android/sdk.
Or just open this project in Android Studio and Run.
- compileSdk / targetSdk 35, minSdk 26 (Android 8.0 — needed for
java.time) - Status: compiles clean and assembles a debug APK. Not yet run on a device here (no
emulator/
adbwas available in the build environment) — verify the runtime on hardware.
Notes / intentional differences
- Fonts. The Flutter app used Google Fonts Plus Jakarta Sans (UI) and Newsreader
(article body). To keep the project building without bundled font binaries, typography
currently uses the platform sans-serif and serif families with all sizes/weights/
letter-spacing preserved. To use the real faces, drop the TTFs into
res/font(or wire the Google Downloadable Fonts provider) and pointUiFont/ArticleFontinui/theme/Type.ktat them — nothing else changes. - Article reader. There is no Compose-native equivalent of Flutter's
flutter_widget_from_html_core, soui/html/HtmlContent.ktis a custom Jsoup-based renderer (paragraphs, headings, links, blockquotes, code blocks, inline code, images, lists, tables, hr, figures) styled to match the oldcustomStylesBuilder. It is not a full HTML engine; exotic markup degrades gracefully. - Object hand-off. Detail screens receive IDs via type-safe routes and resolve the full
object from an in-memory
NavCachepopulated by the list that opened them (mirrors how the Flutter app pushed whole objects). On process death a detail screen shows a small fallback.