Add multi-account, stats dashboard, search/filtering, animations, theme system, and expanded architecture documentation.
4.8 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
Swoosh is an Android microblogging client for Ghost CMS. It provides offline-capable post creation, image uploads, link previews, and scheduled publishing via Ghost's Admin API.
Build & Test Commands
./gradlew assembleDebug # Build debug APK
./gradlew assembleRelease # Build release APK (ProGuard enabled)
./gradlew test # Run all unit tests
./gradlew app:testDebugUnitTest # Run unit tests for debug variant
./gradlew test --tests "*.MobiledocBuilderTest" # Run a single test class
./gradlew test --tests "*.MobiledocBuilderTest.testBasicTextPost" # Run a single test method
Robolectric is used for tests that need Android framework classes. Unit tests include Android resources (unitTests.isIncludeAndroidResources = true).
Architecture
MVVM with Repository pattern, single-module Gradle project.
Package: com.swoosh.microblog
data/api/— Retrofit service (GhostApiService), JWT auth (GhostJwtGenerator,GhostAuthInterceptor), andApiClientsingleton with dynamic base URLdata/db/— Room database withLocalPostentity andLocalPostDaodata/model/— Three model layers:GhostPost(API),LocalPost(Room entity),FeedPost(UI display). Additional models:PostStats,OverallStats,GhostAccount. Enums:PostStatus,QueueStatus,PostFilter,SortOrderdata/repository/—PostRepositorycoordinates local DB and remote API;OpenGraphFetcherparses link previews via Jsoupdata/(root utilities) —AccountManager(multi-account, up to 5),CredentialsManager,FeedPreferences,HashtagParser,MobiledocBuilder,ShareUtils,UrlNormalizerui/animation/—SwooshMotionshared animation specs (bouncy, snappy, gentle, quick)ui/components/— Reusable composables:AnimatedDialog,ConfirmationDialog,PulsingPlaceholderui/feed/— Post feed with search, filtering (All/Published/Draft/Scheduled), sortingui/composer/— Post creation/editing with image uploads, link previews, hashtags, schedulingui/detail/— Full post view with animated delete dialogui/preview/— HTML post previewui/stats/— Statistics dashboard with animated counters (total posts, word counts, reading time)ui/settings/— Settings, account management, theme toggle, disconnectui/setup/— Initial configuration wizard and add-account flowui/theme/— Material 3 theming withThemeMode(Light/Dark/System),ThemeViewModel,ThemePreferencesui/navigation/— Compose Navigation graph with bottom nav (Feed, Stats, Settings)worker/—PostUploadWorker(WorkManager) handles offline queue with exponential backoff
Key data flow: Posts are saved to Room first → queued for upload → PostUploadWorker syncs to Ghost API when network is available.
Technical Details
- Auth: Ghost Admin API keys are split into
id:secret, secret is hex-decoded for HS256 JWT signing (5-min expiry) - Content format: Posts use Ghost's mobiledoc JSON format, built by
MobiledocBuilder(supports text paragraphs and bookmark cards) - Credentials: Stored in
EncryptedSharedPreferences(AES256-GCM) viaCredentialsManager - API client: Base URL is configured at runtime during setup;
ApiClientrebuilds Retrofit instance when URL changes - Multi-account:
AccountManagersupports up to 5 Ghost accounts with UUID-based IDs, per-account credentials, and migration from legacy single-account format - Avatars: Fetched from Ghost post authors (
posts[0].authors[0].profile_image), not/users/me/(which returns 404 for integrations) - Permissions: INTERNET, ACCESS_NETWORK_STATE, CAMERA
- ProGuard: Release build suppresses missing
com.google.errorprone.annotations(pulled in by Google Tink via EncryptedSharedPreferences) - Min SDK 26, Target/Compile SDK 34, Kotlin 1.9.22, Java 17
Versioning
Version is defined in app/build.gradle.kts (versionCode and versionName).
- Format: Semantic versioning
MAJOR.MINOR.PATCH(e.g.,0.2.0) versionCode: Integer, increment by 1 on every release (used by Google Play)versionName: Human-readable, shown in Settings screen
When to bump:
- PATCH (0.2.0 → 0.2.1): Bug fixes, small tweaks, no new features
- MINOR (0.2.0 → 0.3.0): New features, UI changes, significant improvements
- MAJOR (0.x → 1.0): First stable public release
Current: versionName = "0.2.0", versionCode = 2
Process: When making a release commit, bump both versionCode (+1) and versionName in app/build.gradle.kts. Always bump version when creating a release build or PR.