A cheap attempt at a native Bluesky client for Android

TimelineViewModel: actually fetch the required feed

Turns out, the algorithm parameter in getTimeline is a waste of time and resources!

+53 -15
+34 -4
app/src/main/java/industries/geesawra/monarch/datalayer/Bluesky.kt
··· 19 19 import app.bsky.embed.ImagesImage 20 20 import app.bsky.embed.Record 21 21 import app.bsky.embed.Video 22 + import app.bsky.feed.FeedViewPost 22 23 import app.bsky.feed.GeneratorView 23 24 import app.bsky.feed.GetFeedGeneratorsQueryParams 25 + import app.bsky.feed.GetFeedQueryParams 26 + import app.bsky.feed.GetFeedResponse 24 27 import app.bsky.feed.GetTimelineQueryParams 25 28 import app.bsky.feed.GetTimelineResponse 26 29 import app.bsky.feed.Like ··· 141 144 } 142 145 } 143 146 147 + data class Timeline( 148 + public val cursor: String? = null, 149 + public val feed: List<FeedViewPost>, 150 + ) 144 151 145 152 class BlueskyConn(val context: Context) { 146 153 companion object { ··· 450 457 } 451 458 } 452 459 460 + suspend fun fetchFeed(feed: String, cursor: String? = null): Result<Timeline> { 461 + return runCatching { 462 + create().onFailure { 463 + return Result.failure(LoginException(it.message)) 464 + } 465 + 466 + val timeline = client!!.getFeed( 467 + GetFeedQueryParams( 468 + feed = AtUri(feed), 469 + limit = 25, 470 + cursor = cursor 471 + ) 472 + ) 473 + val feed = when (timeline) { 474 + is AtpResponse.Failure<*> -> { 475 + return Result.failure(Exception("Failed to fetch timeline: ${timeline.error}")) 476 + } 477 + 478 + is AtpResponse.Success<GetFeedResponse> -> timeline.response 479 + } 480 + 481 + return Result.success(Timeline(feed.cursor, feed.feed)) 482 + } 483 + } 484 + 453 485 suspend fun fetchTimeline( 454 - algorithm: String, 455 486 cursor: String? = null 456 - ): Result<GetTimelineResponse> { 487 + ): Result<Timeline> { 457 488 return runCatching { 458 489 create().onFailure { 459 490 return Result.failure(LoginException(it.message)) ··· 461 492 462 493 val timeline = client!!.getTimeline( 463 494 GetTimelineQueryParams( 464 - algorithm = algorithm, 465 495 limit = 25, 466 496 cursor = cursor 467 497 ) ··· 474 504 is AtpResponse.Success<GetTimelineResponse> -> timeline.response 475 505 } 476 506 477 - return Result.success(feed) 507 + return Result.success(Timeline(feed.cursor, feed.feed)) 478 508 } 479 509 } 480 510
+19 -11
app/src/main/java/industries/geesawra/monarch/datalayer/TimelineViewModel.kt
··· 116 116 } 117 117 118 118 timelineFetchJob = viewModelScope.launch { 119 - bskyConn.fetchTimeline( 120 - if (uiState.selectedFeed == "Following") { 121 - "" 122 - } else { 123 - uiState.selectedFeed 124 - }, if (fresh) { 125 - null 126 - } else { 127 - uiState.timelineCursor 128 - } 129 - ).onSuccess { response -> 119 + 120 + when (uiState.selectedFeed) { 121 + "Following" -> bskyConn.fetchTimeline( 122 + if (fresh) { 123 + null 124 + } else { 125 + uiState.timelineCursor 126 + } 127 + ) 128 + 129 + else -> bskyConn.fetchFeed( 130 + feed = uiState.selectedFeed, 131 + cursor = if (fresh) { 132 + null 133 + } else { 134 + uiState.timelineCursor 135 + } 136 + ) 137 + }.onSuccess { response -> 130 138 val newSkeets = if (fresh) { 131 139 response.feed.map { SkeetData.fromFeedViewPost(it) }.distinctBy { it.cid } 132 140 } else {