Rebrand from Casera/MyCrib to honeyDue

Total rebrand across KMM project:
- Kotlin package: com.example.casera -> com.tt.honeyDue (dirs + declarations)
- Gradle: rootProject.name, namespace, applicationId
- Android: manifest, strings.xml (all languages), widget resources
- iOS: pbxproj bundle IDs, Info.plist, entitlements, xcconfig
- iOS directories: Casera/ -> HoneyDue/, CaseraTests/ -> HoneyDueTests/, etc.
- Swift source: all class/struct/enum renames
- Deep links: casera:// -> honeydue://, .casera -> .honeydue
- App icons replaced with honeyDue honeycomb icon
- Domains: casera.treytartt.com -> honeyDue.treytartt.com
- Bundle IDs: com.tt.casera -> com.tt.honeyDue
- Database table names preserved

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Trey t
2026-03-07 06:33:57 -06:00
parent 9c574c4343
commit 1e2adf7660
450 changed files with 1730 additions and 1788 deletions

View File

@@ -0,0 +1,7 @@
package com.tt.honeyDue
class WasmPlatform: Platform {
override val name: String = "Web with Kotlin/Wasm"
}
actual fun getPlatform(): Platform = WasmPlatform()

View File

@@ -0,0 +1,31 @@
package com.tt.honeyDue.analytics
/**
* WasmJS/Web implementation of PostHog Analytics.
* Currently a no-op stub - could be implemented with PostHog JS SDK.
*/
actual object PostHogAnalytics {
actual fun initialize() {
// No-op for web
}
actual fun identify(userId: String, properties: Map<String, Any>?) {
// No-op for web
}
actual fun capture(event: String, properties: Map<String, Any>?) {
// No-op for web
}
actual fun screen(screenName: String, properties: Map<String, Any>?) {
// No-op for web
}
actual fun reset() {
// No-op for web
}
actual fun flush() {
// No-op for web
}
}

View File

@@ -0,0 +1,38 @@
package com.tt.honeyDue.data
import kotlinx.browser.localStorage
/**
* WasmJS implementation of PersistenceManager using browser localStorage.
*/
actual class PersistenceManager {
actual fun save(key: String, value: String) {
localStorage.setItem(key, value)
}
actual fun load(key: String): String? {
return localStorage.getItem(key)
}
actual fun remove(key: String) {
localStorage.removeItem(key)
}
actual fun clear() {
// Remove all items with our prefix
val keysToRemove = mutableListOf<String>()
for (i in 0 until localStorage.length) {
val key = localStorage.key(i) ?: continue
if (key.startsWith("dm_")) {
keysToRemove.add(key)
}
}
keysToRemove.forEach { localStorage.removeItem(it) }
}
companion object {
private val instance by lazy { PersistenceManager() }
fun getInstance(): PersistenceManager = instance
}
}

View File

@@ -0,0 +1,43 @@
package com.tt.honeyDue.network
import io.ktor.client.*
import io.ktor.client.engine.js.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.plugins.logging.*
import io.ktor.serialization.kotlinx.json.*
import kotlinx.browser.window
import kotlinx.serialization.json.Json
actual fun getLocalhostAddress(): String = "127.0.0.1"
actual fun getDeviceLanguage(): String {
return window.navigator.language.split("-").firstOrNull() ?: "en"
}
actual fun getDeviceTimezone(): String {
// Use Intl API to get IANA timezone name (e.g., "America/Los_Angeles")
return js("Intl.DateTimeFormat().resolvedOptions().timeZone") as String
}
actual fun createHttpClient(): HttpClient {
return HttpClient(Js) {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
isLenient = true
prettyPrint = true
})
}
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
}
install(DefaultRequest) {
headers.append("Accept-Language", getDeviceLanguage())
headers.append("X-Timezone", getDeviceTimezone())
}
}
}

View File

@@ -0,0 +1,13 @@
package com.tt.honeyDue.platform
import androidx.compose.runtime.Composable
import com.tt.honeyDue.models.Contractor
@Composable
actual fun ContractorImportHandler(
pendingContractorImportUri: Any?,
onClearContractorImport: () -> Unit,
onImportSuccess: (Contractor) -> Unit
) {
// Not implemented for Wasm/Web
}

View File

@@ -0,0 +1,11 @@
package com.tt.honeyDue.platform
import androidx.compose.runtime.Composable
import com.tt.honeyDue.models.Contractor
@Composable
actual fun rememberShareContractor(): (Contractor) -> Unit {
return { _: Contractor ->
// Not implemented for Wasm/Web
}
}

View File

@@ -0,0 +1,18 @@
package com.tt.honeyDue.platform
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
/**
* WASM/Web implementation - no-op since web doesn't have haptic feedback.
*/
class WasmJsHapticFeedbackPerformer : HapticFeedbackPerformer {
override fun perform(type: HapticFeedbackType) {
// Web doesn't support haptic feedback
}
}
@Composable
actual fun rememberHapticFeedback(): HapticFeedbackPerformer {
return remember { WasmJsHapticFeedbackPerformer() }
}

View File

@@ -0,0 +1,19 @@
package com.tt.honeyDue.platform
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.toComposeImageBitmap
import org.jetbrains.skia.Image
@Composable
actual fun rememberImageBitmap(imageData: ImageData): ImageBitmap? {
return remember(imageData) {
try {
val skiaImage = Image.makeFromEncoded(imageData.bytes)
skiaImage.toComposeImageBitmap()
} catch (e: Exception) {
null
}
}
}

View File

@@ -0,0 +1,27 @@
package com.honeydue.platform
import androidx.compose.runtime.Composable
@Composable
actual fun rememberImagePicker(
onImagesPicked: (List<ImageData>) -> Unit
): () -> Unit {
// WASM image picker would require HTML5 file input
// This is a placeholder implementation
return {
// TODO: Implement WASM file input
println("Image picker not yet implemented for WASM")
}
}
@Composable
actual fun rememberCameraPicker(
onImageCaptured: (ImageData) -> Unit
): () -> Unit {
// WASM camera picker would require HTML5 media capture
// This is a placeholder implementation
return {
// TODO: Implement WASM camera capture
println("Camera picker not yet implemented for WASM")
}
}

View File

@@ -0,0 +1,16 @@
package com.tt.honeyDue.platform
import androidx.compose.runtime.Composable
import com.tt.honeyDue.ui.subscription.UpgradeScreen
@Composable
actual fun PlatformUpgradeScreen(
onNavigateBack: () -> Unit,
onSubscriptionChanged: () -> Unit
) {
UpgradeScreen(
onNavigateBack = onNavigateBack,
onPurchase = { _ -> onNavigateBack() },
onRestorePurchases = { }
)
}

View File

@@ -0,0 +1,16 @@
package com.tt.honeyDue.platform
import androidx.compose.runtime.Composable
import com.tt.honeyDue.models.JoinResidenceResponse
/**
* WasmJS implementation is a no-op - file imports are not supported on web.
*/
@Composable
actual fun ResidenceImportHandler(
pendingResidenceImportUri: Any?,
onClearResidenceImport: () -> Unit,
onImportSuccess: (JoinResidenceResponse) -> Unit
) {
// No-op on WasmJS - web doesn't support file imports
}

View File

@@ -0,0 +1,15 @@
package com.tt.honeyDue.platform
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import com.tt.honeyDue.models.Residence
/**
* WasmJS implementation is a no-op - sharing is not supported on web.
*/
@Composable
actual fun rememberShareResidence(): Pair<ResidenceSharingState, (Residence) -> Unit> {
val state = remember { ResidenceSharingState() }
val noOp: (Residence) -> Unit = { /* No-op on WasmJS */ }
return Pair(state, noOp)
}

View File

@@ -0,0 +1,56 @@
package com.tt.honeyDue.storage
import kotlinx.browser.localStorage
/**
* WASM implementation of TaskCacheManager using browser's localStorage.
* Note: Web doesn't have widgets, so dirty flag methods use localStorage for consistency.
*/
actual class TaskCacheManager {
actual fun saveTasks(tasksJson: String) {
localStorage.setItem(KEY_TASKS, tasksJson)
}
actual fun getTasks(): String? {
return localStorage.getItem(KEY_TASKS)
}
actual fun clearTasks() {
localStorage.removeItem(KEY_TASKS)
}
/**
* Check if tasks need refresh. Web doesn't have widgets, always returns false.
*/
actual fun areTasksDirty(): Boolean {
return localStorage.getItem(KEY_DIRTY_FLAG) == "true"
}
/**
* Mark tasks as dirty. Web doesn't have widgets but supports the interface.
*/
actual fun markTasksDirty() {
localStorage.setItem(KEY_DIRTY_FLAG, "true")
}
/**
* Clear the dirty flag.
*/
actual fun clearDirtyFlag() {
localStorage.setItem(KEY_DIRTY_FLAG, "false")
}
companion object {
private const val KEY_TASKS = "cached_tasks"
private const val KEY_DIRTY_FLAG = "tasks_dirty"
private var instance: TaskCacheManager? = null
fun getInstance(): TaskCacheManager {
if (instance == null) {
instance = TaskCacheManager()
}
return instance!!
}
}
}

View File

@@ -0,0 +1,5 @@
package com.honeydue.storage
internal actual fun getPlatformTaskCacheManager(): TaskCacheManager? {
return TaskCacheManager.getInstance()
}

View File

@@ -0,0 +1,33 @@
package com.honeydue.storage
import kotlinx.browser.localStorage
/**
* WASM implementation of TokenManager using browser's localStorage.
*/
actual class TokenManager {
actual fun saveToken(token: String) {
localStorage.setItem(KEY_TOKEN, token)
}
actual fun getToken(): String? {
return localStorage.getItem(KEY_TOKEN)
}
actual fun clearToken() {
localStorage.removeItem(KEY_TOKEN)
}
companion object {
private const val KEY_TOKEN = "auth_token"
private var instance: TokenManager? = null
fun getInstance(): TokenManager {
if (instance == null) {
instance = TokenManager()
}
return instance!!
}
}
}

View File

@@ -0,0 +1,5 @@
package com.honeydue.storage
internal actual fun getPlatformTokenManager(): TokenManager? {
return TokenManager.getInstance()
}

View File

@@ -0,0 +1,16 @@
package com.tt.honeyDue.ui.components.auth
import androidx.compose.runtime.Composable
/**
* WASM stub - Google Sign In not implemented for web WASM target
*/
@Composable
actual fun GoogleSignInButton(
onSignInStarted: () -> Unit,
onSignInSuccess: (idToken: String) -> Unit,
onSignInError: (message: String) -> Unit,
enabled: Boolean
) {
// No-op on WASM
}