@@ -48,6 +48,7 @@ import pub.hackers.android.graphql.LoginByUsernameMutation
4848import pub.hackers.android.graphql.MarkNotificationsAsReadMutation
4949import pub.hackers.android.graphql.MediumGeneratedAltTextQuery
5050import pub.hackers.android.graphql.NotificationsQuery
51+ import pub.hackers.android.graphql.NewsStoriesQuery
5152import pub.hackers.android.graphql.PersonalTimelineQuery
5253import pub.hackers.android.graphql.PinPostMutation
5354import pub.hackers.android.graphql.PostQuotesQuery
@@ -81,10 +82,12 @@ import pub.hackers.android.graphql.UpdateNoteMutation
8182import pub.hackers.android.graphql.ViewerQuery
8283import pub.hackers.android.graphql.type.AccountLinkInput
8384import pub.hackers.android.graphql.type.CreateNoteMediumInput
85+ import pub.hackers.android.graphql.type.NewsOrder as GqlNewsOrder
8486import pub.hackers.android.graphql.type.UpdateAccountInput
8587import pub.hackers.android.graphql.fragment.ActorFields
8688import pub.hackers.android.graphql.fragment.EngagementStatsFields
8789import pub.hackers.android.graphql.fragment.MediaFields
90+ import pub.hackers.android.graphql.fragment.NewsStoryFields
8891import pub.hackers.android.graphql.fragment.PostFields
8992import pub.hackers.android.graphql.fragment.SharedPostFields
9093import pub.hackers.android.graphql.type.PostVisibility as GqlPostVisibility
@@ -237,6 +240,45 @@ class HackersPubRepository @Inject constructor(
237240 }
238241 }
239242
243+ suspend fun getNewsStories (
244+ after : String? = null,
245+ refresh : Boolean = false,
246+ order : NewsOrder = NewsOrder .POPULAR ,
247+ ): Result <NewsStoriesResult > {
248+ return try {
249+ val response = apolloClient.query(
250+ NewsStoriesQuery (
251+ first = Optional .present(20 ),
252+ after = Optional .presentIfNotNull(after),
253+ order = Optional .present(order.toGqlNewsOrder()),
254+ )
255+ )
256+ .apply { if (refresh) fetchPolicy(FetchPolicy .NetworkOnly ) }
257+ .execute()
258+
259+ if (response.hasErrors()) {
260+ Result .failure(Exception (response.errors?.firstOrNull()?.message ? : " Unknown error" ))
261+ } else {
262+ val data = response.data?.newsStories
263+ withContext(Dispatchers .Default ) {
264+ Result .success(
265+ NewsStoriesResult (
266+ stories = data?.edges?.map { edge ->
267+ edge.node.newsStoryFields.toNewsStory()
268+ }?.distinctBy { it.id } ? : emptyList(),
269+ hasNextPage = data?.pageInfo?.hasNextPage ? : false ,
270+ endCursor = data?.pageInfo?.endCursor,
271+ hasPreviousPage = data?.pageInfo?.hasPreviousPage ? : false ,
272+ startCursor = data?.pageInfo?.startCursor,
273+ )
274+ )
275+ }
276+ }
277+ } catch (e: Exception ) {
278+ Result .failure(e)
279+ }
280+ }
281+
240282 suspend fun getSuggestedFilterLanguages (): Result <List <String >> {
241283 return try {
242284 val response = apolloClient.query(SuggestedFilterLanguagesQuery ()).execute()
@@ -1796,6 +1838,37 @@ class HackersPubRepository @Inject constructor(
17961838 }
17971839
17981840 // Extension functions to convert GraphQL fragment types to domain models
1841+ private fun NewsStoryFields.toNewsStory (): NewsStory {
1842+ return NewsStory (
1843+ id = id,
1844+ uuid = uuid.toString(),
1845+ title = title,
1846+ description = description,
1847+ url = url.toString(),
1848+ siteName = siteName,
1849+ author = author,
1850+ image = image?.let { img ->
1851+ PostLinkImage (
1852+ url = img.url.toString(),
1853+ alt = img.alt,
1854+ width = img.width,
1855+ height = img.height,
1856+ )
1857+ },
1858+ creator = creator?.actorFields?.toActor(),
1859+ score = score,
1860+ postCount = postCount,
1861+ discussionCount = discussionCount,
1862+ firstSharedAt = firstSharedAt?.let { Instant .parse(it.toString()) },
1863+ latestActivityAt = latestActivityAt?.let { Instant .parse(it.toString()) },
1864+ sourceBreakdown = NewsSourceBreakdown (
1865+ local = sourceBreakdown.local,
1866+ remote = sourceBreakdown.remote,
1867+ bluesky = sourceBreakdown.bluesky,
1868+ ),
1869+ )
1870+ }
1871+
17991872 private fun PostFields.toPost (
18001873 sharedPost : Post ? = null,
18011874 replyTarget : Post ? = null,
@@ -1911,6 +1984,14 @@ class HackersPubRepository @Inject constructor(
19111984 }
19121985 }
19131986
1987+ private fun NewsOrder.toGqlNewsOrder (): GqlNewsOrder {
1988+ return when (this ) {
1989+ NewsOrder .POPULAR -> GqlNewsOrder .POPULAR
1990+ NewsOrder .NEWEST -> GqlNewsOrder .NEWEST
1991+ NewsOrder .ALL_TIME -> GqlNewsOrder .ALL_TIME
1992+ }
1993+ }
1994+
19141995 private fun ActorFields.toActor (): Actor {
19151996 return Actor (
19161997 id = id,
0 commit comments