@@ -25,11 +25,11 @@ import com.tunjid.heron.data.core.models.Link
2525import com.tunjid.heron.data.core.models.LinkTarget
2626import com.tunjid.heron.data.core.models.Profile
2727import com.tunjid.heron.data.core.models.ProfileWithViewerState
28- import com.tunjid.heron.data.core.models.canRequestData
2928import com.tunjid.heron.data.core.types.Id
3029import com.tunjid.heron.data.core.types.ProfileHandleOrId
3130import com.tunjid.heron.data.core.types.ProfileId
3231import com.tunjid.heron.data.core.types.RecordUri
32+ import com.tunjid.heron.data.core.types.UnknownRecordUri
3333import com.tunjid.heron.data.core.types.UnresolvableProfileException
3434import com.tunjid.heron.data.core.types.profileId
3535import com.tunjid.heron.data.core.types.recordKey
@@ -44,6 +44,7 @@ import com.tunjid.heron.data.lexicons.BlueskyApi
4444import com.tunjid.heron.data.network.NetworkService
4545import com.tunjid.heron.data.network.models.profile
4646import com.tunjid.heron.data.network.models.profileViewerStateEntity
47+ import com.tunjid.heron.data.network.observedItems
4748import com.tunjid.heron.data.utilities.distinctUntilChangedMap
4849import com.tunjid.heron.data.utilities.multipleEntitysaver.MultipleEntitySaverProvider
4950import com.tunjid.heron.data.utilities.multipleEntitysaver.add
@@ -53,9 +54,7 @@ import kotlinx.coroutines.async
5354import kotlinx.coroutines.awaitAll
5455import kotlinx.coroutines.coroutineScope
5556import kotlinx.coroutines.flow.Flow
56- import kotlinx.coroutines.flow.emitAll
5757import kotlinx.coroutines.flow.first
58- import kotlinx.coroutines.flow.flow
5958import kotlinx.coroutines.flow.flowOf
6059import kotlinx.coroutines.flow.map
6160import sh.christian.ozone.api.Did
@@ -111,45 +110,35 @@ internal class OfflineProfileLookup(
111110 responseFetcher : suspend BlueskyApi .() -> AtpResponse <NetworkResponse >,
112111 responseProfileViews : NetworkResponse .() -> List <ProfileView >,
113112 responseCursor : NetworkResponse .() -> String? ,
114- ): Flow <CursorList <ProfileWithViewerState >> = flow {
115- // Final or pending cursor, nothing to fetch
116- if (! cursor.canRequestData) return @flow
117-
118- val response = networkService.runCatchingWithMonitoredNetworkRetry(
119- block = responseFetcher,
120- ).getOrNull()
121- ? : return @flow
122-
123- val profileViews = response.responseProfileViews()
124-
125- val nextCursor = response.responseCursor()
126- ?.let (Cursor ::Next )
127- ? : Cursor .Final
128-
129- // Emit network results immediately for minimal latency
130- emit(
113+ ): Flow <CursorList <ProfileWithViewerState >> = networkService.observedItems(
114+ cursor = cursor,
115+ responseFetcher = responseFetcher,
116+ responseSaver = { response ->
117+ multipleEntitySaverProvider.saveInTransaction {
118+ response.responseProfileViews()
119+ .forEach { profileView ->
120+ add(
121+ viewingProfileId = signedInProfileId,
122+ profileView = profileView,
123+ )
124+ }
125+ }
126+ },
127+ responseCursor = { response ->
128+ response.responseCursor()?.let (Cursor ::Next )
129+ },
130+ networkItems = { response, nextCursor ->
131131 CursorList (
132- items = profileViews .toProfileWithViewerStates(
132+ items = response.responseProfileViews() .toProfileWithViewerStates(
133133 signedInProfileId = signedInProfileId,
134134 profileMapper = ProfileView ::profile,
135135 profileViewerStateMapper = ProfileView ::profileViewerStateEntity,
136136 ),
137137 nextCursor = nextCursor,
138- ),
139- )
140-
141- multipleEntitySaverProvider.saveInTransaction {
142- profileViews
143- .forEach { profileView ->
144- add(
145- viewingProfileId = signedInProfileId,
146- profileView = profileView,
147- )
148- }
149- }
150-
151- emitAll(
152- profileViews.observeProfileWithViewerStates(
138+ )
139+ },
140+ observedItems = { response, nextCursor ->
141+ response.responseProfileViews().observeProfileWithViewerStates(
153142 profileDao = profileDao,
154143 signedInProfileId = signedInProfileId,
155144 profileMapper = ProfileView ::profile,
@@ -160,9 +149,9 @@ internal class OfflineProfileLookup(
160149 items = profileWithViewerStates,
161150 nextCursor = nextCursor,
162151 )
163- },
164- )
165- }
152+ }
153+ },
154+ )
166155
167156 override suspend fun lookupProfileDid (
168157 profileId : Id .Profile ,
@@ -198,7 +187,7 @@ internal class OfflineProfileLookup(
198187 override suspend fun <T : RecordUri > withDidAuthority (
199188 uri : T ,
200189 ): T {
201- if (uri is com.tunjid.heron.data.core.types. UnknownRecordUri ) return uri
190+ if (uri is UnknownRecordUri ) return uri
202191 val profileId = uri.profileId()
203192 if (Did .Regex .matches(profileId.id)) return uri
204193 val did = lookupProfileDid(profileId) ? : return uri
0 commit comments