Skip to content

+ button on pending uploads screen #6327

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ import javax.inject.Named
/**
* Created by root on 01.06.2018.
*/
class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsListContract.View,
open class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsListContract.View,
ContributionsListAdapter.Callback, WikipediaInstructionsDialogFragment.Callback {
@JvmField
@Inject
Expand Down Expand Up @@ -179,16 +179,16 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
): View {
binding = FragmentContributionsListBinding.inflate(
inflater, container, false
)
rvContributionsList = binding!!.contributionsList

contributionsListPresenter!!.onAttachView(this)
binding!!.fabCustomGallery.setOnClickListener { v: View? -> launchCustomSelector() }
binding!!.fabCustomGallery.setOnLongClickListener { view: View? ->
showShortToast(context, fr.free.nrw.commons.R.string.custom_selector_title)
binding!!.fabCustomGallery.setOnLongClickListener {
showShortToast(context, R.string.custom_selector_title)
true
}

Expand All @@ -198,7 +198,7 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
} else {
binding!!.tvContributionsOfUser.visibility = View.VISIBLE
binding!!.tvContributionsOfUser.text =
getString(fr.free.nrw.commons.R.string.contributions_of_user, userName)
getString(R.string.contributions_of_user, userName)
binding!!.fabLayout.visibility = View.GONE
}

Expand Down Expand Up @@ -358,43 +358,43 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
}

private fun initializeAnimations() {
fab_open = AnimationUtils.loadAnimation(activity, fr.free.nrw.commons.R.anim.fab_open)
fab_close = AnimationUtils.loadAnimation(activity, fr.free.nrw.commons.R.anim.fab_close)
rotate_forward = AnimationUtils.loadAnimation(activity, fr.free.nrw.commons.R.anim.rotate_forward)
rotate_backward = AnimationUtils.loadAnimation(activity, fr.free.nrw.commons.R.anim.rotate_backward)
fab_open = AnimationUtils.loadAnimation(activity, R.anim.fab_open)
fab_close = AnimationUtils.loadAnimation(activity, R.anim.fab_close)
rotate_forward = AnimationUtils.loadAnimation(activity,R.anim.rotate_forward)
rotate_backward = AnimationUtils.loadAnimation(activity,R.anim.rotate_backward)
}

private fun setListeners() {
binding!!.fabPlus.setOnClickListener { view: View? -> animateFAB(isFabOpen) }
binding!!.fabCamera.setOnClickListener { view: View? ->
binding!!.fabPlus.setOnClickListener { animateFAB(isFabOpen) }
binding!!.fabCamera.setOnClickListener {
controller!!.initiateCameraPick(
requireActivity(),
inAppCameraLocationPermissionLauncher,
cameraPickLauncherForResult
)
animateFAB(isFabOpen)
}
binding!!.fabCamera.setOnLongClickListener { view: View? ->
binding!!.fabCamera.setOnLongClickListener {
showShortToast(
context,
fr.free.nrw.commons.R.string.add_contribution_from_camera
R.string.add_contribution_from_camera
)
true
}
binding!!.fabGallery.setOnClickListener { view: View? ->
binding!!.fabGallery.setOnClickListener {
controller!!.initiateGalleryPick(requireActivity(), galleryPickLauncherForResult, true)
animateFAB(isFabOpen)
}
binding!!.fabGallery.setOnLongClickListener { view: View? ->
showShortToast(context, fr.free.nrw.commons.R.string.menu_from_gallery)
binding!!.fabGallery.setOnLongClickListener {
showShortToast(context, R.string.menu_from_gallery)
true
}
}

/**
* Launch Custom Selector.
*/
protected fun launchCustomSelector() {
private fun launchCustomSelector() {
controller!!.initiateCustomGalleryPickWithPermission(
requireActivity(),
customSelectorLauncherForResult
Expand Down Expand Up @@ -433,9 +433,9 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
/**
* Shows welcome message if user has no contributions yet i.e. new user.
*/
override fun showWelcomeTip(shouldShow: Boolean) {
override fun showWelcomeTip(numberOfUploads: Boolean) {
binding!!.noContributionsYet.visibility =
if (shouldShow) View.VISIBLE else View.GONE
if (numberOfUploads) View.VISIBLE else View.GONE
}

/**
Expand Down Expand Up @@ -468,9 +468,9 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
}
}

override fun openMediaDetail(position: Int, isWikipediaButtonDisplayed: Boolean) {
override fun openMediaDetail(contribution: Int, isWikipediaPageExists: Boolean) {
if (null != callback) { //Just being safe, ideally they won't be called when detached
callback!!.showDetail(position, isWikipediaButtonDisplayed)
callback!!.showDetail(contribution, isWikipediaPageExists)
}
}

Expand All @@ -482,8 +482,8 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
override fun addImageToWikipedia(contribution: Contribution?) {
showAlertDialog(
requireActivity(),
getString(fr.free.nrw.commons.R.string.add_picture_to_wikipedia_article_title),
getString(fr.free.nrw.commons.R.string.add_picture_to_wikipedia_article_desc),
getString(R.string.add_picture_to_wikipedia_article_title),
getString(R.string.add_picture_to_wikipedia_article_desc),
{
if (contribution != null) {
showAddImageToWikipediaInstructions(contribution)
Expand All @@ -501,7 +501,7 @@ class ContributionsListFragment : CommonsDaggerSupportFragment(), ContributionsL
val fragment = newInstance(contribution)
fragment.callback =
WikipediaInstructionsDialogFragment.Callback { contribution: Contribution?, copyWikicode: Boolean ->
this.onConfirmClicked(
onConfirmClicked(
contribution,
copyWikicode
)
Expand Down
170 changes: 159 additions & 11 deletions app/src/main/java/fr/free/nrw/commons/upload/PendingUploadsFragment.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
package fr.free.nrw.commons.upload

import android.Manifest.permission
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.os.Build
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts.RequestMultiplePermissions
import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult
import androidx.paging.PagedList
import androidx.recyclerview.widget.LinearLayoutManager
import fr.free.nrw.commons.CommonsApplication
Expand All @@ -13,10 +22,13 @@ import fr.free.nrw.commons.contributions.Contribution
import fr.free.nrw.commons.contributions.Contribution.Companion.STATE_IN_PROGRESS
import fr.free.nrw.commons.contributions.Contribution.Companion.STATE_PAUSED
import fr.free.nrw.commons.contributions.Contribution.Companion.STATE_QUEUED
import fr.free.nrw.commons.contributions.ContributionController
import fr.free.nrw.commons.databinding.FragmentPendingUploadsBinding
import fr.free.nrw.commons.di.CommonsDaggerSupportFragment
import fr.free.nrw.commons.filepicker.FilePicker
import fr.free.nrw.commons.utils.DialogUtil.showAlertDialog
import fr.free.nrw.commons.utils.ViewUtil
import fr.free.nrw.commons.utils.ViewUtil.showShortToast
import java.util.Locale
import javax.inject.Inject

Expand All @@ -30,17 +42,46 @@ class PendingUploadsFragment :
PendingUploadsAdapter.Callback {
@Inject
lateinit var pendingUploadsPresenter: PendingUploadsPresenter

private lateinit var binding: FragmentPendingUploadsBinding

private lateinit var uploadProgressActivity: UploadProgressActivity

private lateinit var adapter: PendingUploadsAdapter

private var contributionsSize = 0

private var contributionsList = mutableListOf<Contribution>()

@JvmField
@Inject
var controller: ContributionController? = null

private var fab_close: Animation? = null
private var fab_open: Animation? = null
private var rotate_forward: Animation? = null
private var rotate_backward: Animation? = null
private var isFabOpen = false

private lateinit var inAppCameraLocationPermissionLauncher: ActivityResultLauncher<Array<String>>

private val cameraPickLauncherForResult = registerForActivityResult<Intent, ActivityResult>(
StartActivityForResult()
) { result: ActivityResult? ->
controller!!.handleActivityResultWithCallback(requireActivity()
) { callbacks: FilePicker.Callbacks? ->
controller!!.onPictureReturnedFromCamera(
result!!, requireActivity(), callbacks!!
)
}
}
private val galleryPickLauncherForResult = registerForActivityResult<Intent, ActivityResult>(
StartActivityForResult()
) { result: ActivityResult? ->
controller!!.handleActivityResultWithCallback(requireActivity()
) { callbacks: FilePicker.Callbacks? ->
controller!!.onPictureReturnedFromGallery(
result!!, requireActivity(), callbacks!!
)
}
}


override fun onAttach(context: Context) {
super.onAttach(context)
if (context is UploadProgressActivity) {
Expand All @@ -54,13 +95,43 @@ class PendingUploadsFragment :
savedInstanceState: Bundle?,
): View {
super.onCreate(savedInstanceState)
inAppCameraLocationPermissionLauncher =
registerForActivityResult(RequestMultiplePermissions()) { result ->
val areAllGranted = result.values.all { it }

if (areAllGranted) {
controller?.locationPermissionCallback?.onLocationPermissionGranted()
} else {
activity?.let { currentActivity ->
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
currentActivity.shouldShowRequestPermissionRationale(permission.ACCESS_FINE_LOCATION)
) {
controller?.handleShowRationaleFlowCameraLocation(
currentActivity,
inAppCameraLocationPermissionLauncher,
cameraPickLauncherForResult
)
} else {
controller?.locationPermissionCallback?.onLocationPermissionDenied(
currentActivity.getString(R.string.in_app_camera_location_permission_denied)
)
}
}
}
}

binding = FragmentPendingUploadsBinding.inflate(inflater, container, false)
binding.fabCustomGallery.setOnClickListener { launchCustomSelector() }
binding.fabCustomGallery.setOnLongClickListener {
showShortToast(context, R.string.custom_selector_title)
true
}
pendingUploadsPresenter.onAttachView(this)
initAdapter()
return binding.root
}

fun initAdapter() {
private fun initAdapter() {
adapter = PendingUploadsAdapter(this)
}

Expand All @@ -70,6 +141,8 @@ class PendingUploadsFragment :
) {
super.onViewCreated(view, savedInstanceState)
initRecyclerView()
initializeAnimations()
setListeners()
}

/**
Expand Down Expand Up @@ -98,12 +171,12 @@ class PendingUploadsFragment :
}
}
if (contributionsSize == 0) {
binding.nopendingTextView.visibility = View.VISIBLE
binding.pendingUplaodsLl.visibility = View.GONE
binding.noPendingTextView.visibility = View.VISIBLE
binding.pendingUploadsLl.visibility = View.GONE
uploadProgressActivity.hidePendingIcons()
} else {
binding.nopendingTextView.visibility = View.GONE
binding.pendingUplaodsLl.visibility = View.VISIBLE
binding.noPendingTextView.visibility = View.GONE
binding.pendingUploadsLl.visibility = View.VISIBLE
adapter.submitList(list)
binding.progressTextView.setText("$contributionsSize uploads left")
if ((pausedOrQueuedUploads == contributionsSize) || CommonsApplication.isPaused) {
Expand All @@ -115,6 +188,81 @@ class PendingUploadsFragment :
}
}

private fun initializeAnimations() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, most of this code is duplicated from ContributionsListFragment.kt?
If yes, how about not duplicating it, for instance by creating an abstract base class?

fab_open = AnimationUtils.loadAnimation(activity, R.anim.fab_open)
fab_close = AnimationUtils.loadAnimation(activity, R.anim.fab_close)
rotate_forward = AnimationUtils.loadAnimation(activity, R.anim.rotate_forward)
rotate_backward = AnimationUtils.loadAnimation(activity, R.anim.rotate_backward)
}
private fun setListeners() {
binding.fabPlus.setOnClickListener { animateFAB(isFabOpen) }
binding.fabCamera.setOnClickListener {
controller!!.initiateCameraPick(
requireActivity(),
inAppCameraLocationPermissionLauncher,
cameraPickLauncherForResult
)
animateFAB(isFabOpen)
}
binding.fabCamera.setOnLongClickListener {
showShortToast(
context,
R.string.add_contribution_from_camera
)
true
}
binding.fabGallery.setOnClickListener {
controller!!.initiateGalleryPick(requireActivity(), galleryPickLauncherForResult, true)
animateFAB(isFabOpen)
}
binding.fabGallery.setOnLongClickListener {
showShortToast(context, R.string.menu_from_gallery)
true
}
}

private val customSelectorLauncherForResult = registerForActivityResult<Intent, ActivityResult>(
StartActivityForResult()
) { result: ActivityResult? ->
controller!!.handleActivityResultWithCallback(requireActivity()
) { callbacks: FilePicker.Callbacks? ->
controller!!.onPictureReturnedFromCustomSelector(
result!!, requireActivity(), callbacks!!
)
}
}
protected fun launchCustomSelector() {
controller!!.initiateCustomGalleryPickWithPermission(
requireActivity(),
customSelectorLauncherForResult
)
animateFAB(isFabOpen)
}

private fun animateFAB(isFabOpen: Boolean) {
this.isFabOpen = !isFabOpen
if (binding.fabPlus.isShown) {
if (isFabOpen) {
binding.fabPlus.startAnimation(rotate_backward)
binding.fabCamera.startAnimation(fab_close)
binding.fabGallery.startAnimation(fab_close)
binding.fabCustomGallery.startAnimation(fab_close)
binding.fabCamera.hide()
binding.fabGallery.hide()
binding.fabCustomGallery.hide()
} else {
binding.fabPlus.startAnimation(rotate_forward)
binding.fabCamera.startAnimation(fab_open)
binding.fabGallery.startAnimation(fab_open)
binding.fabCustomGallery.startAnimation(fab_open)
binding.fabCamera.show()
binding.fabGallery.show()
binding.fabCustomGallery.show()
}
this.isFabOpen = !isFabOpen
}
}

/**
* Cancels a specific upload after getting a confirmation from the user using Dialog.
*/
Expand Down Expand Up @@ -162,7 +310,7 @@ class PendingUploadsFragment :
String.format(locale, activity.getString(R.string.yes)),
String.format(locale, activity.getString(R.string.no)),
{
ViewUtil.showShortToast(context, R.string.cancelling_upload)
showShortToast(context, R.string.cancelling_upload)
uploadProgressActivity.hidePendingIcons()
pendingUploadsPresenter.deleteUploads(
listOf(
Expand Down
Loading