DroidFS/app/src/main/java/sushi/hardcore/droidfs/CameraActivity.kt

228 lines
8.8 KiB
Kotlin
Raw Normal View History

2020-08-05 14:06:54 +02:00
package sushi.hardcore.droidfs
2020-08-12 15:14:38 +02:00
import android.content.Intent
2020-08-09 15:27:31 +02:00
import android.graphics.Color
2020-08-05 14:06:54 +02:00
import android.os.Bundle
2020-08-09 15:27:31 +02:00
import android.text.InputType
2020-08-05 14:06:54 +02:00
import android.view.View
2020-08-09 15:27:31 +02:00
import android.view.WindowManager
import android.widget.EditText
2020-08-05 14:06:54 +02:00
import android.widget.Toast
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
2020-08-05 14:06:54 +02:00
import kotlinx.android.synthetic.main.activity_camera.*
import sushi.hardcore.droidfs.provider.RestrictedFileProvider
2020-08-05 14:06:54 +02:00
import sushi.hardcore.droidfs.util.GocryptfsVolume
import sushi.hardcore.droidfs.util.MiscUtils
import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
import java.io.ByteArrayInputStream
import java.text.SimpleDateFormat
import java.util.*
class CameraActivity : BaseActivity() {
2020-08-05 14:06:54 +02:00
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()
2020-08-05 14:06:54 +02:00
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
2020-08-09 15:27:31 +02:00
private var timerDuration = 0
set(value) {
field = value
if (value > 0){
2020-08-12 15:14:38 +02:00
image_timer.setImageResource(R.drawable.icon_timer_on)
2020-08-09 15:27:31 +02:00
} else {
2020-08-12 15:14:38 +02:00
image_timer.setImageResource(R.drawable.icon_timer_off)
2020-08-09 15:27:31 +02:00
}
}
2020-08-05 14:06:54 +02:00
private lateinit var gocryptfsVolume: GocryptfsVolume
private lateinit var outputDirectory: String
private lateinit var fileName: String
private var isFinishingIntentionally = false
2020-08-05 14:06:54 +02:00
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_camera)
gocryptfsVolume = GocryptfsVolume(intent.getIntExtra("sessionID", -1))
outputDirectory = intent.getStringExtra("path")!!
camera.setLifecycleOwner(this)
camera.addCameraListener(object: CameraListener(){
override fun onPictureTaken(result: PictureResult) {
take_photo_button.onPhotoTaken()
val inputStream = ByteArrayInputStream(result.data)
if (gocryptfsVolume.importFile(inputStream, PathUtils.path_join(outputDirectory, fileName))){
Toast.makeText(applicationContext, getString(R.string.picture_save_success, fileName), Toast.LENGTH_SHORT).show()
} else {
ColoredAlertDialogBuilder(applicationContext)
.setTitle(R.string.error)
.setMessage(R.string.picture_save_failed)
.setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> finish() }
.show()
}
}
})
take_photo_button.onClick = ::onClickTakePhoto
}
private fun takePhoto() {
if (currentFilterIndex != 0){
camera.takePictureSnapshot()
} else {
camera.takePicture()
}
}
2020-08-05 14:06:54 +02:00
private fun onClickTakePhoto() {
val baseName = "IMG_"+dateFormat.format(Date())+"_"
do {
fileName = baseName+(random.nextInt(fileNameRandomMax-fileNameRandomMin)+fileNameRandomMin)+".jpg"
} while (gocryptfsVolume.pathExists(fileName))
2020-08-09 15:27:31 +02:00
if (timerDuration > 0){
text_timer.visibility = View.VISIBLE
Thread{
for (i in timerDuration downTo 1){
runOnUiThread { text_timer.text = i.toString() }
Thread.sleep(1000)
}
runOnUiThread {
takePhoto()
2020-08-09 15:27:31 +02:00
text_timer.visibility = View.GONE
}
}.start()
} else {
takePhoto()
2020-08-09 15:27:31 +02:00
}
2020-08-05 14:06:54 +02:00
}
fun onClickFlash(view: View) {
currentFlashModeIndex = MiscUtils.incrementIndex(currentFlashModeIndex, flashModes)
camera.flash = flashModes[currentFlashModeIndex]
image_flash.setImageResource(when (camera.flash) {
Flash.AUTO -> R.drawable.icon_flash_auto
Flash.ON -> R.drawable.icon_flash_on
else -> R.drawable.icon_flash_off
})
}
fun onClickCameraSwitch(view: View) {
camera.toggleFacing()
if (camera.facing == Facing.FRONT){
image_camera_switch.setImageResource(R.drawable.icon_camera_back)
} else {
image_camera_switch.setImageResource(R.drawable.icon_camera_front)
Thread {
Thread.sleep(25)
camera.flash = flashModes[currentFlashModeIndex] //refresh flash mode after switching camera
}.start()
}
}
2020-08-09 15:27:31 +02:00
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
}
}
}
2020-08-09 15:27:31 +02:00
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(getString(R.string.enter_timer_duration))
2020-08-09 15:27:31 +02:00
.setPositiveButton(R.string.ok) { _, _ ->
2020-08-12 15:14:38 +02:00
val enteredValue = dialogEditText.text.toString()
if (enteredValue.isEmpty()){
Toast.makeText(this, getString(R.string.timer_empty_error_msg), Toast.LENGTH_SHORT).show()
} else {
timerDuration = enteredValue.toInt()
}
2020-08-09 15:27:31 +02:00
}
.setNegativeButton(R.string.cancel, null)
.create()
dialogEditText.setOnEditorActionListener { _, _, _ ->
timerDuration = dialogEditText.text.toString().toInt()
dialog.dismiss()
true
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
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]
2020-08-12 15:14:38 +02:00
image_grid.setImageResource(if (camera.grid == Grid.OFF){ R.drawable.icon_grid_off } else { R.drawable.icon_grid_on })
dialog.dismiss()
}
.setNegativeButton(R.string.cancel, null)
.show()
}
2020-08-12 15:14:38 +02:00
private fun openFilterDialog(){
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()
}
2020-08-12 15:14:38 +02:00
fun onClickFilter(view: View) {
if (sharedPrefs.getBoolean("filtersFirstOpening", true)){
ColoredAlertDialogBuilder(this)
.setTitle(R.string.warning)
.setMessage(R.string.filters_warning)
.setPositiveButton(R.string.ok){ _, _ ->
sharedPrefs.edit().putBoolean("filtersFirstOpening", false).apply()
openFilterDialog()
}
.setNegativeButton(R.string.cancel, null)
.show()
} else {
openFilterDialog()
}
}
override fun onDestroy() {
super.onDestroy()
if (!isFinishingIntentionally) {
gocryptfsVolume.close()
RestrictedFileProvider.wipeAll(this)
}
}
override fun onPause() {
super.onPause()
finish()
}
override fun onBackPressed() {
super.onBackPressed()
isFinishingIntentionally = true
}
2020-08-05 14:06:54 +02:00
}