Add Android theme system and fix package naming issues

This commit adds a comprehensive theming system to Android matching iOS, and fixes package declarations throughout the codebase to match directory structure.

Theme System Additions:
- Added 11 themes matching iOS: Default, Teal, Ocean, Forest, Sunset, Monochrome, Lavender, Crimson, Midnight, Desert, Mint
- Created ThemeColors.kt with exact iOS color values for light/dark modes
- Added ThemeManager.kt for dynamic theme switching
- Created Spacing.kt with standardized spacing constants (xs/sm/md/lg/xl)
- Added ThemePickerDialog.kt for theme selection UI
- Integrated theme switching in ProfileScreen.kt
- Updated App.kt to observe ThemeManager for reactive theming

Component Library:
- Added StandardCard.kt and CompactCard.kt for consistent card styling
- Added FormTextField.kt with error/helper text support
- Added FormSection.kt for grouping related form fields
- Added StandardEmptyState.kt for empty state UI

Package Migration:
- Fixed all package declarations to match directory structure (com.example.mycrib.*)
- Updated package declarations in commonMain, androidMain, and iosMain
- Fixed all import statements across entire codebase
- Ensures compilation on both Android and iOS platforms

iOS Theme Rename:
- Renamed "Default" theme to "Teal" in iOS
- Renamed "Bright" theme to "Default" in iOS to make vibrant colors the default

Build Status:
-  Android builds successfully
-  iOS builds successfully

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Trey t
2025-11-22 10:44:54 -06:00
parent e40aed31a7
commit f1f71224aa
146 changed files with 2155 additions and 616 deletions

View File

@@ -22,10 +22,10 @@ import coil3.memory.MemoryCache
import coil3.request.crossfade
import coil3.util.DebugLogger
import okio.FileSystem
import com.mycrib.storage.TokenManager
import com.mycrib.storage.TokenStorage
import com.mycrib.storage.TaskCacheManager
import com.mycrib.storage.TaskCacheStorage
import com.example.mycrib.storage.TokenManager
import com.example.mycrib.storage.TokenStorage
import com.example.mycrib.storage.TaskCacheManager
import com.example.mycrib.storage.TaskCacheStorage
import com.example.mycrib.fcm.FCMManager
import kotlinx.coroutines.launch
@@ -78,21 +78,21 @@ class MainActivity : ComponentActivity(), SingletonImageLoader.Factory {
try {
val authToken = TokenStorage.getToken()
if (authToken != null) {
val notificationApi = com.mycrib.shared.network.NotificationApi()
val request = com.mycrib.shared.models.DeviceRegistrationRequest(
val notificationApi = com.example.mycrib.network.NotificationApi()
val request = com.example.mycrib.models.DeviceRegistrationRequest(
registrationId = fcmToken,
platform = "android"
)
when (val result = notificationApi.registerDevice(authToken, request)) {
is com.mycrib.shared.network.ApiResult.Success -> {
is com.example.mycrib.network.ApiResult.Success -> {
Log.d("MainActivity", "Device registered successfully: ${result.data}")
}
is com.mycrib.shared.network.ApiResult.Error -> {
is com.example.mycrib.network.ApiResult.Error -> {
Log.e("MainActivity", "Failed to register device: ${result.message}")
}
is com.mycrib.shared.network.ApiResult.Loading,
is com.mycrib.shared.network.ApiResult.Idle -> {
is com.example.mycrib.network.ApiResult.Loading,
is com.example.mycrib.network.ApiResult.Idle -> {
// These states shouldn't occur for direct API calls
}
}

View File

@@ -30,23 +30,23 @@ class MyFirebaseMessagingService : FirebaseMessagingService() {
// Note: In a real app, you might want to use WorkManager for reliable delivery
CoroutineScope(Dispatchers.IO).launch {
try {
val authToken = com.mycrib.storage.TokenStorage.getToken()
val authToken = com.example.mycrib.storage.TokenStorage.getToken()
if (authToken != null) {
val notificationApi = com.mycrib.shared.network.NotificationApi()
val request = com.mycrib.shared.models.DeviceRegistrationRequest(
val notificationApi = com.example.mycrib.network.NotificationApi()
val request = com.example.mycrib.models.DeviceRegistrationRequest(
registrationId = token,
platform = "android"
)
when (val result = notificationApi.registerDevice(authToken, request)) {
is com.mycrib.shared.network.ApiResult.Success -> {
is com.example.mycrib.network.ApiResult.Success -> {
Log.d(TAG, "Device registered successfully with new token")
}
is com.mycrib.shared.network.ApiResult.Error -> {
is com.example.mycrib.network.ApiResult.Error -> {
Log.e(TAG, "Failed to register device with new token: ${result.message}")
}
is com.mycrib.shared.network.ApiResult.Loading,
is com.mycrib.shared.network.ApiResult.Idle -> {
is com.example.mycrib.network.ApiResult.Loading,
is com.example.mycrib.network.ApiResult.Idle -> {
// These states shouldn't occur for direct API calls
}
}

View File

@@ -1,4 +1,4 @@
package com.mycrib.shared.network
package com.example.mycrib.network
import io.ktor.client.*
import io.ktor.client.engine.okhttp.*

View File

@@ -1,4 +1,4 @@
package com.mycrib.android.platform
package com.example.mycrib.platform
import android.content.Context
import coil3.ImageLoader

View File

@@ -1,4 +1,4 @@
package com.mycrib.platform
package com.example.mycrib.platform
import android.content.Context
import android.net.Uri

View File

@@ -1,4 +1,4 @@
package com.mycrib.storage
package com.example.mycrib.storage
import android.content.Context
import android.content.SharedPreferences

View File

@@ -1,4 +1,4 @@
package com.mycrib.storage
package com.example.mycrib.storage
internal actual fun getPlatformTaskCacheManager(): TaskCacheManager? {
// Android requires context, so must use initialize() method

View File

@@ -1,4 +1,4 @@
package com.mycrib.storage
package com.example.mycrib.storage
import android.content.Context
import android.content.SharedPreferences

View File

@@ -1,4 +1,4 @@
package com.mycrib.storage
package com.example.mycrib.storage
internal actual fun getPlatformTokenManager(): TokenManager? {
// Android requires context, so must use initialize() method

View File

@@ -1,8 +1,8 @@
package com.mycrib.util
package com.example.mycrib.util
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import com.mycrib.platform.ImageData
import com.example.mycrib.platform.ImageData
import java.io.ByteArrayOutputStream
/**

View File

@@ -1,4 +1,4 @@
package com.mycrib.android.ui.components
package com.example.mycrib.ui.components
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
@@ -10,8 +10,8 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.mycrib.shared.models.TaskSummary
import com.mycrib.shared.models.TaskColumnCategory
import com.example.mycrib.models.TaskSummary
import com.example.mycrib.models.TaskColumnCategory
/**
* Displays a task summary with dynamic categories from the backend.