package top.yeij.cyrene import android.app.Activity import android.app.Application import android.os.Bundle import android.util.Log import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.launch import org.koin.android.ext.koin.androidContext import org.koin.core.context.GlobalContext import org.koin.core.context.startKoin import top.yeij.cyrene.data.local.PreferencesDataStore import top.yeij.cyrene.data.remote.AuthInterceptor import top.yeij.cyrene.data.remote.DynamicUrlInterceptor import top.yeij.cyrene.data.repository.ChatRepositoryImpl import top.yeij.cyrene.di.appModule import top.yeij.cyrene.util.NotificationHelper import top.yeij.cyrene.util.RuntimeLog import java.util.concurrent.atomic.AtomicInteger class CyreneApplication : Application() { private val initScope = CoroutineScope(SupervisorJob() + Dispatchers.IO) private val activityCount = AtomicInteger(0) @Volatile private var notificationHelper: NotificationHelper? = null override fun onCreate() { super.onCreate() RuntimeLog.general("app", "Application onCreate") startKoin { androidContext(this@CyreneApplication) modules(appModule) } // Track foreground/background state registerActivityLifecycleCallbacks(object : ActivityLifecycleCallbacks { override fun onActivityStarted(activity: Activity) { if (activityCount.incrementAndGet() == 1) { RuntimeLog.general("app", "App in foreground") notificationHelper?.cancelAll() getRepo()?.onAppForeground() } } override fun onActivityStopped(activity: Activity) { if (activityCount.decrementAndGet() == 0) { RuntimeLog.general("app", "App in background") getRepo()?.onAppBackground() } } override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {} override fun onActivityResumed(activity: Activity) {} override fun onActivityPaused(activity: Activity) {} override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {} override fun onActivityDestroyed(activity: Activity) {} }) // Set up background notification callback once Koin is ready initScope.launch { val helper = NotificationHelper(this@CyreneApplication) notificationHelper = helper val repo = getRepo() repo?.setNotificationCallback { message -> helper.showMessageNotification(message) } } initScope.launch { val koin = GlobalContext.get() val prefs: PreferencesDataStore = koin.get() val urlInterceptor: DynamicUrlInterceptor = koin.get() val authInterceptor: AuthInterceptor = koin.get() prefs.baseUrl.firstOrNull()?.let { url -> if (url.isNotBlank()) urlInterceptor.baseUrl = url } prefs.token.firstOrNull()?.let { token -> authInterceptor.token = token } } } private fun getRepo(): ChatRepositoryImpl? { return try { GlobalContext.get().get() } catch (_: Throwable) { null } } companion object { private const val TAG = "CyreneApp" } }