Merge branch 'click_to_scroll_to_top' into 'master'
Click tab again to scroll to top Closes #291 See merge request pixeldroid/PixelDroid!351
This commit is contained in:
commit
ad6e8e081f
|
@ -5,16 +5,21 @@ import android.content.Context
|
||||||
import androidx.test.core.app.ActivityScenario
|
import androidx.test.core.app.ActivityScenario
|
||||||
import androidx.test.core.app.ApplicationProvider
|
import androidx.test.core.app.ApplicationProvider
|
||||||
import androidx.test.espresso.Espresso.onView
|
import androidx.test.espresso.Espresso.onView
|
||||||
|
import androidx.test.espresso.action.ViewActions
|
||||||
import androidx.test.espresso.assertion.ViewAssertions.matches
|
import androidx.test.espresso.assertion.ViewAssertions.matches
|
||||||
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition
|
import androidx.test.espresso.contrib.RecyclerViewActions.actionOnItemAtPosition
|
||||||
import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition
|
import androidx.test.espresso.contrib.RecyclerViewActions.scrollToPosition
|
||||||
import androidx.test.espresso.matcher.ViewMatchers.*
|
import androidx.test.espresso.matcher.ViewMatchers.*
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
import org.pixeldroid.app.utils.db.AppDatabase
|
import org.pixeldroid.app.utils.db.AppDatabase
|
||||||
import org.pixeldroid.app.posts.StatusViewHolder
|
import org.pixeldroid.app.posts.StatusViewHolder
|
||||||
import org.pixeldroid.app.testUtility.*
|
import org.pixeldroid.app.testUtility.*
|
||||||
import org.hamcrest.CoreMatchers.not
|
import org.hamcrest.CoreMatchers.not
|
||||||
|
import org.hamcrest.CoreMatchers.sameInstance
|
||||||
|
import org.hamcrest.core.IsInstanceOf
|
||||||
|
import org.hamcrest.core.StringContains.containsString
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
|
@ -75,6 +80,20 @@ class HomeFeedTest {
|
||||||
}
|
}
|
||||||
onView(first(withId(R.id.postPager))).check(matches(isDisplayed()))
|
onView(first(withId(R.id.postPager))).check(matches(isDisplayed()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RepeatTest
|
||||||
|
fun tabReClickScrollUp() {
|
||||||
|
//Wait for the feed to load
|
||||||
|
waitForView(R.id.postPager)
|
||||||
|
|
||||||
|
onView(withId(R.id.list)).perform(scrollToPosition<StatusViewHolder>(4))
|
||||||
|
|
||||||
|
onView(first(IsInstanceOf.instanceOf(TabLayout.TabView::class.java))).perform(ViewActions.click())
|
||||||
|
|
||||||
|
|
||||||
|
onView(first(withId(R.id.description))).check(matches(withText(containsString("@user2"))));
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
@Test
|
@Test
|
||||||
fun clickingReblogButtonWorks() {
|
fun clickingReblogButtonWorks() {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.widget.ImageView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.core.view.NestedScrollingChild
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.paging.ExperimentalPagingApi
|
import androidx.paging.ExperimentalPagingApi
|
||||||
|
@ -19,9 +18,22 @@ import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
import com.google.android.material.tabs.TabLayoutMediator
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
||||||
|
import com.mikepenz.materialdrawer.iconics.iconicsIcon
|
||||||
|
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
|
||||||
|
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
|
||||||
|
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
|
||||||
|
import com.mikepenz.materialdrawer.model.interfaces.*
|
||||||
|
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
|
||||||
|
import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
||||||
|
import com.mikepenz.materialdrawer.widget.AccountHeaderView
|
||||||
|
import org.ligi.tracedroid.sending.sendTraceDroidStackTracesIfExist
|
||||||
import org.pixeldroid.app.databinding.ActivityMainBinding
|
import org.pixeldroid.app.databinding.ActivityMainBinding
|
||||||
import org.pixeldroid.app.postCreation.camera.CameraFragment
|
import org.pixeldroid.app.postCreation.camera.CameraFragment
|
||||||
|
import org.pixeldroid.app.posts.NestedScrollableHost
|
||||||
|
import org.pixeldroid.app.posts.feeds.cachedFeeds.CachedFeedFragment
|
||||||
import org.pixeldroid.app.posts.feeds.cachedFeeds.notifications.NotificationsFragment
|
import org.pixeldroid.app.posts.feeds.cachedFeeds.notifications.NotificationsFragment
|
||||||
import org.pixeldroid.app.posts.feeds.cachedFeeds.postFeeds.PostFeedFragment
|
import org.pixeldroid.app.posts.feeds.cachedFeeds.postFeeds.PostFeedFragment
|
||||||
import org.pixeldroid.app.profile.ProfileActivity
|
import org.pixeldroid.app.profile.ProfileActivity
|
||||||
|
@ -33,20 +45,10 @@ import org.pixeldroid.app.utils.db.entities.HomeStatusDatabaseEntity
|
||||||
import org.pixeldroid.app.utils.db.entities.PublicFeedStatusDatabaseEntity
|
import org.pixeldroid.app.utils.db.entities.PublicFeedStatusDatabaseEntity
|
||||||
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||||
import org.pixeldroid.app.utils.hasInternet
|
import org.pixeldroid.app.utils.hasInternet
|
||||||
import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial
|
|
||||||
import com.mikepenz.materialdrawer.iconics.iconicsIcon
|
|
||||||
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem
|
|
||||||
import com.mikepenz.materialdrawer.model.ProfileDrawerItem
|
|
||||||
import com.mikepenz.materialdrawer.model.ProfileSettingDrawerItem
|
|
||||||
import com.mikepenz.materialdrawer.model.interfaces.*
|
|
||||||
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader
|
|
||||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader
|
|
||||||
import com.mikepenz.materialdrawer.widget.AccountHeaderView
|
|
||||||
import org.ligi.tracedroid.sending.sendTraceDroidStackTracesIfExist
|
|
||||||
import org.pixeldroid.app.posts.NestedScrollableHost
|
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
|
|
||||||
|
|
||||||
class MainActivity : BaseActivity() {
|
class MainActivity : BaseActivity() {
|
||||||
|
|
||||||
private lateinit var header: AccountHeaderView
|
private lateinit var header: AccountHeaderView
|
||||||
|
@ -297,6 +299,20 @@ class MainActivity : BaseActivity() {
|
||||||
return tab_array.size
|
return tab_array.size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
binding.tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
|
||||||
|
override fun onTabSelected(tab: TabLayout.Tab?){}
|
||||||
|
|
||||||
|
override fun onTabUnselected(tab: TabLayout.Tab?) {}
|
||||||
|
|
||||||
|
override fun onTabReselected(tab: TabLayout.Tab?) {
|
||||||
|
tab?.position?.let { position ->
|
||||||
|
val page =
|
||||||
|
//No clue why this works but it does. F to pay respects
|
||||||
|
supportFragmentManager.findFragmentByTag("f$position")
|
||||||
|
(page as? CachedFeedFragment<*>)?.onTabReClicked()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
TabLayoutMediator(binding.tabs, binding.viewPager) { tab, position ->
|
TabLayoutMediator(binding.tabs, binding.viewPager) { tab, position ->
|
||||||
tab.icon = ContextCompat.getDrawable(applicationContext,
|
tab.icon = ContextCompat.getDrawable(applicationContext,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.paging.*
|
import androidx.paging.*
|
||||||
import androidx.paging.LoadState.*
|
import androidx.paging.LoadState.*
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
|
@ -18,6 +19,7 @@ import org.pixeldroid.app.utils.BaseFragment
|
||||||
import org.pixeldroid.app.utils.api.objects.FeedContentDatabase
|
import org.pixeldroid.app.utils.api.objects.FeedContentDatabase
|
||||||
import org.pixeldroid.app.utils.db.AppDatabase
|
import org.pixeldroid.app.utils.db.AppDatabase
|
||||||
import org.pixeldroid.app.utils.db.dao.feedContent.FeedContentDao
|
import org.pixeldroid.app.utils.db.dao.feedContent.FeedContentDao
|
||||||
|
import org.pixeldroid.app.utils.limitedLengthSmoothScrollToPosition
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A fragment representing a list of [FeedContentDatabase] items that are cached by the database.
|
* A fragment representing a list of [FeedContentDatabase] items that are cached by the database.
|
||||||
|
@ -76,6 +78,10 @@ open class CachedFeedFragment<T: FeedContentDatabase> : BaseFragment() {
|
||||||
|
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun onTabReClicked() {
|
||||||
|
binding.list.limitedLengthSmoothScrollToPosition(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ import androidx.browser.customtabs.CustomTabsIntent
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.DefaultLifecycleObserver
|
import androidx.lifecycle.DefaultLifecycleObserver
|
||||||
import androidx.lifecycle.LifecycleOwner
|
import androidx.lifecycle.LifecycleOwner
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import org.pixeldroid.app.R
|
import org.pixeldroid.app.R
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
import kotlin.properties.ReadWriteProperty
|
import kotlin.properties.ReadWriteProperty
|
||||||
|
@ -79,6 +81,29 @@ fun BaseActivity.openUrl(url: String): Boolean{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun RecyclerView.limitedLengthSmoothScrollToPosition(targetItem: Int) {
|
||||||
|
layoutManager?.apply {
|
||||||
|
val maxScroll = 3
|
||||||
|
when (this) {
|
||||||
|
is LinearLayoutManager -> {
|
||||||
|
val topItem = findFirstVisibleItemPosition()
|
||||||
|
val distance = topItem - targetItem
|
||||||
|
val anchorItem = when {
|
||||||
|
distance > maxScroll -> targetItem + maxScroll
|
||||||
|
distance < -maxScroll -> targetItem - maxScroll
|
||||||
|
else -> topItem
|
||||||
|
}
|
||||||
|
if (anchorItem != topItem) scrollToPosition(anchorItem)
|
||||||
|
post {
|
||||||
|
smoothScrollToPosition(targetItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> smoothScrollToPosition(targetItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Updates the application's theme depending on the given preferences and resources
|
* @brief Updates the application's theme depending on the given preferences and resources
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue