PeachApplication.kt

3.0 KB · raw

1package com.peachpasswords23import android.app.Application4import androidx.hilt.work.HiltWorkerFactory5import androidx.lifecycle.DefaultLifecycleObserver6import androidx.lifecycle.LifecycleOwner7import androidx.lifecycle.ProcessLifecycleOwner8import androidx.work.Configuration9import com.peachpasswords.sync.BackgroundSyncPreference10import com.peachpasswords.sync.ForegroundSyncCoordinator11import com.peachpasswords.updates.UpdateCheckWorker12import com.peachpasswords.vault.VaultLockTimer13import com.peachpasswords.vault.VaultRepository14import dagger.hilt.android.HiltAndroidApp15import javax.inject.Inject1617@HiltAndroidApp18class PeachApplication : Application(), Configuration.Provider {19    @Inject lateinit var vault: VaultRepository20    @Inject lateinit var lockTimer: VaultLockTimer21    @Inject lateinit var foregroundSync: ForegroundSyncCoordinator22    @Inject lateinit var backgroundSync: BackgroundSyncPreference23    @Inject lateinit var workerFactory: HiltWorkerFactory2425    override val workManagerConfiguration: Configuration26        get() = Configuration.Builder().setWorkerFactory(workerFactory).build()2728    override fun onCreate() {29        super.onCreate()3031        // Update checks: once a day in the background, plus one now — process32        // start is the honest "app open". Neither ever downloads or installs;33        // the most they do is post a notification.34        UpdateCheckWorker.schedulePeriodic(this)35        UpdateCheckWorker.checkNow(this)36        // Lock the vault the moment the whole app goes to background (CF-1).37        // ProcessLifecycleOwner is process-wide and debounced, so a rotation or a38        // brief Activity restart does not trip it — only a genuine backgrounding.39        ProcessLifecycleOwner.get().lifecycle.addObserver(object : DefaultLifecycleObserver {40            override fun onStart(owner: LifecycleOwner) {41                foregroundSync.triggerForegroundSync()42            }4344            override fun onStop(owner: LifecycleOwner) {45                // A SAF file picker/save dialog or share sheet also stops the46                // process's activities while it's in the foreground — that's47                // an expected, momentary handoff as part of an in-app export/48                // import flow, not a real backgrounding, so it's exempted via49                // VaultRepository.expectTransientBackground().50                if (vault.consumeTransientBackgroundSuppression()) return51                if (backgroundSync.enabled.value && vault.isUnlocked.value) {52                    // Sync-retained mode: the vault stays unlocked in memory so53                    // PeachSyncService can complete sessions while backgrounded.54                    // The UI gate shows the lock screen on resume. The auto-lock55                    // timer keeps running as a safety net — if it fires, it does56                    // a full lock and sync stops.57                    vault.lockUiGate()58                } else {59                    vault.lock()60                    lockTimer.cancel()61                }62            }63        })64    }65}