forked from hardcoresushi/DroidFS
Thumbnails
This commit is contained in:
parent
e3df7be3b5
commit
fd5ddc02b1
@ -91,7 +91,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
|
|||||||
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
||||||
binding = ActivityCameraBinding.inflate(layoutInflater)
|
binding = ActivityCameraBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
gocryptfsVolume = GocryptfsVolume(intent.getIntExtra("sessionID", -1))
|
gocryptfsVolume = GocryptfsVolume(applicationContext, intent.getIntExtra("sessionID", -1))
|
||||||
outputDirectory = intent.getStringExtra("path")!!
|
outputDirectory = intent.getStringExtra("path")!!
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
@ -38,14 +38,5 @@ class ConstValues {
|
|||||||
fun isText(path: String): Boolean {
|
fun isText(path: String): Boolean {
|
||||||
return isExtensionType("text", path)
|
return isExtensionType("text", path)
|
||||||
}
|
}
|
||||||
fun getAssociatedDrawable(path: String): Int {
|
|
||||||
return when {
|
|
||||||
isAudio(path) -> R.drawable.icon_file_audio
|
|
||||||
isImage(path) -> R.drawable.icon_file_image
|
|
||||||
isVideo(path) -> R.drawable.icon_file_video
|
|
||||||
isText(path) -> R.drawable.icon_file_text
|
|
||||||
else -> R.drawable.icon_file_unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -167,7 +167,7 @@ class CreateActivity : VolumeActionActivity() {
|
|||||||
super.onPause()
|
super.onPause()
|
||||||
//Closing volume if leaving activity while showing dialog
|
//Closing volume if leaving activity while showing dialog
|
||||||
if (sessionID != -1 && !isStartingExplorer) {
|
if (sessionID != -1 && !isStartingExplorer) {
|
||||||
GocryptfsVolume(sessionID).close()
|
GocryptfsVolume(applicationContext, sessionID).close()
|
||||||
finish()
|
finish()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ import java.io.FileOutputStream
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.OutputStream
|
import java.io.OutputStream
|
||||||
|
|
||||||
class GocryptfsVolume(var sessionID: Int) {
|
class GocryptfsVolume(val applicationContext: Context, var sessionID: Int) {
|
||||||
private external fun native_close(sessionID: Int)
|
private external fun native_close(sessionID: Int)
|
||||||
private external fun native_is_closed(sessionID: Int): Boolean
|
private external fun native_is_closed(sessionID: Int): Boolean
|
||||||
private external fun native_list_dir(sessionID: Int, dir_path: String): MutableList<ExplorerElement>
|
private external fun native_list_dir(sessionID: Int, dir_path: String): MutableList<ExplorerElement>
|
||||||
@ -47,79 +47,79 @@ class GocryptfsVolume(var sessionID: Int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun close() {
|
fun close() {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
native_close(sessionID)
|
native_close(sessionID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isClosed(): Boolean {
|
fun isClosed(): Boolean {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_is_closed(sessionID)
|
return native_is_closed(sessionID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun listDir(dir_path: String): MutableList<ExplorerElement> {
|
fun listDir(dir_path: String): MutableList<ExplorerElement> {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_list_dir(sessionID, dir_path)
|
return native_list_dir(sessionID, dir_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun mkdir(dir_path: String): Boolean {
|
fun mkdir(dir_path: String): Boolean {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_mkdir(sessionID, dir_path, ConstValues.DIRECTORY_MODE)
|
return native_mkdir(sessionID, dir_path, ConstValues.DIRECTORY_MODE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun rmdir(dir_path: String): Boolean {
|
fun rmdir(dir_path: String): Boolean {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_rmdir(sessionID, dir_path)
|
return native_rmdir(sessionID, dir_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeFile(file_path: String): Boolean {
|
fun removeFile(file_path: String): Boolean {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_remove_file(sessionID, file_path)
|
return native_remove_file(sessionID, file_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun pathExists(file_path: String): Boolean {
|
fun pathExists(file_path: String): Boolean {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_path_exists(sessionID, file_path)
|
return native_path_exists(sessionID, file_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSize(file_path: String): Long {
|
fun getSize(file_path: String): Long {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_get_size(sessionID, file_path)
|
return native_get_size(sessionID, file_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun closeFile(handleID: Int) {
|
fun closeFile(handleID: Int) {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
native_close_file(sessionID, handleID)
|
native_close_file(sessionID, handleID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openReadMode(file_path: String): Int {
|
fun openReadMode(file_path: String): Int {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_open_read_mode(sessionID, file_path)
|
return native_open_read_mode(sessionID, file_path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openWriteMode(file_path: String): Int {
|
fun openWriteMode(file_path: String): Int {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_open_write_mode(sessionID, file_path, ConstValues.FILE_MODE)
|
return native_open_write_mode(sessionID, file_path, ConstValues.FILE_MODE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun readFile(handleID: Int, offset: Long, buff: ByteArray): Int {
|
fun readFile(handleID: Int, offset: Long, buff: ByteArray): Int {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_read_file(sessionID, handleID, offset, buff)
|
return native_read_file(sessionID, handleID, offset, buff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeFile(handleID: Int, offset: Long, buff: ByteArray, buff_size: Int): Int {
|
fun writeFile(handleID: Int, offset: Long, buff: ByteArray, buff_size: Int): Int {
|
||||||
synchronized(this){
|
synchronized(applicationContext) {
|
||||||
return native_write_file(sessionID, handleID, offset, buff, buff_size)
|
return native_write_file(sessionID, handleID, offset, buff, buff_size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -237,4 +237,40 @@ class GocryptfsVolume(var sessionID: Int) {
|
|||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun loadWholeFile(fullPath: String, maxSize: Long? = null): Pair<ByteArray?, Int> {
|
||||||
|
val fileSize = getSize(fullPath)
|
||||||
|
return if (fileSize >= 0) {
|
||||||
|
maxSize?.let {
|
||||||
|
if (fileSize > it) {
|
||||||
|
return Pair(null, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
val fileBuff = ByteArray(fileSize.toInt())
|
||||||
|
val handleID = openReadMode(fullPath)
|
||||||
|
if (handleID == -1) {
|
||||||
|
Pair(null, 3)
|
||||||
|
} else {
|
||||||
|
var offset: Long = 0
|
||||||
|
val ioBuffer = ByteArray(DefaultBS)
|
||||||
|
var length: Int
|
||||||
|
while (readFile(handleID, offset, ioBuffer).also { length = it } > 0) {
|
||||||
|
System.arraycopy(ioBuffer, 0, fileBuff, offset.toInt(), length)
|
||||||
|
offset += length.toLong()
|
||||||
|
}
|
||||||
|
closeFile(handleID)
|
||||||
|
if (offset == fileBuff.size.toLong()) {
|
||||||
|
Pair(fileBuff, 0)
|
||||||
|
} else {
|
||||||
|
Pair(null, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: OutOfMemoryError) {
|
||||||
|
Pair(null, 2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Pair(null, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -170,7 +170,7 @@ class OpenActivity : VolumeActionActivity() {
|
|||||||
if (success){
|
if (success){
|
||||||
startExplorer()
|
startExplorer()
|
||||||
} else {
|
} else {
|
||||||
GocryptfsVolume(sessionID).close()
|
GocryptfsVolume(applicationContext, sessionID).close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -257,7 +257,7 @@ class OpenActivity : VolumeActionActivity() {
|
|||||||
if (intent.action == "pick" && !isFinishingIntentionally){
|
if (intent.action == "pick" && !isFinishingIntentionally){
|
||||||
val sessionID = intent.getIntExtra("sessionID", -1)
|
val sessionID = intent.getIntExtra("sessionID", -1)
|
||||||
if (sessionID != -1){
|
if (sessionID != -1){
|
||||||
GocryptfsVolume(sessionID).close()
|
GocryptfsVolume(applicationContext, sessionID).close()
|
||||||
RestrictedFileProvider.wipeAll(this)
|
RestrictedFileProvider.wipeAll(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
package sushi.hardcore.droidfs.adapters
|
package sushi.hardcore.droidfs.adapters
|
||||||
|
|
||||||
import android.content.Context
|
import android.graphics.drawable.Drawable
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import sushi.hardcore.droidfs.ConstValues.Companion.getAssociatedDrawable
|
import com.bumptech.glide.Glide
|
||||||
|
import com.bumptech.glide.request.target.DrawableImageViewTarget
|
||||||
|
import com.bumptech.glide.request.transition.Transition
|
||||||
|
import sushi.hardcore.droidfs.ConstValues
|
||||||
|
import sushi.hardcore.droidfs.GocryptfsVolume
|
||||||
import sushi.hardcore.droidfs.R
|
import sushi.hardcore.droidfs.R
|
||||||
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
||||||
import sushi.hardcore.droidfs.util.PathUtils
|
import sushi.hardcore.droidfs.util.PathUtils
|
||||||
@ -16,17 +20,17 @@ import java.text.DateFormat
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class ExplorerElementAdapter(
|
class ExplorerElementAdapter(
|
||||||
context: Context,
|
val activity: AppCompatActivity,
|
||||||
private val onExplorerElementClick: (Int) -> Unit,
|
val gocryptfsVolume: GocryptfsVolume?,
|
||||||
private val onExplorerElementLongClick: (Int) -> Unit
|
val onExplorerElementClick: (Int) -> Unit,
|
||||||
|
val onExplorerElementLongClick: (Int) -> Unit
|
||||||
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
||||||
private val dateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault())
|
val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault())
|
||||||
var explorerElements = listOf<ExplorerElement>()
|
var explorerElements = listOf<ExplorerElement>()
|
||||||
set(value) {
|
set(value) {
|
||||||
field = value
|
field = value
|
||||||
unSelectAll()
|
unSelectAll()
|
||||||
}
|
}
|
||||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
|
||||||
val selectedItems: MutableList<Int> = ArrayList()
|
val selectedItems: MutableList<Int> = ArrayList()
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
@ -72,11 +76,7 @@ class ExplorerElementAdapter(
|
|||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
}
|
}
|
||||||
|
|
||||||
open class ExplorerElementViewHolder(
|
open class ExplorerElementViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
||||||
itemView: View,
|
|
||||||
private val onClick: (Int) -> Boolean,
|
|
||||||
private val onLongClick: (Int) -> Boolean,
|
|
||||||
) : RecyclerView.ViewHolder(itemView) {
|
|
||||||
private val textElementName by lazy {
|
private val textElementName by lazy {
|
||||||
itemView.findViewById<TextView>(R.id.text_element_name)
|
itemView.findViewById<TextView>(R.id.text_element_name)
|
||||||
}
|
}
|
||||||
@ -99,57 +99,87 @@ class ExplorerElementAdapter(
|
|||||||
|
|
||||||
open fun bind(explorerElement: ExplorerElement, position: Int) {
|
open fun bind(explorerElement: ExplorerElement, position: Int) {
|
||||||
textElementName.text = explorerElement.name
|
textElementName.text = explorerElement.name
|
||||||
|
(bindingAdapter as ExplorerElementAdapter?)?.let { adapter ->
|
||||||
selectableContainer.setOnClickListener {
|
selectableContainer.setOnClickListener {
|
||||||
setBackground(onClick(position))
|
setBackground(adapter.onItemClick(position))
|
||||||
}
|
}
|
||||||
selectableContainer.setOnLongClickListener {
|
selectableContainer.setOnLongClickListener {
|
||||||
setBackground(onLongClick(position))
|
setBackground(adapter.onItemLongClick(position))
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
open class RegularElementViewHolder(
|
open class RegularElementViewHolder(itemView: View) : ExplorerElementViewHolder(itemView) {
|
||||||
itemView: View,
|
|
||||||
private val dateFormat: DateFormat,
|
|
||||||
onClick: (Int) -> Boolean,
|
|
||||||
onLongClick: (Int) -> Boolean,
|
|
||||||
) : ExplorerElementViewHolder(itemView, onClick, onLongClick) {
|
|
||||||
open fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
|
open fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
|
||||||
super.bind(explorerElement, position)
|
super.bind(explorerElement, position)
|
||||||
textElementSize.text = PathUtils.formatSize(explorerElement.size)
|
textElementSize.text = PathUtils.formatSize(explorerElement.size)
|
||||||
textElementMtime.text = dateFormat.format(explorerElement.mTime)
|
(bindingAdapter as ExplorerElementAdapter?)?.let {
|
||||||
|
textElementMtime.text = it.dateFormat.format(explorerElement.mTime)
|
||||||
|
}
|
||||||
setBackground(isSelected)
|
setBackground(isSelected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileViewHolder(
|
class FileViewHolder(itemView: View) : RegularElementViewHolder(itemView) {
|
||||||
itemView: View,
|
var displayThumbnail = true
|
||||||
dateFormat: DateFormat,
|
var target: DrawableImageViewTarget? = null
|
||||||
onClick: (Int) -> Boolean,
|
|
||||||
onLongClick: (Int) -> Boolean,
|
private fun loadThumbnail(fullPath: String) {
|
||||||
) : RegularElementViewHolder(itemView, dateFormat, onClick, onLongClick) {
|
(bindingAdapter as ExplorerElementAdapter?)?.let { adapter ->
|
||||||
|
adapter.gocryptfsVolume?.let { volume ->
|
||||||
|
displayThumbnail = true
|
||||||
|
Thread {
|
||||||
|
volume.loadWholeFile(fullPath, 50_000_000).first?.let {
|
||||||
|
if (displayThumbnail) {
|
||||||
|
adapter.activity.runOnUiThread {
|
||||||
|
if (displayThumbnail) {
|
||||||
|
target = Glide.with(adapter.activity).load(it).into(object : DrawableImageViewTarget(icon) {
|
||||||
|
override fun onResourceReady(
|
||||||
|
resource: Drawable,
|
||||||
|
transition: Transition<in Drawable>?
|
||||||
|
) {
|
||||||
|
super.onResourceReady(resource, transition)
|
||||||
|
target = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
override fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
|
override fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
|
||||||
super.bind(explorerElement, position, isSelected)
|
super.bind(explorerElement, position, isSelected)
|
||||||
icon.setImageResource(getAssociatedDrawable(explorerElement.name))
|
icon.setImageResource(
|
||||||
|
when {
|
||||||
|
ConstValues.isImage(explorerElement.name) -> {
|
||||||
|
loadThumbnail(explorerElement.fullPath)
|
||||||
|
R.drawable.icon_file_image
|
||||||
|
}
|
||||||
|
ConstValues.isVideo(explorerElement.name) -> {
|
||||||
|
loadThumbnail(explorerElement.fullPath)
|
||||||
|
R.drawable.icon_file_video
|
||||||
|
}
|
||||||
|
ConstValues.isText(explorerElement.name) -> R.drawable.icon_file_text
|
||||||
|
ConstValues.isAudio(explorerElement.name) -> R.drawable.icon_file_audio
|
||||||
|
else -> R.drawable.icon_file_unknown
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class DirectoryViewHolder(
|
|
||||||
itemView: View,
|
class DirectoryViewHolder(itemView: View) : RegularElementViewHolder(itemView) {
|
||||||
dateFormat: DateFormat,
|
|
||||||
onClick: (Int) -> Boolean,
|
|
||||||
onLongClick: (Int) -> Boolean,
|
|
||||||
) : RegularElementViewHolder(itemView, dateFormat, onClick, onLongClick) {
|
|
||||||
override fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
|
override fun bind(explorerElement: ExplorerElement, position: Int, isSelected: Boolean) {
|
||||||
super.bind(explorerElement, position, isSelected)
|
super.bind(explorerElement, position, isSelected)
|
||||||
icon.setImageResource(R.drawable.icon_folder)
|
icon.setImageResource(R.drawable.icon_folder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class ParentFolderViewHolder(
|
|
||||||
itemView: View,
|
class ParentFolderViewHolder(itemView: View): ExplorerElementViewHolder(itemView) {
|
||||||
onClick: (Int) -> Boolean,
|
|
||||||
onLongClick: (Int) -> Boolean,
|
|
||||||
): ExplorerElementViewHolder(itemView, onClick, onLongClick) {
|
|
||||||
override fun bind(explorerElement: ExplorerElement, position: Int) {
|
override fun bind(explorerElement: ExplorerElement, position: Int) {
|
||||||
super.bind(explorerElement, position)
|
super.bind(explorerElement, position)
|
||||||
textElementSize.text = ""
|
textElementSize.text = ""
|
||||||
@ -158,12 +188,22 @@ class ExplorerElementAdapter(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
|
||||||
|
if (holder is FileViewHolder) {
|
||||||
|
//cancel pending thumbnail display
|
||||||
|
holder.displayThumbnail = false
|
||||||
|
holder.target?.let {
|
||||||
|
Glide.with(activity).clear(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
||||||
val view = inflater.inflate(R.layout.adapter_explorer_element, parent, false)
|
val view = activity.layoutInflater.inflate(R.layout.adapter_explorer_element, parent, false)
|
||||||
return when (viewType) {
|
return when (viewType) {
|
||||||
ExplorerElement.REGULAR_FILE_TYPE -> FileViewHolder(view, dateFormat, ::onItemClick, ::onItemLongClick)
|
ExplorerElement.REGULAR_FILE_TYPE -> FileViewHolder(view)
|
||||||
ExplorerElement.DIRECTORY_TYPE -> DirectoryViewHolder(view, dateFormat, ::onItemClick, ::onItemLongClick)
|
ExplorerElement.DIRECTORY_TYPE -> DirectoryViewHolder(view)
|
||||||
ExplorerElement.PARENT_FOLDER_TYPE -> ParentFolderViewHolder(view, ::onItemClick, ::onItemLongClick)
|
ExplorerElement.PARENT_FOLDER_TYPE -> ParentFolderViewHolder(view)
|
||||||
else -> throw IllegalArgumentException()
|
else -> throw IllegalArgumentException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
|||||||
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
||||||
volumeName = intent.getStringExtra("volume_name") ?: ""
|
volumeName = intent.getStringExtra("volume_name") ?: ""
|
||||||
val sessionID = intent.getIntExtra("sessionID", -1)
|
val sessionID = intent.getIntExtra("sessionID", -1)
|
||||||
gocryptfsVolume = GocryptfsVolume(sessionID)
|
gocryptfsVolume = GocryptfsVolume(applicationContext, sessionID)
|
||||||
sortOrderEntries = resources.getStringArray(R.array.sort_orders_entries)
|
sortOrderEntries = resources.getStringArray(R.array.sort_orders_entries)
|
||||||
sortOrderValues = resources.getStringArray(R.array.sort_orders_values)
|
sortOrderValues = resources.getStringArray(R.array.sort_orders_values)
|
||||||
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
||||||
@ -95,7 +95,16 @@ open class BaseExplorerActivity : BaseActivity() {
|
|||||||
setSupportActionBar(toolbar)
|
setSupportActionBar(toolbar)
|
||||||
title = ""
|
title = ""
|
||||||
titleText.text = getString(R.string.volume, volumeName)
|
titleText.text = getString(R.string.volume, volumeName)
|
||||||
explorerAdapter = ExplorerElementAdapter(this, ::onExplorerItemClick, ::onExplorerItemLongClick)
|
explorerAdapter = ExplorerElementAdapter(
|
||||||
|
this,
|
||||||
|
if (sharedPrefs.getBoolean("thumbnails", true)) {
|
||||||
|
gocryptfsVolume
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
::onExplorerItemClick,
|
||||||
|
::onExplorerItemLongClick
|
||||||
|
)
|
||||||
explorerViewModel= ViewModelProvider(this).get(ExplorerViewModel::class.java)
|
explorerViewModel= ViewModelProvider(this).get(ExplorerViewModel::class.java)
|
||||||
currentDirectoryPath = explorerViewModel.currentDirectoryPath
|
currentDirectoryPath = explorerViewModel.currentDirectoryPath
|
||||||
setCurrentPath(currentDirectoryPath)
|
setCurrentPath(currentDirectoryPath)
|
||||||
|
@ -36,7 +36,7 @@ class ExplorerActivity : BaseExplorerActivity() {
|
|||||||
if (result.resultCode == Activity.RESULT_OK) {
|
if (result.resultCode == Activity.RESULT_OK) {
|
||||||
result.data?.let { resultIntent ->
|
result.data?.let { resultIntent ->
|
||||||
val remoteSessionID = resultIntent.getIntExtra("sessionID", -1)
|
val remoteSessionID = resultIntent.getIntExtra("sessionID", -1)
|
||||||
val remoteGocryptfsVolume = GocryptfsVolume(remoteSessionID)
|
val remoteGocryptfsVolume = GocryptfsVolume(applicationContext, remoteSessionID)
|
||||||
val path = resultIntent.getStringExtra("path")
|
val path = resultIntent.getStringExtra("path")
|
||||||
val operationFiles = ArrayList<OperationFile>()
|
val operationFiles = ArrayList<OperationFile>()
|
||||||
if (path == null){ //multiples elements
|
if (path == null){ //multiples elements
|
||||||
|
@ -86,8 +86,7 @@ class ExplorerActivityPick : BaseExplorerActivity() {
|
|||||||
if (!isFinishingIntentionally && !usf_keep_open){
|
if (!isFinishingIntentionally && !usf_keep_open){
|
||||||
val sessionID = intent.getIntExtra("originalSessionID", -1)
|
val sessionID = intent.getIntExtra("originalSessionID", -1)
|
||||||
if (sessionID != -1){
|
if (sessionID != -1){
|
||||||
val v = GocryptfsVolume(sessionID)
|
GocryptfsVolume(applicationContext, sessionID).close()
|
||||||
v.close()
|
|
||||||
}
|
}
|
||||||
super.closeVolumeOnDestroy()
|
super.closeVolumeOnDestroy()
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ abstract class FileViewerActivity: BaseActivity() {
|
|||||||
filePath = intent.getStringExtra("path")!!
|
filePath = intent.getStringExtra("path")!!
|
||||||
originalParentPath = PathUtils.getParentPath(filePath)
|
originalParentPath = PathUtils.getParentPath(filePath)
|
||||||
val sessionID = intent.getIntExtra("sessionID", -1)
|
val sessionID = intent.getIntExtra("sessionID", -1)
|
||||||
gocryptfsVolume = GocryptfsVolume(sessionID)
|
gocryptfsVolume = GocryptfsVolume(applicationContext, sessionID)
|
||||||
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
usf_keep_open = sharedPrefs.getBoolean("usf_keep_open", false)
|
||||||
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
foldersFirst = sharedPrefs.getBoolean("folders_first", true)
|
||||||
windowInsetsController = WindowInsetsControllerCompat(window, window.decorView)
|
windowInsetsController = WindowInsetsControllerCompat(window, window.decorView)
|
||||||
@ -56,51 +56,20 @@ abstract class FileViewerActivity: BaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected fun loadWholeFile(path: String): ByteArray? {
|
protected fun loadWholeFile(path: String): ByteArray? {
|
||||||
val fileSize = gocryptfsVolume.getSize(path)
|
val result = gocryptfsVolume.loadWholeFile(path)
|
||||||
if (fileSize >= 0){
|
if (result.second != 0) {
|
||||||
try {
|
val dialog = CustomAlertDialogBuilder(this, themeValue)
|
||||||
val fileBuff = ByteArray(fileSize.toInt())
|
|
||||||
var success = false
|
|
||||||
val handleID = gocryptfsVolume.openReadMode(path)
|
|
||||||
if (handleID != -1) {
|
|
||||||
var offset: Long = 0
|
|
||||||
val ioBuffer = ByteArray(GocryptfsVolume.DefaultBS)
|
|
||||||
var length: Int
|
|
||||||
while (gocryptfsVolume.readFile(handleID, offset, ioBuffer).also { length = it } > 0){
|
|
||||||
System.arraycopy(ioBuffer, 0, fileBuff, offset.toInt(), length)
|
|
||||||
offset += length.toLong()
|
|
||||||
}
|
|
||||||
gocryptfsVolume.closeFile(handleID)
|
|
||||||
success = offset == fileBuff.size.toLong()
|
|
||||||
}
|
|
||||||
if (success){
|
|
||||||
return fileBuff
|
|
||||||
} else {
|
|
||||||
CustomAlertDialogBuilder(this, themeValue)
|
|
||||||
.setTitle(R.string.error)
|
.setTitle(R.string.error)
|
||||||
.setMessage(R.string.read_file_failed)
|
|
||||||
.setCancelable(false)
|
.setCancelable(false)
|
||||||
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer() }
|
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer() }
|
||||||
.show()
|
when (result.second) {
|
||||||
|
1 -> dialog.setMessage(R.string.get_size_failed)
|
||||||
|
2 -> dialog.setMessage(R.string.outofmemoryerror_msg)
|
||||||
|
else -> dialog.setMessage(R.string.read_file_failed)
|
||||||
}
|
}
|
||||||
} catch (e: OutOfMemoryError){
|
dialog.show()
|
||||||
CustomAlertDialogBuilder(this, themeValue)
|
|
||||||
.setTitle(R.string.error)
|
|
||||||
.setMessage(R.string.outofmemoryerror_msg)
|
|
||||||
.setCancelable(false)
|
|
||||||
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer() }
|
|
||||||
.show()
|
|
||||||
}
|
}
|
||||||
|
return result.first
|
||||||
} else {
|
|
||||||
CustomAlertDialogBuilder(this, themeValue)
|
|
||||||
.setTitle(R.string.error)
|
|
||||||
.setMessage(R.string.get_size_failed)
|
|
||||||
.setCancelable(false)
|
|
||||||
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer() }
|
|
||||||
.show()
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun createPlaylist() {
|
protected fun createPlaylist() {
|
||||||
|
5
app/src/main/res/drawable/icon_image.xml
Normal file
5
app/src/main/res/drawable/icon_image.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<vector android:height="24dp"
|
||||||
|
android:viewportHeight="24" android:viewportWidth="24"
|
||||||
|
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="?attr/colorAccent" android:pathData="M21,19V5c0,-1.1 -0.9,-2 -2,-2H5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2zM8.5,13.5l2.5,3.01L14.5,12l4.5,6H5l3.5,-4.5z"/>
|
||||||
|
</vector>
|
@ -204,4 +204,6 @@
|
|||||||
<string name="encryption_cipher_label">Encryption cipher:</string>
|
<string name="encryption_cipher_label">Encryption cipher:</string>
|
||||||
<string name="theme">Theme</string>
|
<string name="theme">Theme</string>
|
||||||
<string name="theme_summary">Customize app theme</string>
|
<string name="theme_summary">Customize app theme</string>
|
||||||
|
<string name="thumbnails">Thumbnails</string>
|
||||||
|
<string name="thumbnails_summary">Show images and videos thumbnails</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -38,6 +38,13 @@
|
|||||||
android:title="@string/folders_first"
|
android:title="@string/folders_first"
|
||||||
android:summary="@string/folders_first_summary"/>
|
android:summary="@string/folders_first_summary"/>
|
||||||
|
|
||||||
|
<SwitchPreferenceCompat
|
||||||
|
android:defaultValue="true"
|
||||||
|
android:icon="@drawable/icon_image"
|
||||||
|
android:key="thumbnails"
|
||||||
|
android:title="@string/thumbnails"
|
||||||
|
android:summary="@string/thumbnails_summary"/>
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
<SwitchPreferenceCompat
|
||||||
android:defaultValue="true"
|
android:defaultValue="true"
|
||||||
app:icon="@drawable/icon_folder_search"
|
app:icon="@drawable/icon_folder_search"
|
||||||
|
Loading…
Reference in New Issue
Block a user