Export PDF to preferred dir if it was defined
This commit is contained in:
committed by
pynicolas
parent
7c9267a866
commit
53c9bc3630
@@ -117,6 +117,7 @@ dependencies {
|
|||||||
implementation(libs.androidx.camera.view)
|
implementation(libs.androidx.camera.view)
|
||||||
implementation(libs.androidx.datastore)
|
implementation(libs.androidx.datastore)
|
||||||
implementation(libs.androidx.datastore.preferences)
|
implementation(libs.androidx.datastore.preferences)
|
||||||
|
implementation(libs.androidx.documentfile)
|
||||||
implementation(libs.protobuf.javalite)
|
implementation(libs.protobuf.javalite)
|
||||||
implementation(libs.litert)
|
implementation(libs.litert)
|
||||||
implementation(libs.litert.support)
|
implementation(libs.litert.support)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package org.fairscan.app
|
|||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.ClipData
|
import android.content.ClipData
|
||||||
|
import android.content.ContentResolver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
@@ -297,13 +298,15 @@ class MainActivity : ComponentActivity() {
|
|||||||
|
|
||||||
private fun openPdf(fileUri: Uri?) {
|
private fun openPdf(fileUri: Uri?) {
|
||||||
if (fileUri == null) return
|
if (fileUri == null) return
|
||||||
val uri = FileProvider.getUriForFile(
|
val uriToOpen: Uri =
|
||||||
this,
|
if (fileUri.scheme == ContentResolver.SCHEME_CONTENT) {
|
||||||
"${applicationContext.packageName}.fileprovider",
|
fileUri
|
||||||
fileUri.toFile()
|
} else {
|
||||||
)
|
val authority = "${applicationContext.packageName}.fileprovider"
|
||||||
|
FileProvider.getUriForFile(this, authority, fileUri.toFile())
|
||||||
|
}
|
||||||
val openIntent = Intent(Intent.ACTION_VIEW).apply {
|
val openIntent = Intent(Intent.ACTION_VIEW).apply {
|
||||||
setDataAndType(uri, PDF_MIME_TYPE)
|
setDataAndType(uriToOpen, PDF_MIME_TYPE)
|
||||||
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ private fun TextFieldAndPdfInfos(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (uiState.savedFileUri != null) {
|
if (uiState.savedFileUri != null) {
|
||||||
SavedPdfBar(onOpen)
|
SavedPdfBar(uiState, onOpen)
|
||||||
}
|
}
|
||||||
if (uiState.errorMessage != null) {
|
if (uiState.errorMessage != null) {
|
||||||
ErrorBar(uiState.errorMessage)
|
ErrorBar(uiState.errorMessage)
|
||||||
@@ -335,7 +335,8 @@ fun ExportButton(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun SavedPdfBar(onOpen: () -> Unit) {
|
private fun SavedPdfBar(uiState: PdfGenerationUiState, onOpen: () -> Unit) {
|
||||||
|
val dirName = uiState.exportDirName?:stringResource(R.string.download_dirname)
|
||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
horizontalArrangement = Arrangement.Absolute.SpaceBetween,
|
horizontalArrangement = Arrangement.Absolute.SpaceBetween,
|
||||||
@@ -345,7 +346,7 @@ private fun SavedPdfBar(onOpen: () -> Unit) {
|
|||||||
.padding(vertical = 8.dp, horizontal = 16.dp),
|
.padding(vertical = 8.dp, horizontal = 16.dp),
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(R.string.pdf_saved_to),
|
text = stringResource(R.string.pdf_saved_to, dirName),
|
||||||
style = MaterialTheme.typography.bodyMedium,
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
modifier = Modifier.weight(1f),
|
modifier = Modifier.weight(1f),
|
||||||
)
|
)
|
||||||
@@ -428,6 +429,7 @@ fun PreviewExportScreenAfterSaveHorizontal() {
|
|||||||
uiState = PdfGenerationUiState(
|
uiState = PdfGenerationUiState(
|
||||||
generatedPdf = GeneratedPdf(file, 442897L, 3),
|
generatedPdf = GeneratedPdf(file, 442897L, 3),
|
||||||
savedFileUri = file.toUri(),
|
savedFileUri = file.toUri(),
|
||||||
|
exportDirName = "MyVeryVeryLongDirectoryName"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ data class PdfGenerationUiState(
|
|||||||
val generatedPdf: GeneratedPdf? = null,
|
val generatedPdf: GeneratedPdf? = null,
|
||||||
val desiredFilename: String = "",
|
val desiredFilename: String = "",
|
||||||
val savedFileUri: Uri? = null,
|
val savedFileUri: Uri? = null,
|
||||||
|
val exportDirName: String? = null,
|
||||||
val hasSharedPdf: Boolean = false,
|
val hasSharedPdf: Boolean = false,
|
||||||
val errorMessage: String? = null,
|
val errorMessage: String? = null,
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -16,7 +16,9 @@ package org.fairscan.app.ui.screens.export
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.media.MediaScannerConnection
|
import android.media.MediaScannerConnection
|
||||||
|
import android.net.Uri
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
|
import androidx.documentfile.provider.DocumentFile
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -27,6 +29,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asSharedFlow
|
import kotlinx.coroutines.flow.asSharedFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
@@ -36,6 +39,7 @@ import org.fairscan.app.data.GeneratedPdf
|
|||||||
import org.fairscan.app.data.PdfFileManager
|
import org.fairscan.app.data.PdfFileManager
|
||||||
import org.fairscan.app.ui.screens.home.HomeViewModel
|
import org.fairscan.app.ui.screens.home.HomeViewModel
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.FileInputStream
|
||||||
|
|
||||||
private const val PDF_MIME_TYPE = "application/pdf"
|
private const val PDF_MIME_TYPE = "application/pdf"
|
||||||
|
|
||||||
@@ -48,6 +52,7 @@ class ExportViewModel(container: AppContainer): ViewModel() {
|
|||||||
|
|
||||||
private val pdfFileManager = container.pdfFileManager
|
private val pdfFileManager = container.pdfFileManager
|
||||||
private val imageRepository = container.imageRepository
|
private val imageRepository = container.imageRepository
|
||||||
|
private val settingsRepository = container.settingsRepository
|
||||||
private val logger = container.logger
|
private val logger = container.logger
|
||||||
|
|
||||||
private val _events = MutableSharedFlow<ExportEvent>()
|
private val _events = MutableSharedFlow<ExportEvent>()
|
||||||
@@ -121,12 +126,6 @@ class ExportViewModel(container: AppContainer): ViewModel() {
|
|||||||
return _pdfUiState.value.generatedPdf
|
return _pdfUiState.value.generatedPdf
|
||||||
}
|
}
|
||||||
|
|
||||||
fun saveFile(pdfFile: File): File {
|
|
||||||
val copiedFile = pdfFileManager.copyToExternalDir(pdfFile)
|
|
||||||
_pdfUiState.update { it.copy(savedFileUri = copiedFile.toUri()) }
|
|
||||||
return copiedFile
|
|
||||||
}
|
|
||||||
|
|
||||||
fun onSavePdfClicked() {
|
fun onSavePdfClicked() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
_events.emit(ExportEvent.RequestSavePdf)
|
_events.emit(ExportEvent.RequestSavePdf)
|
||||||
@@ -142,13 +141,30 @@ class ExportViewModel(container: AppContainer): ViewModel() {
|
|||||||
private suspend fun performPdfSave(context: Context, homeViewModel: HomeViewModel) {
|
private suspend fun performPdfSave(context: Context, homeViewModel: HomeViewModel) {
|
||||||
try {
|
try {
|
||||||
val pdf = getFinalPdf() ?: return
|
val pdf = getFinalPdf() ?: return
|
||||||
val targetFile = saveFile(pdf.file)
|
|
||||||
|
|
||||||
mediaScan(context, targetFile)
|
val exportDir = settingsRepository.exportDirUri.first()
|
||||||
|
var fileInDownloads: File? = null
|
||||||
|
|
||||||
|
val savedUri: Uri =
|
||||||
|
if (exportDir == null) {
|
||||||
|
fileInDownloads = pdfFileManager.copyToExternalDir(pdf.file)
|
||||||
|
fileInDownloads.toUri()
|
||||||
|
} else {
|
||||||
|
copyViaSaf(context, pdf.file, exportDir.toUri())
|
||||||
|
}
|
||||||
|
|
||||||
|
_pdfUiState.update {
|
||||||
|
it.copy(
|
||||||
|
savedFileUri = savedUri,
|
||||||
|
exportDirName = resolveExportDirName(context, exportDir?.toUri()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fileInDownloads?.let { mediaScan(context, it) }
|
||||||
|
|
||||||
// TODO remove that call: that should be handled through the ExportEvent
|
// TODO remove that call: that should be handled through the ExportEvent
|
||||||
homeViewModel.addRecentDocument(
|
homeViewModel.addRecentDocument(
|
||||||
targetFile.absolutePath,
|
// FIXME This is not a file path
|
||||||
|
savedUri.toString(),
|
||||||
pdf.pageCount
|
pdf.pageCount
|
||||||
)
|
)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -167,10 +183,40 @@ class ExportViewModel(container: AppContainer): ViewModel() {
|
|||||||
) { _, _ -> continuation.resume(Unit) {} }
|
) { _, _ -> continuation.resume(Unit) {} }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun copyViaSaf(
|
||||||
|
context: Context,
|
||||||
|
source: File,
|
||||||
|
exportDirUri: Uri,
|
||||||
|
): Uri {
|
||||||
|
val resolver = context.contentResolver
|
||||||
|
|
||||||
|
val tree = DocumentFile.fromTreeUri(context, exportDirUri)
|
||||||
|
?: throw IllegalStateException("Invalid SAF directory")
|
||||||
|
|
||||||
|
// Name collisions are handled automatically by SAF provider
|
||||||
|
val target = tree.createFile(PDF_MIME_TYPE, source.name)
|
||||||
|
?: throw IllegalStateException("Unable to create SAF file")
|
||||||
|
|
||||||
|
resolver.openOutputStream(target.uri)?.use { output ->
|
||||||
|
FileInputStream(source).use { input ->
|
||||||
|
input.copyTo(output)
|
||||||
|
}
|
||||||
|
} ?: throw IllegalStateException("Failed to open SAF output stream")
|
||||||
|
|
||||||
|
return target.uri
|
||||||
|
}
|
||||||
|
|
||||||
fun cleanUpOldPdfs(thresholdInMillis: Int) {
|
fun cleanUpOldPdfs(thresholdInMillis: Int) {
|
||||||
pdfFileManager.cleanUpOldFiles(thresholdInMillis)
|
pdfFileManager.cleanUpOldFiles(thresholdInMillis)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun resolveExportDirName(context: Context, exportDirUri: Uri?): String? {
|
||||||
|
return if (exportDirUri == null) {
|
||||||
|
null
|
||||||
|
} else {
|
||||||
|
DocumentFile.fromTreeUri(context, exportDirUri)?.name
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data class PdfGenerationActions(
|
data class PdfGenerationActions(
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="delete_page_warning">Chcete smazat tuto stránku?</string>
|
<string name="delete_page_warning">Chcete smazat tuto stránku?</string>
|
||||||
<string name="developer">Vývojář</string>
|
<string name="developer">Vývojář</string>
|
||||||
<string name="discard_scan">Zrušit skenování</string>
|
<string name="discard_scan">Zrušit skenování</string>
|
||||||
|
<string name="download_dirname">stažených</string>
|
||||||
<string name="end_scan">Ukončit skenování</string>
|
<string name="end_scan">Ukončit skenování</string>
|
||||||
<string name="error">Chyba: %1$s</string>
|
<string name="error">Chyba: %1$s</string>
|
||||||
<string name="error_no_document">Nebyl rozpoznán žádná dokument</string>
|
<string name="error_no_document">Nebyl rozpoznán žádná dokument</string>
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<string name="new_document_warning">Toto skenování bude ztraceno. Chcete pokračovat?</string>
|
<string name="new_document_warning">Toto skenování bude ztraceno. Chcete pokračovat?</string>
|
||||||
<string name="open">Otevřít</string>
|
<string name="open">Otevřít</string>
|
||||||
<string name="open_pdf">Otevřít PDF</string>
|
<string name="open_pdf">Otevřít PDF</string>
|
||||||
<string name="pdf_saved_to">PDF bylo uloženo do stažených</string>
|
<string name="pdf_saved_to">PDF bylo uloženo do %1s</string>
|
||||||
<string name="resume">Obnovit</string>
|
<string name="resume">Obnovit</string>
|
||||||
<string name="save">Uložit</string>
|
<string name="save">Uložit</string>
|
||||||
<string name="scan_button">Nové skenování</string>
|
<string name="scan_button">Nové skenování</string>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="delete_page_warning">Möchten Sie diese Seite löschen?</string>
|
<string name="delete_page_warning">Möchten Sie diese Seite löschen?</string>
|
||||||
<string name="developer">Entwickler</string>
|
<string name="developer">Entwickler</string>
|
||||||
<string name="discard_scan">Löschen</string>
|
<string name="discard_scan">Löschen</string>
|
||||||
|
<string name="download_dirname">Downloads</string>
|
||||||
<string name="end_scan">Scan beenden</string>
|
<string name="end_scan">Scan beenden</string>
|
||||||
<string name="error">Fehler: %1$s</string>
|
<string name="error">Fehler: %1$s</string>
|
||||||
<string name="error_no_document">Kein Dokument erkannt</string>
|
<string name="error_no_document">Kein Dokument erkannt</string>
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<string name="new_document_warning">Das aktuelle Dokument geht verloren. Möchten Sie fortfahren?</string>
|
<string name="new_document_warning">Das aktuelle Dokument geht verloren. Möchten Sie fortfahren?</string>
|
||||||
<string name="open">Öffnen</string>
|
<string name="open">Öffnen</string>
|
||||||
<string name="open_pdf">PDF öffnen</string>
|
<string name="open_pdf">PDF öffnen</string>
|
||||||
<string name="pdf_saved_to">PDF gespeichert in Downloads</string>
|
<string name="pdf_saved_to">PDF gespeichert in %1s</string>
|
||||||
<string name="resume">Fortsetzen</string>
|
<string name="resume">Fortsetzen</string>
|
||||||
<string name="save">Speichern</string>
|
<string name="save">Speichern</string>
|
||||||
<string name="scan_button">Neuer Scan</string>
|
<string name="scan_button">Neuer Scan</string>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="delete_page_warning">¿Quieres eliminar esta página?</string>
|
<string name="delete_page_warning">¿Quieres eliminar esta página?</string>
|
||||||
<string name="developer">Desarrollador</string>
|
<string name="developer">Desarrollador</string>
|
||||||
<string name="discard_scan">Descartar escaneo</string>
|
<string name="discard_scan">Descartar escaneo</string>
|
||||||
|
<string name="download_dirname">Descargas</string>
|
||||||
<string name="end_scan">Finalizar escaneo</string>
|
<string name="end_scan">Finalizar escaneo</string>
|
||||||
<string name="error">Error: %1$s</string>
|
<string name="error">Error: %1$s</string>
|
||||||
<string name="error_no_document">No se detectó ningún documento</string>
|
<string name="error_no_document">No se detectó ningún documento</string>
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<string name="new_document_warning">El escaneo actual se perderá. ¿Deseas continuar?</string>
|
<string name="new_document_warning">El escaneo actual se perderá. ¿Deseas continuar?</string>
|
||||||
<string name="open">Abrir</string>
|
<string name="open">Abrir</string>
|
||||||
<string name="open_pdf">Abrir PDF</string>
|
<string name="open_pdf">Abrir PDF</string>
|
||||||
<string name="pdf_saved_to">PDF guardado en Descargas</string>
|
<string name="pdf_saved_to">PDF guardado en %1s</string>
|
||||||
<string name="resume">Reanudar</string>
|
<string name="resume">Reanudar</string>
|
||||||
<string name="save">Guardar</string>
|
<string name="save">Guardar</string>
|
||||||
<string name="scan_button">Nuevo escaneo</string>
|
<string name="scan_button">Nuevo escaneo</string>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="delete_page_warning">Voulez-vous supprimer cette page ?</string>
|
<string name="delete_page_warning">Voulez-vous supprimer cette page ?</string>
|
||||||
<string name="developer">Développeur</string>
|
<string name="developer">Développeur</string>
|
||||||
<string name="discard_scan">Supprimer le scan</string>
|
<string name="discard_scan">Supprimer le scan</string>
|
||||||
|
<string name="download_dirname">Téléchargements</string>
|
||||||
<string name="end_scan">Terminer le scan</string>
|
<string name="end_scan">Terminer le scan</string>
|
||||||
<string name="error">Erreur : %1$s</string>
|
<string name="error">Erreur : %1$s</string>
|
||||||
<string name="error_no_document">Aucun document détecté</string>
|
<string name="error_no_document">Aucun document détecté</string>
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<string name="new_document_warning">Le scan en cours sera perdu. Voulez-vous continuer ?</string>
|
<string name="new_document_warning">Le scan en cours sera perdu. Voulez-vous continuer ?</string>
|
||||||
<string name="open">Ouvrir</string>
|
<string name="open">Ouvrir</string>
|
||||||
<string name="open_pdf">Ouvrir le PDF</string>
|
<string name="open_pdf">Ouvrir le PDF</string>
|
||||||
<string name="pdf_saved_to">PDF enregistré dans Téléchargements</string>
|
<string name="pdf_saved_to">PDF enregistré dans %1s</string>
|
||||||
<string name="resume">Reprendre</string>
|
<string name="resume">Reprendre</string>
|
||||||
<string name="save">Enregistrer</string>
|
<string name="save">Enregistrer</string>
|
||||||
<string name="scan_button">Nouveau scan</string>
|
<string name="scan_button">Nouveau scan</string>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="delete_page_warning">Vuoi eliminare questa pagina?</string>
|
<string name="delete_page_warning">Vuoi eliminare questa pagina?</string>
|
||||||
<string name="developer">Sviluppatore</string>
|
<string name="developer">Sviluppatore</string>
|
||||||
<string name="discard_scan">Scarta scansione</string>
|
<string name="discard_scan">Scarta scansione</string>
|
||||||
|
<string name="download_dirname">Download</string>
|
||||||
<string name="end_scan">Termina scansione</string>
|
<string name="end_scan">Termina scansione</string>
|
||||||
<string name="error">Errore: %1$s</string>
|
<string name="error">Errore: %1$s</string>
|
||||||
<string name="error_no_document">Nessun documento rilevato</string>
|
<string name="error_no_document">Nessun documento rilevato</string>
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<string name="new_document_warning">La scansiona attuale verrà persa. Vuoi continuare?</string>
|
<string name="new_document_warning">La scansiona attuale verrà persa. Vuoi continuare?</string>
|
||||||
<string name="open">Apri</string>
|
<string name="open">Apri</string>
|
||||||
<string name="open_pdf">Apri PDF</string>
|
<string name="open_pdf">Apri PDF</string>
|
||||||
<string name="pdf_saved_to">PDF salvato in Download</string>
|
<string name="pdf_saved_to">PDF salvato in %1s</string>
|
||||||
<string name="resume">Riprendi</string>
|
<string name="resume">Riprendi</string>
|
||||||
<string name="save">Salva</string>
|
<string name="save">Salva</string>
|
||||||
<string name="scan_button">Nuova scansione</string>
|
<string name="scan_button">Nuova scansione</string>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="delete_page_warning">Deseja excluir esta página?</string>
|
<string name="delete_page_warning">Deseja excluir esta página?</string>
|
||||||
<string name="developer">Desenvolvedor</string>
|
<string name="developer">Desenvolvedor</string>
|
||||||
<string name="discard_scan">Descartar digitalização</string>
|
<string name="discard_scan">Descartar digitalização</string>
|
||||||
|
<string name="download_dirname">Downloads</string>
|
||||||
<string name="end_scan">Finalizar digitalização</string>
|
<string name="end_scan">Finalizar digitalização</string>
|
||||||
<string name="error">Erro: %1$s</string>
|
<string name="error">Erro: %1$s</string>
|
||||||
<string name="error_no_document">Nenhum documento detectado</string>
|
<string name="error_no_document">Nenhum documento detectado</string>
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<string name="new_document_warning">A digitalização atual será perdida. Deseja continuar?</string>
|
<string name="new_document_warning">A digitalização atual será perdida. Deseja continuar?</string>
|
||||||
<string name="open">Abrir</string>
|
<string name="open">Abrir</string>
|
||||||
<string name="open_pdf">Abrir PDF</string>
|
<string name="open_pdf">Abrir PDF</string>
|
||||||
<string name="pdf_saved_to">PDF salvo em Downloads</string>
|
<string name="pdf_saved_to">PDF salvo em %1s</string>
|
||||||
<string name="resume">Retomar</string>
|
<string name="resume">Retomar</string>
|
||||||
<string name="save">Salvar</string>
|
<string name="save">Salvar</string>
|
||||||
<string name="scan_button">Nova digitalização</string>
|
<string name="scan_button">Nova digitalização</string>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="delete_page_warning">Вы желаете удалить эту страницу?</string>
|
<string name="delete_page_warning">Вы желаете удалить эту страницу?</string>
|
||||||
<string name="developer">Разработчик</string>
|
<string name="developer">Разработчик</string>
|
||||||
<string name="discard_scan">Отказаться</string>
|
<string name="discard_scan">Отказаться</string>
|
||||||
|
<string name="download_dirname">Download</string>
|
||||||
<string name="end_scan">Закончить</string>
|
<string name="end_scan">Закончить</string>
|
||||||
<string name="error">Ошибка: %1$s</string>
|
<string name="error">Ошибка: %1$s</string>
|
||||||
<string name="error_no_document">Документ не обнаружен</string>
|
<string name="error_no_document">Документ не обнаружен</string>
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<string name="new_document_warning">Результаты текущего сканирования будут потеряны. Желаете продолжить?</string>
|
<string name="new_document_warning">Результаты текущего сканирования будут потеряны. Желаете продолжить?</string>
|
||||||
<string name="open">Открыть</string>
|
<string name="open">Открыть</string>
|
||||||
<string name="open_pdf">Открыть PDF</string>
|
<string name="open_pdf">Открыть PDF</string>
|
||||||
<string name="pdf_saved_to">PDF сохранен в Download</string>
|
<string name="pdf_saved_to">PDF сохранен в %1s</string>
|
||||||
<string name="resume">Продолжить</string>
|
<string name="resume">Продолжить</string>
|
||||||
<string name="save">Сохранить</string>
|
<string name="save">Сохранить</string>
|
||||||
<string name="scan_button">Начать</string>
|
<string name="scan_button">Начать</string>
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
<string name="delete_page_warning">是否要删除此页面?</string>
|
<string name="delete_page_warning">是否要删除此页面?</string>
|
||||||
<string name="developer">开发者</string>
|
<string name="developer">开发者</string>
|
||||||
<string name="discard_scan">放弃扫描</string>
|
<string name="discard_scan">放弃扫描</string>
|
||||||
|
<string name="download_dirname">下载</string>
|
||||||
<string name="end_scan">结束扫描</string>
|
<string name="end_scan">结束扫描</string>
|
||||||
<string name="error">错误: %1$s</string>
|
<string name="error">错误: %1$s</string>
|
||||||
<string name="error_no_document">未检测到任何文档</string>
|
<string name="error_no_document">未检测到任何文档</string>
|
||||||
@@ -33,7 +34,7 @@
|
|||||||
<string name="new_document_warning">当前扫描将丢失。是否继续?</string>
|
<string name="new_document_warning">当前扫描将丢失。是否继续?</string>
|
||||||
<string name="open">打开</string>
|
<string name="open">打开</string>
|
||||||
<string name="open_pdf">打开 PDF</string>
|
<string name="open_pdf">打开 PDF</string>
|
||||||
<string name="pdf_saved_to">PDF 保存到</string>
|
<string name="pdf_saved_to">PDF 已保存到 %1$s</string>
|
||||||
<string name="resume">恢复</string>
|
<string name="resume">恢复</string>
|
||||||
<string name="save">保存</string>
|
<string name="save">保存</string>
|
||||||
<string name="scan_button">新建扫描</string>
|
<string name="scan_button">新建扫描</string>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
<string name="delete_page_warning">Do you want to delete this page?</string>
|
<string name="delete_page_warning">Do you want to delete this page?</string>
|
||||||
<string name="developer">Developer</string>
|
<string name="developer">Developer</string>
|
||||||
<string name="discard_scan">Discard scan</string>
|
<string name="discard_scan">Discard scan</string>
|
||||||
|
<string name="download_dirname">Downloads</string>
|
||||||
<string name="end_scan">End scan</string>
|
<string name="end_scan">End scan</string>
|
||||||
<string name="error">Error: %1$s</string>
|
<string name="error">Error: %1$s</string>
|
||||||
<string name="error_no_document">No document detected</string>
|
<string name="error_no_document">No document detected</string>
|
||||||
@@ -34,7 +35,7 @@
|
|||||||
<string name="new_document_warning">The current scan will be lost. Do you want to continue?</string>
|
<string name="new_document_warning">The current scan will be lost. Do you want to continue?</string>
|
||||||
<string name="open">Open</string>
|
<string name="open">Open</string>
|
||||||
<string name="open_pdf">Open PDF</string>
|
<string name="open_pdf">Open PDF</string>
|
||||||
<string name="pdf_saved_to">PDF saved in Downloads</string>
|
<string name="pdf_saved_to">PDF saved in %1s</string>
|
||||||
<string name="resume">Resume</string>
|
<string name="resume">Resume</string>
|
||||||
<string name="save">Save</string>
|
<string name="save">Save</string>
|
||||||
<string name="scan_button">New Scan</string>
|
<string name="scan_button">New Scan</string>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ activityCompose = "1.10.1"
|
|||||||
composeBom = "2025.08.01"
|
composeBom = "2025.08.01"
|
||||||
camerax = "1.4.2"
|
camerax = "1.4.2"
|
||||||
datastore = "1.2.0"
|
datastore = "1.2.0"
|
||||||
|
documentfile = "1.1.0"
|
||||||
litert = "1.4.0"
|
litert = "1.4.0"
|
||||||
opencv = "4.12.0"
|
opencv = "4.12.0"
|
||||||
assertj = "3.27.4"
|
assertj = "3.27.4"
|
||||||
@@ -47,6 +48,7 @@ androidx-camera-lifecycle = { group = "androidx.camera", name = "camera-lifecycl
|
|||||||
androidx-camera-view = { group = "androidx.camera", name = "camera-view", version.ref = "camerax" }
|
androidx-camera-view = { group = "androidx.camera", name = "camera-view", version.ref = "camerax" }
|
||||||
androidx-datastore = { group = "androidx.datastore", name = "datastore" , version.ref = "datastore" }
|
androidx-datastore = { group = "androidx.datastore", name = "datastore" , version.ref = "datastore" }
|
||||||
androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences" , version.ref = "datastore" }
|
androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences" , version.ref = "datastore" }
|
||||||
|
androidx-documentfile = { group = "androidx.documentfile", name = "documentfile" , version.ref = "documentfile" }
|
||||||
protobuf-javalite = { group = "com.google.protobuf", name="protobuf-javalite", version.ref = "protobufJavaLite"}
|
protobuf-javalite = { group = "com.google.protobuf", name="protobuf-javalite", version.ref = "protobufJavaLite"}
|
||||||
litert = { group = "com.google.ai.edge.litert", name = "litert", version.ref = "litert" }
|
litert = { group = "com.google.ai.edge.litert", name = "litert", version.ref = "litert" }
|
||||||
litert-support = { group = "com.google.ai.edge.litert", name = "litert-support", version.ref = "litert" }
|
litert-support = { group = "com.google.ai.edge.litert", name = "litert-support", version.ref = "litert" }
|
||||||
|
|||||||
Reference in New Issue
Block a user