package com.peachpasswords import android.app.Application import androidx.hilt.work.HiltWorkerFactory import androidx.lifecycle.DefaultLifecycleObserver import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner import androidx.work.Configuration import com.peachpasswords.sync.BackgroundSyncPreference import com.peachpasswords.sync.ForegroundSyncCoordinator import com.peachpasswords.updates.UpdateCheckWorker import com.peachpasswords.vault.VaultLockTimer import com.peachpasswords.vault.VaultRepository import dagger.hilt.android.HiltAndroidApp import javax.inject.Inject @HiltAndroidApp class PeachApplication : Application(), Configuration.Provider { @Inject lateinit var vault: VaultRepository @Inject lateinit var lockTimer: VaultLockTimer @Inject lateinit var foregroundSync: ForegroundSyncCoordinator @Inject lateinit var backgroundSync: BackgroundSyncPreference @Inject lateinit var workerFactory: HiltWorkerFactory override val workManagerConfiguration: Configuration get() = Configuration.Builder().setWorkerFactory(workerFactory).build() override fun onCreate() { super.onCreate() // Update checks: once a day in the background, plus one now — process // start is the honest "app open". Neither ever downloads or installs; // the most they do is post a notification. UpdateCheckWorker.schedulePeriodic(this) UpdateCheckWorker.checkNow(this) // Lock the vault the moment the whole app goes to background (CF-1). // ProcessLifecycleOwner is process-wide and debounced, so a rotation or a // brief Activity restart does not trip it — only a genuine backgrounding. ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver { override fun onStart(owner: LifecycleOwner) { foregroundSync.triggerForegroundSync() } override fun onStop(owner: LifecycleOwner) { // A SAF file picker/save dialog or share sheet also stops the // process's activities while it's in the foreground — that's // an expected, momentary handoff as part of an in-app export/ // import flow, not a real backgrounding, so it's exempted via // VaultRepository.expectTransientBackground(). if (vault.consumeTransientBackgroundSuppression()) return if (backgroundSync.enabled.value && vault.isUnlocked.value) { // Sync-retained mode: the vault stays unlocked in memory so // PeachSyncService can complete sessions while backgrounded. // The UI gate shows the lock screen on resume. The auto-lock // timer keeps running as a safety net — if it fires, it does // a full lock and sync stops. vault.lockUiGate() } else { vault.lock() lockTimer.cancel() } } }) } }