Settings: handle lost access to export folder

This commit is contained in:
Pierre-Yves Nicolas
2026-01-31 06:50:13 +01:00
parent 429d4e7a37
commit 6fa3fe68fb
15 changed files with 62 additions and 20 deletions

View File

@@ -248,6 +248,9 @@ class MainActivity : ComponentActivity() {
} }
} }
val settingsUiState by settingsViewModel.uiState.collectAsStateWithLifecycle() val settingsUiState by settingsViewModel.uiState.collectAsStateWithLifecycle()
LaunchedEffect(Unit) {
settingsViewModel.refreshExportDirName()
}
SettingsScreen( SettingsScreen(
settingsUiState, settingsUiState,
onChooseDirectoryClick = { onChooseDirectoryClick = {

View File

@@ -37,10 +37,8 @@ class SettingsRepository(private val context: Context) {
prefs[EXPORT_DIR_URI] prefs[EXPORT_DIR_URI]
} }
val exportDirName: Flow<String?> = exportDirUri.map { uriString -> fun resolveExportDirName(uri: String): String? {
uriString?.let { return DocumentFile.fromTreeUri(context, uri.toUri())?.name
DocumentFile.fromTreeUri(context, it.toUri())?.name
}
} }
val exportFormat: Flow<ExportFormat> = val exportFormat: Flow<ExportFormat> =

View File

@@ -14,8 +14,6 @@
*/ */
package org.fairscan.app.ui.screens.settings package org.fairscan.app.ui.screens.settings
import android.content.Context
import androidx.activity.compose.BackHandler import androidx.activity.compose.BackHandler
import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@@ -41,14 +39,12 @@ import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.net.toUri
import org.fairscan.app.R import org.fairscan.app.R
import org.fairscan.app.domain.ExportQuality import org.fairscan.app.domain.ExportQuality
import org.fairscan.app.ui.components.BackButton import org.fairscan.app.ui.components.BackButton
@@ -92,7 +88,20 @@ private fun SettingsContent(
onExportQualityChanged: (ExportQuality) -> Unit, onExportQualityChanged: (ExportQuality) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val folderName = uiState.exportDirName ?: stringResource(R.string.download_dirname) println(uiState)
val (folderLabel, folderLabelColor) = when {
uiState.exportDirUri == null ->
stringResource(R.string.download_dirname) to
MaterialTheme.colorScheme.onSurface
uiState.exportDirName != null ->
uiState.exportDirName to
MaterialTheme.colorScheme.onSurface
else ->
stringResource(R.string.export_folder_permission_lost) to
MaterialTheme.colorScheme.error
}
Column( Column(
modifier modifier
@@ -102,13 +111,14 @@ private fun SettingsContent(
) { ) {
DirectorySettingItem( DirectorySettingItem(
label = stringResource(R.string.export_directory), label = stringResource(R.string.export_directory),
folderName = folderName, folderLabel,
onClick = onChooseDirectoryClick folderLabelColor,
onClick = onChooseDirectoryClick,
) )
Spacer(Modifier.height(12.dp)) Spacer(Modifier.height(12.dp))
if (uiState.exportDirName != null) { if (uiState.exportDirUri != null) {
OutlinedButton( OutlinedButton(
onClick = onResetExportDirClick, onClick = onResetExportDirClick,
border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary), border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary),
@@ -156,9 +166,11 @@ private fun SettingsContent(
@Composable @Composable
fun DirectorySettingItem( fun DirectorySettingItem(
label: String, label: String,
folderName: String, folderLabel: String,
folderLabelColor: Color,
onClick: () -> Unit, onClick: () -> Unit,
) {
) {
Column { Column {
Text( Text(
text = label, text = label,
@@ -181,8 +193,9 @@ fun DirectorySettingItem(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
Text( Text(
text = folderName, text = folderLabel,
style = MaterialTheme.typography.bodyLarge style = MaterialTheme.typography.bodyLarge,
color = folderLabelColor,
) )
Icon( Icon(

View File

@@ -16,14 +16,18 @@ package org.fairscan.app.ui.screens.settings
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.fairscan.app.AppContainer import org.fairscan.app.AppContainer
import org.fairscan.app.domain.ExportQuality import org.fairscan.app.domain.ExportQuality
data class SettingsUiState( data class SettingsUiState(
val exportDirUri: String? = null,
val exportDirName: String? = null, val exportDirName: String? = null,
val exportFormat: ExportFormat = ExportFormat.PDF, val exportFormat: ExportFormat = ExportFormat.PDF,
val exportQuality: ExportQuality = ExportQuality.BALANCED, val exportQuality: ExportQuality = ExportQuality.BALANCED,
@@ -33,13 +37,18 @@ class SettingsViewModel(container: AppContainer) : ViewModel() {
private val repo = container.settingsRepository private val repo = container.settingsRepository
private val _dirName = MutableStateFlow<String?>(null)
val dirName: StateFlow<String?> = _dirName
val uiState = combine( val uiState = combine(
repo.exportDirName, repo.exportDirUri,
dirName,
repo.exportFormat, repo.exportFormat,
repo.exportQuality, repo.exportQuality,
) { dir, format, quality -> ) { uri, name, format, quality ->
SettingsUiState( SettingsUiState(
exportDirName = dir, exportDirUri = uri,
exportDirName = name,
exportFormat = format, exportFormat = format,
exportQuality = quality, exportQuality = quality,
) )
@@ -52,6 +61,7 @@ class SettingsViewModel(container: AppContainer) : ViewModel() {
fun setExportDirUri(uri: String?) { fun setExportDirUri(uri: String?) {
viewModelScope.launch { viewModelScope.launch {
repo.setExportDirUri(uri) repo.setExportDirUri(uri)
refreshExportDirName()
} }
} }
@@ -66,4 +76,11 @@ class SettingsViewModel(container: AppContainer) : ViewModel() {
repo.setExportQuality(quality) repo.setExportQuality(quality)
} }
} }
fun refreshExportDirName() {
viewModelScope.launch {
val uri = repo.exportDirUri.first()
_dirName.value = uri?.let { repo.resolveExportDirName(it) }
}
}
} }

View File

@@ -28,6 +28,7 @@
<string name="export">Exportovat</string> <string name="export">Exportovat</string>
<string name="export_as">Exportovat jako %1$s</string> <string name="export_as">Exportovat jako %1$s</string>
<string name="export_directory">Složka pro export</string> <string name="export_directory">Složka pro export</string>
<string name="export_folder_permission_lost">Ztracený přístup ke složce</string>
<string name="export_format">Formát exportu</string> <string name="export_format">Formát exportu</string>
<string name="export_quality">Kvalita exportu</string> <string name="export_quality">Kvalita exportu</string>
<string name="export_quality_low">Nízká</string> <string name="export_quality_low">Nízká</string>

View File

@@ -28,6 +28,7 @@
<string name="export">Exportieren</string> <string name="export">Exportieren</string>
<string name="export_as">Als %1$s exportieren</string> <string name="export_as">Als %1$s exportieren</string>
<string name="export_directory">Exportordner</string> <string name="export_directory">Exportordner</string>
<string name="export_folder_permission_lost">Zugriff auf Ordner verloren</string>
<string name="export_format">Exportformat</string> <string name="export_format">Exportformat</string>
<string name="export_quality">Exportqualität</string> <string name="export_quality">Exportqualität</string>
<string name="export_quality_low">Niedrig</string> <string name="export_quality_low">Niedrig</string>

View File

@@ -28,6 +28,7 @@
<string name="export">Exportar</string> <string name="export">Exportar</string>
<string name="export_as">Exportar como %1$s</string> <string name="export_as">Exportar como %1$s</string>
<string name="export_directory">Carpeta de exportación</string> <string name="export_directory">Carpeta de exportación</string>
<string name="export_folder_permission_lost">Acceso a la carpeta perdido</string>
<string name="export_format">Formato de exportación</string> <string name="export_format">Formato de exportación</string>
<string name="export_quality">Calidad de exportación</string> <string name="export_quality">Calidad de exportación</string>
<string name="export_quality_low">Baja</string> <string name="export_quality_low">Baja</string>

View File

@@ -28,6 +28,7 @@
<string name="export">Exporter</string> <string name="export">Exporter</string>
<string name="export_as">Exporter en %1$s</string> <string name="export_as">Exporter en %1$s</string>
<string name="export_directory">Dossier dexport</string> <string name="export_directory">Dossier dexport</string>
<string name="export_folder_permission_lost">Accès au dossier perdu</string>
<string name="export_format">Format dexport</string> <string name="export_format">Format dexport</string>
<string name="export_quality">Qualité dexport</string> <string name="export_quality">Qualité dexport</string>
<string name="export_quality_low">Basse</string> <string name="export_quality_low">Basse</string>

View File

@@ -28,6 +28,7 @@
<string name="export">Esporta</string> <string name="export">Esporta</string>
<string name="export_as">Esporta come %1$s</string> <string name="export_as">Esporta come %1$s</string>
<string name="export_directory">Cartella di esportazione</string> <string name="export_directory">Cartella di esportazione</string>
<string name="export_folder_permission_lost">Accesso alla cartella perso</string>
<string name="export_format">Formato di esportazione</string> <string name="export_format">Formato di esportazione</string>
<string name="export_quality">Qualità di esportazione</string> <string name="export_quality">Qualità di esportazione</string>
<string name="export_quality_low">Bassa</string> <string name="export_quality_low">Bassa</string>

View File

@@ -28,6 +28,7 @@
<string name="export">Exportar</string> <string name="export">Exportar</string>
<string name="export_as">Exportar como %1$s</string> <string name="export_as">Exportar como %1$s</string>
<string name="export_directory">Diretório de exportação</string> <string name="export_directory">Diretório de exportação</string>
<string name="export_folder_permission_lost">Acesso à pasta perdido</string>
<string name="export_format">Formato de exportação</string> <string name="export_format">Formato de exportação</string>
<string name="export_quality">Qualidade de exportação</string> <string name="export_quality">Qualidade de exportação</string>
<string name="export_quality_low">Baixa</string> <string name="export_quality_low">Baixa</string>

View File

@@ -28,6 +28,7 @@
<string name="export">Экспорт</string> <string name="export">Экспорт</string>
<string name="export_as">Экспортировать как %1$s</string> <string name="export_as">Экспортировать как %1$s</string>
<string name="export_directory">Папка экспорта</string> <string name="export_directory">Папка экспорта</string>
<string name="export_folder_permission_lost">Доступ к папке потерян</string>
<string name="export_format">Формат экспорта</string> <string name="export_format">Формат экспорта</string>
<string name="export_quality">Качество экспорта</string> <string name="export_quality">Качество экспорта</string>
<string name="export_quality_low">Низкое</string> <string name="export_quality_low">Низкое</string>

View File

@@ -28,6 +28,7 @@
<string name="export">Dışa aktar</string> <string name="export">Dışa aktar</string>
<string name="export_as">%1$s olarak dışa aktar</string> <string name="export_as">%1$s olarak dışa aktar</string>
<string name="export_directory">Dışa aktarma dizini</string> <string name="export_directory">Dışa aktarma dizini</string>
<string name="export_folder_permission_lost">Klasör erişimi kaybedildi</string>
<string name="export_format">Dışa aktarma biçimi</string> <string name="export_format">Dışa aktarma biçimi</string>
<string name="export_quality">Dışa aktarma kalitesi</string> <string name="export_quality">Dışa aktarma kalitesi</string>
<string name="export_quality_low">Düşük</string> <string name="export_quality_low">Düşük</string>

View File

@@ -28,6 +28,7 @@
<string name="export">匯出</string> <string name="export">匯出</string>
<string name="export_as">匯出為 %1$s</string> <string name="export_as">匯出為 %1$s</string>
<string name="export_directory">匯出目錄</string> <string name="export_directory">匯出目錄</string>
<string name="export_folder_permission_lost">資料夾存取權限已遺失</string>
<string name="export_format">匯出格式</string> <string name="export_format">匯出格式</string>
<string name="export_quality">匯出品質</string> <string name="export_quality">匯出品質</string>
<string name="export_quality_low"></string> <string name="export_quality_low"></string>

View File

@@ -28,6 +28,7 @@
<string name="export">导出</string> <string name="export">导出</string>
<string name="export_as">导出为 %1$s</string> <string name="export_as">导出为 %1$s</string>
<string name="export_directory">导出目录</string> <string name="export_directory">导出目录</string>
<string name="export_folder_permission_lost">文件夹访问权限已丢失</string>
<string name="export_format">导出格式</string> <string name="export_format">导出格式</string>
<string name="export_quality">导出质量</string> <string name="export_quality">导出质量</string>
<string name="export_quality_low"></string> <string name="export_quality_low"></string>

View File

@@ -32,6 +32,7 @@
<string name="export">Export</string> <string name="export">Export</string>
<string name="export_as">Export as %1$s</string> <string name="export_as">Export as %1$s</string>
<string name="export_directory">Export folder</string> <string name="export_directory">Export folder</string>
<string name="export_folder_permission_lost">Folder access lost</string>
<string name="export_format">Export format</string> <string name="export_format">Export format</string>
<string name="export_quality">Export quality</string> <string name="export_quality">Export quality</string>
<string name="export_quality_low">Low</string> <string name="export_quality_low">Low</string>