Skip to content

Commit 9ebbe03

Browse files
committed
Display tags in TimelineTab and ItemScreen
1 parent 455194e commit 9ebbe03

File tree

9 files changed

+154
-4
lines changed

9 files changed

+154
-4
lines changed

app/src/main/java/com/readrops/app/item/ItemScreenModel.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ class ItemScreenModel(
176176
.flow
177177
.map {
178178
it.map { itemWithFeed ->
179+
itemWithFeed.item.tags = database.tagDao().selectAllByItem(itemWithFeed.item.id)
180+
179181
val stateChange = state.value.stateChanges
180182
.firstOrNull { stateChange -> stateChange.itemId == itemWithFeed.item.id }
181183

@@ -190,7 +192,7 @@ class ItemScreenModel(
190192
!itemWithFeed.isStarred
191193
} else {
192194
itemWithFeed.isStarred
193-
}
195+
},
194196
)
195197
} else {
196198
itemWithFeed

app/src/main/java/com/readrops/app/item/components/SimpleTitle.kt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package com.readrops.app.item.components
22

3+
import androidx.compose.foundation.layout.Arrangement
34
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.FlowRow
46
import androidx.compose.foundation.layout.fillMaxWidth
57
import androidx.compose.foundation.layout.padding
68
import androidx.compose.foundation.shape.CircleShape
@@ -22,6 +24,7 @@ import com.readrops.app.util.DefaultPreview
2224
import com.readrops.app.util.components.FeedIcon
2325
import com.readrops.app.util.components.IconText
2426
import com.readrops.app.util.extensions.displayColor
27+
import com.readrops.app.util.theme.MediumSpacer
2528
import com.readrops.app.util.theme.ReadropsTheme
2629
import com.readrops.app.util.theme.ShortSpacer
2730
import com.readrops.app.util.theme.spacing
@@ -38,6 +41,7 @@ fun SimpleTitle(
3841
) {
3942
val item = itemWithFeed.item
4043
val spacing = MaterialTheme.spacing.mediumSpacing
44+
val accentColor = itemWithFeed.displayColor(MaterialTheme.colorScheme.background.toArgb())
4145

4246
Column(
4347
horizontalAlignment = Alignment.CenterHorizontally,
@@ -100,6 +104,26 @@ fun SimpleTitle(
100104
style = MaterialTheme.typography.labelMedium,
101105
color = onBackgroundColor
102106
)
107+
108+
if (itemWithFeed.item.tags.isNotEmpty()) {
109+
MediumSpacer()
110+
111+
FlowRow(
112+
horizontalArrangement = Arrangement.spacedBy(
113+
MaterialTheme.spacing.shortSpacing,
114+
Alignment.CenterHorizontally
115+
),
116+
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.shortSpacing)
117+
) {
118+
for (tag in itemWithFeed.item.tags) {
119+
TagSurface(
120+
name = tag.name,
121+
backgroundColor = accentColor
122+
)
123+
124+
}
125+
}
126+
}
103127
}
104128
}
105129

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.readrops.app.item.components
2+
3+
import androidx.compose.foundation.layout.padding
4+
import androidx.compose.foundation.shape.RoundedCornerShape
5+
import androidx.compose.material3.MaterialTheme
6+
import androidx.compose.material3.Surface
7+
import androidx.compose.material3.Text
8+
import androidx.compose.runtime.Composable
9+
import androidx.compose.ui.Modifier
10+
import androidx.compose.ui.graphics.Color
11+
import androidx.compose.ui.graphics.toArgb
12+
import androidx.compose.ui.text.style.TextOverflow
13+
import androidx.compose.ui.unit.dp
14+
import com.readrops.app.util.Utils
15+
import com.readrops.app.util.extensions.canDisplayOnBackground
16+
import com.readrops.app.util.theme.spacing
17+
18+
@Composable
19+
fun TagSurface(
20+
name: String,
21+
backgroundColor: Color,
22+
truncateName: Boolean = false,
23+
) {
24+
Surface(
25+
shape = RoundedCornerShape(48.dp),
26+
color = backgroundColor,
27+
contentColor = if (Color.White.toArgb()
28+
.canDisplayOnBackground(backgroundColor.toArgb(), threshold = 2.5f)
29+
) {
30+
Color.White
31+
} else {
32+
Color.Black
33+
}
34+
) {
35+
Text(
36+
text = if (truncateName) {
37+
Utils.truncateString(name, 30)
38+
} else {
39+
name
40+
},
41+
maxLines = 1,
42+
overflow = TextOverflow.Ellipsis,
43+
style = MaterialTheme.typography.bodySmall,
44+
modifier = Modifier.padding(
45+
horizontal = MaterialTheme.spacing.shortSpacing,
46+
vertical = MaterialTheme.spacing.veryShortSpacing
47+
)
48+
)
49+
}
50+
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import androidx.paging.Pager
66
import androidx.paging.PagingConfig
77
import androidx.paging.PagingData
88
import androidx.paging.cachedIn
9+
import androidx.paging.map
910
import androidx.work.workDataOf
1011
import cafe.adriel.voyager.core.model.screenModelScope
1112
import com.readrops.app.R
@@ -49,6 +50,7 @@ import kotlinx.coroutines.flow.emptyFlow
4950
import kotlinx.coroutines.flow.first
5051
import kotlinx.coroutines.flow.firstOrNull
5152
import kotlinx.coroutines.flow.flatMapLatest
53+
import kotlinx.coroutines.flow.map
5254
import kotlinx.coroutines.flow.stateIn
5355
import kotlinx.coroutines.flow.update
5456
import kotlinx.coroutines.launch
@@ -191,7 +193,15 @@ class TimelineScreenModel(
191193
pagingSourceFactory = {
192194
database.itemDao().selectAll(query)
193195
},
194-
).flow
196+
)
197+
.flow
198+
.map { pagingData ->
199+
pagingData.map { itemWithFeed ->
200+
itemWithFeed.item.tags = database.tagDao().selectAllByItem(itemWithFeed.item.id)
201+
202+
itemWithFeed
203+
}
204+
}
195205
.cachedIn(screenModelScope)
196206

197207
_timelineState.update {

app/src/main/java/com/readrops/app/timelime/components/TimelineItem.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.readrops.app.util.theme.ReadropsTheme
2727
import com.readrops.app.util.theme.spacing
2828
import com.readrops.db.entities.Folder
2929
import com.readrops.db.entities.OpenIn
30+
import com.readrops.db.entities.Tag
3031
import com.readrops.db.pojo.ItemWithFeed
3132
import java.time.LocalDateTime
3233

@@ -205,7 +206,18 @@ val itemWithFeed = ItemWithFeed(
205206
at finibus elit libero at mi. Etiam hendrerit sapien eu porta feugiat. Duis porttitor"""
206207
.replace("\n", "")
207208
.trimMargin(),
208-
imageLink = ""
209+
imageLink = "",
210+
tags = listOf(
211+
Tag(name = "Tag 1"),
212+
Tag(name = "Tag 2"),
213+
Tag(name = "Tag 3"),
214+
Tag(name = "Tag 4"),
215+
Tag(name = "Tag 5"),
216+
Tag(name = "Tag 6"),
217+
Tag(name = "Tag 7"),
218+
Tag(name = "Tag 8"),
219+
Tag(name = "Tag 9")
220+
)
209221
),
210222
feedName = "feed name",
211223
color = 0,
@@ -214,7 +226,7 @@ val itemWithFeed = ItemWithFeed(
214226
websiteUrl = "",
215227
folder = Folder(name = "Folder name"),
216228
openIn = OpenIn.LOCAL_VIEW,
217-
openInAsk = true
229+
openInAsk = true,
218230
)
219231

220232
@DefaultPreview

app/src/main/java/com/readrops/app/timelime/components/TimelineItemParts.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.readrops.app.timelime.components
22

33
import androidx.compose.foundation.layout.Arrangement
44
import androidx.compose.foundation.layout.Column
5+
import androidx.compose.foundation.layout.FlowRow
56
import androidx.compose.foundation.layout.PaddingValues
67
import androidx.compose.foundation.layout.Row
78
import androidx.compose.foundation.layout.aspectRatio
@@ -38,6 +39,7 @@ import androidx.compose.ui.unit.dp
3839
import coil3.compose.AsyncImage
3940
import coil3.request.ImageRequest
4041
import com.readrops.app.R
42+
import com.readrops.app.item.components.TagSurface
4143
import com.readrops.app.util.components.FeedIcon
4244
import com.readrops.app.util.extensions.canDisplayOnBackground
4345
import com.readrops.app.util.extensions.displayColor
@@ -211,6 +213,26 @@ fun LargeTimelineItem(
211213
overflow = TextOverflow.Ellipsis,
212214
)
213215
}
216+
217+
if (itemWithFeed.item.tags.isNotEmpty()) {
218+
ShortSpacer()
219+
220+
FlowRow(
221+
modifier = Modifier.fillMaxWidth(),
222+
maxLines = 2,
223+
horizontalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.shortSpacing),
224+
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.shortSpacing)
225+
) {
226+
for (tag in itemWithFeed.item.tags) {
227+
TagSurface(
228+
name = tag.name,
229+
backgroundColor = displayColor,
230+
truncateName = true
231+
)
232+
}
233+
}
234+
235+
}
214236
}
215237

216238
if (itemWithFeed.item.hasImage) {

app/src/main/java/com/readrops/app/util/Utils.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,12 @@ object Utils {
5858
context.startActivity(Intent.createChooser(it, null))
5959
}
6060
}
61+
62+
fun truncateString(text: String, max: Int): String {
63+
return if (text.length > max) {
64+
text.substring(0, max) + "..."
65+
} else {
66+
text
67+
}
68+
}
6169
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.readrops.app
2+
3+
import com.readrops.app.util.Utils
4+
import org.junit.Assert.assertEquals
5+
import org.junit.Assert.assertTrue
6+
import org.junit.Test
7+
8+
class UtilsTest {
9+
10+
@Test
11+
fun truncateStringTest() {
12+
val result =
13+
Utils.truncateString("This is a very very long string with more than 30 characters", 30)
14+
15+
assertEquals(33, result.length)
16+
assertTrue(result.contains("This is a very very long strin"))
17+
assertTrue(result.endsWith("..."))
18+
}
19+
}

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ interface TagDao : BaseDao<Tag> {
1717
@Query("Select * From Tag Where account_id = :accountId")
1818
suspend fun selectAll(accountId: Int): List<Tag>
1919

20+
@Query("Select Tag.* From Tag Inner Join TagJoin on Tag.id = TagJoin.tag_id Where item_id = :itemId")
21+
suspend fun selectAllByItem(itemId: Int): List<Tag>
22+
2023
@Query("Select remote_id From Tag Where account_id = :accountId")
2124
suspend fun selectTagRemoteIds(accountId: Int): List<String>
2225

0 commit comments

Comments
 (0)