Skip to content

Commit a112e29

Browse files
committed
Follow feed openIn parameter when opening an item from a notification
1 parent 144cd9f commit a112e29

File tree

8 files changed

+159
-12
lines changed

8 files changed

+159
-12
lines changed

app/src/main/java/com/readrops/app/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ class MainActivity : ComponentActivity(), KoinComponent {
130130

131131
get<BaseRepository>(parameters = { parametersOf(account) })
132132
.setItemReadState(item)
133-
HomeScreen.openItemScreen(itemId)
133+
HomeScreen.openItem(itemId)
134134
}
135135
}
136136

app/src/main/java/com/readrops/app/home/HomeScreen.kt

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import cafe.adriel.voyager.navigator.tab.TabNavigator
3131
import com.readrops.app.R
3232
import com.readrops.app.account.AccountTab
3333
import com.readrops.app.feeds.FeedTab
34-
import com.readrops.app.item.ItemScreen
3534
import com.readrops.app.more.MoreTab
3635
import com.readrops.app.timelime.TimelineTab
3736
import com.readrops.app.util.components.AndroidScreen
@@ -40,21 +39,13 @@ import kotlinx.coroutines.flow.receiveAsFlow
4039

4140
object HomeScreen : AndroidScreen() {
4241

43-
private val itemChannel = Channel<Int>()
4442
private val tabChannel = Channel<Tab>()
4543

4644
@Composable
4745
override fun Content() {
4846
val navigator = LocalNavigator.currentOrThrow
4947
val scaffoldInsets = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
5048

51-
LaunchedEffect(Unit) {
52-
itemChannel.receiveAsFlow()
53-
.collect {
54-
navigator.push(ItemScreen(it))
55-
}
56-
}
57-
5849
TabNavigator(
5950
tab = TimelineTab
6051
) { tabNavigator ->
@@ -138,8 +129,9 @@ object HomeScreen : AndroidScreen() {
138129
}
139130
}
140131

141-
suspend fun openItemScreen(itemId: Int) {
142-
itemChannel.send(itemId)
132+
suspend fun openItem(itemId: Int) {
133+
tabChannel.send(TimelineTab)
134+
TimelineTab.openItem(itemId)
143135
}
144136

145137
suspend fun openTab(tab: Tab) {

app/src/main/java/com/readrops/app/more/MoreTab.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import cafe.adriel.voyager.navigator.tab.TabOptions
3131
import com.readrops.app.BuildConfig
3232
import com.readrops.app.R
3333
import com.readrops.app.account.selection.adaptiveIconPainterResource
34+
import com.readrops.app.more.debug.DebugScreen
3435
import com.readrops.app.more.preferences.PreferencesScreen
3536
import com.readrops.app.util.components.IconText
3637
import com.readrops.app.util.components.SelectableIconText
@@ -173,6 +174,18 @@ object MoreTab : Tab, KoinComponent {
173174
tint = MaterialTheme.colorScheme.primary,
174175
onClick = { showDonationDialog = true }
175176
)
177+
178+
if (BuildConfig.DEBUG) {
179+
SelectableIconText(
180+
icon = painterResource(id = R.drawable.ic_bug),
181+
text = "Debug",
182+
style = MaterialTheme.typography.titleMedium.copy(fontWeight = FontWeight.Normal),
183+
spacing = MaterialTheme.spacing.largeSpacing,
184+
padding = MaterialTheme.spacing.mediumSpacing,
185+
tint = MaterialTheme.colorScheme.primary,
186+
onClick = { navigator.push(DebugScreen()) }
187+
)
188+
}
176189
}
177190
}
178191
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
package com.readrops.app.more.debug
2+
3+
import android.annotation.SuppressLint
4+
import android.app.PendingIntent
5+
import android.content.Intent
6+
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.foundation.layout.padding
8+
import androidx.compose.material.icons.Icons
9+
import androidx.compose.material.icons.automirrored.filled.ArrowBack
10+
import androidx.compose.material3.ExperimentalMaterial3Api
11+
import androidx.compose.material3.Icon
12+
import androidx.compose.material3.IconButton
13+
import androidx.compose.material3.Scaffold
14+
import androidx.compose.material3.Text
15+
import androidx.compose.material3.TopAppBar
16+
import androidx.compose.runtime.Composable
17+
import androidx.compose.runtime.rememberCoroutineScope
18+
import androidx.compose.ui.Modifier
19+
import androidx.compose.ui.platform.LocalContext
20+
import androidx.compose.ui.res.stringResource
21+
import androidx.core.app.NotificationCompat
22+
import androidx.core.app.NotificationCompat.Builder
23+
import androidx.core.app.NotificationManagerCompat
24+
import cafe.adriel.voyager.navigator.LocalNavigator
25+
import cafe.adriel.voyager.navigator.currentOrThrow
26+
import com.readrops.app.MainActivity
27+
import com.readrops.app.R
28+
import com.readrops.app.ReadropsApp
29+
import com.readrops.app.more.preferences.components.BasePreference
30+
import com.readrops.app.more.preferences.components.PreferenceHeader
31+
import com.readrops.app.sync.SyncWorker.Companion.ACCOUNT_ID_KEY
32+
import com.readrops.app.sync.SyncWorker.Companion.ITEM_ID_KEY
33+
import com.readrops.app.sync.SyncWorker.Companion.SYNC_RESULT_NOTIFICATION_ID
34+
import com.readrops.app.util.components.AndroidScreen
35+
import com.readrops.db.Database
36+
import kotlinx.coroutines.flow.first
37+
import kotlinx.coroutines.launch
38+
import org.koin.core.component.KoinComponent
39+
import org.koin.core.component.get
40+
41+
class DebugScreen : AndroidScreen(), KoinComponent {
42+
43+
@OptIn(ExperimentalMaterial3Api::class)
44+
@SuppressLint("MissingPermission")
45+
@Composable
46+
override fun Content() {
47+
val context = LocalContext.current
48+
val navigator = LocalNavigator.currentOrThrow
49+
val coroutineScope = rememberCoroutineScope()
50+
51+
Scaffold(
52+
topBar = {
53+
TopAppBar(
54+
title = { Text("Debug") },
55+
navigationIcon = {
56+
IconButton(
57+
onClick = { navigator.pop() }
58+
) {
59+
Icon(
60+
imageVector = Icons.AutoMirrored.Default.ArrowBack,
61+
contentDescription = null
62+
)
63+
}
64+
}
65+
)
66+
}
67+
) { paddingValues ->
68+
Column(
69+
modifier = Modifier.padding(paddingValues)
70+
) {
71+
PreferenceHeader(stringResource(R.string.notifications))
72+
73+
BasePreference(
74+
title = "Send notification: Single item from single feed",
75+
onClick = {
76+
coroutineScope.launch {
77+
val database = get<Database>()
78+
79+
val item = database.itemDao().selectFirst()
80+
val account = database.accountDao().selectCurrentAccount().first()
81+
82+
val intent = Intent(context, MainActivity::class.java).apply {
83+
putExtra(ACCOUNT_ID_KEY, account!!.id)
84+
putExtra(ITEM_ID_KEY, item.id)
85+
}
86+
87+
val notificationBuilder = Builder(context, ReadropsApp.SYNC_CHANNEL_ID)
88+
.setContentTitle(item.title)
89+
.setContentText("Test notification")
90+
.setStyle(
91+
NotificationCompat.BigTextStyle().bigText("Test notification")
92+
)
93+
.setSmallIcon(R.drawable.ic_notifications)
94+
.setContentIntent(
95+
PendingIntent.getActivity(
96+
context,
97+
0,
98+
intent,
99+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
100+
)
101+
)
102+
.setAutoCancel(true)
103+
104+
get<NotificationManagerCompat>().notify(
105+
SYNC_RESULT_NOTIFICATION_ID,
106+
notificationBuilder.build()
107+
)
108+
}
109+
}
110+
)
111+
}
112+
}
113+
114+
}
115+
}

app/src/main/java/com/readrops/app/timelime/TimelineScreenModel.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import com.readrops.db.filters.OrderType
2626
import com.readrops.db.filters.QueryFilters
2727
import com.readrops.db.filters.SubFilter
2828
import com.readrops.db.pojo.ItemWithFeed
29+
import com.readrops.db.queries.ItemSelectionQueryBuilder
2930
import com.readrops.db.queries.ItemsQueryBuilder
3031
import kotlinx.coroutines.CoroutineDispatcher
3132
import kotlinx.coroutines.Dispatchers
@@ -36,6 +37,7 @@ import kotlinx.coroutines.flow.asStateFlow
3637
import kotlinx.coroutines.flow.collectLatest
3738
import kotlinx.coroutines.flow.combine
3839
import kotlinx.coroutines.flow.emptyFlow
40+
import kotlinx.coroutines.flow.firstOrNull
3941
import kotlinx.coroutines.flow.flatMapLatest
4042
import kotlinx.coroutines.flow.update
4143
import kotlinx.coroutines.launch
@@ -441,6 +443,11 @@ class TimelineScreenModel(
441443
preferences.displayNotificationsPermission.write(false)
442444
}
443445
}
446+
447+
suspend fun selectItemWithFeed(itemId: Int): ItemWithFeed? {
448+
val query = ItemSelectionQueryBuilder.buildQuery(itemId, currentAccount!!.config.useSeparateState)
449+
return database.itemDao().selectItemById(query).firstOrNull()
450+
}
444451
}
445452

446453
@Stable

app/src/main/java/com/readrops/app/timelime/TimelineTab.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,15 @@ import com.readrops.db.filters.OrderField
7878
import com.readrops.db.filters.OrderType
7979
import com.readrops.db.filters.SubFilter
8080
import com.readrops.db.pojo.ItemWithFeed
81+
import kotlinx.coroutines.channels.Channel
8182
import kotlinx.coroutines.flow.filter
83+
import kotlinx.coroutines.flow.receiveAsFlow
8284

8385

8486
object TimelineTab : Tab {
8587

88+
private val openItemChannel = Channel<Int>()
89+
8690
override val options: TabOptions
8791
@Composable
8892
get() = TabOptions(
@@ -118,6 +122,14 @@ object TimelineTab : Tab {
118122
screenModel.disableDisplayNotificationsPermission()
119123
}
120124

125+
LaunchedEffect(Unit) {
126+
openItemChannel.receiveAsFlow()
127+
.collect { itemId ->
128+
screenModel.selectItemWithFeed(itemId)
129+
?.let { openItem(it, preferences, navigator, context) }
130+
}
131+
}
132+
121133
LaunchedEffect(preferences.displayNotificationsPermission) {
122134
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.TIRAMISU
123135
&& preferences.displayNotificationsPermission
@@ -504,4 +516,8 @@ object TimelineTab : Tab {
504516
}
505517
}
506518
}
519+
520+
suspend fun openItem(itemId: Int) {
521+
openItemChannel.send(itemId)
522+
}
507523
}

db/src/main/java/com/readrops/db/dao/ItemDao.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ interface ItemDao : BaseDao<Item> {
1919
@Query("Select * From Item Where id = :itemId")
2020
suspend fun select(itemId: Int): Item
2121

22+
@Query("Select * From Item Limit 1")
23+
suspend fun selectFirst(): Item
24+
2225
@RawQuery(observedEntities = [Item::class, Feed::class, Folder::class, ItemState::class])
2326
fun selectAll(query: SupportSQLiteQuery): PagingSource<Int, ItemWithFeed>
2427

db/src/main/java/com/readrops/db/queries/ItemSelectionQueryBuilder.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ object ItemSelectionQueryBuilder {
1919
"color",
2020
"read_time",
2121
"Feed.name",
22+
"Feed.open_in",
2223
"Feed.id as feedId",
2324
"siteUrl",
2425
"Folder.id as folder_id",

0 commit comments

Comments
 (0)