New languages (#256)

* Remove custom-onnxruntime-arm64.aar

* Refactor remaining, hardcoded UI strings into localizable resources and added French and Russian to language list

* Fix background auto-advance for Text-to-Speech (TTS)
This commit is contained in:
Aryan 2026-04-29 18:35:23 +05:30 committed by GitHub
parent 224d12d1fb
commit 4582b506f3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 940 additions and 488 deletions

View file

@ -395,7 +395,7 @@ fun PenPlayground(onClose: () -> Unit) {
painter = painterResource(
id = R.drawable.close
),
contentDescription = "Close", tint = Color.Gray
contentDescription = stringResource(R.string.action_close), tint = Color.Gray
)
}
}
@ -505,4 +505,4 @@ fun PenPlayground(onClose: () -> Unit) {
Spacer(Modifier.height(16.dp))
}
}
}
}

View file

@ -138,7 +138,7 @@ internal fun OcrLanguageSelectionDialog(
) {
RadioButton(selected = (language == currentLanguage), onClick = null)
Text(
text = language.displayName,
text = stringResource(language.displayNameRes),
style = MaterialTheme.typography.bodyLarge,
modifier = Modifier.padding(start = 16.dp)
)
@ -146,4 +146,4 @@ internal fun OcrLanguageSelectionDialog(
}
}
}, confirmButton = { TextButton(onClick = onDismiss) { Text(stringResource(R.string.action_cancel)) } })
}
}

View file

@ -60,12 +60,14 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.aryan.reader.R
import io.legere.pdfiumandroid.api.Bookmark
import io.legere.pdfiumandroid.suspend.PdfDocumentKt
import kotlinx.coroutines.delay
@ -255,7 +257,9 @@ internal fun PdfTocTreeItem(
if (hasChildren) {
Icon(
imageVector = if (isExpanded) Icons.Default.KeyboardArrowDown else Icons.AutoMirrored.Filled.KeyboardArrowRight,
contentDescription = if (isExpanded) "Collapse" else "Expand",
contentDescription = stringResource(
if (isExpanded) R.string.content_desc_collapse else R.string.content_desc_expand
),
tint = MaterialTheme.colorScheme.onSurfaceVariant
)
}
@ -301,13 +305,13 @@ internal fun PdfNavigationDrawerContent(
) {
Tab(selected = drawerPagerState.currentPage == 0, onClick = {
drawerScope.launch { drawerPagerState.animateScrollToPage(0) }
}, text = { Text("Chapters") })
}, text = { Text(stringResource(R.string.tab_chapters)) })
Tab(
selected = drawerPagerState.currentPage == 1,
onClick = {
drawerScope.launch { drawerPagerState.animateScrollToPage(1) }
},
text = { Text("Bookmarks") },
text = { Text(stringResource(R.string.tab_bookmarks)) },
modifier = Modifier.testTag("BookmarksTab")
)
Tab(
@ -315,7 +319,7 @@ internal fun PdfNavigationDrawerContent(
onClick = {
drawerScope.launch { drawerPagerState.animateScrollToPage(2) }
},
text = { Text("Highlights") },
text = { Text(stringResource(R.string.tab_highlights)) },
modifier = Modifier.testTag("HighlightsTab")
)
Tab(
@ -323,7 +327,7 @@ internal fun PdfNavigationDrawerContent(
onClick = {
drawerScope.launch { drawerPagerState.animateScrollToPage(3) }
},
text = { Text("Pages") },
text = { Text(stringResource(R.string.tab_pages)) },
modifier = Modifier.testTag("PagesTab")
)
}
@ -340,7 +344,7 @@ internal fun PdfNavigationDrawerContent(
contentAlignment = Alignment.Center
) {
Text(
"Chapters are not available for this book.",
stringResource(R.string.msg_chapters_not_available),
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
@ -434,13 +438,13 @@ internal fun PdfNavigationDrawerContent(
horizontalArrangement = Arrangement.SpaceEvenly
) {
TextButton(onClick = { expandedEntryIndices = flatTableOfContents.indices.toSet() }) {
Text("Expand All")
Text(stringResource(R.string.action_expand_all))
}
TextButton(onClick = { expandedEntryIndices = emptySet() }) {
Text("Collapse All")
Text(stringResource(R.string.action_collapse_all))
}
TextButton(onClick = onScrollToCurrent) {
Text("Locate")
Text(stringResource(R.string.action_locate))
}
}
@ -503,7 +507,7 @@ internal fun PdfNavigationDrawerContent(
contentAlignment = Alignment.Center
) {
Text(
"You haven't added any bookmarks yet.",
stringResource(R.string.no_bookmarks_yet),
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
@ -531,7 +535,7 @@ internal fun PdfNavigationDrawerContent(
)
}, supportingContent = {
Text(
"Page ${bookmark.pageIndex + 1} of ${bookmark.totalPages}",
stringResource(R.string.page_of_pages, bookmark.pageIndex + 1, bookmark.totalPages),
style = MaterialTheme.typography.bodySmall
)
}, trailingContent = {
@ -542,7 +546,7 @@ internal fun PdfNavigationDrawerContent(
}) {
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = "More options for bookmark"
contentDescription = stringResource(R.string.content_desc_more_options_bookmark)
)
}
DropdownMenu(
@ -551,13 +555,13 @@ internal fun PdfNavigationDrawerContent(
bookmarkMenuExpandedFor = null
}) {
DropdownMenuItem(text = {
Text("Rename")
Text(stringResource(R.string.action_rename))
}, onClick = {
showRenameBookmarkDialog = bookmark
bookmarkMenuExpandedFor = null
})
DropdownMenuItem(text = {
Text("Delete")
Text(stringResource(R.string.action_delete))
}, onClick = {
showDeleteConfirmDialogFor = bookmark
bookmarkMenuExpandedFor = null
@ -581,11 +585,11 @@ internal fun PdfNavigationDrawerContent(
AlertDialog(onDismissRequest = {
showRenameBookmarkDialog = null
}, title = { Text("Rename Bookmark") }, text = {
}, title = { Text(stringResource(R.string.dialog_rename_bookmark)) }, text = {
OutlinedTextField(
value = newTitle,
onValueChange = { newTitle = it },
label = { Text("New Title") },
label = { Text(stringResource(R.string.label_new_title)) },
placeholder = {
Text(
text = bookmarkToRename.title,
@ -605,33 +609,33 @@ internal fun PdfNavigationDrawerContent(
onClick = {
onRenameBookmark(bookmarkToRename, newTitle)
showRenameBookmarkDialog = null
}) { Text("Save") }
}) { Text(stringResource(R.string.action_save)) }
}, dismissButton = {
TextButton(
onClick = {
showRenameBookmarkDialog = null
}) { Text("Cancel") }
}) { Text(stringResource(R.string.action_cancel)) }
})
}
showDeleteConfirmDialogFor?.let { bookmarkToDelete ->
AlertDialog(onDismissRequest = {
showDeleteConfirmDialogFor = null
}, title = { Text("Delete Bookmark?") }, text = {
}, title = { Text(stringResource(R.string.dialog_delete_bookmark)) }, text = {
Text(
"Are you sure you want to permanently delete this bookmark?"
stringResource(R.string.dialog_delete_bookmark_desc)
)
}, confirmButton = {
TextButton(
onClick = {
onDeleteBookmark(bookmarkToDelete)
showDeleteConfirmDialogFor = null
}) { Text("Delete") }
}) { Text(stringResource(R.string.action_delete)) }
}, dismissButton = {
TextButton(
onClick = {
showDeleteConfirmDialogFor = null
}) { Text("Cancel") }
}) { Text(stringResource(R.string.action_cancel)) }
})
}
}
@ -645,7 +649,7 @@ internal fun PdfNavigationDrawerContent(
contentAlignment = Alignment.Center
) {
Text(
"You haven't added any highlights yet.",
stringResource(R.string.no_highlights_yet),
style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center
)
@ -662,12 +666,12 @@ internal fun PdfNavigationDrawerContent(
FilterChip(
selected = !filterWithNotesOnly,
onClick = { filterWithNotesOnly = false },
label = { Text("All") }
label = { Text(stringResource(R.string.read_status_all)) }
)
FilterChip(
selected = filterWithNotesOnly,
onClick = { filterWithNotesOnly = true },
label = { Text("With Notes") }
label = { Text(stringResource(R.string.filter_with_notes)) }
)
}
@ -689,7 +693,7 @@ internal fun PdfNavigationDrawerContent(
ListItem(
headlineContent = {
Text(
text = highlight.text.ifBlank { "Highlighted section" },
text = highlight.text.ifBlank { stringResource(R.string.msg_highlighted_section_default) },
maxLines = 2,
overflow = TextOverflow.Ellipsis,
fontWeight = FontWeight.SemiBold
@ -707,7 +711,7 @@ internal fun PdfNavigationDrawerContent(
)
Spacer(Modifier.width(8.dp))
Text(
"Page ${highlight.pageIndex + 1}",
stringResource(R.string.pdf_page_short, highlight.pageIndex + 1),
style = MaterialTheme.typography.labelMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
@ -733,14 +737,20 @@ internal fun PdfNavigationDrawerContent(
Box {
var highlightMenuExpanded by remember { mutableStateOf(false) }
IconButton(onClick = { highlightMenuExpanded = true }) {
Icon(Icons.Default.MoreVert, contentDescription = "Options")
Icon(Icons.Default.MoreVert, contentDescription = stringResource(R.string.content_desc_options))
}
DropdownMenu(
expanded = highlightMenuExpanded,
onDismissRequest = { highlightMenuExpanded = false }
) {
DropdownMenuItem(
text = { Text(if (highlight.note.isNullOrBlank()) "Add Note" else "Edit Note") },
text = {
Text(
stringResource(
if (highlight.note.isNullOrBlank()) R.string.menu_add_note else R.string.menu_edit_note
)
)
},
onClick = {
onNoteRequested(highlight.id)
highlightMenuExpanded = false
@ -748,7 +758,7 @@ internal fun PdfNavigationDrawerContent(
}
)
DropdownMenuItem(
text = { Text("Delete") },
text = { Text(stringResource(R.string.action_delete)) },
onClick = {
showDeleteConfirmDialogFor = highlight
highlightMenuExpanded = false
@ -770,20 +780,20 @@ internal fun PdfNavigationDrawerContent(
showDeleteConfirmDialogFor?.let { highlightToDelete ->
AlertDialog(
onDismissRequest = { showDeleteConfirmDialogFor = null },
title = { Text("Delete Highlight?") },
text = { Text("Are you sure you want to permanently delete this highlight?") },
title = { Text(stringResource(R.string.dialog_delete_highlight)) },
text = { Text(stringResource(R.string.dialog_delete_highlight_desc)) },
confirmButton = {
TextButton(
onClick = {
onDeleteHighlight(highlightToDelete)
showDeleteConfirmDialogFor = null
}
) { Text("Delete") }
) { Text(stringResource(R.string.action_delete)) }
},
dismissButton = {
TextButton(
onClick = { showDeleteConfirmDialogFor = null }
) { Text("Cancel") }
) { Text(stringResource(R.string.action_cancel)) }
}
)
}
@ -809,7 +819,7 @@ internal fun PdfNavigationDrawerContent(
}
}
) {
Text("Locate")
Text(stringResource(R.string.action_locate))
}
}
@ -880,7 +890,7 @@ internal fun PdfNavigationDrawerContent(
if (thumb != null) {
Image(
bitmap = thumb!!.asImageBitmap(),
contentDescription = "Page ${pageIdx + 1}",
contentDescription = stringResource(R.string.pdf_page_short, pageIdx + 1),
modifier = Modifier.fillMaxSize()
)
}
@ -916,4 +926,4 @@ internal fun PdfNavigationDrawerContent(
}
}
}
}
}

View file

@ -22,6 +22,7 @@ package com.aryan.reader.pdf
import android.graphics.Bitmap
import android.graphics.Rect
import android.graphics.RectF
import androidx.annotation.StringRes
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@ -78,7 +79,9 @@ import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.luminance
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@ -95,12 +98,12 @@ import com.aryan.reader.pdf.ocr.OcrSymbol
import timber.log.Timber
import java.util.UUID
enum class OcrLanguage(val displayName: String) {
LATIN("English, Spanish, French, etc."),
DEVANAGARI("Hindi, Marathi, Sanskrit + English"),
CHINESE("Chinese + English"),
JAPANESE("Japanese + English"),
KOREAN("Korean + English")
enum class OcrLanguage(@StringRes val displayNameRes: Int) {
LATIN(R.string.ocr_language_latin),
DEVANAGARI(R.string.ocr_language_devanagari),
CHINESE(R.string.ocr_language_chinese),
JAPANESE(R.string.ocr_language_japanese),
KOREAN(R.string.ocr_language_korean)
}
internal data class OcrSymbolInfo(
@ -232,6 +235,8 @@ internal fun PdfSelectionMenuPopup(
onTts: (() -> Unit)? = null,
onNote: (() -> Unit)? = null
) {
val context = LocalContext.current
Popup(
popupPositionProvider = popupPositionProvider,
onDismissRequest = onDismiss,
@ -266,7 +271,7 @@ internal fun PdfSelectionMenuPopup(
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(
imageVector = Icons.Default.Edit,
contentDescription = "Note",
contentDescription = stringResource(R.string.label_note),
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(14.dp)
)
@ -321,7 +326,7 @@ internal fun PdfSelectionMenuPopup(
) {
Icon(Icons.Default.CopyAll, contentDescription = null, modifier = Modifier.size(18.dp))
Spacer(Modifier.width(8.dp))
Text("Copy Thread")
Text(stringResource(R.string.action_copy_thread))
}
} else {
Row(
@ -360,23 +365,23 @@ internal fun PdfSelectionMenuPopup(
HorizontalDivider()
val actions = mutableListOf<MenuActionItem>()
actions.add(MenuActionItem(iconRes = R.drawable.copy, label = "Copy", onClick = { onCopy(menuState.selectedText) }))
actions.add(MenuActionItem(iconRes = R.drawable.copy, label = context.getString(R.string.action_copy), onClick = { onCopy(menuState.selectedText) }))
if (onTts != null) {
actions.add(MenuActionItem(imageVector = Icons.AutoMirrored.Filled.VolumeUp, label = "Speak", onClick = onTts))
actions.add(MenuActionItem(imageVector = Icons.AutoMirrored.Filled.VolumeUp, label = context.getString(R.string.label_speak), onClick = onTts))
}
if (menuState.selectedText.length <= 2000) {
actions.add(MenuActionItem(iconRes = R.drawable.dictionary, label = "Dict", onClick = { onAiDefine(menuState.selectedText) }))
actions.add(MenuActionItem(iconRes = R.drawable.translate, label = "Translate", onClick = { onTranslate(menuState.selectedText) }))
actions.add(MenuActionItem(imageVector = Icons.Default.Search, label = "Search", onClick = { onSearch(menuState.selectedText) }))
actions.add(MenuActionItem(iconRes = R.drawable.dictionary, label = context.getString(R.string.label_dict), onClick = { onAiDefine(menuState.selectedText) }))
actions.add(MenuActionItem(iconRes = R.drawable.translate, label = context.getString(R.string.action_translate), onClick = { onTranslate(menuState.selectedText) }))
actions.add(MenuActionItem(imageVector = Icons.Default.Search, label = context.getString(R.string.action_search), onClick = { onSearch(menuState.selectedText) }))
}
if (onNote != null) {
val noteLabel = if (menuState.note.isNullOrBlank()) "Note" else "Edit"
val noteLabel = context.getString(if (menuState.note.isNullOrBlank()) R.string.label_note else R.string.label_edit)
actions.add(MenuActionItem(imageVector = Icons.Default.Edit, label = noteLabel, onClick = onNote))
}
if (!menuState.isExistingHighlight) {
actions.add(MenuActionItem(iconRes = R.drawable.select_all, label = "Select All", onClick = { onSelectAll() }))
actions.add(MenuActionItem(iconRes = R.drawable.select_all, label = context.getString(R.string.select_all), onClick = { onSelectAll() }))
}
if (menuState.isExistingHighlight) {
actions.add(MenuActionItem(imageVector = Icons.Default.Delete, label = "Remove", onClick = { onDelete() }, isError = true))
@ -659,7 +664,7 @@ fun PdfHighlightColorRow(
if (selectedColor == colorEnum) {
Icon(
imageVector = Icons.Default.Check,
contentDescription = "Selected",
contentDescription = stringResource(R.string.content_desc_selected),
tint = if (displayColor.luminance() > 0.5f) Color.Black else Color.White,
modifier = Modifier.size(18.dp)
)
@ -752,10 +757,10 @@ fun PdfAnnotationBottomSheet(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceEvenly
) {
PdfBottomSheetToolButton(icon = R.drawable.copy, label = "Copy", effectiveText = effectiveText, onClick = onCopy)
PdfBottomSheetToolButton(icon = R.drawable.dictionary, label = "Dict", effectiveText = effectiveText, onClick = onDictionary)
PdfBottomSheetToolButton(icon = R.drawable.translate, label = "Translate", effectiveText = effectiveText, onClick = onTranslate)
PdfBottomSheetToolButton(icon = R.drawable.search, label = "Search", effectiveText = effectiveText, onClick = onSearch)
PdfBottomSheetToolButton(icon = R.drawable.copy, label = stringResource(R.string.action_copy), effectiveText = effectiveText, onClick = onCopy)
PdfBottomSheetToolButton(icon = R.drawable.dictionary, label = stringResource(R.string.label_dict), effectiveText = effectiveText, onClick = onDictionary)
PdfBottomSheetToolButton(icon = R.drawable.translate, label = stringResource(R.string.action_translate), effectiveText = effectiveText, onClick = onTranslate)
PdfBottomSheetToolButton(icon = R.drawable.search, label = stringResource(R.string.action_search), effectiveText = effectiveText, onClick = onSearch)
}
Spacer(Modifier.height(16.dp))
@ -763,7 +768,7 @@ fun PdfAnnotationBottomSheet(
OutlinedTextField(
value = noteText,
onValueChange = { noteText = it },
placeholder = { Text("Add a note...", color = effectiveText.copy(alpha = 0.5f)) },
placeholder = { Text(stringResource(R.string.placeholder_add_note), color = effectiveText.copy(alpha = 0.5f)) },
modifier = Modifier.fillMaxWidth().heightIn(min = 100.dp),
maxLines = 5,
colors = OutlinedTextFieldDefaults.colors(
@ -793,7 +798,7 @@ fun PdfAnnotationBottomSheet(
) {
Icon(Icons.Default.Delete, contentDescription = null, modifier = Modifier.size(18.dp))
Spacer(Modifier.width(8.dp))
Text("Delete")
Text(stringResource(R.string.action_delete))
}
Button(
onClick = { onSave(noteText) },
@ -802,7 +807,7 @@ fun PdfAnnotationBottomSheet(
contentColor = MaterialTheme.colorScheme.onPrimary
)
) {
Text("Save Note")
Text(stringResource(R.string.action_save_note))
}
}
}
@ -833,4 +838,4 @@ private fun PdfBottomSheetToolButton(
color = effectiveText.copy(alpha = 0.8f)
)
}
}
}

View file

@ -44,6 +44,7 @@ import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
@ -199,7 +200,7 @@ internal fun ThumbnailWithIndicator(
) {
Image(
bitmap = thumbnail.asImageBitmap(),
contentDescription = "Start page thumbnail",
contentDescription = stringResource(R.string.content_desc_start_page_thumbnail),
contentScale = ContentScale.FillBounds,
modifier = Modifier.fillMaxSize()
)
@ -230,7 +231,7 @@ internal fun BookmarkButton(
AnimatedVisibility(visible = isBookmarked, enter = fadeIn(), exit = fadeOut()) {
Icon(
painter = painterResource(id = R.drawable.bookmark),
contentDescription = "Bookmark",
contentDescription = stringResource(R.string.content_desc_bookmark),
modifier = Modifier.size(24.dp),
tint = MaterialTheme.colorScheme.primary
)
@ -271,7 +272,7 @@ internal fun ZoomPercentageIndicator(
// Reset Zoom Button
Icon(
painter = painterResource(id = R.drawable.zoom_out),
contentDescription = "Reset Zoom",
contentDescription = stringResource(R.string.content_desc_reset_zoom),
tint = Color.White,
modifier = Modifier
.size(20.dp)
@ -280,4 +281,4 @@ internal fun ZoomPercentageIndicator(
)
}
}
}
}

View file

@ -32,6 +32,7 @@ import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
@ -73,7 +74,7 @@ internal fun SearchNavigationPill(
Icon(
imageVector = if (mode == SearchHighlightMode.ALL) Icons.Default.Visibility
else Icons.Default.VisibilityOff,
contentDescription = "Toggle Highlights",
contentDescription = stringResource(R.string.content_desc_toggle_search_highlights),
tint = if (mode == SearchHighlightMode.ALL) MaterialTheme.colorScheme.primary
else MaterialTheme.colorScheme.onSurfaceVariant
)
@ -95,7 +96,7 @@ internal fun SearchNavigationPill(
IconButton(onClick = onPrev, enabled = isPrevEnabled) {
Icon(
imageVector = Icons.Default.KeyboardArrowUp,
contentDescription = "Previous",
contentDescription = stringResource(R.string.tooltip_prev_result),
tint = if (isPrevEnabled) MaterialTheme.colorScheme.onSurface
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)
)
@ -122,7 +123,7 @@ internal fun SearchNavigationPill(
IconButton(onClick = onNext, enabled = isNextEnabled) {
Icon(
imageVector = Icons.Default.KeyboardArrowDown,
contentDescription = "Next",
contentDescription = stringResource(R.string.tooltip_next_result),
tint = if (isNextEnabled) MaterialTheme.colorScheme.onSurface
else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.38f)
)
@ -141,12 +142,12 @@ fun PdfSearchResultsPanel(
Surface(modifier = modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
if (lazyResults.itemCount == 0 && lazyResults.loadState.refresh !is LoadState.Loading) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text("No results found.", style = MaterialTheme.typography.bodyLarge)
Text(stringResource(R.string.search_no_results_simple), style = MaterialTheme.typography.bodyLarge)
}
} else {
Column {
Text(
text = stringResource(R.string.msg_results_found_pages),
text = stringResource(R.string.msg_results_found_pages, totalPageCount),
style = MaterialTheme.typography.titleSmall,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)
)
@ -195,6 +196,7 @@ fun PdfSearchResultsList(
onResultClick: (SearchResult) -> Unit,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
Surface(modifier = modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
if (results.isEmpty()) {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
@ -203,7 +205,11 @@ fun PdfSearchResultsList(
} else {
Column {
Text(
text = "${results.size} matches found",
text = context.resources.getQuantityString(
R.plurals.search_matches_count,
results.size,
results.size
),
style = MaterialTheme.typography.titleSmall,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp)
)
@ -233,4 +239,4 @@ fun PdfSearchResultsList(
}
}
}
}
}

View file

@ -61,6 +61,7 @@ import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.input.pointer.positionChanged
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
@ -450,9 +451,9 @@ private fun DragPill(
Box(contentAlignment = Alignment.Center) {
Icon(
painter = painterResource(id = R.drawable.drag_handle),
contentDescription = "Drag to move text box",
contentDescription = stringResource(R.string.content_desc_drag_text_box),
modifier = Modifier.size((20f / scale).dp)
)
}
}
}
}

View file

@ -136,14 +136,14 @@ internal fun PdfTopBar(
description = stringResource(R.string.tooltip_back_desc),
onClick = onNavigateBack
) {
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = stringResource(R.string.action_back))
}
val titleText = when {
isLoadingDocument -> stringResource(R.string.loading_pdf)
errorMessage != null -> stringResource(R.string.error_loading_pdf)
totalPages > 0 && pagerStatePageCount > 0 -> "Page ${currentPageForDisplay + 1} of $totalPages"
totalPages > 0 && pagerStatePageCount > 0 -> stringResource(R.string.page_of_pages, currentPageForDisplay + 1, totalPages)
totalPages > 0 && pagerStatePageCount == 0 -> stringResource(R.string.loading_page)
else -> "PDF Viewer"
else -> stringResource(R.string.pdf_viewer)
}
Text(
text = titleText,
@ -179,16 +179,16 @@ internal fun PdfTopBar(
description = stringResource(R.string.tooltip_dictionary_desc),
onClick = onShowDictionarySettings
) {
Icon(painterResource(id = R.drawable.dictionary), contentDescription = "Dictionary Settings", tint = MaterialTheme.colorScheme.onSurfaceVariant)
Icon(painterResource(id = R.drawable.dictionary), contentDescription = stringResource(R.string.content_desc_dictionary_settings), tint = MaterialTheme.colorScheme.onSurfaceVariant)
}
}
if (BuildConfig.DEBUG) {
TooltipIconButton(text = "Demo Annotations", onClick = onGenerateDemoAnnotations) {
Icon(Icons.Default.BugReport, contentDescription = "Generate Demo Annotations", tint = MaterialTheme.colorScheme.secondary)
TooltipIconButton(text = stringResource(R.string.tooltip_demo_annotations), onClick = onGenerateDemoAnnotations) {
Icon(Icons.Default.BugReport, contentDescription = stringResource(R.string.content_desc_generate_demo_annotations), tint = MaterialTheme.colorScheme.secondary)
}
TooltipIconButton(text = stringResource(R.string.pen_playground), onClick = onShowPenPlayground) {
Icon(Icons.Default.Star, contentDescription = "Open Pen Playground", tint = MaterialTheme.colorScheme.primary)
Icon(Icons.Default.Star, contentDescription = stringResource(R.string.content_desc_open_pen_playground), tint = MaterialTheme.colorScheme.primary)
}
TooltipIconButton(text = stringResource(R.string.import_svg), onClick = onImportSvg) {
Icon(Icons.Default.Brush, contentDescription = stringResource(R.string.import_svg), tint = Color(0xFFE91E63))
@ -392,7 +392,7 @@ internal fun PdfTopBar(
item {
IconButton(onClick = onNewTabClick, modifier = Modifier.padding(start = 8.dp, bottom = 4.dp).size(36.dp)) {
Icon(Icons.Default.Add, contentDescription = "New Tab", tint = MaterialTheme.colorScheme.onSurfaceVariant)
Icon(Icons.Default.Add, contentDescription = stringResource(R.string.content_desc_new_tab), tint = MaterialTheme.colorScheme.onSurfaceVariant)
}
}
}
@ -492,8 +492,8 @@ fun PdfBottomBar(
) {
if (jumpBackPage != null) {
TooltipIconButton(
text = "Jump Back to Page ${jumpBackPage + 1}",
description = "Return to previous page",
text = stringResource(R.string.action_jump_back_to_page, jumpBackPage + 1),
description = stringResource(R.string.desc_return_to_previous_page),
onClick = onJumpBack
) {
Column(
@ -502,7 +502,7 @@ fun PdfBottomBar(
) {
Icon(
Icons.AutoMirrored.Filled.Undo,
contentDescription = "Jump Back",
contentDescription = stringResource(R.string.content_desc_jump_back),
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(16.dp)
)
@ -535,7 +535,7 @@ fun PdfBottomBar(
enabled = !isTtsPlayingOrLoading,
modifier = Modifier.testTag("TocButton")
) {
Icon(Icons.Default.Menu, contentDescription = "Table of Contents")
Icon(Icons.Default.Menu, contentDescription = stringResource(R.string.content_desc_table_of_contents))
}
}
@ -557,7 +557,7 @@ fun PdfBottomBar(
onClick = onToggleHighlights
) {
if (isHighlightingLoading) CircularProgressIndicator(Modifier.size(24.dp))
else Icon(painterResource(id = R.drawable.highlight_text), contentDescription = "Highlight all text", tint = if (showAllTextHighlights) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant)
else Icon(painterResource(id = R.drawable.highlight_text), contentDescription = stringResource(R.string.content_desc_highlight_all_text), tint = if (showAllTextHighlights) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant)
}
}
@ -577,7 +577,7 @@ fun PdfBottomBar(
description = if (isEditMode) stringResource(R.string.tooltip_edit_mode_exit_desc) else stringResource(R.string.tooltip_edit_mode_desc),
onClick = onToggleEditMode
) {
Icon(Icons.Default.Edit, contentDescription = "Toggle Editing Mode", tint = if (isEditMode) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant)
Icon(Icons.Default.Edit, contentDescription = stringResource(R.string.content_desc_toggle_editing_mode), tint = if (isEditMode) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant)
}
}
@ -587,19 +587,19 @@ fun PdfBottomBar(
description = if (isTtsSessionActive) stringResource(R.string.tooltip_tts_stop_desc) else stringResource(R.string.tooltip_tts_start_desc),
onClick = onToggleTts
) {
Icon(if (isTtsSessionActive) painterResource(id = R.drawable.close) else painterResource(id = R.drawable.text_to_speech), contentDescription = if (isTtsSessionActive) "Stop TTS" else "Start TTS", tint = if (isTtsSessionActive) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant)
Icon(if (isTtsSessionActive) painterResource(id = R.drawable.close) else painterResource(id = R.drawable.text_to_speech), contentDescription = if (isTtsSessionActive) stringResource(R.string.content_desc_stop_tts) else stringResource(R.string.content_desc_start_tts), tint = if (isTtsSessionActive) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant)
}
}
if (BuildConfig.FLAVOR != "oss") {
TooltipIconButton(
text = if (isBubbleZoomModeActive) "Exit Smart Zoom" else "Smart Comic Zoom",
description = "Toggle Smart Comic Zoom",
text = if (isBubbleZoomModeActive) stringResource(R.string.action_exit_smart_zoom) else stringResource(R.string.action_smart_comic_zoom),
description = stringResource(R.string.desc_toggle_smart_comic_zoom),
onClick = onToggleBubbleZoom
) {
Icon(
painterResource(R.drawable.comic_bubble),
contentDescription = "Smart Comic Zoom",
contentDescription = stringResource(R.string.content_desc_smart_comic_zoom),
tint = if (isBubbleZoomModeActive) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.onSurfaceVariant
)
}

View file

@ -2089,7 +2089,7 @@ fun PdfViewerScreen(
if (!selectedDictPackage.isNullOrEmpty()) {
ExternalDictionaryHelper.launchDictionary(context, selectedDictPackage!!, text)
} else {
Toast.makeText(context, "Please select a dictionary app first.", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.toast_select_dictionary_first), Toast.LENGTH_SHORT).show()
showDictionarySettingsSheet = true
}
}
@ -2102,7 +2102,7 @@ fun PdfViewerScreen(
if (!selectedTranslatePackage.isNullOrEmpty()) {
ExternalDictionaryHelper.launchTranslate(context, selectedTranslatePackage!!, text)
} else {
Toast.makeText(context, "Please select a translate app first.", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.toast_select_translate_first), Toast.LENGTH_SHORT).show()
showDictionarySettingsSheet = true
}
}
@ -2113,7 +2113,7 @@ fun PdfViewerScreen(
if (!selectedSearchPackage.isNullOrEmpty()) {
ExternalDictionaryHelper.launchSearch(context, selectedSearchPackage!!, text)
} else {
Toast.makeText(context, "Please select a search app first.", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.toast_select_search_first), Toast.LENGTH_SHORT).show()
showDictionarySettingsSheet = true
}
}
@ -3386,7 +3386,7 @@ fun PdfViewerScreen(
contentAlignment = Alignment.Center
) {
Text(
text = errorMessage ?: "Failed to load PDF.",
text = errorMessage ?: stringResource(R.string.error_failed_load_pdf),
color = MaterialTheme.colorScheme.error,
modifier = Modifier.padding(16.dp)
)
@ -4380,7 +4380,10 @@ fun PdfViewerScreen(
)
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "Downloading ${ocrLanguage.displayName.substringBefore("(")} language pack...",
text = stringResource(
R.string.msg_downloading_language_pack,
stringResource(ocrLanguage.displayNameRes).substringBefore("(").trim()
),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onTertiaryContainer
)
@ -4429,7 +4432,10 @@ fun PdfViewerScreen(
}
Spacer(modifier = Modifier.width(12.dp))
Text(
text = "Downloading Bubble Zoom model... ${(progress * 100).toInt()}%",
text = stringResource(
R.string.msg_downloading_bubble_zoom_model_progress,
(progress * 100).toInt()
),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onTertiaryContainer
)
@ -4473,7 +4479,7 @@ fun PdfViewerScreen(
) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Exit slider navigation"
contentDescription = stringResource(R.string.content_desc_exit_slider_navigation)
)
}
@ -4913,15 +4919,23 @@ fun PdfViewerScreen(
)
else -1
val text =
if (index >= 0) "Result ${index + 1} / ${searchData.matches.size}"
else "${searchData.matches.size} Results"
if (index >= 0) context.getString(
R.string.pdf_search_result_position,
index + 1,
searchData.matches.size
)
else context.resources.getQuantityString(
R.plurals.search_results_count,
searchData.matches.size,
searchData.matches.size
)
Triple(text, index > 0, index < searchData.matches.size - 1)
}
is SmartSearchResult.Paged -> {
val page = currentResult?.locationInSource
val text = if (page != null) "Page ${page + 1}"
else "${searchData.totalPageCount}+ Pages"
val text = if (page != null) context.getString(R.string.pdf_page_short, page + 1)
else context.getString(R.string.msg_search_pages_count, searchData.totalPageCount)
Triple(text, true, true)
}
@ -5046,9 +5060,9 @@ fun PdfViewerScreen(
modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
verticalAlignment = Alignment.CenterVertically
) {
Icon(Icons.AutoMirrored.Filled.Undo, contentDescription = "Jump Back", modifier = Modifier.size(18.dp))
Icon(Icons.AutoMirrored.Filled.Undo, contentDescription = stringResource(R.string.content_desc_jump_back), modifier = Modifier.size(18.dp))
Spacer(modifier = Modifier.width(8.dp))
Text("Back to Pg ${lastPage + 1}", style = MaterialTheme.typography.labelLarge)
Text(stringResource(R.string.pdf_back_to_page_short, lastPage + 1), style = MaterialTheme.typography.labelLarge)
}
}
}
@ -5535,7 +5549,7 @@ fun PdfViewerScreen(
Icon(
imageVector = if (isTtsPageBelow) Icons.Default.ArrowDownward
else Icons.Default.ArrowUpward,
contentDescription = "Scroll to reading page"
contentDescription = stringResource(R.string.content_desc_scroll_to_reading_page)
)
}
}
@ -5817,10 +5831,10 @@ fun PdfViewerScreen(
contentDescription = null
)
},
title = { Text("Unlock Page Summarization") },
title = { Text(stringResource(R.string.dialog_unlock_page_summarization)) },
text = {
Text(
"Get concise summaries of any page with Episteme Pro. Upgrade to start using this feature."
stringResource(R.string.dialog_unlock_page_summarization_desc)
)
},
confirmButton = {
@ -5841,13 +5855,13 @@ fun PdfViewerScreen(
AlertDialog(
onDismissRequest = { showInsufficientCreditsDialog = false },
icon = { Icon(painterResource(id = R.drawable.crown), contentDescription = null) },
title = { Text("Out of Credits") },
text = { Text("You don't have enough credits. Get Episteme Pro for 10 free Summaries per day, or add more credits to use Summaries, Cloud TTS and Story Recap.") },
title = { Text(stringResource(R.string.dialog_out_of_credits_title)) },
text = { Text(stringResource(R.string.dialog_out_of_credits_desc)) },
confirmButton = {
TextButton(onClick = {
showInsufficientCreditsDialog = false
onNavigateToPro()
}) { Text("Get Pro / Add Credits") }
}) { Text(stringResource(R.string.action_get_pro_or_add_credits)) }
},
dismissButton = {
TextButton(onClick = { showInsufficientCreditsDialog = false }) {
@ -5874,7 +5888,7 @@ fun PdfViewerScreen(
) {
Image(
bitmap = poppedUpPanelBitmap!!.asImageBitmap(),
contentDescription = "Annotated Page",
contentDescription = stringResource(R.string.content_desc_annotated_page),
modifier = Modifier
.fillMaxWidth()
.padding(16.dp)
@ -5894,7 +5908,7 @@ fun PdfViewerScreen(
) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = "Close Image",
contentDescription = stringResource(R.string.content_desc_close_image),
tint = Color.White
)
}
@ -5913,16 +5927,16 @@ fun PdfViewerScreen(
AlertDialog(
onDismissRequest = { showBubbleZoomDownloadDialog = false },
icon = { Icon(Icons.Default.Info, contentDescription = null) },
title = { Text("Download Bubble Zoom Model") },
title = { Text(stringResource(R.string.dialog_download_bubble_zoom_model)) },
text = {
Text("To use the Bubble Zoom feature, an AI model needs to be downloaded (~134 MB). Do you want to download it now?")
Text(stringResource(R.string.dialog_download_bubble_zoom_model_desc))
},
confirmButton = {
TextButton(onClick = {
showBubbleZoomDownloadDialog = false
viewModel.downloadSpeechBubbleModel(context)
}) {
Text("Download")
Text(stringResource(R.string.action_download))
}
},
dismissButton = {

View file

@ -7,6 +7,7 @@ import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.aryan.reader.FileType
import com.aryan.reader.R
import com.aryan.reader.data.RecentFileItem
import com.aryan.reader.data.RecentFilesRepository
import kotlinx.coroutines.Dispatchers
@ -32,7 +33,8 @@ class ReflowWorker(
Timber.tag("PdfToHtmlPerf").e("FAILURE: KEY_PDF_URI is null | bookId=$bookId")
return@withContext Result.failure()
}
val originalTitle = inputData.getString(KEY_ORIGINAL_TITLE) ?: "Document"
val originalTitle = inputData.getString(KEY_ORIGINAL_TITLE)
?: applicationContext.getString(R.string.default_document_title)
val reflowBookId = "${bookId}_reflow"
Timber.tag("PdfToHtmlPerf").d(
@ -67,11 +69,11 @@ class ReflowWorker(
bookId = reflowBookId,
uriString = destFile.toUri().toString(),
type = FileType.HTML,
displayName = "$originalTitle (Text View)",
displayName = applicationContext.getString(R.string.reflow_display_name_format, originalTitle),
timestamp = System.currentTimeMillis(),
coverImagePath = null,
title = "$originalTitle (Reflow)",
author = "Generated",
title = applicationContext.getString(R.string.reflow_title_format, originalTitle),
author = applicationContext.getString(R.string.generated_author),
isAvailable = true,
isRecent = true,
lastModifiedTimestamp = System.currentTimeMillis(),
@ -101,4 +103,4 @@ class ReflowWorker(
const val KEY_ORIGINAL_TITLE = "original_title"
const val KEY_PROGRESS = "progress"
}
}
}

View file

@ -409,7 +409,7 @@ fun TextAnnotationDock(
FormattingIconButton(
isSelected = activePopup == ActivePopup.FONT_FAMILY,
iconRes = R.drawable.fonts,
contentDescription = "Select Font Family",
contentDescription = stringResource(R.string.content_desc_select_font_family),
onClick = {
activePopup =
if (activePopup == ActivePopup.FONT_FAMILY) ActivePopup.NONE else ActivePopup.FONT_FAMILY
@ -481,7 +481,7 @@ fun TextAnnotationDock(
)
Icon(
imageVector = Icons.Default.KeyboardArrowDown,
contentDescription = "Select Font Size",
contentDescription = stringResource(R.string.content_desc_select_font_size),
tint = Color.Gray,
modifier = Modifier.size(16.dp)
)
@ -561,7 +561,7 @@ fun TextAnnotationDock(
) {
Icon(
painter = painterResource(id = R.drawable.font_background),
contentDescription = "Font Background",
contentDescription = stringResource(R.string.content_desc_font_background),
modifier = Modifier.size(17.dp),
tint = Color.Black
)
@ -587,7 +587,7 @@ fun TextAnnotationDock(
FormattingIconButton(
isSelected = isBold,
iconRes = R.drawable.format_bold,
contentDescription = "Bold",
contentDescription = stringResource(R.string.content_desc_bold),
onClick = {
val newW = if (isBold) FontWeight.Normal else FontWeight.Bold
onUpdateStyle(currentStyle.copy(fontWeight = newW, fontFamily = currentStyle.fontFamily))
@ -605,7 +605,7 @@ fun TextAnnotationDock(
FormattingIconButton(
isSelected = isItalic,
iconRes = R.drawable.format_italic,
contentDescription = "Italic",
contentDescription = stringResource(R.string.content_desc_italic),
onClick = {
val newStyle = if (isItalic) FontStyle.Normal else FontStyle.Italic
onUpdateStyle(currentStyle.copy(fontStyle = newStyle, fontFamily = currentStyle.fontFamily))
@ -625,7 +625,7 @@ fun TextAnnotationDock(
FormattingIconButton(
isSelected = isUnderline,
iconRes = R.drawable.format_underlined,
contentDescription = "Underline",
contentDescription = stringResource(R.string.content_desc_underline),
onClick = {
val hasStrike = currentDec.contains(TextDecoration.LineThrough)
val newDec = if (isUnderline) {
@ -654,7 +654,7 @@ fun TextAnnotationDock(
FormattingIconButton(
isSelected = isStrike,
iconRes = R.drawable.format_strikethrough,
contentDescription = "Strikethrough",
contentDescription = stringResource(R.string.content_desc_strikethrough),
onClick = {
val hasUnd = currentDec.contains(TextDecoration.Underline)
val newDec = if (isStrike) {
@ -682,7 +682,7 @@ fun TextAnnotationDock(
FormattingIconButton(
isSelected = false,
iconRes = R.drawable.text_box,
contentDescription = "Insert Text Box",
contentDescription = stringResource(R.string.content_desc_insert_text_box),
onClick = {
Timber.tag("PdfTextBoxDebug").d("Dock: Insert Text Box icon clicked")
onInsertTextBox()
@ -698,7 +698,7 @@ fun TextAnnotationDock(
FormattingIconButton(
isSelected = false,
iconVector = Icons.Default.Close,
contentDescription = "Close",
contentDescription = stringResource(R.string.action_close),
onClick = {
focusManager.clearFocus()
onClearTextBoxSelection()
@ -739,7 +739,7 @@ private fun FontItem(
if (isSelected) {
Icon(
imageVector = Icons.Default.Check,
contentDescription = "Selected",
contentDescription = stringResource(R.string.content_desc_selected),
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier.size(16.dp)
)
@ -814,7 +814,7 @@ private fun ColorPickerBubble(
) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = "Close",
contentDescription = stringResource(R.string.action_close),
tint = Color.White,
modifier = Modifier.size(16.dp)
)
@ -1193,12 +1193,12 @@ private fun ColorPickerSpectrumContent(
IconButton(onClick = onBack, modifier = Modifier.size(24.dp)) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back",
contentDescription = stringResource(R.string.action_back),
tint = Color.White
)
}
Text(
text = "Spectrum",
text = stringResource(R.string.label_spectrum),
style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.SemiBold,
color = Color.White,
@ -1264,7 +1264,7 @@ private fun ColorPickerSpectrumContent(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
"Hex",
stringResource(R.string.theme_color_hex),
color = Color.Gray,
fontSize = 11.sp,
maxLines = 1
@ -1282,19 +1282,19 @@ private fun ColorPickerSpectrumContent(
horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
RgbInputColumn(
label = "R",
label = stringResource(R.string.color_r),
value = currentColor.red,
onValueChange = { r -> updateFromColor(currentColor.copy(red = r)) },
modifier = Modifier.weight(1f)
)
RgbInputColumn(
label = "G",
label = stringResource(R.string.color_g),
value = currentColor.green,
onValueChange = { g -> updateFromColor(currentColor.copy(green = g)) },
modifier = Modifier.weight(1f)
)
RgbInputColumn(
label = "B",
label = stringResource(R.string.color_b),
value = currentColor.blue,
onValueChange = { b -> updateFromColor(currentColor.copy(blue = b)) },
modifier = Modifier.weight(1f)
@ -1313,7 +1313,7 @@ private fun ColorPickerSpectrumContent(
modifier = Modifier.fillMaxWidth().height(40.dp),
contentPadding = PaddingValues(0.dp)
) {
Text("Done", fontSize = 14.sp)
Text(stringResource(R.string.action_done), fontSize = 14.sp)
}
}
}
@ -1552,4 +1552,4 @@ private fun ColorComparePill(
size = androidx.compose.ui.geometry.Size(size.width / 2, size.height)
)
}
}
}

View file

@ -13,6 +13,7 @@ import android.graphics.RectF
import android.net.Uri
import android.os.Build
import com.aryan.reader.FileType
import com.aryan.reader.R
import io.legere.pdfiumandroid.api.Bookmark
import io.legere.pdfiumandroid.suspend.PdfDocumentKt
import io.legere.pdfiumandroid.suspend.PdfPageKt
@ -452,7 +453,7 @@ class OpdsStreamDocumentWrapper(
textSize = 40f
textAlign = Paint.Align.CENTER
}
canvas.drawText("Page Unavailable", 400f, 600f, paint)
canvas.drawText(context.getString(R.string.msg_page_unavailable), 400f, 600f, paint)
val stream = java.io.ByteArrayOutputStream()
bitmap.compress(Bitmap.CompressFormat.JPEG, 80, stream)
return stream.toByteArray()
@ -509,4 +510,4 @@ class OpdsStreamDocumentWrapper(
override suspend fun getTableOfContents() = emptyList<Bookmark>()
override fun close() {}
}
}