Update v1.0.49 (#330)

* Added PDF top tab strip visibility toggle and fixed WebView hit test NPE

* Refactored desktop reader screens and state management into specialized components

* Added image gallery to reader sidebar and refactored desktop PDF UI components

* Implemented EPUB image gallery

* Refactored reader and library models to use shared common types, centralizing file type resolution and texture management while removing redundant mapping logic

* Standardized UI styling and refactored app navigation layout

* Implemented auto-hiding reader chrome and activity tracking in desktop

* Refactored reader panels into distinct left and right modal layers with platform-specific sizing and keyboard navigation support.

* Added PPTX support for desktop and refactored parsing into a shared module

* Implement paid AI features and account management for the desktop application.

* Implement AI Hub and enhanced Cloud TTS integration for Desktop

* Implement streaming support for AI definition and summarization features

* Implement support for password-protected PDFs and file actions in the desktop reader.

* Implement cloud synchronization for desktop using Firestore and Google Drive

* Implement PDF reflow and "Text View" for the desktop reader

* Refactor OPDS logic to use SharedOpdsController

* Optimize PDF tile rendering performance

* Implement two-page spread support for PDF pagination

* Implement two-page spread support for the PDF viewer

* Improved shared spread zoom in PDF viewer

* Improve PDF spread navigation with fling support and configurable page gaps

* Add brightness control to PDF and EPUB readers

* Refactor folder synchronization to use shared logic engine

* Implement safe string formatting and validation for localized resources

* Implement TTS chunk skip navigation

* Implement deep-linking and playback controls for TTS media sessions

* Implement start index for TTS playback

* Improve TTS navigation, prefetching, and notification duration reporting

* Implement TTS mini playback bar for background reading

* Implement multi-window reader support for the desktop application

* Improve desktop modal window management and visibility syncing

* Implement localized string support for Desktop and shared UI

* Implement language selection and persistence for Desktop

* Implement plural string support for Desktop and migrate hardcoded counts to plurals.xml

* Implement localized banner messages and UI strings using resource-backed SharedText

* Implement compact badge styling for small book covers

* Refactor PDF native interaction and improve HTML import memory safety

* fix language persistence

* Refactor reader overflow menus to use section-based logic

* Refactor PDF layout remapping and improve text box interaction

* Improve CFI resolution and TTS resume accuracy using dynamic chunk offsets

* Centralize PDF annotation export mapping and improve metadata handling

* Add support for threaded comments in PDF highlight annotations

* Flatten highlight comments into a single thread for PDF export and allow author editing

* Integrate page slider into reader chrome and persist toggle state

* Handle fragments and queries in EPUB chapter paths

* Implement dynamic, theme-aware coloring for the reader slider

* Implement customizable app-wide font preference

* Implement one-hand zoom gestures in the PDF viewer

* Implement File Information dialog for PDF and EPUB readers

* Bump version to 1.0.49 (53)

* Refactor PDF reader logic into modular components

* Add ProGuard rules to prevent R8 optimization issues in EPUB reader screens

* Add option to use PDF filenames as display names

* Fix preservation of PDF filename display preference in library projection
This commit is contained in:
Aryan 2026-05-20 22:14:01 +05:30 committed by GitHub
parent dc5196526f
commit 9510293ac3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
245 changed files with 37538 additions and 12460 deletions

View file

@ -0,0 +1,193 @@
package com.aryan.reader
import android.content.Context
import android.view.Window
import android.view.WindowManager
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Slider
import androidx.compose.material3.Switch
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.core.content.edit
import kotlin.math.roundToInt
private const val READER_PREFS_NAME = "reader_prefs"
private const val PREF_READER_BRIGHTNESS_USE_SYSTEM = "reader_brightness_use_system"
private const val PREF_READER_BRIGHTNESS_VALUE = "reader_brightness_value"
private const val DEFAULT_CUSTOM_BRIGHTNESS = 0.75f
private const val MIN_CUSTOM_BRIGHTNESS = 0.05f
data class ReaderBrightnessSettings(
val useSystemBrightness: Boolean = true,
val customBrightness: Float = DEFAULT_CUSTOM_BRIGHTNESS
) {
val safeCustomBrightness: Float
get() = customBrightness.coerceIn(MIN_CUSTOM_BRIGHTNESS, 1f)
}
fun loadReaderBrightnessSettings(context: Context): ReaderBrightnessSettings {
val prefs = context.getSharedPreferences(READER_PREFS_NAME, Context.MODE_PRIVATE)
return ReaderBrightnessSettings(
useSystemBrightness = prefs.getBoolean(PREF_READER_BRIGHTNESS_USE_SYSTEM, true),
customBrightness = prefs.getFloat(PREF_READER_BRIGHTNESS_VALUE, DEFAULT_CUSTOM_BRIGHTNESS)
.coerceIn(MIN_CUSTOM_BRIGHTNESS, 1f)
)
}
fun saveReaderBrightnessSettings(context: Context, settings: ReaderBrightnessSettings) {
context.getSharedPreferences(READER_PREFS_NAME, Context.MODE_PRIVATE).edit {
putBoolean(PREF_READER_BRIGHTNESS_USE_SYSTEM, settings.useSystemBrightness)
putFloat(PREF_READER_BRIGHTNESS_VALUE, settings.safeCustomBrightness)
}
}
@Composable
fun ReaderBrightnessEffect(
window: Window?,
settings: ReaderBrightnessSettings
) {
DisposableEffect(window) {
val originalBrightness = window?.attributes?.screenBrightness
?: WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
onDispose {
window?.setReaderBrightness(originalBrightness)
}
}
LaunchedEffect(window, settings) {
val brightness = if (settings.useSystemBrightness) {
WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
} else {
settings.safeCustomBrightness
}
window?.setReaderBrightness(brightness)
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun ReaderBrightnessSheet(
settings: ReaderBrightnessSettings,
onSettingsChange: (ReaderBrightnessSettings) -> Unit,
onDismiss: () -> Unit
) {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
ModalBottomSheet(
onDismissRequest = onDismiss,
sheetState = sheetState
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 24.dp, vertical = 8.dp)
.padding(bottom = 32.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = stringResource(R.string.reader_brightness_title),
style = MaterialTheme.typography.titleLarge,
fontWeight = FontWeight.Bold
)
TextButton(onClick = onDismiss) {
Text(stringResource(R.string.action_done))
}
}
HorizontalDivider()
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = stringResource(R.string.reader_brightness_system),
style = MaterialTheme.typography.titleMedium
)
Text(
text = stringResource(R.string.reader_brightness_system_desc),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Switch(
checked = settings.useSystemBrightness,
onCheckedChange = { useSystem ->
onSettingsChange(settings.copy(useSystemBrightness = useSystem))
}
)
}
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = stringResource(R.string.reader_brightness_custom),
style = MaterialTheme.typography.titleMedium
)
Text(
text = stringResource(
R.string.reader_brightness_percent,
(settings.safeCustomBrightness * 100f).roundToInt()
),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.primary
)
}
Slider(
value = settings.safeCustomBrightness,
onValueChange = { brightness ->
onSettingsChange(
settings.copy(
useSystemBrightness = false,
customBrightness = brightness.coerceIn(MIN_CUSTOM_BRIGHTNESS, 1f)
)
)
},
valueRange = MIN_CUSTOM_BRIGHTNESS..1f
)
Text(
text = stringResource(R.string.reader_brightness_custom_desc),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Spacer(Modifier.height(4.dp))
}
}
}
private fun Window.setReaderBrightness(brightness: Float) {
attributes = attributes.apply {
screenBrightness = brightness
}
}