forked from hardcoresushi/DroidFS
Camera HDR, grid & filters & Directory size calculation
This commit is contained in:
parent
0518a2a030
commit
6c43750290
@ -15,7 +15,7 @@ android {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 1
|
||||
versionName "1.1.4"
|
||||
versionName "1.1.5"
|
||||
|
||||
ndk {
|
||||
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
@ -41,7 +41,7 @@ dependencies {
|
||||
implementation fileTree(dir: "libs", include: ["*.jar"])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation "androidx.core:core-ktx:1.3.1"
|
||||
implementation "androidx.appcompat:appcompat:1.1.0"
|
||||
implementation "androidx.appcompat:appcompat:1.2.0"
|
||||
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
|
||||
|
||||
implementation "androidx.sqlite:sqlite:2.1.0"
|
||||
|
@ -20,7 +20,7 @@
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
<activity android:name=".CameraActivity"/>
|
||||
<activity android:name=".CameraActivity" android:screenOrientation="nosensor"/>
|
||||
<activity
|
||||
android:name=".SettingsActivity"
|
||||
android:label="@string/title_activity_settings"
|
||||
|
@ -11,6 +11,9 @@ import com.otaliastudios.cameraview.CameraListener
|
||||
import com.otaliastudios.cameraview.PictureResult
|
||||
import com.otaliastudios.cameraview.controls.Facing
|
||||
import com.otaliastudios.cameraview.controls.Flash
|
||||
import com.otaliastudios.cameraview.controls.Grid
|
||||
import com.otaliastudios.cameraview.controls.Hdr
|
||||
import com.otaliastudios.cameraview.filter.Filters
|
||||
import kotlinx.android.synthetic.main.activity_camera.*
|
||||
import sushi.hardcore.droidfs.provider.RestrictedFileProvider
|
||||
import sushi.hardcore.droidfs.util.GocryptfsVolume
|
||||
@ -24,12 +27,16 @@ import java.util.*
|
||||
class CameraActivity : BaseActivity() {
|
||||
companion object {
|
||||
private val flashModes = listOf(Flash.AUTO, Flash.ON, Flash.OFF)
|
||||
private val gridTitles = listOf(R.string.grid_none, R.string.grid_3x3, R.string.grid_4x4)
|
||||
private val gridValues = listOf(Grid.OFF, Grid.DRAW_3X3, Grid.DRAW_4X4)
|
||||
private val filterNames = Filters.values().map { it.toString().toLowerCase(Locale.ROOT).replace("_", " ").capitalize() as CharSequence }.toTypedArray()
|
||||
private const val fileNameRandomMin = 100000
|
||||
private const val fileNameRandomMax = 999999
|
||||
private val dateFormat = SimpleDateFormat("yyyyMMdd_HHmmss")
|
||||
private val random = Random()
|
||||
}
|
||||
private var currentFlashModeIndex = 0
|
||||
private var currentFilterIndex = 0
|
||||
private var timerDuration = 0
|
||||
set(value) {
|
||||
field = value
|
||||
@ -68,6 +75,14 @@ class CameraActivity : BaseActivity() {
|
||||
take_photo_button.onClick = ::onClickTakePhoto
|
||||
}
|
||||
|
||||
private fun takePhoto() {
|
||||
if (currentFilterIndex != 0){
|
||||
camera.takePictureSnapshot()
|
||||
} else {
|
||||
camera.takePicture()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onClickTakePhoto() {
|
||||
val baseName = "IMG_"+dateFormat.format(Date())+"_"
|
||||
do {
|
||||
@ -81,12 +96,12 @@ class CameraActivity : BaseActivity() {
|
||||
Thread.sleep(1000)
|
||||
}
|
||||
runOnUiThread {
|
||||
camera.takePicture()
|
||||
takePhoto()
|
||||
text_timer.visibility = View.GONE
|
||||
}
|
||||
}.start()
|
||||
} else {
|
||||
camera.takePicture()
|
||||
takePhoto()
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,13 +128,26 @@ class CameraActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
fun onClickHDR(view: View) {
|
||||
camera.hdr = when (camera.hdr){
|
||||
Hdr.ON -> {
|
||||
image_hdr.setImageResource(R.drawable.icon_hdr_off)
|
||||
Hdr.OFF
|
||||
}
|
||||
Hdr.OFF -> {
|
||||
image_hdr.setImageResource(R.drawable.icon_hdr_on)
|
||||
Hdr.ON
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onClickTimer(view: View) {
|
||||
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
|
||||
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
|
||||
dialogEditText.inputType = InputType.TYPE_CLASS_NUMBER
|
||||
val dialog = ColoredAlertDialogBuilder(this)
|
||||
.setView(dialogEditTextView)
|
||||
.setTitle("Enter the timer duration (in s)")
|
||||
.setTitle(getString(R.string.enter_timer_duration))
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
timerDuration = dialogEditText.text.toString().toInt()
|
||||
}
|
||||
@ -134,6 +162,29 @@ class CameraActivity : BaseActivity() {
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
fun onClickGrid(view: View) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(getString(R.string.choose_grid))
|
||||
.setSingleChoiceItems(gridTitles.map { getString(it) as CharSequence }.toTypedArray(), gridValues.indexOf(camera.grid)){ dialog, which ->
|
||||
camera.grid = gridValues[which]
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
fun onClickFilter(view: View) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.setTitle(getString(R.string.choose_filter))
|
||||
.setSingleChoiceItems(filterNames, currentFilterIndex){ dialog, which ->
|
||||
camera.filter = Filters.values()[which].newInstance()
|
||||
currentFilterIndex = which
|
||||
dialog.dismiss()
|
||||
}
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
if (!isFinishingIntentionally) {
|
||||
|
@ -12,15 +12,15 @@ import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.content.ContextCompat
|
||||
import sushi.hardcore.droidfs.ConstValues.Companion.getAssociatedDrawable
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
||||
import sushi.hardcore.droidfs.R
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.widgets.ThemeColor
|
||||
import java.text.DateFormat
|
||||
import java.util.*
|
||||
|
||||
class ExplorerElementAdapter(private val context: Context) : BaseAdapter() {
|
||||
private val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, context.resources.configuration.locale)
|
||||
private val dateFormat: DateFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.getDefault())
|
||||
private lateinit var explorerElements: List<ExplorerElement>
|
||||
private val inflater: LayoutInflater = LayoutInflater.from(context)
|
||||
val selectedItems: MutableList<Int> = ArrayList()
|
||||
@ -44,7 +44,11 @@ class ExplorerElementAdapter(private val context: Context) : BaseAdapter() {
|
||||
textElementName.text = currentElement.name
|
||||
val textElementMtime = view.findViewById<TextView>(R.id.text_element_mtime)
|
||||
val textElementSize = view.findViewById<TextView>(R.id.text_element_size)
|
||||
if (!currentElement.isParentFolder){
|
||||
textElementSize.text = PathUtils.formatSize(currentElement.size)
|
||||
} else {
|
||||
textElementSize.text = ""
|
||||
}
|
||||
var drawableId = R.drawable.icon_folder
|
||||
when {
|
||||
currentElement.isDirectory -> {
|
||||
@ -55,12 +59,11 @@ class ExplorerElementAdapter(private val context: Context) : BaseAdapter() {
|
||||
}
|
||||
else -> {
|
||||
textElementMtime.text = dateFormat.format(currentElement.mTime)
|
||||
textElementSize.text = PathUtils.formatSize(currentElement.size)
|
||||
drawableId = getAssociatedDrawable(currentElement.name)
|
||||
}
|
||||
}
|
||||
val elementIcon = view.findViewById<ImageView>(R.id.icon_element)
|
||||
val icon = context.getDrawable(drawableId)
|
||||
val icon = ContextCompat.getDrawable(context, drawableId)
|
||||
icon?.colorFilter = PorterDuffColorFilter(themeColor, PorterDuff.Mode.SRC_IN)
|
||||
elementIcon.setImageDrawable(icon)
|
||||
if (selectedItems.contains(position)) {
|
||||
|
@ -141,7 +141,6 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
}
|
||||
.setTitle(getString(R.string.open_as))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create()
|
||||
.show()
|
||||
}
|
||||
}
|
||||
@ -180,9 +179,18 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
current_path_text.text = getString(R.string.location, currentDirectoryPath)
|
||||
Thread{
|
||||
var totalSize: Long = 0
|
||||
for (e in gocryptfsVolume.recursiveMapFiles(currentDirectoryPath)){
|
||||
if (e.isRegularFile){
|
||||
totalSize += e.size
|
||||
for (element in explorerElements){
|
||||
if (element.isDirectory){
|
||||
var dirSize: Long = 0
|
||||
for (subFile in gocryptfsVolume.recursiveMapFiles(element.fullPath)){
|
||||
if (subFile.isRegularFile){
|
||||
dirSize += subFile.size
|
||||
}
|
||||
}
|
||||
element.size = dirSize
|
||||
totalSize += dirSize
|
||||
} else if (element.isRegularFile) {
|
||||
totalSize += element.size
|
||||
}
|
||||
}
|
||||
total_size_text.text = getString(R.string.total_size, PathUtils.formatSize(totalSize))
|
||||
|
@ -129,7 +129,6 @@ class ExplorerActivity : BaseExplorerActivity() {
|
||||
}
|
||||
.setTitle(getString(R.string.fab_dialog_title))
|
||||
.setNegativeButton(R.string.cancel, null)
|
||||
.create()
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ package sushi.hardcore.droidfs.explorers
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import java.util.*
|
||||
|
||||
class ExplorerElement(val name: String, val elementType: Short, val size: Long, mtime: Long, private val parentPath: String) {
|
||||
class ExplorerElement(val name: String, val elementType: Short, var size: Long, mtime: Long, parentPath: String) {
|
||||
val mTime = Date((mtime * 1000).toString().toLong())
|
||||
val fullPath: String = PathUtils.path_join(parentPath, name)
|
||||
|
||||
|
@ -65,6 +65,7 @@ class ImageViewer: FileViewerActivity() {
|
||||
for ((i, e) in mappedImages.withIndex()){
|
||||
if (filePath == e.fullPath){
|
||||
currentMappedImageIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
wasMapped = true
|
||||
|
@ -10,7 +10,7 @@ object MiscUtils {
|
||||
}
|
||||
fun decrementIndex(index: Int, list: List<Any>): Int {
|
||||
var i = index-1
|
||||
if (i <= 0){
|
||||
if (i < 0){
|
||||
i = list.size-1
|
||||
}
|
||||
return i
|
||||
|
5
app/src/main/res/drawable/icon_grid_on.xml
Normal file
5
app/src/main/res/drawable/icon_grid_on.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20,2L4,2c-1.1,0 -2,0.9 -2,2v16c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM8,20L4,20v-4h4v4zM8,14L4,14v-4h4v4zM8,8L4,8L4,4h4v4zM14,20h-4v-4h4v4zM14,14h-4v-4h4v4zM14,8h-4L10,4h4v4zM20,20h-4v-4h4v4zM20,14h-4v-4h4v4zM20,8h-4L16,4h4v4z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/icon_hdr_off.xml
Normal file
5
app/src/main/res/drawable/icon_hdr_off.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M17.5,15v-2h1.1l0.9,2L21,15l-0.9,-2.1c0.5,-0.2 0.9,-0.8 0.9,-1.4v-1c0,-0.8 -0.7,-1.5 -1.5,-1.5L16,9v4.9l1.1,1.1h0.4zM17.5,10.5h2v1h-2v-1zM13,10.5v0.4l1.5,1.5v-1.9c0,-0.8 -0.7,-1.5 -1.5,-1.5h-1.9l1.5,1.5h0.4zM9.5,9.5l-7,-7 -1.1,1L6.9,9h-0.4v2h-2L4.5,9L3,9v6h1.5v-2.5h2L6.5,15L8,15v-4.9l1.5,1.5L9.5,15h3.4l7.6,7.6 1.1,-1.1 -12.1,-12z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/icon_hdr_on.xml
Normal file
5
app/src/main/res/drawable/icon_hdr_on.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M21,11.5v-1c0,-0.8 -0.7,-1.5 -1.5,-1.5L16,9v6h1.5v-2h1.1l0.9,2L21,15l-0.9,-2.1c0.5,-0.3 0.9,-0.8 0.9,-1.4zM19.5,11.5h-2v-1h2v1zM6.5,11h-2L4.5,9L3,9v6h1.5v-2.5h2L6.5,15L8,15L8,9L6.5,9v2zM13,9L9.5,9v6L13,15c0.8,0 1.5,-0.7 1.5,-1.5v-3c0,-0.8 -0.7,-1.5 -1.5,-1.5zM13,13.5h-2v-3h2v3z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/icon_photo_filter.xml
Normal file
5
app/src/main/res/drawable/icon_photo_filter.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FFFFFF"
|
||||
android:viewportHeight="24" android:viewportWidth="24"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="@android:color/white" android:pathData="M19.02,10v9L5,19L5,5h9L14,3L5.02,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2v-9h-2zM17,10l0.94,-2.06L20,7l-2.06,-0.94L17,4l-0.94,2.06L14,7l2.06,0.94zM13.25,10.75L12,8l-1.25,2.75L8,12l2.75,1.25L12,16l1.25,-2.75L16,12z"/>
|
||||
</vector>
|
@ -11,24 +11,62 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:cameraGesturePinch="zoom"
|
||||
app:cameraGestureTap="autoFocus"
|
||||
app:cameraAutoFocusMarker="@string/cameraview_default_autofocus_marker"
|
||||
app:cameraHdr="on"
|
||||
app:cameraPictureFormat="jpeg"
|
||||
app:cameraAudio="off"/>
|
||||
|
||||
<RelativeLayout
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:layout_alignParentTop="true"
|
||||
android:layout_marginTop="20dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_hdr"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:onClick="onClickHDR"
|
||||
android:src="@drawable/icon_hdr_on"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/image_timer"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_timer"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:onClick="onClickTimer"
|
||||
android:src="@drawable/icon_timer"
|
||||
android:layout_centerInParent="true"
|
||||
android:onClick="onClickTimer"/>
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/image_grid"
|
||||
app:layout_constraintStart_toEndOf="@id/image_hdr"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</RelativeLayout>
|
||||
<ImageView
|
||||
android:id="@+id/image_grid"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:onClick="onClickGrid"
|
||||
android:src="@drawable/icon_grid_on"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/image_filter"
|
||||
app:layout_constraintStart_toEndOf="@+id/image_timer"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image_filter"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="30dp"
|
||||
android:onClick="onClickFilter"
|
||||
android:src="@drawable/icon_photo_filter"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/image_grid"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/text_timer"
|
||||
|
@ -155,4 +155,10 @@
|
||||
<string name="move_failed">Move of %s failed.</string>
|
||||
<string name="move_success_msg">The selected items have been successfully moved.</string>
|
||||
<string name="move_success">Move successful !</string>
|
||||
<string name="enter_timer_duration">Enter the timer duration (in s)</string>
|
||||
<string name="grid_none">None</string>
|
||||
<string name="grid_3x3">3x3</string>
|
||||
<string name="grid_4x4">4x4</string>
|
||||
<string name="choose_grid">Choose grid</string>
|
||||
<string name="choose_filter">Choose filter</string>
|
||||
</resources>
|
||||
|
Loading…
Reference in New Issue
Block a user