Jasmin Fajkic
10/27/2022, 3:36 PMIan Lake
10/27/2022, 7:44 PMJasmin Fajkic
10/27/2022, 7:45 PMIan Lake
10/28/2022, 3:17 AMJasmin Fajkic
10/28/2022, 6:29 AMinternal class CommunityFeedRepositoryImpl @Inject constructor(
private val communityFeedApi: CommunityFeedApi
) : CommunityFeedRepository {
override fun getData(path: String): PagingSource<String, Tile> {
return CommunityPagingSource(
communityFeedApi = communityFeedApi,
path = path
)
}
}
Paging Source
internal class CommunityPagingSource(
private val communityFeedApi: CommunityFeedApi,
private val path: String
) : PagingSource<String, Tile>() {
override fun getRefreshKey(state: PagingState<String, Tile>): String? = null
override suspend fun load(params: LoadParams<String>): LoadResult<String, Tile> {
return runCatching {
val response = communityFeedApi.getData(path, params.key)
if (response.isSuccessful) {
val data = response.body() ?: throw java.lang.Exception()
LoadResult.Page(data = data.tiles, nextKey = data.token, prevKey = null)
} else {
throw java.lang.Exception()
}
}.getOrElse {
LoadResult.Error(it)
}
}
}
ViewModel
internal class CommunityPageViewModel(
private val injectionsProvider: InjectionsProvider,
path: String
) : ViewModel() {
init {
viewModelScope.launch {
injectionsProvider.getFeed(
GetFeed.Parameters(
path = path,
pagingConfig = PAGING_CONFIG
)
)
}
}
init {
injectionsProvider.savePostRepository.newPostStatus
.onEach {
if (it == NewPostStatus.UPLOADED_SUCCESS) {
val tile = injectionsProvider.savePostRepository.newPost.value
if (tile != null) {
// injectionsProvider.communityPagingSource.addNewTile(tile)
}
}
}
}
private val reaction = MutableStateFlow<List<Pair<String, String>>?>(null)
val pagedList: Flow<PagingData<Tile>> =
injectionsProvider.getFeed.flow.cachedIn(viewModelScope)
.combine(reaction) { pagingData, myReaction ->
if (myReaction != null) {
updatePagingData(
pagingData = pagingData,
myReaction = myReaction
)
} else pagingData
}
private fun updatePagingData(
pagingData: PagingData<Tile>,
myReaction: List<Pair<String, String>>
): PagingData<Tile> {
return pagingData.map { tile ->
updateTile(tile, myReaction)
}
}
private fun updateTile(tile: Tile, reactionsList: List<Pair<String, String>>): Tile {
if (tile is PostTile) {
for (pair in reactionsList) {
if (tile.id == pair.first) {
val reactions = tile.reactions?.copy(
myReaction = pair.second
)
return when (tile) {
is QuestionTile -> tile.copy(reactions = reactions)
is ConversationStarterContainerTile -> tile.copy(reactions = reactions)
is MediaTile -> tile.copy(reactions = reactions)
else -> tile
}
}
}
}
return tile
}
fun addReaction(
reactionType: String,
id: String,
onError: () -> Unit
) {
viewModelScope.launch {
injectionsProvider.addReaction(AddReaction.Params(reactionType.toReactionType(), id))
.collectStatus(
counter = ObservableLoadingCounter(),
onSuccess = {
val mutableList = reaction.value?.toMutableList() ?: mutableListOf()
mutableList.add(Pair(id, reactionType))
reaction.value = mutableList
},
onError = onError
)
}
}
private fun String.toReactionType(): ReactionType = ReactionType(replace("_", "-"))
companion object {
private val PAGING_CONFIG = PagingConfig(
pageSize = 50,
initialLoadSize = 50
)
}
}
Interactor
internal class GetFeed @Inject constructor(private val communityFeedRepository: CommunityFeedRepository) :
PagingInteractor<GetFeed.Parameters, Tile>() {
override fun createObservable(params: Parameters): Flow<PagingData<Tile>> =
Pager(config = params.pagingConfig) { communityFeedRepository.getData(params.path) }.flow
data class Parameters(
val path: String,
override val pagingConfig: PagingConfig
) : PagingInteractor.Parameters<Tile>
}
So this is my setup. So should I do it in paging source?Jasmin Fajkic
10/28/2022, 7:39 PMIan Lake
10/28/2022, 9:27 PMIan Lake
10/28/2022, 9:27 PM