Skip to content

Commit 4ad54d9

Browse files
authored
Merge pull request #945 from tunjid/bugfix/1.3.8
Bugfix/1.3.8
2 parents d6a5323 + 601f0b1 commit 4ad54d9

File tree

51 files changed

+1721
-763
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1721
-763
lines changed

data/core/src/commonMain/kotlin/com/tunjid/heron/data/repository/TimelineRepository.kt

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,9 @@ import com.tunjid.heron.data.core.models.Post
4242
import com.tunjid.heron.data.core.models.Preferences
4343
import com.tunjid.heron.data.core.models.Timeline
4444
import com.tunjid.heron.data.core.models.TimelineItem
45+
import com.tunjid.heron.data.core.models.id
4546
import com.tunjid.heron.data.core.models.offset
47+
import com.tunjid.heron.data.core.models.uri
4648
import com.tunjid.heron.data.core.models.value
4749
import com.tunjid.heron.data.core.types.FeedGeneratorUri
4850
import com.tunjid.heron.data.core.types.Id
@@ -149,29 +151,10 @@ sealed interface TimelineRequest {
149151
}
150152
}
151153

152-
class TimelineQuery(
154+
data class TimelineQuery(
153155
override val data: CursorQuery.Data,
154-
val timeline: Timeline,
155-
) : CursorQuery {
156-
157-
override fun equals(other: Any?): Boolean {
158-
if (this === other) return true
159-
if (other == null || this::class != other::class) return false
160-
161-
other as TimelineQuery
162-
163-
if (data != other.data) return false
164-
if (timeline.sourceId != other.timeline.sourceId) return false
165-
166-
return true
167-
}
168-
169-
override fun hashCode(): Int {
170-
var result = data.hashCode()
171-
result = 31 * result + timeline.sourceId.hashCode()
172-
return result
173-
}
174-
}
156+
val source: Timeline.Source,
157+
) : CursorQuery
175158

176159
interface TimelineRepository {
177160

@@ -232,8 +215,8 @@ internal class OfflineTimelineRepository(
232215
override fun timelineItems(
233216
query: TimelineQuery,
234217
cursor: Cursor,
235-
): Flow<CursorList<TimelineItem>> = when (val timeline = query.timeline) {
236-
is Timeline.Home.Following -> observeAndRefreshTimeline(
218+
): Flow<CursorList<TimelineItem>> = when (val source = query.source) {
219+
is Timeline.Source.Following -> observeAndRefreshTimeline(
237220
query = query,
238221
nextCursorFlow = networkService.nextTimelineCursorFlow(
239222
query = query,
@@ -251,15 +234,15 @@ internal class OfflineTimelineRepository(
251234
),
252235
)
253236

254-
is Timeline.Home.Feed -> observeAndRefreshTimeline(
237+
is Timeline.Source.Record.Feed -> observeAndRefreshTimeline(
255238
query = query,
256239
nextCursorFlow = networkService.nextTimelineCursorFlow(
257240
query = query,
258241
currentCursor = cursor,
259242
currentRequestWithNextCursor = {
260243
getFeed(
261244
GetFeedQueryParams(
262-
feed = AtUri(timeline.source.uri),
245+
feed = AtUri(source.uri.uri),
263246
limit = query.data.limit,
264247
cursor = cursor.value,
265248
),
@@ -270,15 +253,15 @@ internal class OfflineTimelineRepository(
270253
),
271254
)
272255

273-
is Timeline.Home.List -> observeAndRefreshTimeline(
256+
is Timeline.Source.Record.List -> observeAndRefreshTimeline(
274257
query = query,
275258
nextCursorFlow = networkService.nextTimelineCursorFlow(
276259
query = query,
277260
currentCursor = cursor,
278261
currentRequestWithNextCursor = {
279262
getListFeed(
280263
GetListFeedQueryParams(
281-
list = AtUri(timeline.source.uri),
264+
list = AtUri(source.uri.uri),
282265
limit = query.data.limit,
283266
cursor = cursor.value,
284267
),
@@ -289,7 +272,7 @@ internal class OfflineTimelineRepository(
289272
),
290273
)
291274

292-
is Timeline.Profile -> when (timeline.type) {
275+
is Timeline.Source.Profile -> when (source.type) {
293276
Timeline.Profile.Type.Likes -> observeAndRefreshTimeline(
294277
query = query,
295278
nextCursorFlow = networkService.nextTimelineCursorFlow(
@@ -298,7 +281,7 @@ internal class OfflineTimelineRepository(
298281
currentRequestWithNextCursor = {
299282
getActorLikes(
300283
GetActorLikesQueryParams(
301-
actor = Did(timeline.profileId.id),
284+
actor = Did(source.profileId.id),
302285
limit = query.data.limit,
303286
cursor = cursor.value,
304287
),
@@ -317,7 +300,7 @@ internal class OfflineTimelineRepository(
317300
currentRequestWithNextCursor = {
318301
getAuthorFeed(
319302
GetAuthorFeedQueryParams(
320-
actor = Did(timeline.profileId.id),
303+
actor = Did(source.profileId.id),
321304
limit = query.data.limit,
322305
cursor = cursor.value,
323306
filter = GetAuthorFeedFilter.PostsWithMedia,
@@ -337,7 +320,7 @@ internal class OfflineTimelineRepository(
337320
currentRequestWithNextCursor = {
338321
getAuthorFeed(
339322
GetAuthorFeedQueryParams(
340-
actor = Did(timeline.profileId.id),
323+
actor = Did(source.profileId.id),
341324
limit = query.data.limit,
342325
cursor = cursor.value,
343326
filter = GetAuthorFeedFilter.PostsNoReplies,
@@ -357,7 +340,7 @@ internal class OfflineTimelineRepository(
357340
currentRequestWithNextCursor = {
358341
getAuthorFeed(
359342
GetAuthorFeedQueryParams(
360-
actor = Did(timeline.profileId.id),
343+
actor = Did(source.profileId.id),
361344
limit = query.data.limit,
362345
cursor = cursor.value,
363346
filter = GetAuthorFeedFilter.PostsWithReplies,
@@ -377,7 +360,7 @@ internal class OfflineTimelineRepository(
377360
currentRequestWithNextCursor = {
378361
getAuthorFeed(
379362
GetAuthorFeedQueryParams(
380-
actor = Did(timeline.profileId.id),
363+
actor = Did(source.profileId.id),
381364
limit = query.data.limit,
382365
cursor = cursor.value,
383366
filter = GetAuthorFeedFilter.PostsWithVideo,
@@ -389,14 +372,6 @@ internal class OfflineTimelineRepository(
389372
),
390373
)
391374
}
392-
393-
is Timeline.StarterPack -> timelineItems(
394-
query = TimelineQuery(
395-
data = query.data,
396-
timeline = timeline.listTimeline,
397-
),
398-
cursor = cursor,
399-
)
400375
}
401376
.distinctUntilChanged()
402377

@@ -409,7 +384,7 @@ internal class OfflineTimelineRepository(
409384
networkRequestBlock = { query ->
410385
getFeed(
411386
GetFeedQueryParams(
412-
feed = AtUri(timeline.source.uri),
387+
feed = AtUri(timeline.uri.uri),
413388
limit = query.data.limit,
414389
cursor = null,
415390
),
@@ -438,7 +413,7 @@ internal class OfflineTimelineRepository(
438413
networkRequestBlock = { query ->
439414
getListFeed(
440415
GetListFeedQueryParams(
441-
list = AtUri(timeline.source.uri),
416+
list = AtUri(timeline.uri.uri),
442417
limit = query.data.limit,
443418
cursor = null,
444419
),
@@ -621,7 +596,7 @@ internal class OfflineTimelineRepository(
621596
.merge()
622597
.scan(emptyList<Timeline.Home>()) { timelines, timeline ->
623598
// Add newest item first
624-
(listOf(timeline) + timelines).distinctBy(Timeline.Home::sourceId)
599+
(listOf(timeline) + timelines).distinctBy { it.source.id }
625600
}
626601
.map { homeTimelines ->
627602
homeTimelines.sortedBy(Timeline.Home::position)
@@ -764,7 +739,7 @@ internal class OfflineTimelineRepository(
764739
timelineDao.updatePreferredTimelinePresentation(
765740
partial = preferredPresentationPartial(
766741
signedInProfileId = signedInProfileId,
767-
sourceId = timeline.sourceId,
742+
sourceId = timeline.source.id,
768743
presentation = presentation,
769744
),
770745
)
@@ -810,12 +785,12 @@ internal class OfflineTimelineRepository(
810785
onResponse = {
811786
multipleEntitySaverProvider.saveInTransaction {
812787
if (timelineDao.isFirstPageForDifferentAnchor(signedInProfileId, query)) {
813-
timelineDao.deleteAllFeedsFor(query.timeline.sourceId)
788+
timelineDao.deleteAllFeedsFor(query.source.id)
814789
timelineDao.insertOrPartiallyUpdateTimelineFetchedAt(
815790
listOf(
816791
TimelinePreferencesEntity(
817792
viewingProfileId = signedInProfileId,
818-
sourceId = query.timeline.sourceId,
793+
sourceId = query.source.id,
819794
lastFetchedAt = query.data.cursorAnchor,
820795
preferredPresentation = null,
821796
),
@@ -825,7 +800,7 @@ internal class OfflineTimelineRepository(
825800
add(
826801
viewingProfileId = signedInProfileId,
827802
query = query,
828-
timeline = query.timeline,
803+
source = query.source,
829804
feedViewPosts = networkFeed(),
830805
)
831806
}
@@ -860,7 +835,7 @@ internal class OfflineTimelineRepository(
860835
add(
861836
viewingProfileId = signedInProfileId,
862837
query = query,
863-
timeline = timeline,
838+
source = timeline.source,
864839
feedViewPosts = fetchedFeedViewPosts,
865840
)
866841
}
@@ -875,22 +850,22 @@ internal class OfflineTimelineRepository(
875850
combine(
876851
timelineDao.lastFetchKey(
877852
viewingProfileId = signedInProfileId?.id,
878-
sourceId = timeline.sourceId,
853+
sourceId = timeline.source.id,
879854
)
880855
.map { it?.lastFetchedAt ?: pollInstant }
881856
.distinctUntilChangedBy(Instant::toEpochMilliseconds)
882857
.flatMapLatest {
883858
timelineDao.feedItems(
884859
viewingProfileId = signedInProfileId?.id,
885-
sourceId = timeline.sourceId,
860+
sourceId = timeline.source.id,
886861
before = it,
887862
limit = 1,
888863
offset = 0,
889864
)
890865
},
891866
timelineDao.feedItems(
892867
viewingProfileId = signedInProfileId?.id,
893-
sourceId = timeline.sourceId,
868+
sourceId = timeline.source.id,
894869
before = pollInstant,
895870
limit = 1,
896871
offset = 0,
@@ -919,7 +894,7 @@ internal class OfflineTimelineRepository(
919894
savedStateDataSource.singleSessionFlow { signedInProfileId ->
920895
timelineDao.feedItems(
921896
viewingProfileId = signedInProfileId?.id,
922-
sourceId = query.timeline.sourceId,
897+
sourceId = query.source.id,
923898
before = query.data.cursorAnchor,
924899
offset = query.data.offset,
925900
limit = query.data.limit,
@@ -948,7 +923,7 @@ internal class OfflineTimelineRepository(
948923
},
949924
block = block@{ entity ->
950925
// Muted posts should only show up on profile timelines
951-
val hideMuted = query.timeline !is Timeline.Profile
926+
val hideMuted = query.source !is Timeline.Source.Profile
952927
var isMuted = isMuted(post)
953928
if (hideMuted && isMuted) return@block
954929

@@ -1247,7 +1222,7 @@ private suspend fun TimelineDao.isFirstPageForDifferentAnchor(
12471222
if (query.data.page != 0) return false
12481223
val lastFetchedAt = lastFetchKey(
12491224
viewingProfileId = signedInProfileId?.id,
1250-
sourceId = query.timeline.sourceId,
1225+
sourceId = query.source.id,
12511226
).first()?.lastFetchedAt
12521227
return lastFetchedAt?.toEpochMilliseconds() != query.data.cursorAnchor.toEpochMilliseconds()
12531228
}

data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/multipleEntitysaver/SaveFeedViewPost.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.tunjid.heron.data.utilities.multipleEntitysaver
1919
import app.bsky.feed.FeedViewPost
2020
import com.tunjid.heron.data.core.models.CursorQuery
2121
import com.tunjid.heron.data.core.models.Timeline
22+
import com.tunjid.heron.data.core.models.id
2223
import com.tunjid.heron.data.core.models.offset
2324
import com.tunjid.heron.data.core.types.PostUri
2425
import com.tunjid.heron.data.core.types.ProfileId
@@ -32,15 +33,15 @@ import com.tunjid.heron.data.network.models.profileEntity
3233
internal fun MultipleEntitySaver.add(
3334
viewingProfileId: ProfileId?,
3435
query: CursorQuery,
35-
timeline: Timeline,
36+
source: Timeline.Source,
3637
feedViewPosts: List<FeedViewPost>,
3738
) {
3839
for (index in feedViewPosts.indices) {
3940
val feedView = feedViewPosts[index]
4041
// Extract data from feed
4142
add(
4243
feedView.feedItemEntity(
43-
sourceId = timeline.sourceId,
44+
sourceId = source.id,
4445
itemSort = query.itemSortKey(index),
4546
viewingProfileId = viewingProfileId,
4647
),

data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/multipleEntitysaver/SaveMessageView.kt

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -141,40 +141,44 @@ private fun MultipleEntitySaver.add(
141141
messageId: MessageId,
142142
record: RecordViewRecordUnion.ViewRecord,
143143
) {
144-
record.value.embeds?.forEach { embed ->
145-
val postView = PostView(
146-
uri = record.value.uri,
147-
cid = record.value.cid,
148-
author = record.value.author,
149-
record = record.value.value,
150-
embed = when (embed) {
151-
is MessagePost.ExternalView -> TimelinePost.ExternalView(embed.value)
152-
is MessagePost.ImagesView -> TimelinePost.ImagesView(embed.value)
153-
is MessagePost.RecordView -> TimelinePost.RecordView(embed.value)
154-
is MessagePost.RecordWithMediaView -> TimelinePost.RecordWithMediaView(embed.value)
155-
is MessagePost.Unknown -> TimelinePost.Unknown(embed.value)
156-
is MessagePost.VideoView -> TimelinePost.VideoView(embed.value)
157-
},
158-
replyCount = record.value.replyCount,
159-
repostCount = record.value.repostCount,
160-
likeCount = record.value.likeCount,
161-
quoteCount = record.value.quoteCount,
162-
indexedAt = record.value.indexedAt,
163-
viewer = null,
164-
labels = record.value.labels,
165-
threadgate = null,
166-
)
167-
add(
168-
viewingProfileId = viewingProfileId,
169-
postView = postView,
170-
)
171-
add(
172-
entity = MessagePostEntity(
173-
messageId = messageId,
174-
postUri = postView.uri.atUri.let(::PostUri),
175-
),
176-
)
177-
}
144+
// This is an error in the upstream lexicon. Only one embed should in a record
145+
// Here, the first (and only) embed present is actually written.
146+
val embed = record.value.embeds?.firstOrNull()
147+
148+
val postView = PostView(
149+
uri = record.value.uri,
150+
cid = record.value.cid,
151+
author = record.value.author,
152+
record = record.value.value,
153+
embed = when (embed) {
154+
is MessagePost.ExternalView -> TimelinePost.ExternalView(embed.value)
155+
is MessagePost.ImagesView -> TimelinePost.ImagesView(embed.value)
156+
is MessagePost.RecordView -> TimelinePost.RecordView(embed.value)
157+
is MessagePost.RecordWithMediaView -> TimelinePost.RecordWithMediaView(embed.value)
158+
is MessagePost.Unknown -> TimelinePost.Unknown(embed.value)
159+
is MessagePost.VideoView -> TimelinePost.VideoView(embed.value)
160+
null -> null
161+
},
162+
replyCount = record.value.replyCount,
163+
repostCount = record.value.repostCount,
164+
likeCount = record.value.likeCount,
165+
quoteCount = record.value.quoteCount,
166+
indexedAt = record.value.indexedAt,
167+
viewer = null,
168+
labels = record.value.labels,
169+
threadgate = null,
170+
)
171+
172+
add(
173+
viewingProfileId = viewingProfileId,
174+
postView = postView,
175+
)
176+
add(
177+
entity = MessagePostEntity(
178+
messageId = messageId,
179+
postUri = postView.uri.atUri.let(::PostUri),
180+
),
181+
)
178182
}
179183

180184
internal fun MultipleEntitySaver.add(

data/core/src/commonMain/kotlin/com/tunjid/heron/data/utilities/writequeue/Writable.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import com.tunjid.heron.data.core.models.NotificationPreferences
2121
import com.tunjid.heron.data.core.models.Post
2222
import com.tunjid.heron.data.core.models.Profile
2323
import com.tunjid.heron.data.core.models.Timeline
24+
import com.tunjid.heron.data.core.models.sourceId
2425
import com.tunjid.heron.data.core.utilities.Outcome
2526
import kotlin.time.Instant
2627
import kotlinx.serialization.Serializable

0 commit comments

Comments
 (0)