Start of profile tabs
This commit is contained in:
parent
e1f7018b19
commit
35948439e9
@ -10,6 +10,7 @@ import android.widget.ImageView
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
@ -18,9 +19,13 @@ import androidx.paging.PagingDataAdapter
|
|||||||
import androidx.recyclerview.widget.DiffUtil
|
import androidx.recyclerview.widget.DiffUtil
|
||||||
import androidx.recyclerview.widget.GridLayoutManager
|
import androidx.recyclerview.widget.GridLayoutManager
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.bumptech.glide.Glide
|
import com.bumptech.glide.Glide
|
||||||
import com.bumptech.glide.request.RequestOptions
|
import com.bumptech.glide.request.RequestOptions
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
|
import com.google.android.material.tabs.TabLayout
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.pixeldroid.app.R
|
import org.pixeldroid.app.R
|
||||||
@ -37,6 +42,7 @@ import org.pixeldroid.app.utils.*
|
|||||||
import org.pixeldroid.app.utils.api.PixelfedAPI
|
import org.pixeldroid.app.utils.api.PixelfedAPI
|
||||||
import org.pixeldroid.app.utils.api.objects.Account
|
import org.pixeldroid.app.utils.api.objects.Account
|
||||||
import org.pixeldroid.app.utils.api.objects.Attachment
|
import org.pixeldroid.app.utils.api.objects.Attachment
|
||||||
|
import org.pixeldroid.app.utils.api.objects.Results
|
||||||
import org.pixeldroid.app.utils.api.objects.Status
|
import org.pixeldroid.app.utils.api.objects.Status
|
||||||
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||||
import retrofit2.HttpException
|
import retrofit2.HttpException
|
||||||
@ -47,11 +53,9 @@ class ProfileActivity : BaseThemedWithBarActivity() {
|
|||||||
private lateinit var domain : String
|
private lateinit var domain : String
|
||||||
private lateinit var accountId : String
|
private lateinit var accountId : String
|
||||||
private lateinit var binding: ActivityProfileBinding
|
private lateinit var binding: ActivityProfileBinding
|
||||||
private lateinit var profileAdapter: PagingDataAdapter<Status, RecyclerView.ViewHolder>
|
|
||||||
private lateinit var viewModel: FeedViewModel<Status>
|
private lateinit var viewModel: FeedViewModel<Status>
|
||||||
|
|
||||||
private var user: UserDatabaseEntity? = null
|
private var user: UserDatabaseEntity? = null
|
||||||
private var job: Job? = null
|
|
||||||
|
|
||||||
@OptIn(ExperimentalPagingApi::class)
|
@OptIn(ExperimentalPagingApi::class)
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
@ -79,36 +83,60 @@ class ProfileActivity : BaseThemedWithBarActivity() {
|
|||||||
)
|
)
|
||||||
)[FeedViewModel::class.java] as FeedViewModel<Status>
|
)[FeedViewModel::class.java] as FeedViewModel<Status>
|
||||||
|
|
||||||
profileAdapter = ProfilePostsAdapter()
|
val tabs = createSearchTabs(account)
|
||||||
initAdapter(binding.profileProgressBar, binding.profileRefreshLayout,
|
setupTabs(tabs)
|
||||||
binding.profilePostsRecyclerView, binding.motionLayout, binding.errorLayout,
|
|
||||||
profileAdapter)
|
|
||||||
|
|
||||||
binding.profilePostsRecyclerView.layoutManager = GridLayoutManager(this, 3)
|
|
||||||
|
|
||||||
binding.profileRefreshLayout.setOnRefreshListener {
|
|
||||||
setContent(account)
|
|
||||||
profileAdapter.refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
setContent(account)
|
setContent(account)
|
||||||
job = launch(job, lifecycleScope, viewModel, profileAdapter)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private fun createSearchTabs(account: Account?): Array<Fragment>{
|
||||||
* Shows or hides the error in the profile
|
|
||||||
*/
|
val profileGridFragment = ProfileFeedFragment()
|
||||||
private fun showError(errorText: String = getString(R.string.profile_error), show: Boolean = true){
|
val profileFeedFragment = ProfileFeedFragment()
|
||||||
if(show){
|
val profileBookmarksFragment = ProfileFeedFragment() // TODO: bookmark fragment
|
||||||
binding.profileProgressBar.visibility = View.GONE
|
val arguments = Bundle()
|
||||||
binding.motionLayout.transitionToEnd()
|
arguments.putSerializable(Account.ACCOUNT_TAG, account)
|
||||||
binding.errorLayout.errorText.text = errorText
|
profileGridFragment.arguments = arguments
|
||||||
} else if(binding.motionLayout.progress == 1F) {
|
profileFeedFragment.arguments = arguments
|
||||||
binding.motionLayout.transitionToStart()
|
profileBookmarksFragment.arguments = arguments
|
||||||
}
|
return arrayOf(
|
||||||
binding.profileRefreshLayout.isRefreshing = false
|
profileGridFragment,
|
||||||
|
profileFeedFragment,
|
||||||
|
profileBookmarksFragment
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setupTabs(
|
||||||
|
tabs: Array<Fragment>
|
||||||
|
){
|
||||||
|
binding.viewPager.adapter = object : FragmentStateAdapter(this) {
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
return tabs[position]
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int {
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TabLayoutMediator(binding.profileTabs, binding.viewPager) { tab, position ->
|
||||||
|
tab.tabLabelVisibility = TabLayout.TAB_LABEL_VISIBILITY_UNLABELED
|
||||||
|
when (position) {
|
||||||
|
0 -> {
|
||||||
|
tab.setText("Grid view")
|
||||||
|
tab.setIcon(R.drawable.grid_on_black_24dp)
|
||||||
|
}
|
||||||
|
1 -> {
|
||||||
|
tab.setText("Feed view")
|
||||||
|
tab.setIcon(R.drawable.feed_view)
|
||||||
|
}
|
||||||
|
2 -> {
|
||||||
|
tab.setText("Bookmarks")
|
||||||
|
tab.setIcon(R.drawable.bookmark)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.attach()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun setContent(account: Account?) {
|
private fun setContent(account: Account?) {
|
||||||
if(account != null) {
|
if(account != null) {
|
||||||
setViews(account)
|
setViews(account)
|
||||||
@ -120,9 +148,17 @@ class ProfileActivity : BaseThemedWithBarActivity() {
|
|||||||
api.verifyCredentials()
|
api.verifyCredentials()
|
||||||
} catch (exception: IOException) {
|
} catch (exception: IOException) {
|
||||||
Log.e("ProfileActivity:", exception.toString())
|
Log.e("ProfileActivity:", exception.toString())
|
||||||
return@launchWhenResumed showError()
|
Toast.makeText(
|
||||||
|
applicationContext, "Could not get your profile",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
return@launchWhenResumed
|
||||||
} catch (exception: HttpException) {
|
} catch (exception: HttpException) {
|
||||||
return@launchWhenResumed showError()
|
Toast.makeText(
|
||||||
|
applicationContext, "Could not get your profile",
|
||||||
|
Toast.LENGTH_SHORT
|
||||||
|
).show()
|
||||||
|
return@launchWhenResumed
|
||||||
}
|
}
|
||||||
setViews(myAccount)
|
setViews(myAccount)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,58 @@
|
|||||||
|
package org.pixeldroid.app.profile
|
||||||
|
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.LayoutInflater
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.lifecycle.ViewModelProvider
|
||||||
|
import androidx.paging.ExperimentalPagingApi
|
||||||
|
import org.pixeldroid.app.posts.feeds.uncachedFeeds.*
|
||||||
|
import org.pixeldroid.app.posts.feeds.uncachedFeeds.profile.ProfileContentRepository
|
||||||
|
import org.pixeldroid.app.utils.api.objects.Account
|
||||||
|
import org.pixeldroid.app.utils.api.objects.Status
|
||||||
|
import org.pixeldroid.app.utils.db.entities.UserDatabaseEntity
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fragment to show a list of [Account]s, as a result of a search.
|
||||||
|
*/
|
||||||
|
class ProfileFeedFragment : UncachedFeedFragment<Status>() {
|
||||||
|
|
||||||
|
private lateinit var accountId : String
|
||||||
|
private var user: UserDatabaseEntity? = null
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
adapter = ProfilePostsAdapter()
|
||||||
|
|
||||||
|
//get the currently active user
|
||||||
|
user = db.userDao().getActiveUser()
|
||||||
|
// Set profile according to given account
|
||||||
|
val account = arguments?.getSerializable(Account.ACCOUNT_TAG) as Account?
|
||||||
|
accountId = account?.id ?: user!!.user_id
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalPagingApi::class)
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater, container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View? {
|
||||||
|
|
||||||
|
val view = super.onCreateView(inflater, container, savedInstanceState)
|
||||||
|
|
||||||
|
// Get the view model
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
viewModel = ViewModelProvider(requireActivity(), ProfileViewModelFactory(
|
||||||
|
ProfileContentRepository(
|
||||||
|
apiHolder.setToCurrentUser(),
|
||||||
|
accountId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)["Profile", FeedViewModel::class.java] as FeedViewModel<Status>
|
||||||
|
|
||||||
|
launch()
|
||||||
|
initSearch()
|
||||||
|
|
||||||
|
return view
|
||||||
|
}
|
||||||
|
}
|
5
app/src/main/res/drawable/bookmark.xml
Normal file
5
app/src/main/res/drawable/bookmark.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
|
||||||
|
</vector>
|
5
app/src/main/res/drawable/feed_view.xml
Normal file
5
app/src/main/res/drawable/feed_view.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp" android:tint="#000000"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M2,21h19v-3H2v3zM20,8H3c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h17c0.55,0 1,-0.45 1,-1V9c0,-0.55 -0.45,-1 -1,-1zM2,3v3h19V3H2z"/>
|
||||||
|
</vector>
|
@ -46,7 +46,6 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:text="@string/default_nposts"
|
android:text="@string/default_nposts"
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/descriptionTextView" />
|
app:layout_constraintTop_toBottomOf="@+id/descriptionTextView" />
|
||||||
|
|
||||||
@ -89,7 +88,6 @@
|
|||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/profilePictureImageView" />
|
app:layout_constraintTop_toBottomOf="@id/profilePictureImageView" />
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/descriptionTextView"
|
android:id="@+id/descriptionTextView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -123,49 +121,26 @@
|
|||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/profilePictureImageView"
|
app:layout_constraintStart_toEndOf="@+id/profilePictureImageView"
|
||||||
app:layout_constraintTop_toTopOf="@+id/profilePictureImageView" />
|
app:layout_constraintTop_toTopOf="@+id/profilePictureImageView" />
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/profileTabs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/nbPostsTextView"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
</com.google.android.material.appbar.CollapsingToolbarLayout>
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
<ProgressBar
|
|
||||||
android:id="@+id/profileProgressBar"
|
|
||||||
style="?android:attr/progressBarStyle"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="16dp" />
|
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
android:id="@+id/profileRefreshLayout"
|
android:id="@+id/view_pager"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
|
||||||
|
|
||||||
<androidx.constraintlayout.motion.widget.MotionLayout
|
|
||||||
android:id="@+id/motionLayout"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginTop="8dp"
|
|
||||||
android:visibility="visible"
|
|
||||||
app:layoutDescription="@xml/error_layout_xml_error_scene">
|
|
||||||
|
|
||||||
<include
|
|
||||||
android:id="@+id/errorLayout"
|
|
||||||
layout="@layout/error_layout"
|
|
||||||
tools:layout_editor_absoluteX="50dp" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/profilePostsRecyclerView"
|
|
||||||
android:visibility="visible"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layoutManager="LinearLayoutManager"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/errorLayout"
|
|
||||||
tools:listitem="@layout/fragment_profile_posts" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.motion.widget.MotionLayout>
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
48
app/src/main/res/layout/fragment_profile_feed.xml
Normal file
48
app/src/main/res/layout/fragment_profile_feed.xml
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/profileProgressBar"
|
||||||
|
style="?android:attr/progressBarStyle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginTop="16dp" />
|
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/profileRefreshLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
|
<androidx.constraintlayout.motion.widget.MotionLayout
|
||||||
|
android:id="@+id/motionLayout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:visibility="visible"
|
||||||
|
app:layoutDescription="@xml/error_layout_xml_error_scene">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/errorLayout"
|
||||||
|
layout="@layout/error_layout"
|
||||||
|
tools:layout_editor_absoluteX="50dp" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/profilePostsRecyclerView"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layoutManager="LinearLayoutManager"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/errorLayout"
|
||||||
|
tools:listitem="@layout/fragment_profile_posts" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.motion.widget.MotionLayout>
|
||||||
|
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
Loading…
x
Reference in New Issue
Block a user