Follow users, load followers and following lists, and search within the Central Hub community.
CentralHubFollowingManager manages follow and unfollow actions and emits follow events so your UI can react immediately.
class FollowingViewModel : ViewModel(), KoinComponent {
private val followingManager: CentralHubFollowingManager = get()
val followEvents = followingManager.followEvents
suspend fun followUser(userId: String) {
followingManager.followUser(
userId = userId,
onSuccess = { /* User followed */ },
onFailure = { error -> /* Handle error */ },
)
}
suspend fun unfollowUser(userId: String) {
followingManager.unfollowUser(
userId = userId,
onSuccess = { /* User unfollowed */ },
onFailure = { error -> /* Handle error */ },
)
}
}CentralHubFollowersProvider loads followers and following lists with sorting and pagination support.
FollowersSortType.Latest — newest followers first.FollowersSortType.Earliest — oldest followers first.class FollowersViewModel : ViewModel(), KoinComponent {
private val followersProvider: CentralHubFollowersProvider = get()
val followersState = followersProvider.state
suspend fun loadFollowers(userId: String) {
followersProvider.loadData(
userId = userId,
sortType = FollowersSortType.Latest,
pageLimit = 20,
)
}
fun loadMore(
followingType: FollowingType,
sortType: FollowersSortType,
) {
followersProvider.loadNextPage(
followingType = followingType,
sortType = sortType,
pageLimit = 20,
)
}
}CentralHubSearchProvider searches users across the community or within follower subsets.
SearchType.ALL — search all users.SearchType.FOLLOWING — search only followed users.SearchType.FOLLOWERS — search only followers.class SearchViewModel : ViewModel(), KoinComponent {
private val searchProvider: CentralHubSearchProvider = get()
val searchState = searchProvider.state
suspend fun search(
query: String,
searchType: SearchType = SearchType.ALL,
) {
if (query.isNotBlank()) {
searchProvider.search(
query = query,
searchType = searchType,
pageLimit = 20,
)
}
}
suspend fun loadMoreResults(
query: String,
searchType: SearchType,
) {
searchProvider.loadNextSearchPage(
query = query,
searchType = searchType,
pageLimit = 20,
)
}
fun clearSearch() {
searchProvider.clear()
}
override fun onCleared() {
super.onCleared()
searchProvider.destroy()
}
}data class FollowersState(
val followers: List<Follower>,
val following: List<Follower>,
val followersCount: Int,
val followingCount: Int,
val followersNextPage: String?,
val followingNextPage: String?,
val loadingStatus: LoadingStatus,
val nextPageLoadingStatus: LoadingStatus,
val followActionLoadingStatus: LoadingStatus,
)data class CentralHubSearchState(
val searchResults: List<Follower>,
val loadingStatus: LoadingStatus,
val nextPageLoadingStatus: LoadingStatus,
val followActionLoadingStatus: LoadingStatus,
val allDataLoaded: Boolean,
)