Added handling of multiple images in a post (#111)
* Changed Post interaction icons and added click feedback * added reblog and unreblog api implementations * Use fancy animated buttons * WIP reposter * WIP reblog button * renamed ViewHolder => PostViewHolder * activated reblogger in feed * added custom html parser, still need to fix clickable links * added parsed HTML in notifications * fixed mention click * added tests for reblog and clickable mentions * adapted unit tests to work with new html parser * changed incoherent comment * made hashtags slightly less useless * removed unit test that were no longer valid * removed useless test * trying to fix tests * fixing tests * trying to improve coverage a little * removed unused code to improve coverage * changed cast to type converter * added failure responses to help coverage * added mock server response for reblogging * fixed broken json * trying to fix a broken test * added handling of multiple images in a post * Tweak tests * Typo in test * Add scrolls to make tests pass on small screens * fixed old JSON in mockserver * fixed linter issue * merged with master again * added test for albums Co-authored-by: Matthieu <61561059+Wv5twkFEKh54vo4tta9yu7dHa3@users.noreply.github.com>
This commit is contained in:
parent
8265ac2d62
commit
2339fb0967
|
@ -144,6 +144,21 @@ class MockedServerTest {
|
|||
onView(withId(R.id.list)).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clickingTabOnAlbumShowsNextPhoto() {
|
||||
ActivityScenario.launch(MainActivity::class.java).onActivity {
|
||||
a -> run {
|
||||
//Wait for the feed to load
|
||||
Thread.sleep(1000)
|
||||
//Pick the second photo
|
||||
a.findViewById<TabLayout>(R.id.postTabs).getTabAt(1)?.select()
|
||||
}
|
||||
}
|
||||
|
||||
//Check that the tabs are shown
|
||||
onView(first(withId(R.id.postTabs))).check(matches(isDisplayed()))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun clickingLikeButtonWorks() {
|
||||
ActivityScenario.launch(MainActivity::class.java)
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,73 @@
|
|||
package com.h.pixeldroid
|
||||
|
||||
import android.graphics.Color
|
||||
import android.graphics.drawable.ColorDrawable
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.RequestBuilder
|
||||
import com.h.pixeldroid.utils.ImageConverter
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.*
|
||||
import java.io.Serializable
|
||||
|
||||
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
|
||||
private const val IMG_URL = "imgurl"
|
||||
private const val RQST_BLDR = "rqstbldr"
|
||||
|
||||
/**
|
||||
* A simple [Fragment] subclass.
|
||||
* Use the [ImageFragment.newInstance] factory method to
|
||||
* create an instance of this fragment.
|
||||
*/
|
||||
class ImageFragment : Fragment() {
|
||||
private lateinit var imgUrl: String
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
arguments?.let {
|
||||
imgUrl = it.getString(IMG_URL)!!
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater, container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
): View? {
|
||||
|
||||
// Inflate the layout for this fragment
|
||||
return inflater.inflate(R.layout.fragment_image, container, false)
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
//Load the image into to view
|
||||
val imageView : ImageView = view.findViewById(R.id.imageImageView)!!
|
||||
val picRequest = Glide.with(this)
|
||||
.asDrawable().fitCenter()
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
|
||||
picRequest.load(imgUrl).into(imageView)
|
||||
}
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Use this factory method to create a new instance of
|
||||
* this fragment using the provided parameters.
|
||||
*
|
||||
* @param imageUrl the url of the image we want to create a fragment for
|
||||
* @return A new instance of fragment ImageFragment.
|
||||
*/
|
||||
@JvmStatic
|
||||
fun newInstance(imageUrl: String) =
|
||||
ImageFragment().apply {
|
||||
arguments = Bundle().apply {
|
||||
putString(IMG_URL, imageUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,7 +30,7 @@ class PostFragment : Fragment() {
|
|||
.asDrawable().fitCenter()
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
|
||||
status?.setupPost(root, picRequest, root.postPicture, root.profilePic)
|
||||
status?.setupPost(root, picRequest, this)
|
||||
|
||||
//Setup arguments needed for the onclicklisteners
|
||||
val holder = PostViewHolder(root, requireContext())
|
||||
|
|
|
@ -39,7 +39,7 @@ class HomeFragment : FeedFragment<Status, PostViewHolder>() {
|
|||
.asDrawable().fitCenter()
|
||||
.placeholder(ColorDrawable(Color.GRAY))
|
||||
|
||||
adapter = HomeRecyclerViewAdapter()
|
||||
adapter = HomeRecyclerViewAdapter(this)
|
||||
list.adapter = adapter
|
||||
|
||||
|
||||
|
@ -82,7 +82,7 @@ class HomeFragment : FeedFragment<Status, PostViewHolder>() {
|
|||
/**
|
||||
* [RecyclerView.Adapter] that can display a list of Statuses
|
||||
*/
|
||||
inner class HomeRecyclerViewAdapter
|
||||
inner class HomeRecyclerViewAdapter(private val homeFragment: HomeFragment)
|
||||
: FeedsRecyclerViewAdapter<Status, PostViewHolder>() {
|
||||
private val api = pixelfedAPI
|
||||
private val credential = "Bearer $accessToken"
|
||||
|
@ -104,7 +104,7 @@ class HomeFragment : FeedFragment<Status, PostViewHolder>() {
|
|||
holder.postPic.maxHeight = metrics.heightPixels
|
||||
|
||||
//Setup the post layout
|
||||
post.setupPost(holder.postView, picRequest, holder.postPic, holder.profilePic)
|
||||
post.setupPost(holder.postView, picRequest, homeFragment)
|
||||
|
||||
//Set the special HTML text
|
||||
post.setDescription(holder.postView, api, credential)
|
||||
|
|
|
@ -3,18 +3,21 @@ package com.h.pixeldroid.objects
|
|||
import android.content.Context
|
||||
import android.graphics.Typeface
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.os.Build
|
||||
import android.text.Html
|
||||
import android.text.Spanned
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.ImageView
|
||||
import android.view.View.GONE
|
||||
import android.view.View.VISIBLE
|
||||
import android.widget.LinearLayout
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.core.text.toSpanned
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||
import com.bumptech.glide.RequestBuilder
|
||||
import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.h.pixeldroid.ImageFragment
|
||||
import com.h.pixeldroid.R
|
||||
import com.h.pixeldroid.api.PixelfedAPI
|
||||
import com.h.pixeldroid.fragments.feeds.PostViewHolder
|
||||
|
@ -27,6 +30,9 @@ import com.h.pixeldroid.utils.PostUtils.Companion.retrieveComments
|
|||
import com.h.pixeldroid.utils.PostUtils.Companion.toggleCommentInput
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.unLikePostCall
|
||||
import com.h.pixeldroid.utils.PostUtils.Companion.undoReblogPost
|
||||
|
||||
import kotlinx.android.synthetic.main.post_fragment.view.*
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
/*
|
||||
|
@ -93,11 +99,11 @@ data class Status(
|
|||
}
|
||||
|
||||
fun getUsername() : CharSequence {
|
||||
var name = account?.display_name
|
||||
var name = account.display_name
|
||||
if (name.isEmpty()) {
|
||||
name = account?.username
|
||||
name = account.username
|
||||
}
|
||||
return name!!
|
||||
return name
|
||||
}
|
||||
|
||||
fun getNLikes() : CharSequence {
|
||||
|
@ -110,11 +116,49 @@ data class Status(
|
|||
return "$nShares Shares"
|
||||
}
|
||||
|
||||
private fun setupPostPics(rootView: View, request: RequestBuilder<Drawable>, homeFragment: Fragment) {
|
||||
//Check whether or not we need to activate the viewPager
|
||||
if(media_attachments?.size == 1) {
|
||||
rootView.postPicture.visibility = VISIBLE
|
||||
rootView.postPager.visibility = GONE
|
||||
rootView.postTabs.visibility = GONE
|
||||
request.load(this.getPostUrl()).into(rootView.postPicture)
|
||||
} else if(media_attachments?.size!! > 1) {
|
||||
//Only show the viewPager and tabs
|
||||
rootView.postPicture.visibility = GONE
|
||||
rootView.postPager.visibility = VISIBLE
|
||||
rootView.postTabs.visibility = VISIBLE
|
||||
|
||||
val tabs : ArrayList<ImageFragment> = ArrayList()
|
||||
|
||||
//Fill the tabs with each mediaAttachment
|
||||
for(media in media_attachments) {
|
||||
tabs.add(ImageFragment.newInstance(media.url))
|
||||
}
|
||||
setupTabs(tabs, rootView, homeFragment)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupTabs(tabs: ArrayList<ImageFragment>, rootView: View, homeFragment: Fragment) {
|
||||
//Attach the given tabs to the view pager
|
||||
rootView.postPager.adapter = object : FragmentStateAdapter(homeFragment) {
|
||||
override fun createFragment(position: Int): Fragment {
|
||||
return tabs[position]
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
return media_attachments?.size ?: 0
|
||||
}
|
||||
}
|
||||
TabLayoutMediator(rootView.postTabs, rootView.postPager) { tab, _ ->
|
||||
tab.icon = rootView.context.getDrawable(R.drawable.ic_dot_blue_12dp)
|
||||
}.attach()
|
||||
}
|
||||
|
||||
fun setupPost(
|
||||
rootView: View,
|
||||
request: RequestBuilder<Drawable>,
|
||||
postPic: ImageView,
|
||||
profilePic: ImageView
|
||||
homeFragment: Fragment
|
||||
) {
|
||||
//Setup username as a button that opens the profile
|
||||
val username = rootView.findViewById<TextView>(R.id.username)
|
||||
|
@ -135,13 +179,13 @@ data class Status(
|
|||
nshares.setTypeface(null, Typeface.BOLD)
|
||||
|
||||
//Setup images
|
||||
request.load(this.getPostUrl()).into(postPic)
|
||||
setupPostPics(rootView, request, homeFragment)
|
||||
ImageConverter.setRoundImageFromURL(
|
||||
rootView,
|
||||
this.getProfilePicUrl(),
|
||||
profilePic
|
||||
rootView.profilePic
|
||||
)
|
||||
profilePic.setOnClickListener { account.openProfile(rootView.context) }
|
||||
rootView.profilePic.setOnClickListener { account.openProfile(rootView.context) }
|
||||
|
||||
//Set comment initial visibility
|
||||
rootView.findViewById<LinearLayout>(R.id.commentIn).visibility = View.GONE
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="12dp" android:tint="#003DFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="12dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#010101" android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"/>
|
||||
</vector>
|
|
@ -0,0 +1,5 @@
|
|||
<vector android:height="24dp" android:tint="#003DFF"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#010101" android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"/>
|
||||
</vector>
|
|
@ -0,0 +1,16 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ImageFragment">
|
||||
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/imageImageView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"/>
|
||||
|
||||
|
||||
</FrameLayout>
|
|
@ -39,14 +39,44 @@
|
|||
app:layout_constraintTop_toTopOf="@+id/profilePic"
|
||||
tools:text="Account" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/postPicture"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/postConstraint"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:adjustViewBounds="true"
|
||||
app:layout_constraintTop_toBottomOf="@+id/profilePic"
|
||||
tools:src="@color/browser_actions_bg_grey"/>
|
||||
app:layout_constraintTop_toBottomOf="@+id/profilePic">
|
||||
|
||||
<androidx.viewpager2.widget.ViewPager2
|
||||
android:id="@+id/postPager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
</androidx.viewpager2.widget.ViewPager2>
|
||||
|
||||
<com.google.android.material.tabs.TabLayout
|
||||
android:id="@+id/postTabs"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/postPager"
|
||||
app:tabMode="auto">
|
||||
</com.google.android.material.tabs.TabLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/postPicture"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:adjustViewBounds="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:src="@color/browser_actions_bg_grey"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/commenter"
|
||||
|
@ -78,7 +108,7 @@
|
|||
app:layout_constraintEnd_toStartOf="@id/commenter"
|
||||
app:layout_constraintHorizontal_chainStyle="spread"
|
||||
app:layout_constraintStart_toStartOf="@id/profilePic"
|
||||
app:layout_constraintTop_toBottomOf="@id/postPicture"/>
|
||||
app:layout_constraintTop_toBottomOf="@id/postConstraint"/>
|
||||
|
||||
<at.connyduck.sparkbutton.SparkButton
|
||||
android:id="@+id/reblogger"
|
||||
|
|
Loading…
Reference in New Issue