Skip to content

Commit

Permalink
Merge pull request #188 from PermanentOrg/VSP-985
Browse files Browse the repository at this point in the history
Floating Action Island implementation
  • Loading branch information
flaviahandrea-vsp authored Jan 13, 2023
2 parents a78913c + 3922dae commit c0b3716
Show file tree
Hide file tree
Showing 15 changed files with 462 additions and 315 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ android {
applicationId "org.permanent.PermanentArchive"
minSdkVersion 26
targetSdkVersion 32
versionCode 41
versionName "1.6.0"
versionCode 42
versionName "1.6.1"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.permanent.permanent.ui

enum class RelocationIslandState {
BLANK, POPULATED, PROCESSING, DONE
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.permanent.permanent.ui.myFiles

import android.animation.ValueAnimator
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
Expand All @@ -8,19 +9,23 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.dialog_cancel_uploads.view.*
import kotlinx.android.synthetic.main.dialog_delete.view.*
import kotlinx.android.synthetic.main.dialog_delete.view.tvTitle
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.permanent.permanent.BuildConfig
import org.permanent.permanent.R
import org.permanent.permanent.databinding.DialogRenameRecordBinding
Expand All @@ -41,6 +46,7 @@ import org.permanent.permanent.viewmodels.MyFilesViewModel
import org.permanent.permanent.viewmodels.RenameRecordViewModel
import org.permanent.permanent.viewmodels.SingleLiveEvent


const val PARCELABLE_RECORD_KEY = "parcelable_record_key"
const val PARCELABLE_FILES_KEY = "parcelable_files_key"

Expand Down Expand Up @@ -112,6 +118,10 @@ class MyFilesFragment : PermanentBaseFragment() {
}
arguments?.getParcelableArrayList<Uri>(MainActivity.SAVE_TO_PERMANENT_FILE_URIS_KEY)
?.let { showSaveToPermanentFragment(it) }
if (viewModel.isRelocationMode.value == true) resizeIslandWidthAnimated(
binding.flFloatingActionIsland.width,
ISLAND_WIDTH_LARGE
)
}
}
return binding.root
Expand Down Expand Up @@ -281,8 +291,27 @@ class MyFilesFragment : PermanentBaseFragment() {
shareManagementFragment?.show(parentFragmentManager, shareManagementFragment?.tag)
}

private val shrinkIslandRequestObserver = Observer<Void> {
resizeIslandWidthAnimated(binding.flFloatingActionIsland.width, ISLAND_WIDTH_SMALL)
}

private val onRecordRelocateRequest = Observer<Pair<Record, RelocationType>> {
viewModel.setRelocationMode(it)
lifecycleScope.launch {
delay(DELAY_TO_RESIZE_MILLIS)
resizeIslandWidthAnimated(binding.flFloatingActionIsland.width, ISLAND_WIDTH_LARGE)
}
}

private fun resizeIslandWidthAnimated(currentWidth: Int, newWidth: Int) {
val widthAnimator = ValueAnimator.ofInt(currentWidth, newWidth)
widthAnimator.duration = RESIZE_DURATION_MILLIS
widthAnimator.interpolator = DecelerateInterpolator()
widthAnimator.addUpdateListener { animation ->
binding.flFloatingActionIsland.layoutParams.width = animation.animatedValue as Int
binding.flFloatingActionIsland.requestLayout()
}
widthAnimator.start()
}

private val onSortRequest = Observer<SortType> {
Expand Down Expand Up @@ -385,11 +414,13 @@ class MyFilesFragment : PermanentBaseFragment() {
viewModel.getOnCancelAllUploads().observe(this, onCancelAllUploads)
viewModel.getOnFileViewRequest().observe(this, onFileViewRequest)
viewModel.getOnRecordSelected().observe(this, onRecordSelectedObserver)
viewModel.getShrinkIslandRequest().observe(this, shrinkIslandRequestObserver)
renameDialogViewModel.getOnRecordRenamed().observe(this, onRecordRenamed)
renameDialogViewModel.getOnShowMessage().observe(this, onShowMessage)
addOptionsFragment?.getOnFilesSelected()?.observe(this, onFilesSelectedToUpload)
saveToPermanentFragment?.getOnFilesUploadRequest()?.observe(this, onFilesUploadRequest)
saveToPermanentFragment?.getOnCurrentArchiveChangedEvent()?.observe(this, onCurrentArchiveChangedObserver)
saveToPermanentFragment?.getOnCurrentArchiveChangedEvent()
?.observe(this, onCurrentArchiveChangedObserver)
}

override fun disconnectViewModelEvents() {
Expand All @@ -408,12 +439,14 @@ class MyFilesFragment : PermanentBaseFragment() {
viewModel.getOnCancelAllUploads().removeObserver(onCancelAllUploads)
viewModel.getOnFileViewRequest().removeObserver(onFileViewRequest)
viewModel.getOnRecordSelected().removeObserver(onRecordSelectedObserver)
viewModel.getShrinkIslandRequest().removeObserver(shrinkIslandRequestObserver)
renameDialogViewModel.getOnRecordRenamed().removeObserver(onRecordRenamed)
renameDialogViewModel.getOnShowMessage().removeObserver(onShowMessage)
addOptionsFragment?.getOnFilesSelected()?.removeObserver(onFilesSelectedToUpload)
addOptionsFragment?.getOnRefreshFolder()?.removeObserver(onRefreshFolder)
saveToPermanentFragment?.getOnFilesUploadRequest()?.removeObserver(onFilesUploadRequest)
saveToPermanentFragment?.getOnCurrentArchiveChangedEvent()?.removeObserver(onCurrentArchiveChangedObserver)
saveToPermanentFragment?.getOnCurrentArchiveChangedEvent()
?.removeObserver(onCurrentArchiveChangedObserver)
recordOptionsFragment?.getOnFileDownloadRequest()?.removeObserver(onFileDownloadRequest)
recordOptionsFragment?.getOnRecordDeleteRequest()?.removeObserver(onRecordDeleteRequest)
recordOptionsFragment?.getOnRecordRenameRequest()?.removeObserver(onRecordRenameRequest)
Expand All @@ -433,4 +466,11 @@ class MyFilesFragment : PermanentBaseFragment() {
super.onPause()
disconnectViewModelEvents()
}

companion object {
const val ISLAND_WIDTH_SMALL = 160
const val ISLAND_WIDTH_LARGE = 960
const val RESIZE_DURATION_MILLIS = 500L
const val DELAY_TO_RESIZE_MILLIS = 500L
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.permanent.permanent.ui.public

import android.animation.ValueAnimator
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
Expand All @@ -8,19 +9,23 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.DecelerateInterpolator
import android.widget.Toast
import androidx.core.os.bundleOf
import androidx.databinding.DataBindingUtil
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.dialog_cancel_uploads.view.*
import kotlinx.android.synthetic.main.dialog_delete.view.*
import kotlinx.android.synthetic.main.dialog_delete.view.tvTitle
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.permanent.permanent.BuildConfig
import org.permanent.permanent.R
import org.permanent.permanent.databinding.DialogRenameRecordBinding
Expand All @@ -30,8 +35,11 @@ import org.permanent.permanent.models.NavigationFolderIdentifier
import org.permanent.permanent.models.Record
import org.permanent.permanent.ui.*
import org.permanent.permanent.ui.myFiles.*
import org.permanent.permanent.ui.myFiles.MyFilesFragment.Companion.DELAY_TO_RESIZE_MILLIS
import org.permanent.permanent.ui.myFiles.MyFilesFragment.Companion.ISLAND_WIDTH_LARGE
import org.permanent.permanent.ui.myFiles.MyFilesFragment.Companion.ISLAND_WIDTH_SMALL
import org.permanent.permanent.ui.myFiles.MyFilesFragment.Companion.RESIZE_DURATION_MILLIS
import org.permanent.permanent.ui.myFiles.download.DownloadsAdapter
import org.permanent.permanent.ui.shareManagement.ShareManagementFragment
import org.permanent.permanent.ui.shares.PreviewState
import org.permanent.permanent.viewmodels.PublicFilesViewModel
import org.permanent.permanent.viewmodels.RenameRecordViewModel
Expand All @@ -53,16 +61,13 @@ class PublicFilesFragment : PermanentBaseFragment() {
private var addOptionsFragment: AddOptionsFragment? = null
private var recordOptionsFragment: RecordOptionsFragment? = null
private var sortOptionsFragment: SortOptionsFragment? = null
private var shareManagementFragment: ShareManagementFragment? = null

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
binding = FragmentPublicFilesBinding.inflate(inflater, container, false)
viewModel = ViewModelProvider(this).get(PublicFilesViewModel::class.java)
renameDialogViewModel = ViewModelProvider(this).get(RenameRecordViewModel::class.java)
viewModel = ViewModelProvider(this)[PublicFilesViewModel::class.java]
renameDialogViewModel = ViewModelProvider(this)[RenameRecordViewModel::class.java]
prefsHelper = PreferencesHelper(
requireContext().getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
)
Expand All @@ -76,6 +81,10 @@ class PublicFilesFragment : PermanentBaseFragment() {
viewModel.loadRootFiles()
initDownloadsRecyclerView(binding.rvDownloads)
initFilesRecyclerView(binding.rvFiles)
if (viewModel.isRelocationMode.value == true) resizeIslandWidthAnimated(
binding.flFloatingActionIsland.width,
ISLAND_WIDTH_LARGE
)
return binding.root
}

Expand Down Expand Up @@ -159,9 +168,7 @@ class PublicFilesFragment : PermanentBaseFragment() {

private val onRecordDeleteRequest = Observer<Record> { record ->
val viewDialog: View = layoutInflater.inflate(R.layout.dialog_delete, null)
val alert = AlertDialog.Builder(context)
.setView(viewDialog)
.create()
val alert = AlertDialog.Builder(context).setView(viewDialog).create()
viewDialog.tvTitle.text = getString(R.string.delete_record_title, record.displayName)
viewDialog.btnDelete.setOnClickListener {
viewModel.delete(record)
Expand All @@ -175,17 +182,15 @@ class PublicFilesFragment : PermanentBaseFragment() {

private val onRecordRenameRequest = Observer<Record> { record ->
renameDialogBinding = DataBindingUtil.inflate(
LayoutInflater.from(context),
R.layout.dialog_rename_record, null, false
LayoutInflater.from(context), R.layout.dialog_rename_record, null, false
)
renameDialogBinding.executePendingBindings()
renameDialogBinding.lifecycleOwner = this
renameDialogBinding.viewModel = renameDialogViewModel
renameDialogViewModel.setRecordName(record.displayName)

alertDialog = androidx.appcompat.app.AlertDialog.Builder(requireContext())
.setView(renameDialogBinding.root)
.create()
.setView(renameDialogBinding.root).create()
renameDialogBinding.tvTitle.text =
getString(R.string.rename_record_title, record.displayName)
renameDialogBinding.btnRename.setOnClickListener {
Expand All @@ -199,9 +204,7 @@ class PublicFilesFragment : PermanentBaseFragment() {

private val onCancelAllUploads = Observer<Void> {
val viewDialog: View = layoutInflater.inflate(R.layout.dialog_cancel_uploads, null)
val alert = AlertDialog.Builder(context)
.setView(viewDialog)
.create()
val alert = AlertDialog.Builder(context).setView(viewDialog).create()
viewDialog.btnCancelAll.setOnClickListener {
viewModel.cancelAllUploads()
alert.dismiss()
Expand All @@ -217,8 +220,27 @@ class PublicFilesFragment : PermanentBaseFragment() {
findNavController().navigate(R.id.action_publicFilesFragment_to_fileActivity, bundle)
}

private val shrinkIslandRequestObserver = Observer<Void> {
resizeIslandWidthAnimated(binding.flFloatingActionIsland.width, ISLAND_WIDTH_SMALL)
}

private val onRecordRelocateRequest = Observer<Pair<Record, RelocationType>> {
viewModel.setRelocationMode(it)
lifecycleScope.launch {
delay(DELAY_TO_RESIZE_MILLIS)
resizeIslandWidthAnimated(binding.flFloatingActionIsland.width, ISLAND_WIDTH_LARGE)
}
}

private fun resizeIslandWidthAnimated(currentWidth: Int, newWidth: Int) {
val widthAnimator = ValueAnimator.ofInt(currentWidth, newWidth)
widthAnimator.duration = RESIZE_DURATION_MILLIS
widthAnimator.interpolator = DecelerateInterpolator()
widthAnimator.addUpdateListener { animation ->
binding.flFloatingActionIsland.layoutParams.width = animation.animatedValue as Int
binding.flFloatingActionIsland.requestLayout()
}
widthAnimator.start()
}

private val onSortRequest = Observer<SortType> {
Expand Down Expand Up @@ -264,13 +286,16 @@ class PublicFilesFragment : PermanentBaseFragment() {
private fun initFilesRecyclerView(rvFiles: RecyclerView) {
recordsRecyclerView = rvFiles
recordsListAdapter = RecordsListAdapter(
this, false, viewModel.getIsRelocationMode(),
this,
false,
viewModel.getIsRelocationMode(),
isForSharesScreen = false,
isForSearchScreen = false,
recordListener = viewModel
)
recordsGridAdapter = RecordsGridAdapter(
this, false,
this,
false,
viewModel.getIsRelocationMode(),
MutableLiveData(PreviewState.ACCESS_GRANTED),
isForSharePreviewScreen = false,
Expand Down Expand Up @@ -307,6 +332,7 @@ class PublicFilesFragment : PermanentBaseFragment() {
viewModel.getOnRecordDeleteRequest().observe(this, onRecordDeleteRequest)
viewModel.getOnCancelAllUploads().observe(this, onCancelAllUploads)
viewModel.getOnFileViewRequest().observe(this, onFileViewRequest)
viewModel.getShrinkIslandRequest().observe(this, shrinkIslandRequestObserver)
renameDialogViewModel.getOnRecordRenamed().observe(this, onRecordRenamed)
renameDialogViewModel.getOnShowMessage().observe(this, onShowMessage)
addOptionsFragment?.getOnFilesSelected()?.observe(this, onFilesSelectedToUpload)
Expand All @@ -327,6 +353,7 @@ class PublicFilesFragment : PermanentBaseFragment() {
viewModel.getOnRecordDeleteRequest().removeObserver(onRecordDeleteRequest)
viewModel.getOnCancelAllUploads().removeObserver(onCancelAllUploads)
viewModel.getOnFileViewRequest().removeObserver(onFileViewRequest)
viewModel.getShrinkIslandRequest().removeObserver(shrinkIslandRequestObserver)
renameDialogViewModel.getOnRecordRenamed().removeObserver(onRecordRenamed)
renameDialogViewModel.getOnShowMessage().removeObserver(onShowMessage)
addOptionsFragment?.getOnFilesSelected()?.removeObserver(onFilesSelectedToUpload)
Expand Down
Loading

0 comments on commit c0b3716

Please sign in to comment.