String extraction (#174)
* Refactored the EPUB reader to use localized string resources instead of hardcoded strings across multiple components. * Refactored the PDF viewer and annotation components to use centralized string resources instead of hardcoded text. * Updated `strings.xml` with extensive translation hints and localization metadata.
This commit is contained in:
parent
17a0097d4a
commit
b027331bd1
20 changed files with 716 additions and 313 deletions
|
|
@ -72,6 +72,7 @@ import androidx.compose.ui.graphics.toArgb
|
|||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.IntRect
|
||||
import androidx.compose.ui.unit.IntSize
|
||||
|
|
@ -81,6 +82,7 @@ import androidx.compose.ui.viewinterop.AndroidView
|
|||
import androidx.compose.ui.window.Popup
|
||||
import androidx.compose.ui.window.PopupPositionProvider
|
||||
import androidx.core.net.toUri
|
||||
import com.aryan.reader.R
|
||||
import com.aryan.reader.ReaderTexture
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -415,8 +417,8 @@ fun ChapterWebView(
|
|||
val urlToShow = showExternalLinkDialog!!
|
||||
AlertDialog(
|
||||
onDismissRequest = { showExternalLinkDialog = null },
|
||||
title = { Text("External Link") },
|
||||
text = { Text("You clicked on an external link:\n\n$urlToShow\n\nWhat would you like to do?") },
|
||||
title = { Text(stringResource(R.string.dialog_external_link_title)) },
|
||||
text = { Text(stringResource(R.string.dialog_external_link_desc, urlToShow)) },
|
||||
confirmButton = {
|
||||
Row(horizontalArrangement = Arrangement.End) {
|
||||
TextButton(onClick = {
|
||||
|
|
@ -425,23 +427,21 @@ fun ChapterWebView(
|
|||
context.startActivity(intent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Timber.e(e, "No activity found to handle intent for URL: $urlToShow")
|
||||
Toast.makeText(
|
||||
context, "No browser found to open the link.", Toast.LENGTH_LONG
|
||||
).show()
|
||||
Toast.makeText(context, context.getString(R.string.error_no_browser), Toast.LENGTH_LONG).show()
|
||||
}
|
||||
showExternalLinkDialog = null
|
||||
}) { Text("Open") }
|
||||
}) { Text(stringResource(R.string.action_open)) }
|
||||
TextButton(onClick = {
|
||||
val clipboard =
|
||||
context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText("Copied Link", urlToShow)
|
||||
clipboard.setPrimaryClip(clip)
|
||||
showExternalLinkDialog = null
|
||||
}) { Text("Copy") }
|
||||
}) { Text(stringResource(R.string.action_copy)) }
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showExternalLinkDialog = null }) { Text("Cancel") }
|
||||
TextButton(onClick = { showExternalLinkDialog = null }) { Text(stringResource(R.string.action_cancel)) }
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ import com.aryan.reader.epub.EpubChapter
|
|||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import java.util.UUID
|
||||
import kotlin.math.min
|
||||
|
||||
private const val BOOKMARK_PREFS_NAME = "epub_reader_bookmarks"
|
||||
|
||||
|
|
@ -445,10 +444,10 @@ fun PaletteManagerDialog(
|
|||
}
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(onClick = { onSave(tempPalette) }) { Text("Save") }
|
||||
TextButton(onClick = { onSave(tempPalette) }) { Text(stringResource(R.string.action_save)) }
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = onDismiss) { Text("Cancel") }
|
||||
TextButton(onClick = onDismiss) { Text(stringResource(R.string.action_cancel)) }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
@ -528,10 +527,10 @@ fun AnnotationBottomSheet(
|
|||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
BottomSheetToolButton(icon = R.drawable.copy, label = "Copy", onClick = onCopy, effectiveText = effectiveText)
|
||||
BottomSheetToolButton(icon = R.drawable.dictionary, label = "Dict", onClick = onDictionary, effectiveText = effectiveText)
|
||||
BottomSheetToolButton(icon = R.drawable.translate, label = "Translate", onClick = onTranslate, effectiveText = effectiveText)
|
||||
BottomSheetToolButton(icon = R.drawable.search, label = "Search", onClick = onSearch, effectiveText = effectiveText)
|
||||
BottomSheetToolButton(icon = R.drawable.copy, label = stringResource(R.string.action_copy), onClick = onCopy, effectiveText = effectiveText)
|
||||
BottomSheetToolButton(icon = R.drawable.dictionary, label = stringResource(R.string.label_dict), onClick = onDictionary, effectiveText = effectiveText)
|
||||
BottomSheetToolButton(icon = R.drawable.translate, label = stringResource(R.string.dict_translate), onClick = onTranslate, effectiveText = effectiveText)
|
||||
BottomSheetToolButton(icon = R.drawable.search, label = stringResource(R.string.action_search), onClick = onSearch, effectiveText = effectiveText)
|
||||
}
|
||||
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
|
@ -540,7 +539,7 @@ fun AnnotationBottomSheet(
|
|||
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),
|
||||
|
|
@ -652,23 +651,23 @@ fun PaginatedTextSelectionMenu(
|
|||
}
|
||||
|
||||
val actions = mutableListOf<MenuActionItem>()
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.copy, label = "Copy", onClick = onCopy))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.copy, label = stringResource(R.string.action_copy), onClick = onCopy))
|
||||
if (onTts != null) {
|
||||
actions.add(MenuActionItem(imageVector = Icons.AutoMirrored.Filled.VolumeUp, label = "Speak", onClick = onTts))
|
||||
actions.add(MenuActionItem(imageVector = Icons.AutoMirrored.Filled.VolumeUp, label = stringResource(R.string.label_speak), onClick = onTts))
|
||||
}
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.dictionary, label = "Dict", onClick = onDictionary))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.translate, label = "Translate", onClick = onTranslate))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.search, label = "Search", onClick = onSearch))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.dictionary, label = stringResource(R.string.label_dict), onClick = onDictionary))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.translate, label = stringResource(R.string.dict_translate), onClick = onTranslate))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.search, label = stringResource(R.string.action_search), onClick = onSearch))
|
||||
|
||||
if (onNote != null) {
|
||||
actions.add(MenuActionItem(imageVector = Icons.Default.Edit, label = "Note", onClick = onNote))
|
||||
actions.add(MenuActionItem(imageVector = Icons.Default.Edit, label = stringResource(R.string.label_note), onClick = onNote))
|
||||
}
|
||||
|
||||
if (onSelectAll != null) {
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.select_all, label = "Select All", onClick = onSelectAll))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.select_all, label = stringResource(R.string.select_all), onClick = onSelectAll))
|
||||
}
|
||||
if (onDelete != null) {
|
||||
actions.add(MenuActionItem(imageVector = Icons.Default.Delete, label = "Remove", onClick = onDelete, isError = true))
|
||||
actions.add(MenuActionItem(imageVector = Icons.Default.Delete, label = stringResource(R.string.action_remove), onClick = onDelete, isError = true))
|
||||
}
|
||||
|
||||
Column(modifier = Modifier.padding(bottom = 4.dp)) {
|
||||
|
|
@ -753,7 +752,7 @@ fun HighlightColorRow(
|
|||
if (selectedColor == colorEnum) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Check,
|
||||
contentDescription = "Selected",
|
||||
contentDescription = stringResource(R.string.content_desc_selected),
|
||||
tint = if (colorEnum == HighlightColor.WHITE || colorEnum == HighlightColor.YELLOW) Color.Black else Color.White,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
|
|
@ -825,13 +824,13 @@ fun PaginatedTextSelectionMenu(
|
|||
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)
|
||||
)
|
||||
Spacer(Modifier.width(6.dp))
|
||||
Text(
|
||||
"Note",
|
||||
stringResource(R.string.label_note),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontWeight = FontWeight.Bold
|
||||
|
|
@ -851,24 +850,24 @@ fun PaginatedTextSelectionMenu(
|
|||
}
|
||||
|
||||
val actions = mutableListOf<MenuActionItem>()
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.copy, label = "Copy", onClick = onCopy))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.copy, label = stringResource(R.string.action_copy), onClick = onCopy))
|
||||
if (onTts != null) {
|
||||
actions.add(MenuActionItem(imageVector = Icons.AutoMirrored.Filled.VolumeUp, label = "Speak", onClick = onTts))
|
||||
actions.add(MenuActionItem(imageVector = Icons.AutoMirrored.Filled.VolumeUp, label = stringResource(R.string.label_speak), onClick = onTts))
|
||||
}
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.dictionary, label = "Dict", onClick = onDictionary))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.translate, label = "Translate", onClick = onTranslate))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.search, label = "Search", onClick = onSearch))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.dictionary, label = stringResource(R.string.label_dict), onClick = onDictionary))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.translate, label = stringResource(R.string.dict_translate), onClick = onTranslate))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.search, label = stringResource(R.string.action_search), onClick = onSearch))
|
||||
|
||||
if (onNote != null) {
|
||||
val noteLabel = if (existingNote.isNullOrBlank()) "Note" else "Edit"
|
||||
val noteLabel = if (existingNote.isNullOrBlank()) stringResource(R.string.label_note) else stringResource(R.string.label_edit)
|
||||
actions.add(MenuActionItem(imageVector = Icons.Default.Edit, label = noteLabel, onClick = onNote))
|
||||
}
|
||||
|
||||
if (onSelectAll != null) {
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.select_all, label = "Select All", onClick = onSelectAll))
|
||||
actions.add(MenuActionItem(iconRes = R.drawable.select_all, label = stringResource(R.string.select_all), onClick = onSelectAll))
|
||||
}
|
||||
if (onDelete != null) {
|
||||
actions.add(MenuActionItem(imageVector = Icons.Default.Delete, label = "Remove", onClick = onDelete, isError = true))
|
||||
actions.add(MenuActionItem(imageVector = Icons.Default.Delete, label = stringResource(R.string.action_remove), onClick = onDelete, isError = true))
|
||||
}
|
||||
|
||||
Column(modifier = Modifier.padding(bottom = 4.dp)) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
*/
|
||||
package com.aryan.reader.epubreader
|
||||
|
||||
import android.content.Context
|
||||
import com.aryan.reader.R
|
||||
import timber.log.Timber
|
||||
import com.aryan.reader.epub.EpubBook
|
||||
import com.aryan.reader.paginatedreader.LocatorConverter
|
||||
|
|
@ -40,6 +42,7 @@ data class ChapterLoadingResult(
|
|||
* the initial chunk to display based on navigation state (CFI, overrides, etc.).
|
||||
*/
|
||||
suspend fun loadChapterContent(
|
||||
context: Context,
|
||||
epubBook: EpubBook,
|
||||
chapterIndex: Int,
|
||||
chunkTargetOverride: Int?,
|
||||
|
|
@ -64,12 +67,12 @@ suspend fun loadChapterContent(
|
|||
chunkOfElements.joinToString(separator = "\n") { it.outerHtml() }
|
||||
}
|
||||
if (chunkedList.isEmpty()) {
|
||||
head to listOf("<body><p>This chapter is empty.</p></body>")
|
||||
head to listOf("<body><p>${context.getString(R.string.chapter_empty)}</p></body>")
|
||||
} else {
|
||||
head to chunkedList
|
||||
}
|
||||
} else {
|
||||
"" to listOf("<h1>Chapter not found</h1>")
|
||||
"" to listOf("<h1>${context.getString(R.string.chapter_not_found)}</h1>")
|
||||
}
|
||||
|
||||
var targetChunk = 0
|
||||
|
|
@ -104,7 +107,7 @@ suspend fun loadChapterContent(
|
|||
Timber.e(e, "Failed to parse chapter")
|
||||
ChapterLoadingResult(
|
||||
head = "",
|
||||
chunks = listOf("<h1>Error loading chapter</h1><p>${e.message}</p>"),
|
||||
chunks = listOf("<h1>${context.getString(R.string.error_loading_chapter)}</h1><p>${e.message}</p>"),
|
||||
startChunkIndex = 0,
|
||||
isSuccess = false,
|
||||
errorMessage = e.message
|
||||
|
|
|
|||
|
|
@ -277,7 +277,7 @@ fun EpubReaderTopBar(
|
|||
onDismissRequest = { showMoreMenu = false }
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text("Customize Toolbar") },
|
||||
text = { Text(stringResource(R.string.title_customize_toolbar)) },
|
||||
onClick = {
|
||||
showMoreMenu = false
|
||||
onCustomizeTools()
|
||||
|
|
@ -1078,7 +1078,7 @@ fun AutoScrollControls(
|
|||
) {
|
||||
Icon(
|
||||
imageVector = if (isPlaying) Icons.Default.Pause else Icons.Default.PlayArrow,
|
||||
contentDescription = if (isPlaying) stringResource(R.string.content_desc_pause_playback) else stringResource(R.string.content_desc_start_playback),
|
||||
contentDescription = if (isPlaying) stringResource(R.string.tooltip_tts_pause) else stringResource(R.string.content_desc_start_playback),
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
}
|
||||
|
|
@ -1395,7 +1395,7 @@ fun CustomizeToolsSheet(
|
|||
)
|
||||
Spacer(modifier = Modifier.height(8.dp))
|
||||
Text(
|
||||
text = "Select the tools you want to keep visible. Unchecking a tool hides it from the UI to give you a distraction-free reading space.",
|
||||
text = stringResource(R.string.desc_customize_toolbar),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
|
|
@ -1495,17 +1495,19 @@ fun TtsControlsSheet(
|
|||
ttsController.sliceAndRetainPosition()
|
||||
}
|
||||
|
||||
val ttsSample = stringResource(R.string.tts_sample_text)
|
||||
|
||||
ModalBottomSheet(
|
||||
onDismissRequest = onDismiss,
|
||||
contentWindowInsets = { WindowInsets.navigationBars }
|
||||
) {
|
||||
Column(modifier = Modifier.padding(horizontal = 24.dp).padding(bottom = 24.dp)) {
|
||||
Text("Voice Adjustments", style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold)
|
||||
Text(stringResource(R.string.tts_voice_adjustments), style = MaterialTheme.typography.titleLarge, fontWeight = FontWeight.Bold)
|
||||
Spacer(Modifier.height(16.dp))
|
||||
|
||||
// Rate Slider
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text("Speed (${"%.1f".format(rate)}x)", modifier = Modifier.weight(1f), style = MaterialTheme.typography.bodyMedium)
|
||||
Text(stringResource(R.string.tts_speed_label, "%.1f".format(rate)), modifier = Modifier.weight(1f), style = MaterialTheme.typography.bodyMedium)
|
||||
IconButton(onClick = {
|
||||
rate = 1.0f
|
||||
ttsController.pause()
|
||||
|
|
@ -1534,7 +1536,7 @@ fun TtsControlsSheet(
|
|||
|
||||
// Pitch Slider
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text("Pitch (${"%.1f".format(pitch)}x)", modifier = Modifier.weight(1f), style = MaterialTheme.typography.bodyMedium)
|
||||
Text(stringResource(R.string.tts_pitch_label, "%.1f".format(pitch)), modifier = Modifier.weight(1f), style = MaterialTheme.typography.bodyMedium)
|
||||
IconButton(onClick = {
|
||||
pitch = 1.0f
|
||||
ttsController.pause()
|
||||
|
|
@ -1568,7 +1570,7 @@ fun TtsControlsSheet(
|
|||
if (ttsState.isPlaying) ttsController.pause()
|
||||
tts?.setSpeechRate(rate)
|
||||
tts?.setPitch(pitch)
|
||||
tts?.speak("This is how your current voice settings sound.", TextToSpeech.QUEUE_FLUSH, null, null)
|
||||
tts?.speak(ttsSample, TextToSpeech.QUEUE_FLUSH, null, null)
|
||||
},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
enabled = isTtsReady,
|
||||
|
|
@ -1611,14 +1613,14 @@ fun TtsControlsSheet(
|
|||
} else {
|
||||
Icon(
|
||||
painter = painterResource(if (ttsState.isPlaying) R.drawable.pause else R.drawable.play),
|
||||
contentDescription = if (ttsState.isPlaying) "Pause Book" else "Play Book",
|
||||
contentDescription = if (ttsState.isPlaying) stringResource(R.string.tts_pause_book) else stringResource(R.string.tts_resume_book),
|
||||
modifier = Modifier.size(32.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(8.dp))
|
||||
Text(
|
||||
text = if (ttsState.isPlaying) "Pause Book" else "Resume Book",
|
||||
text = if (ttsState.isPlaying) stringResource(R.string.tts_pause_book) else stringResource(R.string.tts_resume_book),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
color = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
)
|
||||
|
|
@ -1635,7 +1637,7 @@ fun TtsControlsSheet(
|
|||
) {
|
||||
Icon(Icons.Default.Settings, contentDescription = null)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Text("System Voice / Engine Settings")
|
||||
Text(stringResource(R.string.tts_system_settings))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -551,7 +551,7 @@ private fun BookmarksList(
|
|||
onDismissRequest = { bookmarkMenuExpandedFor = null }
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text(stringResource(R.string.menu_rename)) },
|
||||
text = { Text(stringResource(R.string.action_rename)) },
|
||||
onClick = {
|
||||
showRenameBookmarkDialog = bookmark
|
||||
bookmarkMenuExpandedFor = null
|
||||
|
|
@ -680,12 +680,12 @@ private fun HighlightsList(
|
|||
androidx.compose.material3.FilterChip(
|
||||
selected = !filterWithNotesOnly,
|
||||
onClick = { filterWithNotesOnly = false },
|
||||
label = { Text("All") }
|
||||
label = { Text(stringResource(R.string.filter_all)) }
|
||||
)
|
||||
androidx.compose.material3.FilterChip(
|
||||
selected = filterWithNotesOnly,
|
||||
onClick = { filterWithNotesOnly = true },
|
||||
label = { Text("With Notes") }
|
||||
label = { Text(stringResource(R.string.filter_with_notes)) }
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -773,7 +773,7 @@ private fun HighlightsList(
|
|||
)
|
||||
HorizontalDivider()
|
||||
DropdownMenuItem(
|
||||
text = { Text(if (highlight.note.isNullOrBlank()) "Add Note" else "Edit Note") },
|
||||
text = { Text(if (highlight.note.isNullOrBlank()) stringResource(R.string.menu_add_note) else stringResource(R.string.menu_edit_note)) },
|
||||
onClick = {
|
||||
onEditNote(highlight)
|
||||
highlightMenuExpandedFor = null
|
||||
|
|
|
|||
|
|
@ -702,7 +702,7 @@ fun EpubReaderHost(
|
|||
if (!selectedDictPackage.isNullOrEmpty()) {
|
||||
ExternalDictionaryHelper.launchDictionary(context, selectedDictPackage!!, word)
|
||||
} 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
|
||||
}
|
||||
}
|
||||
|
|
@ -712,7 +712,7 @@ fun EpubReaderHost(
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -721,7 +721,7 @@ fun EpubReaderHost(
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
@ -1371,6 +1371,7 @@ fun EpubReaderHost(
|
|||
activeFragmentId = null
|
||||
|
||||
val result = loadChapterContent(
|
||||
context = context,
|
||||
epubBook = epubBook,
|
||||
chapterIndex = currentChapterIndex,
|
||||
chunkTargetOverride = chunkTargetOverride,
|
||||
|
|
@ -2835,7 +2836,7 @@ fun EpubReaderHost(
|
|||
|
||||
if (pullToTurnEnabled && currentChapterIndex > 0) {
|
||||
ChapterChangeIndicator(
|
||||
text = "Release for Previous Chapter",
|
||||
text = stringResource(R.string.release_for_previous_chapter),
|
||||
progress = pullToPrevProgress,
|
||||
isPullingDown = true,
|
||||
modifier = Modifier
|
||||
|
|
@ -2846,7 +2847,7 @@ fun EpubReaderHost(
|
|||
|
||||
if (pullToTurnEnabled && currentChapterIndex < chapters.size - 1) {
|
||||
ChapterChangeIndicator(
|
||||
text = "Release for Next Chapter",
|
||||
text = stringResource(R.string.release_for_next_chapter),
|
||||
progress = pullToNextProgress,
|
||||
isPullingDown = false,
|
||||
modifier = Modifier
|
||||
|
|
|
|||
|
|
@ -481,7 +481,7 @@ fun ReaderTextFormatPanel(
|
|||
|
||||
// FONT & ALIGNMENT SECTION
|
||||
Text(
|
||||
text = "FONT & ALIGNMENT",
|
||||
text = stringResource(R.string.section_font_alignment),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontWeight = FontWeight.Bold,
|
||||
|
|
@ -504,7 +504,7 @@ fun ReaderTextFormatPanel(
|
|||
) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Text(
|
||||
text = "Aa",
|
||||
text = stringResource(R.string.label_aa_preview),
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.onSecondaryContainer,
|
||||
|
|
@ -570,7 +570,7 @@ fun ReaderTextFormatPanel(
|
|||
|
||||
// LAYOUT & SPACING SECTION
|
||||
Text(
|
||||
text = "LAYOUT & SPACING",
|
||||
text = stringResource(R.string.section_layout_spacing),
|
||||
style = MaterialTheme.typography.labelSmall,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
fontWeight = FontWeight.Bold,
|
||||
|
|
@ -581,7 +581,7 @@ fun ReaderTextFormatPanel(
|
|||
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
|
||||
// Size
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
Text("Font Size", style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp))
|
||||
Text(stringResource(R.string.label_font_size), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp))
|
||||
Slider(
|
||||
value = currentFontSize,
|
||||
onValueChange = onFontSizeChange,
|
||||
|
|
@ -589,11 +589,11 @@ fun ReaderTextFormatPanel(
|
|||
steps = 24,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(if (currentFontSize in 0.99f..1.01f) "Orig" else "%.1fx".format(currentFontSize), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp), textAlign = TextAlign.End)
|
||||
Text(if (currentFontSize in 0.99f..1.01f) stringResource(R.string.label_original) else "%.1fx".format(currentFontSize), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp), textAlign = TextAlign.End)
|
||||
}
|
||||
// Lines
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
Text("Line Height", style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp))
|
||||
Text(stringResource(R.string.label_line_height), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp))
|
||||
Slider(
|
||||
value = currentLineHeight,
|
||||
onValueChange = onLineHeightChange,
|
||||
|
|
@ -601,11 +601,11 @@ fun ReaderTextFormatPanel(
|
|||
steps = 19,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(if (currentLineHeight <= 1.01f) "Orig" else "%.1fx".format(currentLineHeight), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp), textAlign = TextAlign.End)
|
||||
Text(if (currentLineHeight <= 1.01f) stringResource(R.string.label_original) else "%.1fx".format(currentLineHeight), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp), textAlign = TextAlign.End)
|
||||
}
|
||||
// Paragraph Gap
|
||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp)) {
|
||||
Text("Paragraph Gap", style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp))
|
||||
Text(stringResource(R.string.label_paragraph_gap), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp))
|
||||
Slider(
|
||||
value = currentParagraphGap,
|
||||
onValueChange = onParagraphGapChange,
|
||||
|
|
@ -613,7 +613,7 @@ fun ReaderTextFormatPanel(
|
|||
steps = 29,
|
||||
modifier = Modifier.weight(1f)
|
||||
)
|
||||
Text(if (currentParagraphGap in 0.99f..1.01f) "Orig" else "%.1fx".format(currentParagraphGap), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp), textAlign = TextAlign.End)
|
||||
Text(if (currentParagraphGap in 0.99f..1.01f) stringResource(R.string.label_original) else "%.1fx".format(currentParagraphGap), style = MaterialTheme.typography.labelMedium, modifier = Modifier.width(40.dp), textAlign = TextAlign.End)
|
||||
}
|
||||
}
|
||||
Spacer(Modifier.height(8.dp))
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import android.os.Build
|
|||
import android.widget.Toast
|
||||
import timber.log.Timber
|
||||
import androidx.core.net.toUri
|
||||
import com.aryan.reader.R
|
||||
|
||||
data class ExternalDictionaryApp(
|
||||
val label: String,
|
||||
|
|
@ -72,7 +73,7 @@ object ExternalDictionaryHelper {
|
|||
sortedApps.add(
|
||||
0,
|
||||
ExternalDictionaryApp(
|
||||
label = "Search",
|
||||
label = context.getString(R.string.dict_app_label_search),
|
||||
packageName = GOOGLE_SEARCH_PKG,
|
||||
icon = null
|
||||
)
|
||||
|
|
@ -127,7 +128,7 @@ object ExternalDictionaryHelper {
|
|||
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Failed to launch dictionary app: $packageName")
|
||||
Toast.makeText(context, "Error opening dictionary", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, context.getString(R.string.error_opening_dictionary), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -172,7 +173,7 @@ object ExternalDictionaryHelper {
|
|||
launchGenericSend(context, packageName, query)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Failed to launch translate app: $packageName")
|
||||
Toast.makeText(context, "Error opening translate app", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, context.getString(R.string.error_opening_translate), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +211,7 @@ object ExternalDictionaryHelper {
|
|||
launchGenericSend(context, packageName, query)
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e, "Failed to launch search app: $packageName")
|
||||
Toast.makeText(context, "Error opening search app", Toast.LENGTH_SHORT).show()
|
||||
Toast.makeText(context, context.getString(R.string.error_opening_search), Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue