From bad270851f7dde5a81490135056b20cf05fd574e Mon Sep 17 00:00:00 2001 From: Hardcore Sushi Date: Fri, 4 Sep 2020 13:30:12 +0200 Subject: [PATCH] ImageViewer: delete button & ui behavior improvements --- app/build.gradle | 2 +- .../droidfs/file_viewers/ImageViewer.kt | 125 ++++++++++++------ .../widgets/ColoredAlertDialogBuilder.kt | 20 ++- .../main/res/layout/activity_image_viewer.xml | 15 ++- app/src/main/res/values/strings.xml | 3 +- 5 files changed, 120 insertions(+), 45 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 7d29b90..1206554 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -42,7 +42,7 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "androidx.core:core-ktx:1.3.1" implementation "androidx.appcompat:appcompat:1.2.0" - implementation "androidx.constraintlayout:constraintlayout:2.0.0" + implementation "androidx.constraintlayout:constraintlayout:2.0.1" implementation "androidx.sqlite:sqlite:2.1.0" implementation "androidx.preference:preference:1.1.1" diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/ImageViewer.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/ImageViewer.kt index 7c2c50d..c8726c2 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/ImageViewer.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/ImageViewer.kt @@ -15,9 +15,10 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransformation import kotlinx.android.synthetic.main.activity_image_viewer.* import sushi.hardcore.droidfs.ConstValues import sushi.hardcore.droidfs.R -import sushi.hardcore.droidfs.util.MiscUtils import sushi.hardcore.droidfs.explorers.ExplorerElement +import sushi.hardcore.droidfs.util.MiscUtils import sushi.hardcore.droidfs.util.PathUtils +import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder import sushi.hardcore.droidfs.widgets.ZoomableImageView import java.io.File import java.security.MessageDigest @@ -28,6 +29,7 @@ class ImageViewer: FileViewerActivity() { private const val hideDelay: Long = 3000 private const val MIN_SWIPE_DISTANCE = 150 } + private lateinit var fileName: String private lateinit var glideImage: RequestBuilder private var x1 = 0F private var x2 = 0F @@ -43,44 +45,56 @@ class ImageViewer: FileViewerActivity() { action_bar.visibility = View.GONE } override fun viewFile() { - val imageBuff = loadWholeFile(filePath) - if (imageBuff != null){ - setContentView(R.layout.activity_image_viewer) - image_viewer.setOnInteractionListener(object : ZoomableImageView.OnInteractionListener{ - override fun onSingleTap(event: MotionEvent?) { - handler.removeCallbacks(hideUI) - if (action_buttons.visibility == View.GONE){ - action_buttons.visibility = View.VISIBLE - action_bar.visibility = View.VISIBLE - handler.postDelayed(hideUI, hideDelay) - } else { - hideUI.run() - } + setContentView(R.layout.activity_image_viewer) + image_viewer.setOnInteractionListener(object : ZoomableImageView.OnInteractionListener { + override fun onSingleTap(event: MotionEvent?) { + handler.removeCallbacks(hideUI) + if (action_buttons.visibility == View.GONE) { + action_buttons.visibility = View.VISIBLE + action_bar.visibility = View.VISIBLE + handler.postDelayed(hideUI, hideDelay) + } else { + hideUI.run() } - override fun onTouch(event: MotionEvent?) { - if (!image_viewer.isZoomed){ - when(event?.action){ - MotionEvent.ACTION_DOWN -> { - x1 = event.x - } - MotionEvent.ACTION_UP -> { - x2 = event.x - val deltaX = x2 - x1 - if (abs(deltaX) > MIN_SWIPE_DISTANCE){ - swipeImage(deltaX) - } + } + + override fun onTouch(event: MotionEvent?) { + if (!image_viewer.isZoomed) { + when (event?.action) { + MotionEvent.ACTION_DOWN -> { + x1 = event.x + } + MotionEvent.ACTION_UP -> { + x2 = event.x + val deltaX = x2 - x1 + if (abs(deltaX) > MIN_SWIPE_DISTANCE) { + swipeImage(deltaX) } } } } - }) - glideImage = Glide.with(this).load(imageBuff) + } + }) + loadImage() + handler.postDelayed(hideUI, hideDelay) + } + + private fun loadImage(){ + loadWholeFile(filePath)?.let { + glideImage = Glide.with(this).load(it) glideImage.into(image_viewer) - text_filename.text = File(filePath).name - handler.postDelayed(hideUI, hideDelay) + fileName = File(filePath).name + text_filename.text = fileName + rotationAngle = 0F } } + override fun onUserInteraction() { + super.onUserInteraction() + handler.removeCallbacks(hideUI) + handler.postDelayed(hideUI, hideDelay) + } + private fun swipeImage(deltaX: Float){ if (!wasMapped){ for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){ @@ -103,26 +117,61 @@ class ImageViewer: FileViewerActivity() { } else { MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages) } - loadWholeFile(mappedImages[currentMappedImageIndex].fullPath)?.let { - glideImage = Glide.with(applicationContext).load(it) - glideImage.into(image_viewer) - text_filename.text = File(mappedImages[currentMappedImageIndex].fullPath).name - rotationAngle = 0F - } + filePath = mappedImages[currentMappedImageIndex].fullPath + loadImage() + } + + fun onClickDelete(view: View) { + ColoredAlertDialogBuilder(this) + .keepFullScreen() + .setTitle(R.string.warning) + .setPositiveButton(R.string.ok) { _, _ -> + if (gocryptfsVolume.removeFile(filePath)){ + currentMappedImageIndex = MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages) + mappedImages.clear() + wasMapped = false + swipeImage(-1F) + } else { + ColoredAlertDialogBuilder(this) + .keepFullScreen() + .setTitle(R.string.error) + .setMessage(getString(R.string.remove_failed, fileName)) + .setPositiveButton(R.string.ok, null) + .show() + } + } + .setNegativeButton(R.string.cancel, null) + .setMessage(getString(R.string.single_delete_confirm, fileName)) + .show() } fun onClickSlideshow(view: View) { if (!slideshowActive){ slideshowActive = true Thread { + Thread.sleep(ConstValues.slideshow_delay) while (slideshowActive){ runOnUiThread { swipeImage(-1F) } Thread.sleep(ConstValues.slideshow_delay) } }.start() + hideUI.run() + Toast.makeText(this, R.string.slideshow_started, Toast.LENGTH_SHORT).show() } else { - slideshowActive = false - Toast.makeText(this, R.string.slideshow_stopped, Toast.LENGTH_SHORT).show() + stopSlideshow() + } + } + + private fun stopSlideshow(){ + slideshowActive = false + Toast.makeText(this, R.string.slideshow_stopped, Toast.LENGTH_SHORT).show() + } + + override fun onBackPressed() { + if (slideshowActive){ + stopSlideshow() + } else { + super.onBackPressed() } } diff --git a/app/src/main/java/sushi/hardcore/droidfs/widgets/ColoredAlertDialogBuilder.kt b/app/src/main/java/sushi/hardcore/droidfs/widgets/ColoredAlertDialogBuilder.kt index 2f8a548..eb5a008 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/widgets/ColoredAlertDialogBuilder.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/widgets/ColoredAlertDialogBuilder.kt @@ -2,10 +2,19 @@ package sushi.hardcore.droidfs.widgets import androidx.appcompat.app.AlertDialog import android.content.Context +import android.view.WindowManager class ColoredAlertDialogBuilder: AlertDialog.Builder { constructor(context: Context): super(context) constructor(context: Context, themeResId: Int): super(context, themeResId) + + private var keepFullScreen = false + + fun keepFullScreen(): AlertDialog.Builder { + keepFullScreen = true + return this + } + private fun applyColor(dialog: AlertDialog){ dialog.setOnShowListener{ val themeColor = ThemeColor.getThemeColor(context) @@ -14,16 +23,19 @@ class ColoredAlertDialogBuilder: AlertDialog.Builder { } } } - override fun show(): AlertDialog? { - val dialog = super.create() - applyColor(dialog) + + override fun show(): AlertDialog { + val dialog = create() dialog.show() - return null + return dialog } override fun create(): AlertDialog { val dialog = super.create() applyColor(dialog) + if (keepFullScreen){ + dialog.window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) + } return dialog } } \ No newline at end of file diff --git a/app/src/main/res/layout/activity_image_viewer.xml b/app/src/main/res/layout/activity_image_viewer.xml index 2000905..4a45947 100644 --- a/app/src/main/res/layout/activity_image_viewer.xml +++ b/app/src/main/res/layout/activity_image_viewer.xml @@ -27,8 +27,21 @@ android:singleLine="true" android:ellipsize="end" android:textSize="20sp" - android:layout_marginEnd="40dp" android:layout_alignParentStart="true" + android:layout_toStartOf="@id/image_delete" + android:layout_centerVertical="true"/> + + Unable to access this file About GitHub - Want to read the documentation, request feature, report bug, read the source code… Check the DroidFS\'s repository ! + Want to read the documentation, review the source code, request feature, report bug… Check the DroidFS\'s repository ! Share Export/Decrypt Copying selected items… @@ -172,4 +172,5 @@ DroidFS doesn\'t have write access to this path. You can try to move the volume to a writable location. DroidFS can\'t write on removable SD cards, please move the volume to internal storage. Slideshow stopped + Slideshow started