fix follow{ing,ers} for mastodon, start fixing viewmodel brokenness

This commit is contained in:
Matthieu 2021-04-29 15:42:08 +02:00
parent 0526e480b8
commit ac2eca9e57
10 changed files with 40 additions and 45 deletions

View File

@ -73,21 +73,20 @@ class MainActivity : BaseActivity() {
setupDrawer() setupDrawer()
val tabs: List<() -> Fragment> = listOf( val tabs: List<Fragment> = listOf(
{
PostFeedFragment<HomeStatusDatabaseEntity>() PostFeedFragment<HomeStatusDatabaseEntity>()
.apply { .apply {
arguments = Bundle().apply { putBoolean("home", true) } arguments = Bundle().apply { putBoolean("home", true) }
} }
}, ,
{ SearchDiscoverFragment() }, SearchDiscoverFragment() ,
{ CameraFragment() }, CameraFragment() ,
{ NotificationsFragment() }, NotificationsFragment() ,
{
PostFeedFragment<PublicFeedStatusDatabaseEntity>() PostFeedFragment<PublicFeedStatusDatabaseEntity>()
.apply { .apply {
arguments = Bundle().apply { putBoolean("home", false) } arguments = Bundle().apply { putBoolean("home", false) }
}
} }
) )
setupTabs(tabs) setupTabs(tabs)
@ -270,10 +269,10 @@ class MainActivity : BaseActivity() {
} }
private fun setupTabs(tab_array: List<() -> Fragment>){ private fun setupTabs(tab_array: List<Fragment>){
binding.viewPager.adapter = object : FragmentStateAdapter(this) { binding.viewPager.adapter = object : FragmentStateAdapter(this) {
override fun createFragment(position: Int): Fragment { override fun createFragment(position: Int): Fragment {
return tab_array[position]() return tab_array[position]
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {

View File

@ -53,10 +53,10 @@ class NotificationsFragment : CachedFeedFragment<Notification>() {
// get the view model // get the view model
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
viewModel = ViewModelProvider( viewModel = ViewModelProvider(
this, requireActivity(),
ViewModelFactory(db, db.notificationDao(), NotificationsRemoteMediator(apiHolder, db)) ViewModelFactory(db, db.notificationDao(), NotificationsRemoteMediator(apiHolder, db))
) )
.get(FeedViewModel::class.java) as FeedViewModel<Notification> .get("notifications", FeedViewModel::class.java) as FeedViewModel<Notification>
launch() launch()
initSearch() initSearch()

View File

@ -20,6 +20,7 @@ import org.pixeldroid.app.posts.feeds.cachedFeeds.ViewModelFactory
import org.pixeldroid.app.utils.api.objects.FeedContentDatabase import org.pixeldroid.app.utils.api.objects.FeedContentDatabase
import org.pixeldroid.app.utils.api.objects.Status import org.pixeldroid.app.utils.api.objects.Status
import org.pixeldroid.app.utils.displayDimensionsInPx import org.pixeldroid.app.utils.displayDimensionsInPx
import kotlin.properties.Delegates
/** /**
@ -32,14 +33,17 @@ class PostFeedFragment<T: FeedContentDatabase>: CachedFeedFragment<T>() {
private lateinit var mediator: RemoteMediator<Int, T> private lateinit var mediator: RemoteMediator<Int, T>
private lateinit var dao: FeedContentDao<T> private lateinit var dao: FeedContentDao<T>
private var home by Delegates.notNull<Boolean>()
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
adapter = PostsAdapter(requireContext().displayDimensionsInPx()) adapter = PostsAdapter(requireContext().displayDimensionsInPx())
home = requireArguments().get("home") as Boolean
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
if (requireArguments().get("home") as Boolean){ if (home){
mediator = HomeFeedRemoteMediator(apiHolder, db) as RemoteMediator<Int, T> mediator = HomeFeedRemoteMediator(apiHolder, db) as RemoteMediator<Int, T>
dao = db.homePostDao() as FeedContentDao<T> dao = db.homePostDao() as FeedContentDao<T>
} }
@ -59,8 +63,8 @@ class PostFeedFragment<T: FeedContentDatabase>: CachedFeedFragment<T>() {
// get the view model // get the view model
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
viewModel = ViewModelProvider(this, ViewModelFactory(db, dao, mediator)) viewModel = ViewModelProvider(requireActivity(), ViewModelFactory(db, dao, mediator))
.get(FeedViewModel::class.java) as FeedViewModel<T> .get(if(home) "home" else "public", FeedViewModel::class.java) as FeedViewModel<T>
launch() launch()
initSearch() initSearch()

View File

@ -65,9 +65,6 @@ open class UncachedFeedFragment<T: FeedContent> : BaseFragment() {
binding.motionLayout, binding.errorLayout, adapter) binding.motionLayout, binding.errorLayout, adapter)
binding.swipeRefreshLayout.setOnRefreshListener { binding.swipeRefreshLayout.setOnRefreshListener {
//It shouldn't be necessary to also retry() in addition to refresh(),
//but if we don't do this, reloads after an error fail immediately...
adapter.retry()
adapter.refresh() adapter.refresh()
} }

View File

@ -52,7 +52,7 @@ class AccountListFragment : UncachedFeedFragment<Account>() {
// get the view model // get the view model
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
viewModel = ViewModelProvider(this, ViewModelFactory( viewModel = ViewModelProvider(requireActivity(), ViewModelFactory(
FollowersContentRepository( FollowersContentRepository(
apiHolder.setToCurrentUser(), apiHolder.setToCurrentUser(),
id, id,
@ -60,7 +60,7 @@ class AccountListFragment : UncachedFeedFragment<Account>() {
) )
) )
) )
.get(FeedViewModel::class.java) as FeedViewModel<Account> .get("accountList", FeedViewModel::class.java) as FeedViewModel<Account>
launch() launch()
initSearch() initSearch()

View File

@ -41,25 +41,22 @@ class FollowersPagingSource(
throw HttpException(response) throw HttpException(response)
} }
val nextPosition: String = if(response.headers()["Link"] != null){ val nextPosition: String = response.headers()["Link"]
//Header is of the form: // Header is of the form:
// Link: <https://mastodon.social/api/v1/accounts/1/followers?limit=2&max_id=7628164>; rel="next", <https://mastodon.social/api/v1/accounts/1/followers?limit=2&since_id=7628165>; rel="prev" // Link: <https://mastodon.social/api/v1/accounts/1/followers?limit=2&max_id=7628164>; rel="next", <https://mastodon.social/api/v1/accounts/1/followers?limit=2&since_id=7628165>; rel="prev"
// So we want the first max_id value. In case there are arguments after // So we want the first max_id value. In case there are arguments after
// the max_id in the URL, we make sure to stop at the first '?' // the max_id in the URL, we make sure to stop at the first '?'
response.headers()["Link"] ?.substringAfter("max_id=", "")
.orEmpty() ?.substringBefore('?', "")
.substringAfter("max_id=", "") ?.substringBefore('>', "")
.substringBefore('?', "")
.substringBefore('>', "") ?: // No Link header, so we just increment the position value (Pixelfed case)
} else {
// No Link header, so we just increment the position value
(position?.toBigIntegerOrNull() ?: 1.toBigInteger()).inc().toString() (position?.toBigIntegerOrNull() ?: 1.toBigInteger()).inc().toString()
}
LoadResult.Page( LoadResult.Page(
data = accounts, data = accounts,
prevKey = null, prevKey = null,
nextKey = if (accounts.isEmpty()) null else nextPosition nextKey = if (accounts.isEmpty() or nextPosition.isEmpty()) null else nextPosition
) )
} catch (exception: IOException) { } catch (exception: IOException) {
LoadResult.Error(exception) LoadResult.Error(exception)
@ -68,8 +65,5 @@ class FollowersPagingSource(
} }
} }
override fun getRefreshKey(state: PagingState<String, Account>): String? = override fun getRefreshKey(state: PagingState<String, Account>): String? = null
state.anchorPosition?.run {
state.closestItemToPosition(this)?.id
}
} }

View File

@ -37,14 +37,14 @@ class SearchAccountFragment : UncachedFeedFragment<Account>() {
// get the view model // get the view model
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
viewModel = ViewModelProvider(this, ViewModelFactory( viewModel = ViewModelProvider(requireActivity(), ViewModelFactory(
SearchContentRepository<Account>( SearchContentRepository<Account>(
apiHolder.setToCurrentUser(), apiHolder.setToCurrentUser(),
Results.SearchType.accounts, Results.SearchType.accounts,
query query
) )
) )
).get(FeedViewModel::class.java) as FeedViewModel<Account> ).get("searchAccounts", FeedViewModel::class.java) as FeedViewModel<Account>
launch() launch()
initSearch() initSearch()

View File

@ -44,7 +44,7 @@ class SearchHashtagFragment : UncachedFeedFragment<Tag>() {
// get the view model // get the view model
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
viewModel = ViewModelProvider(this, ViewModelFactory( viewModel = ViewModelProvider(requireActivity(), ViewModelFactory(
SearchContentRepository<Tag>( SearchContentRepository<Tag>(
apiHolder.setToCurrentUser(), apiHolder.setToCurrentUser(),
Results.SearchType.hashtags, Results.SearchType.hashtags,
@ -52,7 +52,7 @@ class SearchHashtagFragment : UncachedFeedFragment<Tag>() {
) )
) )
) )
.get(FeedViewModel::class.java) as FeedViewModel<Tag> .get("searchHashtag", FeedViewModel::class.java) as FeedViewModel<Tag>
launch() launch()
initSearch() initSearch()

View File

@ -46,8 +46,9 @@ class SearchPagingSource<T: FeedContent>(
} }
} }
override fun getRefreshKey(state: PagingState<Int, T>): Int? = /**
state.anchorPosition?.run { * FIXME if implemented with [PagingState.anchorPosition], this breaks refreshes? How is this
state.closestItemToPosition(this)?.id?.toIntOrNull() * supposed to work?
} */
override fun getRefreshKey(state: PagingState<Int, T>): Int? = null
} }

View File

@ -41,7 +41,7 @@ class SearchPostsFragment : UncachedFeedFragment<Status>() {
// get the view model // get the view model
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
viewModel = ViewModelProvider(this, ViewModelFactory( viewModel = ViewModelProvider(requireActivity(), ViewModelFactory(
SearchContentRepository<Status>( SearchContentRepository<Status>(
apiHolder.setToCurrentUser(), apiHolder.setToCurrentUser(),
Results.SearchType.statuses, Results.SearchType.statuses,
@ -49,7 +49,7 @@ class SearchPostsFragment : UncachedFeedFragment<Status>() {
) )
) )
) )
.get(FeedViewModel::class.java) as FeedViewModel<Status> .get("searchPosts", FeedViewModel::class.java) as FeedViewModel<Status>
launch() launch()
initSearch() initSearch()