Ensure single ImageRepository instance across Activity recreations

This commit is contained in:
Pierre-Yves Nicolas
2026-01-22 13:43:01 +01:00
parent af9030fd7a
commit 7f4da8dee3
3 changed files with 53 additions and 12 deletions

View File

@@ -94,3 +94,15 @@ class AppContainer(context: Context) {
return now - lastModified > 24 * 60 * 60 * 1000 // 24h return now - lastModified > 24 * 60 * 60 * 1000 // 24h
} }
} }
class SessionViewModelFactory(
private val application: Application,
private val launchMode: LaunchMode,
private val appContainer: AppContainer
) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return SessionViewModel(application, launchMode, appContainer) as T
}
}

View File

@@ -43,7 +43,6 @@ import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.toClipEntry import androidx.compose.ui.platform.toClipEntry
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.core.content.ContextCompat.checkSelfPermission import androidx.core.content.ContextCompat.checkSelfPermission
import androidx.core.content.FileProvider
import androidx.core.net.toFile import androidx.core.net.toFile
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@@ -63,11 +62,11 @@ import org.fairscan.app.ui.screens.about.createEmailWithImageIntent
import org.fairscan.app.ui.screens.camera.CameraEvent import org.fairscan.app.ui.screens.camera.CameraEvent
import org.fairscan.app.ui.screens.camera.CameraScreen import org.fairscan.app.ui.screens.camera.CameraScreen
import org.fairscan.app.ui.screens.camera.CameraViewModel import org.fairscan.app.ui.screens.camera.CameraViewModel
import org.fairscan.app.ui.screens.export.ExportActions
import org.fairscan.app.ui.screens.export.ExportEvent import org.fairscan.app.ui.screens.export.ExportEvent
import org.fairscan.app.ui.screens.export.ExportResult import org.fairscan.app.ui.screens.export.ExportResult
import org.fairscan.app.ui.screens.export.ExportScreenWrapper import org.fairscan.app.ui.screens.export.ExportScreenWrapper
import org.fairscan.app.ui.screens.export.ExportViewModel import org.fairscan.app.ui.screens.export.ExportViewModel
import org.fairscan.app.ui.screens.export.ExportActions
import org.fairscan.app.ui.screens.home.HomeScreen import org.fairscan.app.ui.screens.home.HomeScreen
import org.fairscan.app.ui.screens.home.HomeViewModel import org.fairscan.app.ui.screens.home.HomeViewModel
import org.fairscan.app.ui.screens.settings.ExportFormat import org.fairscan.app.ui.screens.settings.ExportFormat
@@ -76,7 +75,6 @@ import org.fairscan.app.ui.screens.settings.SettingsViewModel
import org.fairscan.app.ui.theme.FairScanTheme import org.fairscan.app.ui.theme.FairScanTheme
import org.opencv.android.OpenCVLoader import org.opencv.android.OpenCVLoader
import java.io.File import java.io.File
import java.util.UUID
class MainActivity : ComponentActivity() { class MainActivity : ComponentActivity() {
@@ -85,27 +83,32 @@ class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
initLibraries() initLibraries()
val appContainer = (application as FairScanApp).appContainer val appContainer = (application as FairScanApp).appContainer
val launchMode = resolveLaunchMode(intent) val launchMode = resolveLaunchMode(intent)
sessionDir = when (launchMode) {
LaunchMode.NORMAL -> filesDir val sessionViewModel: SessionViewModel by viewModels {
LaunchMode.EXTERNAL_SCAN_TO_PDF -> SessionViewModelFactory(
File(appContainer.sessionsRoot(), UUID.randomUUID().toString()).apply { mkdirs() } application = application,
launchMode = launchMode,
appContainer = appContainer
)
} }
val sessionContainer = ScanSessionContainer(this, sessionDir)
val imageRepository = sessionViewModel.imageRepository
val viewModel: MainViewModel by viewModels { val viewModel: MainViewModel by viewModels {
appContainer.viewModelFactory { appContainer.viewModelFactory {
MainViewModel(sessionContainer.imageRepository, launchMode) MainViewModel(imageRepository, launchMode)
} }
} }
val exportViewModel: ExportViewModel by viewModels { val exportViewModel: ExportViewModel by viewModels {
appContainer.viewModelFactory { appContainer.viewModelFactory {
ExportViewModel(appContainer, sessionContainer.imageRepository) ExportViewModel(appContainer, imageRepository)
} }
} }
val aboutViewModel: AboutViewModel by viewModels { val aboutViewModel: AboutViewModel by viewModels {
appContainer.viewModelFactory { appContainer.viewModelFactory {
AboutViewModel(appContainer, sessionContainer.imageRepository) AboutViewModel(appContainer, imageRepository)
} }
} }
val homeViewModel: HomeViewModel by viewModels { appContainer.homeViewModelFactory } val homeViewModel: HomeViewModel by viewModels { appContainer.homeViewModelFactory }
@@ -126,7 +129,7 @@ class MainActivity : ComponentActivity() {
val cameraPermission = rememberCameraPermissionState() val cameraPermission = rememberCameraPermissionState()
CollectCameraEvents(cameraViewModel, viewModel) CollectCameraEvents(cameraViewModel, viewModel)
CollectExportEvents(context, exportViewModel) CollectExportEvents(context, exportViewModel)
CollectAboutEvents(context, aboutViewModel, sessionContainer.imageRepository) CollectAboutEvents(context, aboutViewModel, imageRepository)
FairScanTheme { FairScanTheme {
val navigation = navigation(viewModel, launchMode) val navigation = navigation(viewModel, launchMode)

View File

@@ -14,10 +14,36 @@
*/ */
package org.fairscan.app package org.fairscan.app
import android.app.Application
import android.content.Context import android.content.Context
import androidx.lifecycle.AndroidViewModel
import org.fairscan.app.data.ImageRepository import org.fairscan.app.data.ImageRepository
import org.fairscan.app.platform.OpenCvTransformations import org.fairscan.app.platform.OpenCvTransformations
import java.io.File import java.io.File
import java.util.UUID
class SessionViewModel(
app: Application,
launchMode: LaunchMode,
appContainer: AppContainer
) : AndroidViewModel(app) {
val sessionDir: File = when (launchMode) {
LaunchMode.NORMAL ->
app.filesDir
LaunchMode.EXTERNAL_SCAN_TO_PDF ->
File(appContainer.sessionsRoot(), UUID.randomUUID().toString())
.apply { mkdirs() }
}
private val sessionContainer = ScanSessionContainer(
context = app,
scanRootDir = sessionDir
)
val imageRepository: ImageRepository = sessionContainer.imageRepository
}
class ScanSessionContainer( class ScanSessionContainer(
context: Context, context: Context,