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,70 @@
package com.tt.honeyDue.storage
import platform.Foundation.NSUserDefaults
import kotlin.concurrent.Volatile
/**
* iOS implementation of TaskCacheManager using NSUserDefaults.
* Note: iOS widget dirty flag is handled by native Swift WidgetDataManager
* using App Groups shared storage, but we provide these methods for KMM compatibility.
*/
actual class TaskCacheManager {
private val userDefaults = NSUserDefaults.standardUserDefaults
actual fun saveTasks(tasksJson: String) {
userDefaults.setObject(tasksJson, KEY_TASKS)
userDefaults.synchronize()
}
actual fun getTasks(): String? {
return userDefaults.stringForKey(KEY_TASKS)
}
actual fun clearTasks() {
userDefaults.removeObjectForKey(KEY_TASKS)
userDefaults.synchronize()
}
/**
* Check if tasks need refresh due to widget interactions.
* Note: iOS primarily uses native Swift WidgetDataManager for this.
*/
actual fun areTasksDirty(): Boolean {
return userDefaults.boolForKey(KEY_DIRTY_FLAG)
}
/**
* Mark tasks as dirty (needs refresh).
*/
actual fun markTasksDirty() {
userDefaults.setBool(true, KEY_DIRTY_FLAG)
userDefaults.synchronize()
}
/**
* Clear the dirty flag after tasks have been refreshed.
*/
actual fun clearDirtyFlag() {
userDefaults.setBool(false, KEY_DIRTY_FLAG)
userDefaults.synchronize()
}
companion object {
private const val KEY_TASKS = "cached_tasks"
private const val KEY_DIRTY_FLAG = "tasks_dirty"
@Volatile
private var instance: TaskCacheManager? = null
fun getInstance(): TaskCacheManager {
return instance ?: synchronized(this) {
instance ?: TaskCacheManager().also { instance = it }
}
}
}
}
// Helper function for synchronization on iOS
private fun <T> synchronized(lock: Any, block: () -> T): T {
return block()
}

View File

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

View File

@@ -0,0 +1,32 @@
package com.tt.honeyDue.storage
import platform.Foundation.NSUserDefaults
/**
* iOS implementation of theme storage using NSUserDefaults.
*/
actual class ThemeStorageManager {
private val defaults = NSUserDefaults.standardUserDefaults
actual fun saveThemeId(themeId: String) {
defaults.setObject(themeId, forKey = KEY_THEME_ID)
defaults.synchronize()
}
actual fun getThemeId(): String? {
return defaults.stringForKey(KEY_THEME_ID)
}
actual fun clearThemeId() {
defaults.removeObjectForKey(KEY_THEME_ID)
defaults.synchronize()
}
companion object {
private const val KEY_THEME_ID = "theme_id"
private val instance by lazy { ThemeStorageManager() }
fun getInstance(): ThemeStorageManager = instance
}
}

View File

@@ -0,0 +1,96 @@
package com.tt.honeyDue.storage
import kotlin.concurrent.Volatile
/**
* Protocol for iOS Keychain operations. Implemented in Swift (KeychainHelper)
* and injected before DataManager initialization.
*
* Kotlin/Native cannot directly use the Security framework (SecItem* APIs)
* because CFStringRef keys like kSecClass don't bridge to NSCopying.
*/
interface KeychainDelegate {
fun save(key: String, value: String): Boolean
fun get(key: String): String?
fun delete(key: String): Boolean
}
/**
* iOS implementation of TokenManager.
*
* Uses iOS Keychain via [KeychainDelegate] for secure token storage.
* If delegate is missing, operations fail closed (no insecure fallback).
*
* On first read, migrates any existing NSUserDefaults token to Keychain.
*/
actual class TokenManager {
private val prefs = platform.Foundation.NSUserDefaults.standardUserDefaults
actual fun saveToken(token: String) {
val delegate = keychainDelegate
if (delegate != null) {
delegate.save(TOKEN_KEY, token)
// Clean up old NSUserDefaults entry if it exists
prefs.removeObjectForKey(TOKEN_KEY)
prefs.synchronize()
} else {
// Fail closed: never store auth tokens in insecure storage.
println("TokenManager: Keychain delegate not set, refusing to save token insecurely")
}
}
actual fun getToken(): String? {
val delegate = keychainDelegate
// Try Keychain first
if (delegate != null) {
val keychainToken = delegate.get(TOKEN_KEY)
if (keychainToken != null) return keychainToken
// Check NSUserDefaults for migration
val oldToken = prefs.stringForKey(TOKEN_KEY)
if (oldToken != null) {
// Migrate to Keychain
delegate.save(TOKEN_KEY, oldToken)
prefs.removeObjectForKey(TOKEN_KEY)
prefs.synchronize()
return oldToken
}
return null
}
// Fail closed: no insecure fallback reads.
println("TokenManager: Keychain delegate not set, refusing insecure token read")
return null
}
actual fun clearToken() {
keychainDelegate?.delete(TOKEN_KEY)
prefs.removeObjectForKey(TOKEN_KEY)
prefs.synchronize()
}
companion object {
private const val TOKEN_KEY = "auth_token"
/**
* Set from Swift in iOSApp.init() BEFORE DataManager.initialize().
* This enables Keychain storage for auth tokens.
*/
var keychainDelegate: KeychainDelegate? = null
@Volatile
private var instance: TokenManager? = null
fun getInstance(): TokenManager {
return instance ?: synchronized(this) {
instance ?: TokenManager().also { instance = it }
}
}
}
}
// Helper function for synchronization on iOS
private fun <T> synchronized(lock: Any, block: () -> T): T {
return block()
}

View File

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