CameraScreen: improve UI for import
This commit is contained in:
@@ -123,6 +123,7 @@ class MainActivity : ComponentActivity() {
|
||||
val context = LocalContext.current
|
||||
val currentScreen by viewModel.currentScreen.collectAsStateWithLifecycle()
|
||||
val liveAnalysisState by cameraViewModel.liveAnalysisState.collectAsStateWithLifecycle()
|
||||
val importState by cameraViewModel.importState.collectAsStateWithLifecycle()
|
||||
val document by viewModel.documentUiModel.collectAsStateWithLifecycle()
|
||||
val documentUiState by viewModel.documentUiState.collectAsStateWithLifecycle()
|
||||
val exportUiState by exportViewModel.uiState.collectAsStateWithLifecycle()
|
||||
@@ -168,18 +169,20 @@ class MainActivity : ComponentActivity() {
|
||||
}
|
||||
is Screen.Main.Camera -> {
|
||||
val pickMultiple = rememberLauncherForActivityResult(
|
||||
ActivityResultContracts.PickMultipleVisualMedia(10)) { uris ->
|
||||
if (uris.isNotEmpty()) cameraViewModel.importPhotos(uris)
|
||||
ActivityResultContracts.PickMultipleVisualMedia(10)) {
|
||||
uris -> cameraViewModel.importPhotos(uris)
|
||||
}
|
||||
CameraScreen(
|
||||
viewModel,
|
||||
cameraViewModel,
|
||||
navigation,
|
||||
liveAnalysisState,
|
||||
importState,
|
||||
onImageAnalyzed = { image -> cameraViewModel.liveAnalysis(image) },
|
||||
onFinalizePressed = onExportClick,
|
||||
cameraPermission = cameraPermission,
|
||||
onImportClicked = {
|
||||
cameraViewModel.onImportClicked()
|
||||
pickMultiple.launch(PickVisualMediaRequest(
|
||||
ActivityResultContracts.PickVisualMedia.ImageOnly))
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
@@ -56,6 +57,7 @@ import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Card
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LinearProgressIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.Surface
|
||||
@@ -86,7 +88,9 @@ import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.platform.LocalConfiguration
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalResources
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Devices
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -124,6 +128,7 @@ fun CameraScreen(
|
||||
cameraViewModel: CameraViewModel,
|
||||
navigation: Navigation,
|
||||
liveAnalysisState: LiveAnalysisState,
|
||||
importState: ImportState,
|
||||
onImageAnalyzed: (ImageProxy) -> Unit,
|
||||
onFinalizePressed: () -> Unit,
|
||||
cameraPermission: CameraPermissionState,
|
||||
@@ -211,6 +216,7 @@ fun CameraScreen(
|
||||
document.pageCount(),
|
||||
liveAnalysisState,
|
||||
captureState,
|
||||
importState,
|
||||
showDetectionError,
|
||||
isLandscape = isLandscape,
|
||||
isDebugMode,
|
||||
@@ -286,7 +292,11 @@ private fun CameraScreenScaffold(
|
||||
onBack = navigation.back,
|
||||
bottomBar = { Bar(cameraUiState.pageCount, onFinalizePressed, onImportClicked) }
|
||||
) { modifier ->
|
||||
if (!isCameraPermissionGranted) {
|
||||
if (cameraUiState.importState is ImportState.Selecting) {
|
||||
// display nothing: photo picker is active
|
||||
} else if (cameraUiState.importState is ImportState.Importing) {
|
||||
ImportInProgress(cameraUiState.importState, modifier)
|
||||
} else if (!isCameraPermissionGranted) {
|
||||
CameraPermissionRationale(onRequestCameraPermission, modifier)
|
||||
} else {
|
||||
CameraPreviewBox(
|
||||
@@ -312,6 +322,43 @@ private fun CameraScreenScaffold(
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ImportInProgress(state: ImportState.Importing, modifier: Modifier) {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(Color.Black.copy(alpha = 0.6f)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().padding(32.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Text(
|
||||
text = LocalResources.current.getQuantityString(
|
||||
R.plurals.importing_photos,
|
||||
state.total,
|
||||
state.total
|
||||
),
|
||||
color = Color.White
|
||||
)
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
if (state.total > 1) {
|
||||
LinearProgressIndicator(
|
||||
progress = { state.processed.toFloat() / state.total },
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
} else {
|
||||
LinearProgressIndicator(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CameraPreviewBox(
|
||||
cameraPreview: @Composable (() -> Unit),
|
||||
@@ -540,10 +587,11 @@ private fun Bar(
|
||||
),
|
||||
border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary)
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.AddPhotoAlternate,
|
||||
// TODO Externalize string
|
||||
contentDescription = "Import photos",)
|
||||
Icon(Icons.Default.AddPhotoAlternate, contentDescription = null)
|
||||
Spacer(Modifier.width(4.dp))
|
||||
Text(stringResource(R.string.import_photos),
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis)
|
||||
}
|
||||
MainActionButton(
|
||||
onClick = onFinalizePressed,
|
||||
@@ -613,9 +661,16 @@ fun CameraScreenPreviewWithNoPermission() {
|
||||
ScreenPreview(CaptureState.Idle, isCameraPermissionGranted = false)
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun CameraScreenPreviewImporting() {
|
||||
ScreenPreview(CaptureState.Idle, ImportState.Importing(2, 3))
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ScreenPreview(
|
||||
captureState: CaptureState,
|
||||
importState: ImportState = ImportState.Idle,
|
||||
rotationDegrees: Float = 0f,
|
||||
isCameraPermissionGranted: Boolean = true,
|
||||
) {
|
||||
@@ -649,7 +704,7 @@ private fun ScreenPreview(
|
||||
showPageNumbers = false,
|
||||
),
|
||||
cameraUiState = CameraUiState(pageCount = 4, LiveAnalysisState(), captureState,
|
||||
false, rotationDegrees > 0, false, false),
|
||||
importState, false, rotationDegrees > 0, false, false),
|
||||
onCapture = {},
|
||||
onFinalizePressed = {},
|
||||
onDebugModeSwitched = {},
|
||||
|
||||
@@ -27,10 +27,17 @@ data class LiveAnalysisState(
|
||||
val stableQuad: Quad? = null,
|
||||
)
|
||||
|
||||
sealed class ImportState {
|
||||
object Idle : ImportState()
|
||||
object Selecting : ImportState()
|
||||
data class Importing(val processed: Int, val total: Int) : ImportState()
|
||||
}
|
||||
|
||||
data class CameraUiState(
|
||||
val pageCount: Int,
|
||||
val liveAnalysisState: LiveAnalysisState,
|
||||
val captureState: CaptureState,
|
||||
val importState: ImportState,
|
||||
val showDetectionError: Boolean,
|
||||
val isLandscape: Boolean,
|
||||
val isDebugMode: Boolean,
|
||||
|
||||
@@ -56,6 +56,9 @@ class CameraViewModel(appContainer: AppContainer): ViewModel() {
|
||||
private val _captureState = MutableStateFlow<CaptureState>(CaptureState.Idle)
|
||||
val captureState: StateFlow<CaptureState> = _captureState
|
||||
|
||||
private val _importState = MutableStateFlow<ImportState>(ImportState.Idle)
|
||||
val importState: StateFlow<ImportState> = _importState
|
||||
|
||||
private val _isTorchEnabled = MutableStateFlow(false)
|
||||
val isTorchEnabled: StateFlow<Boolean> = _isTorchEnabled
|
||||
|
||||
@@ -87,7 +90,7 @@ class CameraViewModel(appContainer: AppContainer): ViewModel() {
|
||||
}
|
||||
|
||||
fun liveAnalysis(imageProxy: ImageProxy) {
|
||||
if (_captureState.value !is CaptureState.Idle) {
|
||||
if (_captureState.value !is CaptureState.Idle || _importState.value !is ImportState.Idle) {
|
||||
imageProxy.close()
|
||||
return
|
||||
}
|
||||
@@ -188,16 +191,28 @@ class CameraViewModel(appContainer: AppContainer): ViewModel() {
|
||||
}
|
||||
|
||||
fun importPhotos(uris: List<Uri>) {
|
||||
if (uris.isEmpty()) {
|
||||
_importState.value = ImportState.Idle
|
||||
return
|
||||
}
|
||||
viewModelScope.launch {
|
||||
for (uri in uris) {
|
||||
_importState.value = ImportState.Importing(0, uris.size)
|
||||
uris.forEachIndexed { index, uri ->
|
||||
val photoToImport = imageLoader.load(uri)
|
||||
val page = processCapturedImage(photoToImport, 0)
|
||||
page?.let {
|
||||
_events.emit(CameraEvent.ImageCaptured(it))
|
||||
}
|
||||
_importState.value = ImportState.Importing(index + 1, uris.size)
|
||||
}
|
||||
_importState.value = ImportState.Idle
|
||||
}
|
||||
}
|
||||
|
||||
fun onImportClicked() {
|
||||
_importState.value = ImportState.Selecting
|
||||
resetLiveAnalysis()
|
||||
}
|
||||
}
|
||||
|
||||
sealed class CaptureState {
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">الحجم الكلي: %1$s</string>
|
||||
<string name="filename">اسم الملف</string>
|
||||
<string name="grant_permission">امنح الأذن</string>
|
||||
<string name="import_photos">استيراد</string>
|
||||
<string name="last_saved_pdf_files">ملفات PDF المحفوظة حديثًا على هذا الجهاز:</string>
|
||||
<string name="libraries">المكتبات</string>
|
||||
<string name="libraries_open_source">مكتبات مفتوحة المصدر</string>
|
||||
@@ -82,6 +83,14 @@
|
||||
<item quantity="many">حُفظ %1$d ملفًا في %3$s</item>
|
||||
<item quantity="other">حُفظ %1$d ملف في %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="zero">جارٍ استيراد 0 صورة</item>
|
||||
<item quantity="one">جارٍ استيراد صورة واحدة</item>
|
||||
<item quantity="two">جارٍ استيراد صورتين</item>
|
||||
<item quantity="few">جارٍ استيراد %d صور</item>
|
||||
<item quantity="many">جارٍ استيراد %d صورة</item>
|
||||
<item quantity="other">جارٍ استيراد %d صورة</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="zero">لا صفحات</item>
|
||||
<item quantity="one">%d صفحة</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Celková velikost: %1$s</string>
|
||||
<string name="filename">Název souboru</string>
|
||||
<string name="grant_permission">Povolit přístup</string>
|
||||
<string name="import_photos">Import</string>
|
||||
<string name="last_saved_pdf_files">Poslední PDF uložené v tomto zařízení:</string>
|
||||
<string name="libraries">Kníhovny</string>
|
||||
<string name="libraries_open_source">Open-source knihovny</string>
|
||||
@@ -80,6 +81,12 @@
|
||||
<item quantity="many">%1$d souborů uloženo do %3$s</item>
|
||||
<item quantity="other">%1$d souborů uloženo do %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="one">Importování 1 fotografie</item>
|
||||
<item quantity="few">Importování %d fotografií</item>
|
||||
<item quantity="many">Importování %d fotografií</item>
|
||||
<item quantity="other">Importování %d fotografií</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="one">%d stránka</item> <!-- 1 -->
|
||||
<item quantity="few">%d stránky</item> <!-- 2–4 -->
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Gesamtgröße: %1$s</string>
|
||||
<string name="filename">Dateiname</string>
|
||||
<string name="grant_permission">Berechtigung erteilen</string>
|
||||
<string name="import_photos">Importieren</string>
|
||||
<string name="last_saved_pdf_files">Zuletzt auf diesem Gerät gespeicherte PDFs:</string>
|
||||
<string name="libraries">Bibliotheken</string>
|
||||
<string name="libraries_open_source">Open-Source-Bibliotheken</string>
|
||||
@@ -78,6 +79,10 @@
|
||||
<item quantity="one">%2$s gespeichert in %3$s</item>
|
||||
<item quantity="other">%1$d Dateien gespeichert in %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="one">1 Foto wird importiert</item>
|
||||
<item quantity="other">%d Fotos werden importiert</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="one">%d Seite</item>
|
||||
<item quantity="other">%d Seiten</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Tamaño total: %1$s</string>
|
||||
<string name="filename">Nombre del archivo</string>
|
||||
<string name="grant_permission">Conceder permiso</string>
|
||||
<string name="import_photos">Importar</string>
|
||||
<string name="last_saved_pdf_files">PDF recientes guardados en este dispositivo:</string>
|
||||
<string name="libraries">Bibliotecas</string>
|
||||
<string name="libraries_open_source">Bibliotecas de código abierto</string>
|
||||
@@ -78,6 +79,10 @@
|
||||
<item quantity="one">%2$s guardado en %3$s</item>
|
||||
<item quantity="other">%1$d archivos guardados en %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">Importando 1 foto</item>
|
||||
<item quantity="other">Importando %d fotos</item>
|
||||
</plurals>
|
||||
<plurals name="page_count" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">%d página</item>
|
||||
<item quantity="other">%d páginas</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Taille totale : %1$s</string>
|
||||
<string name="filename">Nom de fichier</string>
|
||||
<string name="grant_permission">Autoriser</string>
|
||||
<string name="import_photos">Importer</string>
|
||||
<string name="last_saved_pdf_files">Derniers PDF enregistrés sur l’appareil :</string>
|
||||
<string name="libraries">Bibliothèques</string>
|
||||
<string name="libraries_open_source">Bibliothèques open source</string>
|
||||
@@ -78,6 +79,10 @@
|
||||
<item quantity="one">%2$s enregistré dans %3$s</item>
|
||||
<item quantity="other">%1$d fichiers enregistrés dans %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">Import de %d photo</item>
|
||||
<item quantity="other">Import de %d photos</item>
|
||||
</plurals>
|
||||
<plurals name="page_count" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">%d page</item>
|
||||
<item quantity="other">%d pages</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Tamaño total: %1$s</string>
|
||||
<string name="filename">Nome do ficheiro</string>
|
||||
<string name="grant_permission">Conceder permiso</string>
|
||||
<string name="import_photos">Importar</string>
|
||||
<string name="last_saved_pdf_files">PDF recentes gardados neste dispositivo:</string>
|
||||
<string name="libraries">Bibliotecas</string>
|
||||
<string name="libraries_open_source">Bibliotecas de código aberto</string>
|
||||
@@ -78,6 +79,10 @@
|
||||
<item quantity="one">%2$s gardado en %3$s</item>
|
||||
<item quantity="other">%1$d ficheiros gardados en %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="one">Importando 1 foto</item>
|
||||
<item quantity="other">Importando %d fotos</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="one">%d páxina</item>
|
||||
<item quantity="other">%d páxinas</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Dimensione totale: %1$s</string>
|
||||
<string name="filename">Nome file</string>
|
||||
<string name="grant_permission">Concendi autorizzazione</string>
|
||||
<string name="import_photos">Importa</string>
|
||||
<string name="last_saved_pdf_files">PDF recenti salvati su questo dispositivo:</string>
|
||||
<string name="libraries">Librerie</string>
|
||||
<string name="libraries_open_source">Librerie open source</string>
|
||||
@@ -78,6 +79,10 @@
|
||||
<item quantity="one">%2$s salvato in %3$s</item>
|
||||
<item quantity="other">%1$d file salvati in %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">Importazione di 1 foto</item>
|
||||
<item quantity="other">Importazione di %d foto</item>
|
||||
</plurals>
|
||||
<plurals name="page_count" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">%d pagina</item>
|
||||
<item quantity="other">%d pagine</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Tamanho total: %1$s</string>
|
||||
<string name="filename">Nome do arquivo</string>
|
||||
<string name="grant_permission">Conceder permissão</string>
|
||||
<string name="import_photos">Importar</string>
|
||||
<string name="last_saved_pdf_files">PDFs recentes salvos neste dispositivo:</string>
|
||||
<string name="libraries">Bibliotecas</string>
|
||||
<string name="libraries_open_source">Bibliotecas de código aberto</string>
|
||||
@@ -78,6 +79,10 @@
|
||||
<item quantity="one">%2$s salvo em %3$s</item>
|
||||
<item quantity="other">%1$d arquivos salvos em %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">Importando %d foto</item>
|
||||
<item quantity="other">Importando %d fotos</item>
|
||||
</plurals>
|
||||
<plurals name="page_count" tools:ignore="MissingQuantity">
|
||||
<item quantity="one">%d página</item>
|
||||
<item quantity="other">%d páginas</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Общий размер: %1$s</string>
|
||||
<string name="filename">Имя файла</string>
|
||||
<string name="grant_permission">Предоставить разрешение</string>
|
||||
<string name="import_photos">Импорт</string>
|
||||
<string name="last_saved_pdf_files">Последние PDF, сохранённые на этом устройстве:</string>
|
||||
<string name="libraries">Библиотеки</string>
|
||||
<string name="libraries_open_source">Библиотеки с открытым исходным кодом</string>
|
||||
@@ -80,6 +81,12 @@
|
||||
<item quantity="many">%1$d файлов сохранено в %3$s</item>
|
||||
<item quantity="other">%1$d файла сохранено в %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="one">Импорт %d фото</item>
|
||||
<item quantity="few">Импорт %d фото</item>
|
||||
<item quantity="many">Импорт %d фото</item>
|
||||
<item quantity="other">Импорт %d фото</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="one">%d страница</item>
|
||||
<item quantity="few">%d страницы</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">Toplam boyut: %1$s</string>
|
||||
<string name="filename">Dosya adı</string>
|
||||
<string name="grant_permission">İzin ver</string>
|
||||
<string name="import_photos">İçe aktar</string>
|
||||
<string name="last_saved_pdf_files">Bu cihaza kaydedilen son PDF\'ler:</string>
|
||||
<string name="libraries">Kütüphaneler</string>
|
||||
<string name="libraries_open_source">Açık kaynaklı kütüphaneler</string>
|
||||
@@ -78,6 +79,10 @@
|
||||
<item quantity="one">%2$s, %3$s konumuna kaydedildi</item>
|
||||
<item quantity="other">%1$d dosya %3$s konumuna kaydedildi</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="one">1 foto içe aktarılıyor</item>
|
||||
<item quantity="other">%d foto içe aktarılıyor</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="one">%d sayfa</item>
|
||||
<item quantity="other">%d sayfa</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">總計大小:%1$s</string>
|
||||
<string name="filename">檔案名稱</string>
|
||||
<string name="grant_permission">授予權限</string>
|
||||
<string name="import_photos">匯入</string>
|
||||
<string name="last_saved_pdf_files">此裝置上最近儲存的 PDF:</string>
|
||||
<string name="libraries">函式庫</string>
|
||||
<string name="libraries_open_source">開放原始碼函式庫</string>
|
||||
@@ -78,6 +79,9 @@
|
||||
<item quantity="one">%2$s 已儲存至 %3$s</item>
|
||||
<item quantity="other">%1$d 個檔案已儲存至 %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="other">正在匯入 %d 張照片</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="one">%d 頁</item>
|
||||
<item quantity="other">%d 頁</item>
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
<string name="file_size_total">总大小:%1$s</string>
|
||||
<string name="filename">文件名字</string>
|
||||
<string name="grant_permission">授予权限</string>
|
||||
<string name="import_photos">导入</string>
|
||||
<string name="last_saved_pdf_files">最近保存在此设备上的 PDF:</string>
|
||||
<string name="libraries">库</string>
|
||||
<string name="libraries_open_source">开源库</string>
|
||||
@@ -77,6 +78,9 @@
|
||||
<plurals name="files_saved_to">
|
||||
<item quantity="other">%1$d 个文件已保存到 %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="other">正在导入 %d 张照片</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="other">%d 页</item>
|
||||
</plurals>
|
||||
|
||||
@@ -47,6 +47,7 @@
|
||||
<string name="file_size_total">Total size: %1$s</string>
|
||||
<string name="filename">Filename</string>
|
||||
<string name="grant_permission">Grant permission</string>
|
||||
<string name="import_photos">Import</string>
|
||||
<string name="last_saved_pdf_files">Recent PDFs saved on this device:</string>
|
||||
<string name="libraries">Libraries</string>
|
||||
<string name="libraries_open_source">Open-source libraries</string>
|
||||
@@ -82,6 +83,10 @@
|
||||
<item quantity="one">%2$s saved to %3$s</item>
|
||||
<item quantity="other">%1$d files saved to %3$s</item>
|
||||
</plurals>
|
||||
<plurals name="importing_photos">
|
||||
<item quantity="one">Importing 1 photo</item>
|
||||
<item quantity="other">Importing %d photos</item>
|
||||
</plurals>
|
||||
<plurals name="page_count">
|
||||
<item quantity="one">%d page</item>
|
||||
<item quantity="other">%d pages</item>
|
||||
|
||||
Reference in New Issue
Block a user