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:
@@ -0,0 +1,7 @@
|
||||
package com.tt.honeyDue
|
||||
|
||||
class WasmPlatform: Platform {
|
||||
override val name: String = "Web with Kotlin/Wasm"
|
||||
}
|
||||
|
||||
actual fun getPlatform(): Platform = WasmPlatform()
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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() }
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
}
|
||||
}
|
||||
@@ -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 = { }
|
||||
)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
@@ -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!!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.honeydue.storage
|
||||
|
||||
internal actual fun getPlatformTaskCacheManager(): TaskCacheManager? {
|
||||
return TaskCacheManager.getInstance()
|
||||
}
|
||||
@@ -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!!
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.honeydue.storage
|
||||
|
||||
internal actual fun getPlatformTokenManager(): TokenManager? {
|
||||
return TokenManager.getInstance()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user