Image swipe

This commit is contained in:
Hardcore Sushi 2020-08-01 16:43:48 +02:00
parent 5a444f2829
commit 400aa831b2
14 changed files with 160 additions and 102 deletions

View File

@ -15,7 +15,7 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode 1 versionCode 1
versionName "1.1.1" versionName "1.1.2"
ndk { ndk {
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a' abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'

View File

@ -121,7 +121,7 @@ class ChangePasswordActivity : BaseActivity() {
} }
} }
if (changePasswordImmediately){ if (changePasswordImmediately){
if (GocryptfsVolume.change_password(rootCipherDir, oldPassword, givenHash, newPassword, returnedHash)) { if (GocryptfsVolume.changePassword(rootCipherDir, oldPassword, givenHash, newPassword, returnedHash)) {
val editor = sharedPrefs.edit() val editor = sharedPrefs.edit()
if (sharedPrefs.getString(rootCipherDir, null) != null){ if (sharedPrefs.getString(rootCipherDir, null) != null){
editor.remove(rootCipherDir) editor.remove(rootCipherDir)

View File

@ -91,7 +91,7 @@ class CreateActivity : BaseActivity() {
} }
} }
if (goodDirectory) { if (goodDirectory) {
if (GocryptfsVolume.create_volume(rootCipherDir, password, GocryptfsVolume.ScryptDefaultLogN, ConstValues.creator)) { if (GocryptfsVolume.createVolume(rootCipherDir, password, GocryptfsVolume.ScryptDefaultLogN, ConstValues.creator)) {
var returnedHash: ByteArray? = null var returnedHash: ByteArray? = null
if (usf_fingerprint && checkbox_save_password.isChecked){ if (usf_fingerprint && checkbox_save_password.isChecked){
returnedHash = ByteArray(GocryptfsVolume.KeyLen) returnedHash = ByteArray(GocryptfsVolume.KeyLen)

View File

@ -167,7 +167,7 @@ open class BaseExplorerActivity : BaseActivity() {
} }
protected fun setCurrentPath(path: String) { protected fun setCurrentPath(path: String) {
explorerElements = gocryptfsVolume.list_dir(path) explorerElements = gocryptfsVolume.listDir(path)
text_dir_empty.visibility = if (explorerElements.size == 0) View.VISIBLE else View.INVISIBLE text_dir_empty.visibility = if (explorerElements.size == 0) View.VISIBLE else View.INVISIBLE
sortExplorerElements() sortExplorerElements()
if (path.isNotEmpty()) { //not root if (path.isNotEmpty()) { //not root

View File

@ -44,7 +44,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (fileName.isEmpty()) { if (fileName.isEmpty()) {
Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.error_filename_empty, Toast.LENGTH_SHORT).show()
} else { } else {
val handleID = gocryptfsVolume.open_write_mode(PathUtils.path_join(currentDirectoryPath, fileName)) val handleID = gocryptfsVolume.openWriteMode(PathUtils.path_join(currentDirectoryPath, fileName))
if (handleID == -1) { if (handleID == -1) {
ColoredAlertDialogBuilder(this) ColoredAlertDialogBuilder(this)
.setTitle(R.string.error) .setTitle(R.string.error)
@ -52,7 +52,7 @@ class ExplorerActivity : BaseExplorerActivity() {
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show() .show()
} else { } else {
gocryptfsVolume.close_file(handleID) gocryptfsVolume.closeFile(handleID)
setCurrentPath(currentDirectoryPath) setCurrentPath(currentDirectoryPath)
invalidateOptionsMenu() invalidateOptionsMenu()
} }
@ -120,7 +120,7 @@ class ExplorerActivity : BaseExplorerActivity() {
for (uri in uris) { for (uri in uris) {
val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(activity, uri)) val dstPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(activity, uri))
contentResolver.openInputStream(uri)?.let { contentResolver.openInputStream(uri)?.let {
success = gocryptfsVolume.import_file(it, dstPath) success = gocryptfsVolume.importFile(it, dstPath)
} }
if (!success) { if (!success) {
stopTask { stopTask {
@ -194,7 +194,7 @@ class ExplorerActivity : BaseExplorerActivity() {
failedItem = if (element.isDirectory) { failedItem = if (element.isDirectory) {
recursiveExportDirectory(fullPath, outputDir) recursiveExportDirectory(fullPath, outputDir)
} else { } else {
if (gocryptfsVolume.export_file(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath if (gocryptfsVolume.exportFile(fullPath, PathUtils.path_join(outputDir, element.name))) null else fullPath
} }
if (failedItem != null) { if (failedItem != null) {
stopTask { stopTask {
@ -400,18 +400,6 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
} }
private fun recursiveMapFiles(rootPath: String): MutableList<ExplorerElement> {
val result = mutableListOf<ExplorerElement>()
val explorerElements = gocryptfsVolume.list_dir(rootPath)
result.addAll(explorerElements)
for (e in explorerElements){
if (e.isDirectory){
result.addAll(recursiveMapFiles(e.getFullPath()))
}
}
return result
}
private fun cancelCopy() { private fun cancelCopy() {
if (modeSelectLocation){ if (modeSelectLocation){
modeSelectLocation = false modeSelectLocation = false
@ -424,15 +412,15 @@ class ExplorerActivity : BaseExplorerActivity() {
private fun copyFile(srcPath: String, dstPath: String): Boolean { private fun copyFile(srcPath: String, dstPath: String): Boolean {
var success = true var success = true
val originalHandleId = gocryptfsVolume.open_read_mode(srcPath) val originalHandleId = gocryptfsVolume.openReadMode(srcPath)
if (originalHandleId != -1){ if (originalHandleId != -1){
val newHandleId = gocryptfsVolume.open_write_mode(dstPath) val newHandleId = gocryptfsVolume.openWriteMode(dstPath)
if (newHandleId != -1){ if (newHandleId != -1){
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS)
var length: Int var length: Int
while (gocryptfsVolume.read_file(originalHandleId, offset, ioBuffer).also { length = it } > 0) { while (gocryptfsVolume.readFile(originalHandleId, offset, ioBuffer).also { length = it } > 0) {
val written = gocryptfsVolume.write_file(newHandleId, offset, ioBuffer, length).toLong() val written = gocryptfsVolume.writeFile(newHandleId, offset, ioBuffer, length).toLong()
if (written == length.toLong()) { if (written == length.toLong()) {
offset += written offset += written
} else { } else {
@ -440,11 +428,11 @@ class ExplorerActivity : BaseExplorerActivity() {
break break
} }
} }
gocryptfsVolume.close_file(newHandleId) gocryptfsVolume.closeFile(newHandleId)
} else { } else {
success = false success = false
} }
gocryptfsVolume.close_file(originalHandleId) gocryptfsVolume.closeFile(originalHandleId)
} else { } else {
success = false success = false
} }
@ -452,9 +440,9 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
private fun recursiveCopyDirectory(srcDirectoryPath: String, outputPath: String): String? { private fun recursiveCopyDirectory(srcDirectoryPath: String, outputPath: String): String? {
val mappedElements = recursiveMapFiles(srcDirectoryPath) val mappedElements = gocryptfsVolume.recursiveMapFiles(srcDirectoryPath)
val dstDirectoryPath = PathUtils.path_join(outputPath, File(srcDirectoryPath).name) val dstDirectoryPath = PathUtils.path_join(outputPath, File(srcDirectoryPath).name)
if (!gocryptfsVolume.path_exists(dstDirectoryPath)) { if (!gocryptfsVolume.pathExists(dstDirectoryPath)) {
if (!gocryptfsVolume.mkdir(dstDirectoryPath)) { if (!gocryptfsVolume.mkdir(dstDirectoryPath)) {
return dstDirectoryPath return dstDirectoryPath
} }
@ -477,15 +465,15 @@ class ExplorerActivity : BaseExplorerActivity() {
private fun importFileFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, srcPath: String, dstPath: String): Boolean { private fun importFileFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, srcPath: String, dstPath: String): Boolean {
var success = true var success = true
val srcHandleID = remote_gocryptfsVolume.open_read_mode(srcPath) val srcHandleID = remote_gocryptfsVolume.openReadMode(srcPath)
if (srcHandleID != -1) { if (srcHandleID != -1) {
val dstHandleID = gocryptfsVolume.open_write_mode(dstPath) val dstHandleID = gocryptfsVolume.openWriteMode(dstPath)
if (dstHandleID != -1) { if (dstHandleID != -1) {
var length: Int var length: Int
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS)
var offset: Long = 0 var offset: Long = 0
while (remote_gocryptfsVolume.read_file(srcHandleID, offset, ioBuffer).also { length = it } > 0){ while (remote_gocryptfsVolume.readFile(srcHandleID, offset, ioBuffer).also { length = it } > 0){
val written = gocryptfsVolume.write_file(dstHandleID, offset, ioBuffer, length).toLong() val written = gocryptfsVolume.writeFile(dstHandleID, offset, ioBuffer, length).toLong()
if (written == length.toLong()) { if (written == length.toLong()) {
offset += length.toLong() offset += length.toLong()
} else { } else {
@ -493,17 +481,17 @@ class ExplorerActivity : BaseExplorerActivity() {
break break
} }
} }
gocryptfsVolume.close_file(dstHandleID) gocryptfsVolume.closeFile(dstHandleID)
} }
remote_gocryptfsVolume.close_file(srcHandleID) remote_gocryptfsVolume.closeFile(srcHandleID)
} }
return success return success
} }
private fun recursiveImportDirectoryFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, remote_directory_path: String, outputPath: String): String? { private fun recursiveImportDirectoryFromOtherVolume(remote_gocryptfsVolume: GocryptfsVolume, remote_directory_path: String, outputPath: String): String? {
val mappedElements = recursiveMapFiles(remote_directory_path) val mappedElements = gocryptfsVolume.recursiveMapFiles(remote_directory_path)
val dstDirectoryPath = PathUtils.path_join(outputPath, File(remote_directory_path).name) val dstDirectoryPath = PathUtils.path_join(outputPath, File(remote_directory_path).name)
if (!gocryptfsVolume.path_exists(dstDirectoryPath)) { if (!gocryptfsVolume.pathExists(dstDirectoryPath)) {
if (!gocryptfsVolume.mkdir(dstDirectoryPath)) { if (!gocryptfsVolume.mkdir(dstDirectoryPath)) {
return dstDirectoryPath return dstDirectoryPath
} }
@ -526,14 +514,14 @@ class ExplorerActivity : BaseExplorerActivity() {
private fun recursiveExportDirectory(plain_directory_path: String, output_dir: String?): String? { private fun recursiveExportDirectory(plain_directory_path: String, output_dir: String?): String? {
if (File(PathUtils.path_join(output_dir, plain_directory_path)).mkdir()) { if (File(PathUtils.path_join(output_dir, plain_directory_path)).mkdir()) {
val explorerElements = gocryptfsVolume.list_dir(plain_directory_path) val explorerElements = gocryptfsVolume.listDir(plain_directory_path)
for (e in explorerElements) { for (e in explorerElements) {
val fullPath = PathUtils.path_join(plain_directory_path, e.name) val fullPath = PathUtils.path_join(plain_directory_path, e.name)
if (e.isDirectory) { if (e.isDirectory) {
val failedItem = recursiveExportDirectory(fullPath, output_dir) val failedItem = recursiveExportDirectory(fullPath, output_dir)
failedItem?.let { return it } failedItem?.let { return it }
} else { } else {
if (!gocryptfsVolume.export_file(fullPath, PathUtils.path_join(output_dir, fullPath))) { if (!gocryptfsVolume.exportFile(fullPath, PathUtils.path_join(output_dir, fullPath))) {
return fullPath return fullPath
} }
} }
@ -544,14 +532,14 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
private fun recursiveRemoveDirectory(plain_directory_path: String): String? { private fun recursiveRemoveDirectory(plain_directory_path: String): String? {
val explorerElements = gocryptfsVolume.list_dir(plain_directory_path) val explorerElements = gocryptfsVolume.listDir(plain_directory_path)
for (e in explorerElements) { for (e in explorerElements) {
val fullPath = PathUtils.path_join(plain_directory_path, e.name) val fullPath = PathUtils.path_join(plain_directory_path, e.name)
if (e.isDirectory) { if (e.isDirectory) {
val result = recursiveRemoveDirectory(fullPath) val result = recursiveRemoveDirectory(fullPath)
result?.let { return it } result?.let { return it }
} else { } else {
if (!gocryptfsVolume.remove_file(fullPath)) { if (!gocryptfsVolume.removeFile(fullPath)) {
return fullPath return fullPath
} }
} }
@ -572,7 +560,7 @@ class ExplorerActivity : BaseExplorerActivity() {
val result = recursiveRemoveDirectory(fullPath) val result = recursiveRemoveDirectory(fullPath)
result?.let{ failedItem = it } result?.let{ failedItem = it }
} else { } else {
if (!gocryptfsVolume.remove_file(fullPath)) { if (!gocryptfsVolume.removeFile(fullPath)) {
failedItem = fullPath failedItem = fullPath
} }
} }

View File

@ -2,7 +2,6 @@ package sushi.hardcore.droidfs.explorers
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.util.Log
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
@ -33,13 +32,13 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
if (intent.action == Intent.ACTION_SEND) { if (intent.action == Intent.ACTION_SEND) {
val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM) val uri = intent.getParcelableExtra<Uri>(Intent.EXTRA_STREAM)
val outputPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri)) val outputPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri))
errorMsg = if (gocryptfsVolume.import_file(this, uri, outputPath)) null else getString(R.string.import_failed, outputPath) errorMsg = if (gocryptfsVolume.importFile(this, uri, outputPath)) null else getString(R.string.import_failed, outputPath)
} else if (intent.action == Intent.ACTION_SEND_MULTIPLE) { } else if (intent.action == Intent.ACTION_SEND_MULTIPLE) {
val uris = intent.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM) val uris = intent.getParcelableArrayListExtra<Uri>(Intent.EXTRA_STREAM)
if (uris != null){ if (uris != null){
for (uri in uris) { for (uri in uris) {
val outputPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri)) val outputPath = PathUtils.path_join(currentDirectoryPath, PathUtils.getFilenameFromURI(this, uri))
if (!gocryptfsVolume.import_file(this, uri, outputPath)) { if (!gocryptfsVolume.importFile(this, uri, outputPath)) {
errorMsg = getString(R.string.import_failed, outputPath) errorMsg = getString(R.string.import_failed, outputPath)
break break
} }

View File

@ -29,21 +29,21 @@ abstract class FileViewerActivity: BaseActivity() {
} }
abstract fun viewFile() abstract fun viewFile()
fun loadWholeFile(path: String): ByteArray? { fun loadWholeFile(path: String): ByteArray? {
val fileSize = gocryptfsVolume.get_size(path) val fileSize = gocryptfsVolume.getSize(path)
if (fileSize >= 0){ if (fileSize >= 0){
try { try {
val fileBuff = ByteArray(fileSize.toInt()) val fileBuff = ByteArray(fileSize.toInt())
var success = false var success = false
val handleID = gocryptfsVolume.open_read_mode(path) val handleID = gocryptfsVolume.openReadMode(path)
if (handleID != -1) { if (handleID != -1) {
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS) val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS)
var length: Int var length: Int
while (gocryptfsVolume.read_file(handleID, offset, ioBuffer).also { length = it } > 0){ while (gocryptfsVolume.readFile(handleID, offset, ioBuffer).also { length = it } > 0){
System.arraycopy(ioBuffer, 0, fileBuff, offset.toInt(), length) System.arraycopy(ioBuffer, 0, fileBuff, offset.toInt(), length)
offset += length.toLong() offset += length.toLong()
} }
gocryptfsVolume.close_file(handleID) gocryptfsVolume.closeFile(handleID)
success = offset == fileBuff.size.toLong() success = offset == fileBuff.size.toLong()
} }
if (success){ if (success){

View File

@ -15,8 +15,8 @@ class GocryptfsDataSource(private val gocryptfsVolume: GocryptfsVolume, private
dataSpec?.let { dataSpec?.let {
fileOffset = dataSpec.position fileOffset = dataSpec.position
} }
handleID = gocryptfsVolume.open_read_mode(filePath) handleID = gocryptfsVolume.openReadMode(filePath)
fileSize = gocryptfsVolume.get_size(filePath) fileSize = gocryptfsVolume.getSize(filePath)
return fileSize return fileSize
} }
@ -25,7 +25,7 @@ class GocryptfsDataSource(private val gocryptfsVolume: GocryptfsVolume, private
} }
override fun close() { override fun close() {
gocryptfsVolume.close_file(handleID) gocryptfsVolume.closeFile(handleID)
} }
override fun addTransferListener(transferListener: TransferListener?) { override fun addTransferListener(transferListener: TransferListener?) {
@ -44,7 +44,7 @@ class GocryptfsDataSource(private val gocryptfsVolume: GocryptfsVolume, private
} else { } else {
ByteArray(tmpReadLength) ByteArray(tmpReadLength)
} }
val read = gocryptfsVolume.read_file(handleID, fileOffset, tmpBuff) val read = gocryptfsVolume.readFile(handleID, fileOffset, tmpBuff)
System.arraycopy(tmpBuff, 0, buffer, offset+totalRead, read) System.arraycopy(tmpBuff, 0, buffer, offset+totalRead, read)
fileOffset += read fileOffset += read
totalRead += read totalRead += read

View File

@ -4,20 +4,30 @@ import android.graphics.Bitmap
import android.graphics.Matrix import android.graphics.Matrix
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.os.Handler import android.os.Handler
import android.view.MotionEvent
import android.view.View import android.view.View
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.RequestBuilder import com.bumptech.glide.RequestBuilder
import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool import com.bumptech.glide.load.engine.bitmap_recycle.BitmapPool
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import kotlinx.android.synthetic.main.activity_image_viewer.* import kotlinx.android.synthetic.main.activity_image_viewer.*
import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.util.PathUtils
import java.security.MessageDigest import java.security.MessageDigest
import kotlin.math.abs
class ImageViewer: FileViewerActivity() { class ImageViewer: FileViewerActivity() {
companion object { companion object {
private const val hideDelay: Long = 3000 private const val hideDelay: Long = 3000
private const val MIN_SWIPE_DISTANCE = 150
} }
private lateinit var glideImage: RequestBuilder<Drawable> private lateinit var glideImage: RequestBuilder<Drawable>
private var x1 = 0F
private var x2 = 0F
private val mappedImages = mutableListOf<String>()
private var wasMapped = false
private var currentMappedImageIndex = -1
private var rotationAngle: Float = 0F private var rotationAngle: Float = 0F
private val handler = Handler() private val handler = Handler()
private val hideActionButtons = Runnable { action_buttons.visibility = View.GONE } private val hideActionButtons = Runnable { action_buttons.visibility = View.GONE }
@ -31,6 +41,50 @@ class ImageViewer: FileViewerActivity() {
} }
} }
override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
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){
if (!wasMapped){
for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){
if (e.isRegularFile && ConstValues.isImage(e.name)){
mappedImages.add(e.getFullPath())
}
}
mappedImages.sortWith(Comparator { p1, p2 -> p1.compareTo(p2) })
currentMappedImageIndex = mappedImages.indexOf(filePath)
wasMapped = true
}
if (deltaX < 0){
if (currentMappedImageIndex == mappedImages.size-1){
currentMappedImageIndex = 0
} else {
currentMappedImageIndex += 1
}
} else {
if (currentMappedImageIndex == 0){
currentMappedImageIndex = mappedImages.size-1
} else {
currentMappedImageIndex -= 1
}
}
loadWholeFile(mappedImages[currentMappedImageIndex])?.let {
glideImage = Glide.with(this).load(it)
glideImage.into(image_viewer)
}
}
}
}
}
return super.dispatchTouchEvent(event)
}
class RotateTransformation(private val rotationAngle: Float): BitmapTransformation() { class RotateTransformation(private val rotationAngle: Float): BitmapTransformation() {
override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap { override fun transform(pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int): Bitmap {
@ -45,6 +99,7 @@ class ImageViewer: FileViewerActivity() {
} }
private fun rotateImage(){ private fun rotateImage(){
image_viewer.restoreZoomNormal()
glideImage.transform(RotateTransformation(rotationAngle)).into(image_viewer) glideImage.transform(RotateTransformation(rotationAngle)).into(image_viewer)
} }
fun onCLickRotateRight(view: View){ fun onCLickRotateRight(view: View){

View File

@ -68,14 +68,14 @@ class TextEditor: FileViewerActivity() {
private fun save(): Boolean{ private fun save(): Boolean{
var success = false var success = false
val content = editor.text.toString().toByteArray() val content = editor.text.toString().toByteArray()
val handleID = gocryptfsVolume.open_write_mode(filePath) val handleID = gocryptfsVolume.openWriteMode(filePath)
if (handleID != -1){ if (handleID != -1){
val buff = ByteArrayInputStream(content) val buff = ByteArrayInputStream(content)
var offset: Long = 0 var offset: Long = 0
val io_buffer = ByteArray(GocryptfsVolume.DefaultBS) val io_buffer = ByteArray(GocryptfsVolume.DefaultBS)
var length: Int var length: Int
while (buff.read(io_buffer).also { length = it } > 0) { while (buff.read(io_buffer).also { length = it } > 0) {
val written = gocryptfsVolume.write_file(handleID, offset, io_buffer, length).toLong() val written = gocryptfsVolume.writeFile(handleID, offset, io_buffer, length).toLong()
if (written == length.toLong()) { if (written == length.toLong()) {
offset += written offset += written
} else { } else {
@ -85,7 +85,7 @@ class TextEditor: FileViewerActivity() {
if (offset == content.size.toLong()){ if (offset == content.size.toLong()){
success = gocryptfsVolume.truncate(filePath, offset) success = gocryptfsVolume.truncate(filePath, offset)
} }
gocryptfsVolume.close_file(handleID) gocryptfsVolume.closeFile(handleID)
buff.close() buff.close()
} }
if (success){ if (success){

View File

@ -34,7 +34,7 @@ object ExternalProvider {
val tmpFileUri = RestrictedFileProvider.newFile(fileName) val tmpFileUri = RestrictedFileProvider.newFile(fileName)
if (tmpFileUri != null){ if (tmpFileUri != null){
storedFiles.add(tmpFileUri) storedFiles.add(tmpFileUri)
if (gocryptfsVolume.export_file(context, file_path, tmpFileUri)) { if (gocryptfsVolume.exportFile(context, file_path, tmpFileUri)) {
return Pair(tmpFileUri, getContentType(fileName, previous_content_type)) return Pair(tmpFileUri, getContentType(fileName, previous_content_type))
} }
} }

View File

@ -25,9 +25,9 @@ class GocryptfsVolume(var sessionID: Int) {
const val KeyLen = 32 const val KeyLen = 32
const val ScryptDefaultLogN = 16 const val ScryptDefaultLogN = 16
const val DefaultBS = 4096 const val DefaultBS = 4096
external fun create_volume(root_cipher_dir: String, password: CharArray, logN: Int, creator: String): Boolean external fun createVolume(root_cipher_dir: String, password: CharArray, logN: Int, creator: String): Boolean
external fun init(root_cipher_dir: String, password: CharArray?, givenHash: ByteArray?, returnedHash: ByteArray?): Int external fun init(root_cipher_dir: String, password: CharArray?, givenHash: ByteArray?, returnedHash: ByteArray?): Int
external fun change_password(root_cipher_dir: String, old_password: CharArray?, givenHash: ByteArray?, new_password: CharArray, returnedHash: ByteArray?): Boolean external fun changePassword(root_cipher_dir: String, old_password: CharArray?, givenHash: ByteArray?, new_password: CharArray, returnedHash: ByteArray?): Boolean
init { init {
System.loadLibrary("gocryptfs_jni") System.loadLibrary("gocryptfs_jni")
@ -38,7 +38,7 @@ class GocryptfsVolume(var sessionID: Int) {
native_close(sessionID) native_close(sessionID)
} }
fun list_dir(dir_path: String): MutableList<ExplorerElement> { fun listDir(dir_path: String): MutableList<ExplorerElement> {
return native_list_dir(sessionID, dir_path) return native_list_dir(sessionID, dir_path)
} }
@ -50,35 +50,35 @@ class GocryptfsVolume(var sessionID: Int) {
return native_rmdir(sessionID, dir_path) return native_rmdir(sessionID, dir_path)
} }
fun remove_file(file_path: String): Boolean { fun removeFile(file_path: String): Boolean {
return native_remove_file(sessionID, file_path) return native_remove_file(sessionID, file_path)
} }
fun path_exists(file_path: String): Boolean { fun pathExists(file_path: String): Boolean {
return native_path_exists(sessionID, file_path) return native_path_exists(sessionID, file_path)
} }
fun get_size(file_path: String): Long { fun getSize(file_path: String): Long {
return native_get_size(sessionID, file_path) return native_get_size(sessionID, file_path)
} }
fun close_file(handleID: Int) { fun closeFile(handleID: Int) {
native_close_file(sessionID, handleID) native_close_file(sessionID, handleID)
} }
fun open_read_mode(file_path: String): Int { fun openReadMode(file_path: String): Int {
return native_open_read_mode(sessionID, file_path) return native_open_read_mode(sessionID, file_path)
} }
fun open_write_mode(file_path: String): Int { fun openWriteMode(file_path: String): Int {
return native_open_write_mode(sessionID, file_path) return native_open_write_mode(sessionID, file_path)
} }
fun read_file(handleID: Int, offset: Long, buff: ByteArray): Int { fun readFile(handleID: Int, offset: Long, buff: ByteArray): Int {
return native_read_file(sessionID, handleID, offset, buff) return native_read_file(sessionID, handleID, offset, buff)
} }
fun write_file(handleID: Int, offset: Long, buff: ByteArray, buff_size: Int): Int { fun writeFile(handleID: Int, offset: Long, buff: ByteArray, buff_size: Int): Int {
return native_write_file(sessionID, handleID, offset, buff, buff_size) return native_write_file(sessionID, handleID, offset, buff, buff_size)
} }
@ -90,7 +90,7 @@ class GocryptfsVolume(var sessionID: Int) {
return native_rename(sessionID, old_path, new_path) return native_rename(sessionID, old_path, new_path)
} }
fun export_file(handleID: Int, os: OutputStream): Boolean { fun exportFile(handleID: Int, os: OutputStream): Boolean {
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(DefaultBS) val ioBuffer = ByteArray(DefaultBS)
var length: Int var length: Int
@ -102,29 +102,29 @@ class GocryptfsVolume(var sessionID: Int) {
return true return true
} }
fun export_file(src_path: String, os: OutputStream): Boolean { fun exportFile(src_path: String, os: OutputStream): Boolean {
var success = false var success = false
val srcHandleId = open_read_mode(src_path) val srcHandleId = openReadMode(src_path)
if (srcHandleId != -1) { if (srcHandleId != -1) {
success = export_file(srcHandleId, os) success = exportFile(srcHandleId, os)
close_file(srcHandleId) closeFile(srcHandleId)
} }
return success return success
} }
fun export_file(src_path: String, dst_path: String): Boolean { fun exportFile(src_path: String, dst_path: String): Boolean {
return export_file(src_path, FileOutputStream(dst_path)) return exportFile(src_path, FileOutputStream(dst_path))
} }
fun export_file(context: Context, src_path: String, output_path: Uri): Boolean { fun exportFile(context: Context, src_path: String, output_path: Uri): Boolean {
val os = context.contentResolver.openOutputStream(output_path) val os = context.contentResolver.openOutputStream(output_path)
if (os != null){ if (os != null){
return export_file(src_path, os) return exportFile(src_path, os)
} }
return false return false
} }
fun import_file(inputStream: InputStream, handleID: Int): Boolean { fun importFile(inputStream: InputStream, handleID: Int): Boolean {
var offset: Long = 0 var offset: Long = 0
val ioBuffer = ByteArray(DefaultBS) val ioBuffer = ByteArray(DefaultBS)
var length: Int var length: Int
@ -142,22 +142,33 @@ class GocryptfsVolume(var sessionID: Int) {
return true return true
} }
fun import_file(inputStream: InputStream, dst_path: String): Boolean { fun importFile(inputStream: InputStream, dst_path: String): Boolean {
var success = false var success = false
val dstHandleId = open_write_mode(dst_path) val dstHandleId = openWriteMode(dst_path)
if (dstHandleId != -1) { if (dstHandleId != -1) {
success = import_file(inputStream, dstHandleId) success = importFile(inputStream, dstHandleId)
close_file(dstHandleId) closeFile(dstHandleId)
} }
return success return success
} }
fun import_file(context: Context, src_uri: Uri, dst_path: String): Boolean { fun importFile(context: Context, src_uri: Uri, dst_path: String): Boolean {
val inputStream = context.contentResolver.openInputStream(src_uri) val inputStream = context.contentResolver.openInputStream(src_uri)
if (inputStream != null){ if (inputStream != null){
return import_file(inputStream, dst_path) return importFile(inputStream, dst_path)
} }
return false return false
} }
fun recursiveMapFiles(rootPath: String): MutableList<ExplorerElement> {
val result = mutableListOf<ExplorerElement>()
val explorerElements = listDir(rootPath)
result.addAll(explorerElements)
for (e in explorerElements){
if (e.isDirectory){
result.addAll(recursiveMapFiles(e.getFullPath()))
}
}
return result
}
} }

View File

@ -112,8 +112,16 @@ public class ZoomableImageView extends androidx.appcompat.widget.AppCompatImageV
}); });
} }
public void setMaxZoom(float x) { public boolean isZoomed(){
maxScale = x; return saveScale > minScale;
}
public void restoreZoomNormal(){
float origScale = saveScale;
saveScale = minScale;
float mScaleFactor = minScale / origScale;
matrix.postScale(mScaleFactor, mScaleFactor, viewWidth/2, viewHeight/2);
fixTrans();
} }
@Override @Override
@ -124,20 +132,17 @@ public class ZoomableImageView extends androidx.appcompat.widget.AppCompatImageV
@Override @Override
public boolean onDoubleTap(MotionEvent e) { public boolean onDoubleTap(MotionEvent e) {
// Double tap is detected // Double tap is detected
float origScale = saveScale;
float mScaleFactor;
if (saveScale >= maxScale) { if (saveScale >= maxScale) {
saveScale = minScale; restoreZoomNormal();
mScaleFactor = minScale / origScale;
matrix.postScale(mScaleFactor, mScaleFactor, viewWidth/2, viewHeight/2);
} else { } else {
float origScale = saveScale;
saveScale *= 1.5; saveScale *= 1.5;
mScaleFactor = saveScale / origScale; float mScaleFactor = saveScale / origScale;
matrix.postScale(mScaleFactor, mScaleFactor, e.getX(), e.getY()); matrix.postScale(mScaleFactor, mScaleFactor, e.getX(), e.getY());
fixTrans();
} }
fixTrans();
return false; return false;
} }

View File

@ -31,10 +31,10 @@ void jbyteArray_to_unsignedCharArray(const jbyte* src, unsigned char* dst, const
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_util_GocryptfsVolume_00024Companion_create_1volume(JNIEnv *env, jclass clazz, Java_sushi_hardcore_droidfs_util_GocryptfsVolume_00024Companion_createVolume(JNIEnv *env, jclass clazz,
jstring jroot_cipher_dir, jcharArray jpassword, jstring jroot_cipher_dir, jcharArray jpassword,
jint logN, jint logN,
jstring jcreator) { jstring jcreator) {
const char* root_cipher_dir = (*env)->GetStringUTFChars(env, jroot_cipher_dir, NULL); const char* root_cipher_dir = (*env)->GetStringUTFChars(env, jroot_cipher_dir, NULL);
const char* creator = (*env)->GetStringUTFChars(env, jcreator, NULL); const char* creator = (*env)->GetStringUTFChars(env, jcreator, NULL);
GoString gofilename = {root_cipher_dir, strlen(root_cipher_dir)}, gocreator = {creator, strlen(creator)}; GoString gofilename = {root_cipher_dir, strlen(root_cipher_dir)}, gocreator = {creator, strlen(creator)};
@ -127,12 +127,12 @@ Java_sushi_hardcore_droidfs_util_GocryptfsVolume_00024Companion_init(JNIEnv *env
} }
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_sushi_hardcore_droidfs_util_GocryptfsVolume_00024Companion_change_1password(JNIEnv *env, jclass clazz, Java_sushi_hardcore_droidfs_util_GocryptfsVolume_00024Companion_changePassword(JNIEnv *env, jclass clazz,
jstring jroot_cipher_dir, jstring jroot_cipher_dir,
jcharArray jold_password, jcharArray jold_password,
jbyteArray jgiven_hash, jbyteArray jgiven_hash,
jcharArray jnew_password, jcharArray jnew_password,
jbyteArray jreturned_hash) { jbyteArray jreturned_hash) {
const char* root_cipher_dir = (*env)->GetStringUTFChars(env, jroot_cipher_dir, NULL); const char* root_cipher_dir = (*env)->GetStringUTFChars(env, jroot_cipher_dir, NULL);
GoString go_root_cipher_dir = {root_cipher_dir, strlen(root_cipher_dir)}; GoString go_root_cipher_dir = {root_cipher_dir, strlen(root_cipher_dir)};