Skip to content

Commit

Permalink
feat: add RTL support and theme option to ReadableContent
Browse files Browse the repository at this point in the history
- Added support for Right-to-Left (RTL) text direction in ReadableContent.
- Implemented theme customization for ReadableContent.
  • Loading branch information
DesarrolloAntonio committed May 30, 2024
1 parent e2309af commit e672fbb
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ sealed class NavItem(
object SettingsNavItem : NavItem("settings")
object TermsOfUseNavItem : NavItem("termsOfUse")
object PrivacyPolicyNavItem : NavItem("privacyPolicy")
object ReadableContentNavItem : NavItem("readable_content/{bookmarkId}/{bookmarkUrl}/{bookmarkDate}/{bookmarkTitle}") {
fun createRoute(bookmarkId: Int, bookmarkUrl: String, bookmarkDate: String, bookmarkTitle: String): String {
object ReadableContentNavItem : NavItem("readable_content/{bookmarkId}/{bookmarkUrl}/{bookmarkDate}/{bookmarkTitle}/{bookmarkIsRtl}") {
fun createRoute(bookmarkId: Int, bookmarkUrl: String, bookmarkDate: String, bookmarkTitle: String, bookmarkIsRtl: Boolean): String {
val encodedUrl = Uri.encode(bookmarkUrl)
val encodedDate = Uri.encode(bookmarkDate)
val encodedTitle = Uri.encode(bookmarkTitle)
return "readable_content/$bookmarkId/$encodedUrl/$encodedDate/$encodedTitle"
val encodedIsRtl = bookmarkIsRtl.toString()
return "readable_content/$bookmarkId/$encodedUrl/$encodedDate/$encodedTitle/$encodedIsRtl"
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import com.desarrollodroide.pagekeeper.ui.settings.SettingsScreen
import com.desarrollodroide.pagekeeper.ui.settings.TermsOfUseScreen
import java.io.File
import com.desarrollodroide.pagekeeper.R
import com.desarrollodroide.pagekeeper.extensions.isRTLText
import com.desarrollodroide.pagekeeper.ui.readablecontent.ReadableContentScreen

@RequiresApi(Build.VERSION_CODES.N)
Expand Down Expand Up @@ -107,12 +108,12 @@ fun HomeScreen(
bookmarkId = bookmark.id,
bookmarkUrl = bookmark.url,
bookmarkDate = bookmark.modified,
bookmarkTitle = bookmark.title
bookmarkTitle = bookmark.title,
bookmarkIsRtl = bookmark.title.isRTLText() || bookmark.excerpt.isRTLText()
))
},
)
}

}
}
composable(NavItem.SettingsNavItem.route) {
Expand Down Expand Up @@ -153,13 +154,15 @@ fun HomeScreen(
navArgument("bookmarkId") { type = NavType.IntType },
navArgument("bookmarkUrl") { type = NavType.StringType },
navArgument("bookmarkDate") { type = NavType.StringType },
navArgument("bookmarkTitle") { type = NavType.StringType }
navArgument("bookmarkTitle") { type = NavType.StringType },
navArgument("bookmarkIsRtl") { type = NavType.BoolType }
)
) { backStackEntry ->
val bookmarkId = backStackEntry.arguments?.getInt("bookmarkId") ?: 0
val bookmarkUrl = backStackEntry.arguments?.getString("bookmarkUrl")?.let { Uri.decode(it) } ?: ""
val bookmarkDate = backStackEntry.arguments?.getString("bookmarkDate")?.let { Uri.decode(it) } ?: ""
val bookmarkTitle = backStackEntry.arguments?.getString("bookmarkTitle")?.let { Uri.decode(it) } ?: ""
val bookmarkIsRtl = backStackEntry.arguments?.getBoolean("bookmarkIsRtl")?: false

ReadableContentScreen(
readableContentViewModel = get(),
Expand All @@ -170,7 +173,8 @@ fun HomeScreen(
navController.navigateUp()
},
openUrlInBrowser = openUrlInBrowser,
bookmarkTitle = bookmarkTitle
bookmarkTitle = bookmarkTitle,
isRtl = bookmarkIsRtl
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,18 @@ import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.compose.BackHandler
import androidx.annotation.RequiresApi
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material3.CenterAlignedTopAppBar
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.ui.viewinterop.AndroidView
import com.desarrollodroide.data.helpers.ThemeMode
import com.desarrollodroide.pagekeeper.ui.components.InfiniteProgressDialog

@RequiresApi(Build.VERSION_CODES.N)
Expand All @@ -38,26 +31,35 @@ fun ReadableContentScreen(
bookmarkId: Int,
openUrlInBrowser: (String) -> Unit,
bookmarkDate: String,
bookmarkTitle: String
bookmarkTitle: String,
isRtl: Boolean
) {
BackHandler {
onBack()
}
BackHandler { onBack() }

LaunchedEffect(Unit) {
readableContentViewModel.loadInitialData()
readableContentViewModel.getBookmarkReadableContent(bookmarkId)
}
val readableContentState = readableContentViewModel.readableContentState.collectAsState()

val themeMode by readableContentViewModel.themeMode.collectAsState()
val isDarkTheme = when (themeMode) {
ThemeMode.DARK -> true
ThemeMode.LIGHT -> false
ThemeMode.AUTO -> isSystemInDarkTheme()
}

val themeCss = if (isDarkTheme) DARK_THEME_CSS else LIGHT_THEME_CSS
val directionCss = if (isRtl) RTL_CSS else LTR_CSS

val readableContentState by readableContentViewModel.readableContentState.collectAsState()

Scaffold(
topBar = {
CenterAlignedTopAppBar(
title = { Text("Content", style = MaterialTheme.typography.titleLarge) },
navigationIcon = {
IconButton(onClick = onBack) {
Icon(
Icons.AutoMirrored.Filled.ArrowBack,
contentDescription = "Back"
)
Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = "Back")
}
},
colors = TopAppBarDefaults.centerAlignedTopAppBarColors(
Expand All @@ -67,70 +69,57 @@ fun ReadableContentScreen(
},
containerColor = MaterialTheme.colorScheme.background
) { paddingValues ->
Box(
modifier = Modifier
.padding(paddingValues)
.fillMaxWidth()
) {
if (readableContentState.value.isLoading) {
Box(modifier = Modifier.padding(paddingValues).fillMaxWidth()) {
if (readableContentState.isLoading) {
InfiniteProgressDialog(onDismissRequest = {})
} else {
LazyColumn(
modifier = Modifier
.fillMaxWidth()
) {
LazyColumn(modifier = Modifier.fillMaxWidth()) {
item {
TopSection(
title = bookmarkTitle,
date = bookmarkDate,
onClick = { openUrlInBrowser.invoke(bookmarkUrl) }
onClick = { openUrlInBrowser(bookmarkUrl) }
)
}
item {
if (readableContentState.value.error != null) {
ErrorView(errorMessage = readableContentState.value.error ?: "Error getting readable content")
} else {
readableContentState.value.data?.let { readableMessage ->
AndroidView(factory = { context ->
WebView(context).apply {
webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
val css = """
(function() {
var style = document.createElement('style');
style.innerHTML = `
img {
max-width: 100%;
height: auto;
}
`;
document.head.appendChild(style);
})();
""".trimIndent()
view?.evaluateJavascript(css, null)
}
readableContentState.error?.let { error ->
ErrorView(errorMessage = error)
} ?: readableContentState.data?.let { readableMessage ->
AndroidView(factory = { context ->
WebView(context).apply {
webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
val css = """
(function() {
var style = document.createElement('style');
style.innerHTML = `
img {
max-width: 100%;
height: auto;
}
$directionCss
$themeCss
`;
document.head.appendChild(style);
})();
""".trimIndent()
view?.evaluateJavascript(css, null)
}

override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
request?.url?.let { url ->
val intent = Intent(Intent.ACTION_VIEW, url)
context.startActivity(intent)
return true
}
return false
override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
request?.url?.let { url ->
val intent = Intent(Intent.ACTION_VIEW, url)
context.startActivity(intent)
return true
}
return false
}
settings.javaScriptEnabled = true
loadDataWithBaseURL(
null,
readableMessage.html,
"text/html",
"UTF-8",
null
)
}
})
}
settings.javaScriptEnabled = true
loadDataWithBaseURL(null, readableMessage.html, "text/html", "UTF-8", null)
}
})
}
}
}
Expand All @@ -139,4 +128,36 @@ fun ReadableContentScreen(
}
}

private const val DARK_THEME_CSS = """
body {
background-color: #121212;
color: #ffffff;
}
a {
color: #bb86fc;
}
"""

private const val LIGHT_THEME_CSS = """
body {
background-color: #ffffff;
color: #000000;
}
a {
color: #1a0dab;
}
"""

private const val RTL_CSS = """
body {
direction: rtl;
text-align: right;
}
"""

private const val LTR_CSS = """
body {
direction: ltr;
text-align: left;
}
"""
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.desarrollodroide.common.result.Result
import com.desarrollodroide.data.helpers.ThemeMode
import com.desarrollodroide.data.local.preferences.SettingsPreferenceDataSource
import com.desarrollodroide.domain.usecase.GetBookmarkReadableContentUseCase
import com.desarrollodroide.model.ReadableMessage
Expand All @@ -26,10 +27,14 @@ class ReadableContentViewModel(
private val _readableContentState = MutableStateFlow(UiState<ReadableMessage>(idle = true))
val readableContentState = _readableContentState.asStateFlow()

val themeMode = MutableStateFlow<ThemeMode>(ThemeMode.AUTO)


fun loadInitialData() {
viewModelScope.launch {
serverUrl = settingsPreferenceDataSource.getUrl()
token = settingsPreferenceDataSource.getToken()
themeMode.value = settingsPreferenceDataSource.getThemeMode()
}
}

Expand Down

0 comments on commit e672fbb

Please sign in to comment.