From 5c0f317a043724a524898fddb1fb7e8583877963 Mon Sep 17 00:00:00 2001 From: Hardcore Sushi Date: Tue, 25 Aug 2020 15:43:47 +0200 Subject: [PATCH] ImageViewer title & slideshow --- .../sushi/hardcore/droidfs/ConstValues.kt | 1 + .../droidfs/file_viewers/ImageViewer.kt | 134 +++++++++++------- .../droidfs/file_viewers/TextEditor.kt | 6 +- .../droidfs/widgets/ZoomableImageView.java | 24 +++- app/src/main/res/drawable/icon_slideshow.xml | 5 + .../main/res/layout/activity_image_viewer.xml | 33 +++++ app/src/main/res/values/strings.xml | 1 + 7 files changed, 148 insertions(+), 56 deletions(-) create mode 100644 app/src/main/res/drawable/icon_slideshow.xml diff --git a/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt b/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt index 78f7597..f3e5292 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/ConstValues.kt @@ -11,6 +11,7 @@ class ConstValues { val fakeUri: Uri = Uri.parse("fakeuri://droidfs") const val MAX_KERNEL_WRITE = 128*1024 const val wipe_passes = 2 + const val slideshow_delay: Long = 4000 private val fileExtensions = mapOf( Pair("image", listOf("png", "jpg", "jpeg")), Pair("video", listOf("mp4", "webm")), 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 4b4d81d..7c2c50d 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 @@ -1,11 +1,13 @@ package sushi.hardcore.droidfs.file_viewers +import android.content.res.Configuration import android.graphics.Bitmap import android.graphics.Matrix import android.graphics.drawable.Drawable import android.os.Handler import android.view.MotionEvent import android.view.View +import android.widget.Toast import com.bumptech.glide.Glide import com.bumptech.glide.RequestBuilder import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool @@ -16,6 +18,8 @@ import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.util.MiscUtils import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.util.PathUtils +import sushi.hardcore.droidfs.widgets.ZoomableImageView +import java.io.File import java.security.MessageDigest import kotlin.math.abs @@ -30,60 +34,96 @@ class ImageViewer: FileViewerActivity() { private val mappedImages = mutableListOf() private lateinit var sortOrder: String private var wasMapped = false + private var slideshowActive = false private var currentMappedImageIndex = -1 private var rotationAngle: Float = 0F private val handler = Handler() - private val hideActionButtons = Runnable { action_buttons.visibility = View.GONE } + private val hideUI = Runnable { + action_buttons.visibility = View.GONE + action_bar.visibility = View.GONE + } override fun viewFile() { val imageBuff = loadWholeFile(filePath) if (imageBuff != null){ setContentView(R.layout.activity_image_viewer) - glideImage = Glide.with(this).load(imageBuff) - glideImage.into(image_viewer) - handler.postDelayed(hideActionButtons, hideDelay) - } - } - - override fun dispatchTouchEvent(event: MotionEvent?): Boolean { - if (!image_viewer.isZoomed){ - when(event?.action){ - MotionEvent.ACTION_DOWN -> { - x1 = event.x + 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() + } } - MotionEvent.ACTION_UP -> { - x2 = event.x - val deltaX = x2 - x1 - if (abs(deltaX) > MIN_SWIPE_DISTANCE){ - if (!wasMapped){ - for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){ - if (e.isRegularFile && ConstValues.isImage(e.name)){ - mappedImages.add(e) + 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) } } - sortOrder = intent.getStringExtra("sortOrder") ?: "name" - ExplorerElement.sortBy(sortOrder, mappedImages) - for ((i, e) in mappedImages.withIndex()){ - if (filePath == e.fullPath){ - currentMappedImageIndex = i - break - } - } - wasMapped = true - } - currentMappedImageIndex = if (deltaX < 0){ - MiscUtils.incrementIndex(currentMappedImageIndex, mappedImages) - } else { - MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages) - } - loadWholeFile(mappedImages[currentMappedImageIndex].fullPath)?.let { - glideImage = Glide.with(this).load(it) - glideImage.into(image_viewer) } } } - } + }) + glideImage = Glide.with(this).load(imageBuff) + glideImage.into(image_viewer) + text_filename.text = File(filePath).name + handler.postDelayed(hideUI, hideDelay) + } + } + + private fun swipeImage(deltaX: Float){ + if (!wasMapped){ + for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){ + if (e.isRegularFile && ConstValues.isImage(e.name)){ + mappedImages.add(e) + } + } + sortOrder = intent.getStringExtra("sortOrder") ?: "name" + ExplorerElement.sortBy(sortOrder, mappedImages) + for ((i, e) in mappedImages.withIndex()){ + if (filePath == e.fullPath){ + currentMappedImageIndex = i + break + } + } + wasMapped = true + } + currentMappedImageIndex = if (deltaX < 0){ + MiscUtils.incrementIndex(currentMappedImageIndex, mappedImages) + } 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 + } + } + + fun onClickSlideshow(view: View) { + if (!slideshowActive){ + slideshowActive = true + Thread { + while (slideshowActive){ + runOnUiThread { swipeImage(-1F) } + Thread.sleep(ConstValues.slideshow_delay) + } + }.start() + } else { + slideshowActive = false + Toast.makeText(this, R.string.slideshow_stopped, Toast.LENGTH_SHORT).show() } - return super.dispatchTouchEvent(event) } class RotateTransformation(private val rotationAngle: Float): BitmapTransformation() { @@ -112,16 +152,8 @@ class ImageViewer: FileViewerActivity() { rotateImage() } - override fun onUserInteraction() { - super.onUserInteraction() - action_buttons?.let { - handler.removeCallbacks(hideActionButtons) - if (it.visibility == View.GONE){ - it.visibility = View.VISIBLE - handler.postDelayed(hideActionButtons, hideDelay) - } else { - it.visibility = View.GONE - } - } + override fun onConfigurationChanged(newConfig: Configuration) { + super.onConfigurationChanged(newConfig) + image_viewer.restoreZoomNormal() } } \ No newline at end of file diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt index 08649ac..d4c8d83 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt @@ -72,10 +72,10 @@ class TextEditor: FileViewerActivity() { if (handleID != -1){ val buff = ByteArrayInputStream(content) var offset: Long = 0 - val io_buffer = ByteArray(GocryptfsVolume.DefaultBS) + val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) var length: Int - while (buff.read(io_buffer).also { length = it } > 0) { - val written = gocryptfsVolume.writeFile(handleID, offset, io_buffer, length).toLong() + while (buff.read(ioBuffer).also { length = it } > 0) { + val written = gocryptfsVolume.writeFile(handleID, offset, ioBuffer, length).toLong() if (written == length.toLong()) { offset += written } else { diff --git a/app/src/main/java/sushi/hardcore/droidfs/widgets/ZoomableImageView.java b/app/src/main/java/sushi/hardcore/droidfs/widgets/ZoomableImageView.java index 421e1a6..51a70f0 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/widgets/ZoomableImageView.java +++ b/app/src/main/java/sushi/hardcore/droidfs/widgets/ZoomableImageView.java @@ -35,6 +35,13 @@ public class ZoomableImageView extends androidx.appcompat.widget.AppCompatImageV ScaleGestureDetector mScaleDetector; + public interface OnInteractionListener { + void onTouch(MotionEvent event); + void onSingleTap(MotionEvent event); + } + + OnInteractionListener onInteractionListener = null; + Context context; public ZoomableImageView(Context context) { @@ -124,15 +131,28 @@ public class ZoomableImageView extends androidx.appcompat.widget.AppCompatImageV fixTrans(); } + public void setOnInteractionListener(OnInteractionListener listener){ + onInteractionListener = listener; + } + @Override public boolean onSingleTapConfirmed(MotionEvent e) { + if (onInteractionListener != null){ + onInteractionListener.onSingleTap(e); + } return false; } @Override - public boolean onDoubleTap(MotionEvent e) { - // Double tap is detected + public boolean dispatchTouchEvent(MotionEvent event) { + if (onInteractionListener != null){ + onInteractionListener.onTouch(event); + } + return super.dispatchTouchEvent(event); + } + @Override + public boolean onDoubleTap(MotionEvent e) { if (saveScale >= maxScale) { restoreZoomNormal(); } else { diff --git a/app/src/main/res/drawable/icon_slideshow.xml b/app/src/main/res/drawable/icon_slideshow.xml new file mode 100644 index 0000000..8e41c7d --- /dev/null +++ b/app/src/main/res/drawable/icon_slideshow.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/activity_image_viewer.xml b/app/src/main/res/layout/activity_image_viewer.xml index d55fbf0..2000905 100644 --- a/app/src/main/res/layout/activity_image_viewer.xml +++ b/app/src/main/res/layout/activity_image_viewer.xml @@ -1,5 +1,6 @@ + + + + + + + + DroidFS doesn\'t have write access to this path. You will only have read-only access to this volume. 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