- Build config: build.gradle (app + root), settings.gradle, AndroidManifest - Application entry: PantreeApplication (Hilt), MainActivity (Compose host) - Data layer: - ApiService (Retrofit interface, all 20 endpoints) - ApiModels (all request/response DTOs) - AuthInterceptor (JWT Bearer header injection) - TokenStore (EncryptedSharedPreferences) - SyncPreferences (DataStore, last-sync timestamp) - PantreeDatabase (Room, 5 entities) - Entities: PantryItemEntity, RecipeEntity, RecipeIngredientEntity, ShoppingListEntity, ShoppingListItemEntity - DAOs: PantryDao, RecipeDao, ShoppingListDao - Repositories: AuthRepository, PantryRepository, RecipeRepository, ShoppingListRepository, SyncRepository - DI: AppModule (Hilt, provides OkHttp/Retrofit/Room/DAOs) - Util: Result<T> sealed class, safeApiCall, toUserMessage (human-readable error mapping) - Sync: SyncManager (DefaultLifecycleObserver, triggers on app open/foreground) - Theme: Color, Type, Theme (Material 3, light + dark) - Navigation: Screen sealed class, PantreeNavGraph (deep links for password reset) - Shared components: LoadingState, ErrorState, EmptyState, OfflineBanner, PantreeTopBar - Auth screens: SplashScreen, SignInScreen, SignUpScreen, ForgotPasswordScreen, ResetPasswordScreen + AuthViewModel - Pantry screen: PantryScreen (list/add/edit/delete dialogs) + PantryViewModel - Recipe screens: RecipesScreen (filter chips, search, availability badges) + RecipeDetailScreen (scale 1x/2x/3x, ingredient pantry status) + RecipeViewModel - Shopping screens: ShoppingListsScreen + ShoppingListDetailScreen (check-off, progress bar, merge feedback, add-from-recipes) + ShoppingListViewModel - Settings screen: sign out + account deletion (15-day window copy) + SettingsViewModel - Tests: ResultTest (unit), RecipeDetailScreenTest (unit), PantryScreenTest (instrumented) - README: architecture, module structure, UI states table, sync strategy, setup Every screen handles loading / error / empty / success states. Offline: cached Room data shown read-only.
129 lines
3.9 KiB
Groovy
129 lines
3.9 KiB
Groovy
plugins {
|
|
id 'com.android.application'
|
|
id 'org.jetbrains.kotlin.android'
|
|
id 'com.google.dagger.hilt.android'
|
|
id 'com.google.devtools.ksp'
|
|
}
|
|
|
|
android {
|
|
namespace 'com.pantree.app'
|
|
compileSdk 34
|
|
|
|
defaultConfig {
|
|
applicationId "com.pantree.app"
|
|
minSdk 26
|
|
targetSdk 34
|
|
versionCode 1
|
|
versionName "1.0.0"
|
|
|
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
vectorDrawables {
|
|
useSupportLibrary true
|
|
}
|
|
|
|
buildConfigField "String", "BASE_URL", '"https://api.pantree.app/v1/"'
|
|
buildConfigField "String", "GOOGLE_WEB_CLIENT_ID", '"YOUR_GOOGLE_WEB_CLIENT_ID"'
|
|
}
|
|
|
|
buildTypes {
|
|
release {
|
|
minifyEnabled true
|
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
}
|
|
debug {
|
|
buildConfigField "String", "BASE_URL", '"http://10.0.2.2:3000/v1/"'
|
|
}
|
|
}
|
|
|
|
compileOptions {
|
|
sourceCompatibility JavaVersion.VERSION_17
|
|
targetCompatibility JavaVersion.VERSION_17
|
|
}
|
|
|
|
kotlinOptions {
|
|
jvmTarget = '17'
|
|
}
|
|
|
|
buildFeatures {
|
|
compose true
|
|
buildConfig true
|
|
}
|
|
|
|
composeOptions {
|
|
kotlinCompilerExtensionVersion '1.5.11'
|
|
}
|
|
|
|
packaging {
|
|
resources {
|
|
excludes += '/META-INF/{AL2.0,LGPL2.1}'
|
|
}
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
// Core
|
|
implementation 'androidx.core:core-ktx:1.13.0'
|
|
implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.7.0'
|
|
implementation 'androidx.activity:activity-compose:1.9.0'
|
|
|
|
// Compose BOM
|
|
implementation platform('androidx.compose:compose-bom:2024.04.01')
|
|
implementation 'androidx.compose.ui:ui'
|
|
implementation 'androidx.compose.ui:ui-graphics'
|
|
implementation 'androidx.compose.ui:ui-tooling-preview'
|
|
implementation 'androidx.compose.material3:material3'
|
|
implementation 'androidx.compose.material:material-icons-extended'
|
|
|
|
// Navigation
|
|
implementation 'androidx.navigation:navigation-compose:2.7.7'
|
|
|
|
// Hilt DI
|
|
implementation 'com.google.dagger:hilt-android:2.51.1'
|
|
ksp 'com.google.dagger:hilt-android-compiler:2.51.1'
|
|
implementation 'androidx.hilt:hilt-navigation-compose:1.2.0'
|
|
|
|
// Room
|
|
implementation 'androidx.room:room-runtime:2.6.1'
|
|
implementation 'androidx.room:room-ktx:2.6.1'
|
|
ksp 'androidx.room:room-compiler:2.6.1'
|
|
|
|
// Retrofit + OkHttp
|
|
implementation 'com.squareup.retrofit2:retrofit:2.11.0'
|
|
implementation 'com.squareup.retrofit2:converter-gson:2.11.0'
|
|
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
|
|
implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
|
|
|
|
// Gson
|
|
implementation 'com.google.code.gson:gson:2.10.1'
|
|
|
|
// ViewModel + StateFlow
|
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0'
|
|
implementation 'androidx.lifecycle:lifecycle-runtime-compose:2.7.0'
|
|
|
|
// EncryptedSharedPreferences
|
|
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
|
|
|
|
// Google Identity (One Tap)
|
|
implementation 'com.google.android.gms:play-services-auth:21.1.1'
|
|
|
|
// Coil (image loading)
|
|
implementation 'io.coil-kt:coil-compose:2.6.0'
|
|
|
|
// DataStore
|
|
implementation 'androidx.datastore:datastore-preferences:1.1.0'
|
|
|
|
// Coroutines
|
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.0'
|
|
|
|
// Testing
|
|
testImplementation 'junit:junit:4.13.2'
|
|
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.0'
|
|
testImplementation 'io.mockk:mockk:1.13.10'
|
|
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
|
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
|
|
androidTestImplementation platform('androidx.compose:compose-bom:2024.04.01')
|
|
androidTestImplementation 'androidx.compose.ui:ui-test-junit4'
|
|
debugImplementation 'androidx.compose.ui:ui-tooling'
|
|
debugImplementation 'androidx.compose.ui:ui-test-manifest'
|
|
}
|