From 5f99afc8adca8df6205edcb22fc9f9d5511a3a33 Mon Sep 17 00:00:00 2001 From: Shinokuni Date: Tue, 10 Dec 2024 15:15:07 +0100 Subject: [PATCH] Follow Feed openIn parameter in TimelineTab --- .../java/com/readrops/app/item/ItemScreen.kt | 30 ++-------- .../com/readrops/app/timelime/TimelineItem.kt | 6 +- .../app/timelime/TimelineScreenModel.kt | 10 +++- .../com/readrops/app/timelime/TimelineTab.kt | 60 +++++++++++++------ .../readrops/app/util/ContextExtensions.kt | 33 ++++++++++ .../java/com/readrops/app/util/Extensions.kt | 4 -- .../java/com/readrops/db/pojo/ItemWithFeed.kt | 4 +- .../readrops/db/queries/ItemsQueryBuilder.kt | 1 + 8 files changed, 95 insertions(+), 53 deletions(-) create mode 100644 app/src/main/java/com/readrops/app/util/ContextExtensions.kt diff --git a/app/src/main/java/com/readrops/app/item/ItemScreen.kt b/app/src/main/java/com/readrops/app/item/ItemScreen.kt index 865039a8..04564078 100644 --- a/app/src/main/java/com/readrops/app/item/ItemScreen.kt +++ b/app/src/main/java/com/readrops/app/item/ItemScreen.kt @@ -1,10 +1,6 @@ package com.readrops.app.item -import android.content.Intent -import android.net.Uri import android.widget.RelativeLayout -import androidx.browser.customtabs.CustomTabColorSchemeParams -import androidx.browser.customtabs.CustomTabsIntent import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.IntrinsicSize @@ -39,7 +35,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.NestedScrollSource import androidx.compose.ui.input.nestedscroll.nestedScroll @@ -52,7 +47,6 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.net.toUri import androidx.core.view.children import androidx.lifecycle.compose.collectAsStateWithLifecycle import cafe.adriel.voyager.koin.koinScreenModel @@ -66,6 +60,8 @@ import com.readrops.app.util.components.AndroidScreen import com.readrops.app.util.components.CenteredProgressIndicator import com.readrops.app.util.components.FeedIcon import com.readrops.app.util.components.IconText +import com.readrops.app.util.openInCustomTab +import com.readrops.app.util.openUrl import com.readrops.app.util.theme.MediumSpacer import com.readrops.app.util.theme.ShortSpacer import com.readrops.app.util.theme.spacing @@ -151,29 +147,11 @@ class ItemScreen( primaryColor } - val colorScheme = when (state.theme) { - "light" -> CustomTabsIntent.COLOR_SCHEME_LIGHT - "dark" -> CustomTabsIntent.COLOR_SCHEME_DARK - else -> CustomTabsIntent.COLOR_SCHEME_SYSTEM - } - fun openUrl(url: String) { if (state.openInExternalBrowser) { - val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url)) - context.startActivity(intent) + context.openUrl(url) } else { - CustomTabsIntent.Builder() - .setDefaultColorSchemeParams( - CustomTabColorSchemeParams - .Builder() - .setToolbarColor(accentColor.toArgb()) - .build() - ) - .setShareState(CustomTabsIntent.SHARE_STATE_ON) - .setUrlBarHidingEnabled(true) - .setColorScheme(colorScheme) - .build() - .launchUrl(context, url.toUri()) + context.openInCustomTab(url, state.theme, accentColor) } } diff --git a/app/src/main/java/com/readrops/app/timelime/TimelineItem.kt b/app/src/main/java/com/readrops/app/timelime/TimelineItem.kt index 65f7c3fb..1a329571 100644 --- a/app/src/main/java/com/readrops/app/timelime/TimelineItem.kt +++ b/app/src/main/java/com/readrops/app/timelime/TimelineItem.kt @@ -6,7 +6,6 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.material3.CardDefaults -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.SwipeToDismissBox @@ -27,6 +26,7 @@ import com.readrops.app.util.DefaultPreview import com.readrops.app.util.theme.ReadropsTheme import com.readrops.app.util.theme.spacing import com.readrops.db.entities.Folder +import com.readrops.db.entities.OpenIn import com.readrops.db.pojo.ItemWithFeed import java.time.LocalDateTime @@ -38,7 +38,6 @@ enum class TimelineItemSize { const val readAlpha = 0.6f -@OptIn(ExperimentalMaterial3Api::class) @Composable fun TimelineItem( itemWithFeed: ItemWithFeed, @@ -168,7 +167,8 @@ private val itemWithFeed = ItemWithFeed( feedId = 0, feedIconUrl = "", websiteUrl = "", - folder = Folder(name = "Folder name") + folder = Folder(name = "Folder name"), + openIn = OpenIn.LOCAL_VIEW ) @DefaultPreview diff --git a/app/src/main/java/com/readrops/app/timelime/TimelineScreenModel.kt b/app/src/main/java/com/readrops/app/timelime/TimelineScreenModel.kt index 5f1233ca..98dd551f 100644 --- a/app/src/main/java/com/readrops/app/timelime/TimelineScreenModel.kt +++ b/app/src/main/java/com/readrops/app/timelime/TimelineScreenModel.kt @@ -127,6 +127,8 @@ class TimelineScreenModel( preferences.showReadItems.flow, preferences.orderField.flow, preferences.orderType.flow, + preferences.theme.flow, + preferences.openLinksWith.flow, transform = { TimelinePreferences( itemSize = when (it[0]) { @@ -138,7 +140,9 @@ class TimelineScreenModel( displayNotificationsPermission = it[2] as Boolean, showReadItems = it[3] as Boolean, orderField = OrderField.valueOf(it[4] as String), - orderType = OrderType.valueOf(it[5] as String) + orderType = OrderType.valueOf(it[5] as String), + theme = it[6] as String, + openInExternalBrowser = it[7] as String == "external_navigator" ) } ) @@ -473,7 +477,9 @@ data class TimelinePreferences( val displayNotificationsPermission: Boolean = false, val showReadItems: Boolean = true, val orderField: OrderField = OrderField.DATE, - val orderType: OrderType = OrderType.DESC + val orderType: OrderType = OrderType.DESC, + val theme: String = "light", + val openInExternalBrowser: Boolean = false ) sealed interface DialogState { diff --git a/app/src/main/java/com/readrops/app/timelime/TimelineTab.kt b/app/src/main/java/com/readrops/app/timelime/TimelineTab.kt index e0df2bcd..6851a899 100644 --- a/app/src/main/java/com/readrops/app/timelime/TimelineTab.kt +++ b/app/src/main/java/com/readrops/app/timelime/TimelineTab.kt @@ -2,6 +2,7 @@ package com.readrops.app.timelime import android.Manifest import android.annotation.SuppressLint +import android.content.Context import androidx.activity.compose.BackHandler import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.result.contract.ActivityResultContracts @@ -40,6 +41,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.snapshotFlow import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource @@ -53,6 +55,7 @@ import androidx.paging.compose.collectAsLazyPagingItems import androidx.paging.compose.itemKey import cafe.adriel.voyager.koin.koinScreenModel import cafe.adriel.voyager.navigator.LocalNavigator +import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.tab.Tab import cafe.adriel.voyager.navigator.tab.TabOptions @@ -64,7 +67,10 @@ import com.readrops.app.util.components.CenteredProgressIndicator import com.readrops.app.util.components.Placeholder import com.readrops.app.util.components.RefreshScreen import com.readrops.app.util.components.dialog.TwoChoicesDialog +import com.readrops.app.util.openInCustomTab +import com.readrops.app.util.openUrl import com.readrops.app.util.theme.spacing +import com.readrops.db.entities.OpenIn import com.readrops.db.filters.MainFilter import com.readrops.db.filters.OrderField import com.readrops.db.filters.OrderType @@ -99,10 +105,17 @@ object TimelineTab : Tab { val topAppBarState = rememberTopAppBarState() val topAppBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(topAppBarState) - val launcher = rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()) { - screenModel.disableDisplayNotificationsPermission() + val lazyColumnPadding = if (preferences.itemSize == TimelineItemSize.COMPACT) { + 0.dp + } else { + MaterialTheme.spacing.shortSpacing } + val launcher = + rememberLauncherForActivityResult(contract = ActivityResultContracts.RequestPermission()) { + screenModel.disableDisplayNotificationsPermission() + } + LaunchedEffect(preferences.displayNotificationsPermission) { if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU && preferences.displayNotificationsPermission @@ -317,19 +330,8 @@ object TimelineTab : Tab { LazyColumn( state = lazyListState, - contentPadding = PaddingValues( - vertical = if (preferences.itemSize == TimelineItemSize.COMPACT) { - 0.dp - } else { - MaterialTheme.spacing.shortSpacing - } - ), - verticalArrangement = Arrangement.spacedBy( - if (preferences.itemSize == TimelineItemSize.COMPACT) { - 0.dp - } else - MaterialTheme.spacing.shortSpacing - ) + contentPadding = PaddingValues(vertical = lazyColumnPadding), + verticalArrangement = Arrangement.spacedBy(lazyColumnPadding) ) { items( count = items.itemCount, @@ -342,7 +344,12 @@ object TimelineTab : Tab { itemWithFeed = itemWithFeed, onClick = { screenModel.setItemRead(itemWithFeed.item) - navigator.push(ItemScreen(itemWithFeed.item.id)) + openItem( + itemWithFeed = itemWithFeed, + preferences = preferences, + navigator = navigator, + context = context + ) }, onFavorite = { screenModel.updateStarState(itemWithFeed.item) @@ -430,7 +437,26 @@ object TimelineTab : Tab { ) } - null -> {} + else -> {} + } + } + } + + private fun openItem( + itemWithFeed: ItemWithFeed, + preferences: TimelinePreferences, + navigator: Navigator, + context: Context + ) { + val url = itemWithFeed.item.link!! + + if (itemWithFeed.openIn == OpenIn.LOCAL_VIEW) { + navigator.push(ItemScreen(itemWithFeed.item.id)) + } else { + if (preferences.openInExternalBrowser) { + context.openUrl(url) + } else { + context.openInCustomTab(url, preferences.theme, Color(itemWithFeed.color)) } } } diff --git a/app/src/main/java/com/readrops/app/util/ContextExtensions.kt b/app/src/main/java/com/readrops/app/util/ContextExtensions.kt new file mode 100644 index 00000000..bd92a122 --- /dev/null +++ b/app/src/main/java/com/readrops/app/util/ContextExtensions.kt @@ -0,0 +1,33 @@ +package com.readrops.app.util + +import android.content.Context +import android.content.Intent +import android.net.Uri +import androidx.browser.customtabs.CustomTabColorSchemeParams +import androidx.browser.customtabs.CustomTabsIntent +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.core.net.toUri + +fun Context.openUrl(url: String) = startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) + +fun Context.openInCustomTab(url: String, theme: String?, color: Color) { + val colorScheme = when (theme) { + "light" -> CustomTabsIntent.COLOR_SCHEME_LIGHT + "dark" -> CustomTabsIntent.COLOR_SCHEME_DARK + else -> CustomTabsIntent.COLOR_SCHEME_SYSTEM + } + + CustomTabsIntent.Builder() + .setDefaultColorSchemeParams( + CustomTabColorSchemeParams + .Builder() + .setToolbarColor(color.toArgb()) + .build() + ) + .setShareState(CustomTabsIntent.SHARE_STATE_ON) + .setUrlBarHidingEnabled(true) + .setColorScheme(colorScheme) + .build() + .launchUrl(this, url.toUri()) +} diff --git a/app/src/main/java/com/readrops/app/util/Extensions.kt b/app/src/main/java/com/readrops/app/util/Extensions.kt index 876dddf0..f62fd35b 100644 --- a/app/src/main/java/com/readrops/app/util/Extensions.kt +++ b/app/src/main/java/com/readrops/app/util/Extensions.kt @@ -1,8 +1,5 @@ package com.readrops.app.util -import android.content.Context -import android.content.Intent -import android.net.Uri import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -11,7 +8,6 @@ import java.io.Serializable fun TextStyle.toDp(): Dp = fontSize.value.dp -fun Context.openUrl(url: String) = startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url))) val Data.serializables by lazy { mutableMapOf() diff --git a/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.kt b/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.kt index fc24ce77..4ba98c0f 100644 --- a/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.kt +++ b/db/src/main/java/com/readrops/db/pojo/ItemWithFeed.kt @@ -5,6 +5,7 @@ import androidx.room.ColumnInfo import androidx.room.Embedded import com.readrops.db.entities.Folder import com.readrops.db.entities.Item +import com.readrops.db.entities.OpenIn data class ItemWithFeed( @Embedded val item: Item, @@ -19,5 +20,6 @@ data class ItemWithFeed( // as since kotlin 2.0.20 it wouldn't work anymore, because of Item properties mutability // TODO see how to resolve this by improving Item immutability @ColumnInfo(name = "is_starred") val isStarred: Boolean = false, - @ColumnInfo(name = "is_read") val isRead: Boolean = false + @ColumnInfo(name = "is_read") val isRead: Boolean = false, + @ColumnInfo(name = "open_in") val openIn: OpenIn? ) \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/queries/ItemsQueryBuilder.kt b/db/src/main/java/com/readrops/db/queries/ItemsQueryBuilder.kt index 7d9486c4..86dd9daf 100644 --- a/db/src/main/java/com/readrops/db/queries/ItemsQueryBuilder.kt +++ b/db/src/main/java/com/readrops/db/queries/ItemsQueryBuilder.kt @@ -24,6 +24,7 @@ object ItemsQueryBuilder { "read_time", "Feed.id as feedId", "Feed.account_id", + "Feed.open_in", "Folder.id as folder_id", "Folder.name as folder_name" )