Take Photo feature

This commit is contained in:
Hardcore Sushi 2020-08-05 14:06:54 +02:00
parent 03d5b468f2
commit 0bfb952365
48 changed files with 564 additions and 394 deletions

View File

@ -15,7 +15,7 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 29 targetSdkVersion 29
versionCode 1 versionCode 1
versionName "1.1.2" versionName "1.1.3"
ndk { ndk {
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a' abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
@ -40,15 +40,16 @@ android {
dependencies { dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"]) implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1' implementation "androidx.core:core-ktx:1.3.1"
implementation 'androidx.appcompat:appcompat:1.1.0' implementation "androidx.appcompat:appcompat:1.1.0"
testImplementation 'junit:junit:4.12' implementation "androidx.constraintlayout:constraintlayout:1.1.3"
implementation 'androidx.sqlite:sqlite:2.1.0' implementation "androidx.sqlite:sqlite:2.1.0"
implementation 'androidx.preference:preference:1.1.1' implementation "androidx.preference:preference:1.1.1"
implementation 'com.github.clans:fab:1.6.4' implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
implementation 'com.jaredrummler:cyanea:1.0.2' implementation "com.jaredrummler:cyanea:1.0.2"
implementation 'com.github.bumptech.glide:glide:4.11.0' implementation "com.github.bumptech.glide:glide:4.11.0"
implementation 'com.google.android.exoplayer:exoplayer-core:2.11.7' implementation "com.google.android.exoplayer:exoplayer-core:2.11.7"
implementation 'com.google.android.exoplayer:exoplayer-ui:2.11.7' implementation "com.google.android.exoplayer:exoplayer-ui:2.11.7"
implementation "com.otaliastudios:cameraview:2.6.3"
} }

View File

@ -4,25 +4,27 @@
<permission <permission
android:name="${applicationId}.WRITE_TEMPORARY_STORAGE" android:name="${applicationId}.WRITE_TEMPORARY_STORAGE"
android:protectionLevel="signature"/> android:protectionLevel="signature" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" /> <uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" /> <uses-permission android:name="android.permission.USE_BIOMETRIC" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<application <application
android:name=".ColoredApplication" android:name=".ColoredApplication"
android:allowBackup="false" android:allowBackup="false"
android:icon="@mipmap/icon_launcher" android:icon="@mipmap/icon_launcher"
android:label="@string/app_name" android:label="@string/app_name"
android:requestLegacyExternalStorage="true"
android:supportsRtl="true" android:supportsRtl="true"
android:theme="@style/AppTheme" android:theme="@style/AppTheme">
android:requestLegacyExternalStorage="true"> <activity android:name=".CameraActivity"/>
<activity <activity
android:name=".SettingsActivity" android:name=".SettingsActivity"
android:label="@string/title_activity_settings" android:label="@string/title_activity_settings"
android:parentActivityName=".MainActivity"/> android:parentActivityName=".MainActivity" />
<activity android:name=".explorers.ExplorerActivity" /> <activity android:name=".explorers.ExplorerActivity" />
<activity android:name=".explorers.ExplorerActivityPick" /> <activity android:name=".explorers.ExplorerActivityPick" />
<activity android:name=".explorers.ExplorerActivityDrop" /> <activity android:name=".explorers.ExplorerActivityDrop" />
@ -34,7 +36,9 @@
<intent-filter android:label="@string/share_menu_label"> <intent-filter android:label="@string/share_menu_label">
<action android:name="android.intent.action.SEND" /> <action android:name="android.intent.action.SEND" />
<action android:name="android.intent.action.SEND_MULTIPLE" /> <action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="*/*" /> <data android:mimeType="*/*" />
</intent-filter> </intent-filter>
</activity> </activity>
@ -52,19 +56,28 @@
android:screenOrientation="nosensor"> android:screenOrientation="nosensor">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name=".file_viewers.ImageViewer" android:configChanges="screenSize|orientation" /> <!-- don't reload content on configuration change --> <activity
<activity android:name=".file_viewers.VideoPlayer" android:configChanges="screenSize|orientation" /> android:name=".file_viewers.ImageViewer"
<activity android:name=".file_viewers.AudioPlayer" android:configChanges="screenSize|orientation" /> android:configChanges="screenSize|orientation" /> <!-- don't reload content on configuration change -->
<activity android:name=".file_viewers.TextEditor" android:configChanges="screenSize|orientation" /> <activity
android:name=".file_viewers.VideoPlayer"
android:configChanges="screenSize|orientation" />
<activity
android:name=".file_viewers.AudioPlayer"
android:configChanges="screenSize|orientation" />
<activity
android:name=".file_viewers.TextEditor"
android:configChanges="screenSize|orientation" />
<provider <provider
android:name=".provider.RestrictedFileProvider" android:name=".provider.RestrictedFileProvider"
android:authorities="${applicationId}.temporary_provider" android:authorities="${applicationId}.temporary_provider"
android:exported="true" android:exported="true"
android:writePermission="${applicationId}.WRITE_TEMPORARY_STORAGE"/> android:writePermission="${applicationId}.WRITE_TEMPORARY_STORAGE" />
</application> </application>
</manifest> </manifest>

View File

@ -0,0 +1,89 @@
package sushi.hardcore.droidfs
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
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 kotlinx.android.synthetic.main.activity_camera.*
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.io.FileOutputStream
import java.io.InputStream
import java.text.SimpleDateFormat
import java.util.*
class CameraActivity : AppCompatActivity() {
companion object {
private val flashModes = listOf(Flash.AUTO, Flash.ON, Flash.OFF)
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 lateinit var gocryptfsVolume: GocryptfsVolume
private lateinit var outputDirectory: String
private lateinit var fileName: String
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 onClickTakePhoto() {
val baseName = "IMG_"+dateFormat.format(Date())+"_"
do {
fileName = baseName+(random.nextInt(fileNameRandomMax-fileNameRandomMin)+fileNameRandomMin)+".jpg"
} while (gocryptfsVolume.pathExists(fileName))
camera.takePicture()
}
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()
}
}
}

View File

@ -113,15 +113,4 @@ class ExplorerElementAdapter(private val context: Context) : BaseAdapter() {
unSelectAll() unSelectAll()
this.explorerElements = explorer_elements this.explorerElements = explorer_elements
} }
val currentDirectoryTotalSize: Long
get() {
var totalSize: Long = 0
for (e in explorerElements) {
if (e.isRegularFile) {
totalSize += e.size
}
}
return totalSize
}
} }

View File

@ -0,0 +1,32 @@
package sushi.hardcore.droidfs.adapters
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.BaseAdapter
import android.widget.TextView
import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.widgets.ColoredImageView
open class IconTextDialogAdapter(private val context: Context): BaseAdapter() {
private val inflater: LayoutInflater = LayoutInflater.from(context)
lateinit var items: List<List<Any>>
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
val view: View = convertView ?: inflater.inflate(R.layout.adapter_dialog_icon_text, parent, false)
val text = view.findViewById<TextView>(R.id.text)
text.text = context.getString(items[position][1] as Int)
val icon = view.findViewById<ColoredImageView>(R.id.icon)
icon.setImageDrawable(context.getDrawable(items[position][2] as Int))
return view
}
override fun getItem(position: Int): Any {
return items[position][0] as String
}
override fun getItemId(position: Int): Long { return 0 }
override fun getCount(): Int { return items.size }
}

View File

@ -1,36 +1,24 @@
package sushi.hardcore.droidfs.adapters package sushi.hardcore.droidfs.adapters
import android.content.Context import android.content.Context
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.BaseAdapter import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.widget.LinearLayoutCompat
import androidx.core.view.marginEnd
import androidx.core.view.setPadding
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.widgets.ColoredImageView import sushi.hardcore.droidfs.widgets.ColoredImageView
class OpenAsDialogAdapter(private val context: Context): BaseAdapter() { class OpenAsDialogAdapter(context: Context) : IconTextDialogAdapter(context) {
private val inflater: LayoutInflater = LayoutInflater.from(context) private val openAsItems = listOf(
private val items = listOf( listOf("image", R.string.image, R.drawable.icon_file_image),
listOf("image", context.getString(R.string.image), R.drawable.icon_file_image), listOf("video", R.string.video, R.drawable.icon_file_video),
listOf("video", context.getString(R.string.video), R.drawable.icon_file_video), listOf("audio", R.string.audio, R.drawable.icon_file_audio),
listOf("audio", context.getString(R.string.audio), R.drawable.icon_file_audio), listOf("text", R.string.text, R.drawable.icon_file_text)
listOf("text", context.getString(R.string.text), R.drawable.icon_file_text)
) )
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { init {
val view: View = convertView ?: inflater.inflate(R.layout.adapter_dialog_icon_text, parent, false) items = openAsItems
val text = view.findViewById<TextView>(R.id.text)
text.text = items[position][1] as String
val icon = view.findViewById<ColoredImageView>(R.id.icon)
icon.setImageDrawable(context.getDrawable(items[position][2] as Int))
return view
} }
override fun getItem(position: Int): String {
return items[position][0] as String
}
override fun getItemId(position: Int): Long { return 0 }
override fun getCount(): Int { return items.size }
} }

View File

@ -13,33 +13,35 @@ import sushi.hardcore.droidfs.ConstValues
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.util.WidgetUtil import sushi.hardcore.droidfs.util.WidgetUtil
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
import sushi.hardcore.droidfs.widgets.NonScrollableColoredBorderListView
import java.util.* import java.util.*
class SavedVolumesAdapter(val context: Context, val shared_prefs: SharedPreferences) : BaseAdapter() { class SavedVolumesAdapter(val context: Context, private val sharedPrefs: SharedPreferences) : BaseAdapter() {
private val inflater: LayoutInflater = LayoutInflater.from(context) private val inflater: LayoutInflater = LayoutInflater.from(context)
private val saved_volumes_paths: MutableList<String> = ArrayList() private lateinit var nonScrollableColoredBorderListView: NonScrollableColoredBorderListView
private val shared_prefs_editor: Editor = shared_prefs.edit() private val savedVolumesPaths: MutableList<String> = ArrayList()
private val sharedPrefsEditor: Editor = sharedPrefs.edit()
init { init {
val saved_volumes_paths_set = shared_prefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set<String> val savedVolumesPathsSet = sharedPrefs.getStringSet(ConstValues.saved_volumes_key, HashSet()) as Set<String>
for (volume_path in saved_volumes_paths_set) { for (volume_path in savedVolumesPathsSet) {
saved_volumes_paths.add(volume_path) savedVolumesPaths.add(volume_path)
} }
} }
private fun update_shared_prefs() { private fun updateSharedPrefs() {
val saved_volumes_paths_set = saved_volumes_paths.toSet() val savedVolumesPathsSet = savedVolumesPaths.toSet()
shared_prefs_editor.remove(ConstValues.saved_volumes_key) sharedPrefsEditor.remove(ConstValues.saved_volumes_key)
shared_prefs_editor.putStringSet(ConstValues.saved_volumes_key, saved_volumes_paths_set) sharedPrefsEditor.putStringSet(ConstValues.saved_volumes_key, savedVolumesPathsSet)
shared_prefs_editor.apply() sharedPrefsEditor.apply()
} }
override fun getCount(): Int { override fun getCount(): Int {
return saved_volumes_paths.size return savedVolumesPaths.size
} }
override fun getItem(position: Int): String { override fun getItem(position: Int): String {
return saved_volumes_paths[position] return savedVolumesPaths[position]
} }
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
@ -47,32 +49,35 @@ class SavedVolumesAdapter(val context: Context, val shared_prefs: SharedPreferen
} }
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View { override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
if (!::nonScrollableColoredBorderListView.isInitialized){
nonScrollableColoredBorderListView = parent as NonScrollableColoredBorderListView
}
val view: View = convertView ?: inflater.inflate(R.layout.adapter_saved_volume, parent, false) val view: View = convertView ?: inflater.inflate(R.layout.adapter_saved_volume, parent, false)
val volume_name_textview = view.findViewById<TextView>(R.id.volume_name_textview) val volumeNameTextview = view.findViewById<TextView>(R.id.volume_name_textview)
val currentVolume = getItem(position) val currentVolume = getItem(position)
volume_name_textview.text = currentVolume volumeNameTextview.text = currentVolume
val delete_imageview = view.findViewById<ImageView>(R.id.delete_imageview) val deleteImageview = view.findViewById<ImageView>(R.id.delete_imageview)
delete_imageview.setOnClickListener { deleteImageview.setOnClickListener {
val volume_path = saved_volumes_paths[position] val volumePath = savedVolumesPaths[position]
val dialog = ColoredAlertDialogBuilder(context) val dialog = ColoredAlertDialogBuilder(context)
dialog.setTitle(R.string.warning) dialog.setTitle(R.string.warning)
if (shared_prefs.getString(volume_path, null) != null){ if (sharedPrefs.getString(volumePath, null) != null){
dialog.setMessage(context.getString(R.string.delete_hash_or_all)) dialog.setMessage(context.getString(R.string.delete_hash_or_all))
dialog.setPositiveButton(context.getString(R.string.delete_all)) { _, _ -> dialog.setPositiveButton(context.getString(R.string.delete_all)) { _, _ ->
saved_volumes_paths.removeAt(position) savedVolumesPaths.removeAt(position)
shared_prefs_editor.remove(volume_path) sharedPrefsEditor.remove(volumePath)
update_shared_prefs() updateSharedPrefs()
refresh(parent) refresh(parent)
} }
dialog.setNegativeButton(context.getString(R.string.delete_hash)) { _, _ -> dialog.setNegativeButton(context.getString(R.string.delete_hash)) { _, _ ->
shared_prefs_editor.remove(volume_path) sharedPrefsEditor.remove(volumePath)
shared_prefs_editor.apply() sharedPrefsEditor.apply()
} }
} else { } else {
dialog.setMessage(context.getString(R.string.ask_delete_volume_path)) dialog.setMessage(context.getString(R.string.ask_delete_volume_path))
dialog.setPositiveButton(R.string.ok) {_, _ -> dialog.setPositiveButton(R.string.ok) {_, _ ->
saved_volumes_paths.removeAt(position) savedVolumesPaths.removeAt(position)
update_shared_prefs() updateSharedPrefs()
refresh(parent) refresh(parent)
} }
dialog.setNegativeButton(R.string.cancel, null) dialog.setNegativeButton(R.string.cancel, null)
@ -86,13 +91,15 @@ class SavedVolumesAdapter(val context: Context, val shared_prefs: SharedPreferen
notifyDataSetChanged() notifyDataSetChanged()
if (count == 0){ if (count == 0){
WidgetUtil.hide(parent) WidgetUtil.hide(parent)
} else {
nonScrollableColoredBorderListView.layoutParams.height = nonScrollableColoredBorderListView.computeHeight()
} }
} }
fun addVolumePath(volume_path: String) { fun addVolumePath(volume_path: String) {
if (!saved_volumes_paths.contains(volume_path)) { if (!savedVolumesPaths.contains(volume_path)) {
saved_volumes_paths.add(volume_path) savedVolumesPaths.add(volume_path)
update_shared_prefs() updateSharedPrefs()
} }
} }
} }

View File

@ -23,16 +23,16 @@ import sushi.hardcore.droidfs.ConstValues.Companion.isText
import sushi.hardcore.droidfs.ConstValues.Companion.isVideo import sushi.hardcore.droidfs.ConstValues.Companion.isVideo
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.adapters.DialogSingleChoiceAdapter import sushi.hardcore.droidfs.adapters.DialogSingleChoiceAdapter
import sushi.hardcore.droidfs.adapters.OpenAsDialogAdapter
import sushi.hardcore.droidfs.adapters.ExplorerElementAdapter import sushi.hardcore.droidfs.adapters.ExplorerElementAdapter
import sushi.hardcore.droidfs.adapters.OpenAsDialogAdapter
import sushi.hardcore.droidfs.file_viewers.AudioPlayer import sushi.hardcore.droidfs.file_viewers.AudioPlayer
import sushi.hardcore.droidfs.file_viewers.ImageViewer import sushi.hardcore.droidfs.file_viewers.ImageViewer
import sushi.hardcore.droidfs.file_viewers.TextEditor import sushi.hardcore.droidfs.file_viewers.TextEditor
import sushi.hardcore.droidfs.file_viewers.VideoPlayer import sushi.hardcore.droidfs.file_viewers.VideoPlayer
import sushi.hardcore.droidfs.provider.RestrictedFileProvider import sushi.hardcore.droidfs.provider.RestrictedFileProvider
import sushi.hardcore.droidfs.util.ExternalProvider import sushi.hardcore.droidfs.util.ExternalProvider
import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.util.GocryptfsVolume import sushi.hardcore.droidfs.util.GocryptfsVolume
import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
open class BaseExplorerActivity : BaseActivity() { open class BaseExplorerActivity : BaseActivity() {
@ -49,6 +49,7 @@ open class BaseExplorerActivity : BaseActivity() {
} }
protected lateinit var explorerElements: MutableList<ExplorerElement> protected lateinit var explorerElements: MutableList<ExplorerElement>
protected lateinit var explorerAdapter: ExplorerElementAdapter protected lateinit var explorerAdapter: ExplorerElementAdapter
private var isCreating = true
private var usf_open = false private var usf_open = false
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -100,7 +101,7 @@ open class BaseExplorerActivity : BaseActivity() {
explorerAdapter.onItemClick(position) explorerAdapter.onItemClick(position)
if (explorerAdapter.selectedItems.isEmpty()) { if (explorerAdapter.selectedItems.isEmpty()) {
if (!wasSelecting) { if (!wasSelecting) {
val fullPath = explorerElements[position].getFullPath() val fullPath = explorerElements[position].fullPath
when { when {
explorerElements[position].isDirectory -> { explorerElements[position].isDirectory -> {
setCurrentPath(fullPath) setCurrentPath(fullPath)
@ -171,7 +172,15 @@ open class BaseExplorerActivity : BaseActivity() {
explorerAdapter.setExplorerElements(explorerElements) explorerAdapter.setExplorerElements(explorerElements)
currentDirectoryPath = path currentDirectoryPath = path
current_path_text.text = getString(R.string.location, currentDirectoryPath) current_path_text.text = getString(R.string.location, currentDirectoryPath)
total_size_text.text = getString(R.string.total_size, PathUtils.formatSize(explorerAdapter.currentDirectoryTotalSize)) Thread{
var totalSize: Long = 0
for (e in gocryptfsVolume.recursiveMapFiles(currentDirectoryPath)){
if (e.isRegularFile){
totalSize += e.size
}
}
total_size_text.text = getString(R.string.total_size, PathUtils.formatSize(totalSize))
}.start()
} }
private fun askCloseVolume() { private fun askCloseVolume() {
@ -222,8 +231,7 @@ open class BaseExplorerActivity : BaseActivity() {
} }
} }
fun onClickAddFolder(view: View?) { protected fun openDialogCreateFolder() {
findViewById<FloatingActionMenu>(R.id.fam_explorer).close(true)
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null) val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text) val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
val dialog = ColoredAlertDialogBuilder(this) val dialog = ColoredAlertDialogBuilder(this)
@ -245,7 +253,7 @@ open class BaseExplorerActivity : BaseActivity() {
dialog.show() dialog.show()
} }
fun rename(old_name: String, new_name: String){ protected fun rename(old_name: String, new_name: String){
if (new_name.isEmpty()) { if (new_name.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 {
@ -262,7 +270,7 @@ open class BaseExplorerActivity : BaseActivity() {
} }
} }
fun handleMenuItems(menu: Menu){ protected fun handleMenuItems(menu: Menu){
menu.findItem(R.id.rename).isVisible = false menu.findItem(R.id.rename).isVisible = false
if (usf_open){ if (usf_open){
menu.findItem(R.id.external_open)?.isVisible = false menu.findItem(R.id.external_open)?.isVisible = false
@ -350,6 +358,10 @@ open class BaseExplorerActivity : BaseActivity() {
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
ExternalProvider.removeFiles(this) if (isCreating){
isCreating = false
} else {
ExternalProvider.removeFiles(this)
}
} }
} }

View File

@ -10,11 +10,10 @@ import android.view.WindowManager
import android.widget.EditText import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import com.github.clans.fab.FloatingActionButton import sushi.hardcore.droidfs.CameraActivity
import com.github.clans.fab.FloatingActionMenu
import kotlinx.android.synthetic.main.activity_explorer.*
import sushi.hardcore.droidfs.OpenActivity import sushi.hardcore.droidfs.OpenActivity
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.adapters.IconTextDialogAdapter
import sushi.hardcore.droidfs.util.* import sushi.hardcore.droidfs.util.*
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
import java.io.File import java.io.File
@ -59,43 +58,71 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
} }
fun onClickCreateFile(view: View) { fun onClickFAB(view: View) {
findViewById<FloatingActionMenu>(R.id.fam_explorer).close(true) if (modeSelectLocation){
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null) openDialogCreateFolder()
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text) } else {
val dialog = ColoredAlertDialogBuilder(this) val adapter = IconTextDialogAdapter(this)
.setView(dialogEditTextView) adapter.items = listOf(
.setTitle(getString(R.string.enter_file_name)) listOf("importFromOtherVolumes", R.string.import_from_other_volume, R.drawable.icon_transfert),
.setPositiveButton(R.string.ok) { _, _ -> listOf("importFiles", R.string.import_files, R.drawable.icon_encrypt),
val fileName = dialogEditText.text.toString() listOf("createFile", R.string.new_file, R.drawable.icon_file_unknown),
createNewFile(fileName) listOf("createFolder", R.string.mkdir, R.drawable.icon_folder),
} listOf("takePhoto", R.string.take_photo, R.drawable.icon_camera)
.setNegativeButton(R.string.cancel, null) )
.create() ColoredAlertDialogBuilder(this)
dialogEditText.setOnEditorActionListener { _, _, _ -> .setSingleChoiceItems(adapter, -1){ thisDialog, which ->
val fileName = dialogEditText.text.toString() when (adapter.getItem(which)){
dialog.dismiss() "importFromOtherVolumes" -> {
createNewFile(fileName) val intent = Intent(this, OpenActivity::class.java)
true intent.action = "pick"
startActivityForResult(intent, PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE)
}
"importFiles" -> {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT)
intent.type = "*/*"
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
intent.addCategory(Intent.CATEGORY_OPENABLE)
startActivityForResult(intent, PICK_FILES_REQUEST_CODE)
}
"createFile" -> {
val dialogEditTextView = layoutInflater.inflate(R.layout.dialog_edit_text, null)
val dialogEditText = dialogEditTextView.findViewById<EditText>(R.id.dialog_edit_text)
val dialog = ColoredAlertDialogBuilder(this)
.setView(dialogEditTextView)
.setTitle(getString(R.string.enter_file_name))
.setPositiveButton(R.string.ok) { _, _ ->
val fileName = dialogEditText.text.toString()
createNewFile(fileName)
}
.setNegativeButton(R.string.cancel, null)
.create()
dialogEditText.setOnEditorActionListener { _, _, _ ->
val fileName = dialogEditText.text.toString()
dialog.dismiss()
createNewFile(fileName)
true
}
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
dialog.show()
}
"createFolder" -> {
openDialogCreateFolder()
}
"takePhoto" -> {
val intent = Intent(this, CameraActivity::class.java)
intent.putExtra("path", currentDirectoryPath)
intent.putExtra("sessionID", gocryptfsVolume.sessionID)
startActivity(intent)
}
}
thisDialog.dismiss()
}
.setTitle(getString(R.string.fab_dialog_title))
.setNegativeButton(R.string.cancel, null)
.create()
.show()
} }
dialog.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE)
dialog.show()
}
fun onClickAddFile(view: View?) {
fam_explorer.close(true)
val i = Intent(Intent.ACTION_OPEN_DOCUMENT)
i.type = "*/*"
i.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
i.addCategory(Intent.CATEGORY_OPENABLE)
startActivityForResult(i, PICK_FILES_REQUEST_CODE)
}
fun onClickAddFileFromOtherVolume(view: View?) {
fam_explorer.close(true)
val intent = Intent(this, OpenActivity::class.java)
intent.action = "pick"
startActivityForResult(intent, PICK_OTHER_VOLUME_ITEMS_REQUEST_CODE)
} }
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
@ -323,9 +350,6 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
modeSelectLocation = true modeSelectLocation = true
unselectAll() unselectAll()
findViewById<FloatingActionButton>(R.id.fab_add_file).visibility = View.GONE
findViewById<FloatingActionButton>(R.id.fab_import_file).visibility = View.GONE
findViewById<FloatingActionButton>(R.id.fab_import_file_from_other_volume).visibility = View.GONE
true true
} }
R.id.validate -> { R.id.validate -> {
@ -333,11 +357,10 @@ class ExplorerActivity : BaseExplorerActivity() {
override fun doTask(activity: AppCompatActivity) { override fun doTask(activity: AppCompatActivity) {
var failedItem: String? = null var failedItem: String? = null
for (element in filesToCopy) { for (element in filesToCopy) {
val originalPath = element.getFullPath()
failedItem = if (element.isDirectory) { failedItem = if (element.isDirectory) {
recursiveCopyDirectory(originalPath, currentDirectoryPath) recursiveCopyDirectory(element.fullPath, currentDirectoryPath)
} else { } else {
if (copyFile(originalPath, PathUtils.path_join(currentDirectoryPath, element.name))) null else originalPath if (copyFile(element.fullPath, PathUtils.path_join(currentDirectoryPath, element.name))) null else element.fullPath
} }
if (failedItem != null) { if (failedItem != null) {
stopTask { stopTask {
@ -385,7 +408,7 @@ class ExplorerActivity : BaseExplorerActivity() {
R.id.share -> { R.id.share -> {
val paths: MutableList<String> = ArrayList() val paths: MutableList<String> = ArrayList()
for (i in explorerAdapter.selectedItems) { for (i in explorerAdapter.selectedItems) {
paths.add(explorerElements[i].getFullPath()) paths.add(explorerElements[i].fullPath)
} }
ExternalProvider.share(this, gocryptfsVolume, paths) ExternalProvider.share(this, gocryptfsVolume, paths)
unselectAll() unselectAll()
@ -403,9 +426,6 @@ class ExplorerActivity : BaseExplorerActivity() {
private fun cancelCopy() { private fun cancelCopy() {
if (modeSelectLocation){ if (modeSelectLocation){
modeSelectLocation = false modeSelectLocation = false
findViewById<FloatingActionButton>(R.id.fab_add_file).visibility = View.VISIBLE
findViewById<FloatingActionButton>(R.id.fab_import_file).visibility = View.VISIBLE
findViewById<FloatingActionButton>(R.id.fab_import_file_from_other_volume).visibility = View.VISIBLE
filesToCopy.clear() filesToCopy.clear()
} }
} }
@ -457,15 +477,14 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
} }
for (e in mappedElements) { for (e in mappedElements) {
val srcPath = e.getFullPath() val dstPath = PathUtils.path_join(dstDirectoryPath, PathUtils.getRelativePath(srcDirectoryPath, e.fullPath))
val dstPath = PathUtils.path_join(dstDirectoryPath, PathUtils.getRelativePath(srcDirectoryPath, srcPath))
if (e.isDirectory) { if (e.isDirectory) {
if (!gocryptfsVolume.mkdir(dstPath)){ if (!gocryptfsVolume.mkdir(dstPath)){
return srcPath return e.fullPath
} }
} else { } else {
if (!copyFile(srcPath, dstPath)) { if (!copyFile(e.fullPath, dstPath)) {
return srcPath return e.fullPath
} }
} }
} }
@ -506,15 +525,14 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
} }
for (e in mappedElements) { for (e in mappedElements) {
val srcPath = e.getFullPath() val dstPath = PathUtils.path_join(dstDirectoryPath, PathUtils.getRelativePath(remote_directory_path, e.fullPath))
val dstPath = PathUtils.path_join(dstDirectoryPath, PathUtils.getRelativePath(remote_directory_path, srcPath))
if (e.isDirectory) { if (e.isDirectory) {
if (!gocryptfsVolume.mkdir(dstPath)){ if (!gocryptfsVolume.mkdir(dstPath)){
return srcPath return e.fullPath
} }
} else { } else {
if (!importFileFromOtherVolume(remote_gocryptfsVolume, srcPath, dstPath)) { if (!importFileFromOtherVolume(remote_gocryptfsVolume, e.fullPath, dstPath)) {
return srcPath return e.fullPath
} }
} }
} }

View File

@ -4,6 +4,7 @@ import android.content.Intent
import android.net.Uri import android.net.Uri
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
@ -13,6 +14,10 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
setContentView(R.layout.activity_explorer_drop) setContentView(R.layout.activity_explorer_drop)
} }
fun onClickFAB(view: View) {
openDialogCreateFolder()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.explorer_drop, menu) menuInflater.inflate(R.menu.explorer_drop, menu)
handleMenuItems(menu) handleMenuItems(menu)

View File

@ -5,6 +5,7 @@ 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, val size: Long, mtime: Long, private val parentPath: String) {
val mTime = Date((mtime * 1000).toString().toLong()) val mTime = Date((mtime * 1000).toString().toLong())
val fullPath: String = PathUtils.path_join(parentPath, name)
val isDirectory: Boolean val isDirectory: Boolean
get() = elementType.toInt() == 0 get() = elementType.toInt() == 0
@ -15,15 +16,11 @@ class ExplorerElement(val name: String, val elementType: Short, val size: Long,
val isRegularFile: Boolean val isRegularFile: Boolean
get() = elementType.toInt() == 1 get() = elementType.toInt() == 1
fun getFullPath(): String {
return PathUtils.path_join(parentPath, name)
}
companion object { companion object {
fun sortBy(sortOrder: String, explorerElements: MutableList<ExplorerElement>) { fun sortBy(sortOrder: String, explorerElements: MutableList<ExplorerElement>) {
when (sortOrder) { when (sortOrder) {
"name" -> { "name" -> {
explorerElements.sortWith(Comparator { o1, o2 -> o1.name.compareTo(o2.name) }) explorerElements.sortWith(Comparator { o1, o2 -> o1.fullPath.compareTo(o2.fullPath) })
} }
"size" -> { "size" -> {
explorerElements.sortWith(Comparator { o1, o2 -> (o1.size - o2.size).toInt() }) explorerElements.sortWith(Comparator { o1, o2 -> (o1.size - o2.size).toInt() })
@ -32,7 +29,7 @@ class ExplorerElement(val name: String, val elementType: Short, val size: Long,
explorerElements.sortWith(Comparator { o1, o2 -> o1.mTime.compareTo(o2.mTime) }) explorerElements.sortWith(Comparator { o1, o2 -> o1.mTime.compareTo(o2.mTime) })
} }
"name_desc" -> { "name_desc" -> {
explorerElements.sortWith(Comparator { o1, o2 -> o2.name.compareTo(o1.name) }) explorerElements.sortWith(Comparator { o1, o2 -> o2.fullPath.compareTo(o1.fullPath) })
} }
"size_desc" -> { "size_desc" -> {
explorerElements.sortWith(Comparator { o1, o2 -> (o2.size - o1.size).toInt() }) explorerElements.sortWith(Comparator { o1, o2 -> (o2.size - o1.size).toInt() })

View File

@ -13,11 +13,8 @@ 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.ConstValues
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
<<<<<<< HEAD
=======
import sushi.hardcore.droidfs.util.MiscUtils import sushi.hardcore.droidfs.util.MiscUtils
import sushi.hardcore.droidfs.explorers.ExplorerElement import sushi.hardcore.droidfs.explorers.ExplorerElement
>>>>>>> ccc453a... Sorted image swipe & ExplorerViewModel
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils
import java.security.MessageDigest import java.security.MessageDigest
import kotlin.math.abs import kotlin.math.abs
@ -66,26 +63,18 @@ class ImageViewer: FileViewerActivity() {
sortOrder = intent.getStringExtra("sortOrder") ?: "name" sortOrder = intent.getStringExtra("sortOrder") ?: "name"
ExplorerElement.sortBy(sortOrder, mappedImages) ExplorerElement.sortBy(sortOrder, mappedImages)
for ((i, e) in mappedImages.withIndex()){ for ((i, e) in mappedImages.withIndex()){
if (filePath == e.getFullPath()){ if (filePath == e.fullPath){
currentMappedImageIndex = i currentMappedImageIndex = i
} }
} }
wasMapped = true wasMapped = true
} }
if (deltaX < 0){ currentMappedImageIndex = if (deltaX < 0){
if (currentMappedImageIndex == mappedImages.size-1){ MiscUtils.incrementIndex(currentMappedImageIndex, mappedImages)
currentMappedImageIndex = 0
} else {
currentMappedImageIndex += 1
}
} else { } else {
if (currentMappedImageIndex == 0){ MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages)
currentMappedImageIndex = mappedImages.size-1
} else {
currentMappedImageIndex -= 1
}
} }
loadWholeFile(mappedImages[currentMappedImageIndex].getFullPath())?.let { loadWholeFile(mappedImages[currentMappedImageIndex].fullPath)?.let {
glideImage = Glide.with(this).load(it) glideImage = Glide.with(this).load(it)
glideImage.into(image_viewer) glideImage.into(image_viewer)
} }

View File

@ -84,6 +84,7 @@ class RestrictedFileProvider: ContentProvider() {
Wiper.wipe(file) Wiper.wipe(file)
} }
} }
dbHelper?.close()
context.deleteDatabase(DB_NAME) context.deleteDatabase(DB_NAME)
} }
@ -134,28 +135,26 @@ class RestrictedFileProvider: ContentProvider() {
} }
override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? { override fun query(uri: Uri, projection: Array<String>?, selection: String?, selectionArgs: Array<String>?, sortOrder: String?): Cursor? {
var resultCursor: MatrixCursor? = null
val temporaryFile = getFileFromUri(uri) val temporaryFile = getFileFromUri(uri)
temporaryFile?.let{ temporaryFile?.let{
val fileName = val fileName = dbHelper?.readableDatabase?.query(TABLE_FILES, arrayOf(TemporaryFileColumns.COLUMN_NAME), TemporaryFileColumns.COLUMN_UUID + "=?", arrayOf(uri.lastPathSegment), null, null, null)
dbHelper?.readableDatabase?.query(TABLE_FILES, arrayOf(TemporaryFileColumns.COLUMN_NAME), TemporaryFileColumns.COLUMN_UUID + "=?", arrayOf(uri.lastPathSegment), null, null, null)
fileName?.let{ fileName?.let{
if (fileName.moveToNext()) { if (fileName.moveToNext()) {
val cursor = MatrixCursor( resultCursor = MatrixCursor(
arrayOf( arrayOf(
MediaStore.MediaColumns.DISPLAY_NAME, MediaStore.MediaColumns.DISPLAY_NAME,
MediaStore.MediaColumns.SIZE MediaStore.MediaColumns.SIZE
) )
) )
cursor.newRow() resultCursor!!.newRow()
.add(fileName.getString(0)) .add(fileName.getString(0))
.add(temporaryFile.length()) .add(temporaryFile.length())
fileName.close()
return cursor
} }
fileName.close() fileName.close()
} }
} }
return null return resultCursor
} }
override fun delete(uri: Uri, givenSelection: String?, givenSelectionArgs: Array<String>?): Int { override fun delete(uri: Uri, givenSelection: String?, givenSelectionArgs: Array<String>?): Int {

View File

@ -166,7 +166,7 @@ class GocryptfsVolume(var sessionID: Int) {
result.addAll(explorerElements) result.addAll(explorerElements)
for (e in explorerElements){ for (e in explorerElements){
if (e.isDirectory){ if (e.isDirectory){
result.addAll(recursiveMapFiles(e.getFullPath())) result.addAll(recursiveMapFiles(e.fullPath))
} }
} }
return result return result

View File

@ -0,0 +1,18 @@
package sushi.hardcore.droidfs.util
object MiscUtils {
fun incrementIndex(index: Int, list: List<Any>): Int {
var i = index+1
if (i >= list.size){
i = 0
}
return i
}
fun decrementIndex(index: Int, list: List<Any>): Int {
var i = index-1
if (i <= 0){
i = list.size-1
}
return i
}
}

View File

@ -12,12 +12,9 @@ import androidx.core.content.ContextCompat
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
open class ColoredBorderListView: ListView { open class ColoredBorderListView: ListView {
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) { applyColor() }
applyColor() constructor(context: Context, attrs: AttributeSet): super(context, attrs) { applyColor() }
} constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) { applyColor() }
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){ private fun applyColor(){
val background = ContextCompat.getDrawable(context, R.drawable.listview_border) as StateListDrawable val background = ContextCompat.getDrawable(context, R.drawable.listview_border) as StateListDrawable
val dcs = background.constantState as DrawableContainer.DrawableContainerState val dcs = background.constantState as DrawableContainer.DrawableContainerState

View File

@ -1,18 +0,0 @@
package sushi.hardcore.droidfs.widgets
import android.content.Context
import android.content.res.ColorStateList
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatButton
class ColoredButton: AppCompatButton {
constructor(context: Context) : super(context) {
applyColor()
}
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){
super.setBackgroundTintList(ColorStateList.valueOf(ThemeColor.getThemeColor(context)))
}
}

View File

@ -6,12 +6,9 @@ import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatCheckBox import androidx.appcompat.widget.AppCompatCheckBox
class ColoredCheckBox: AppCompatCheckBox { class ColoredCheckBox: AppCompatCheckBox {
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) { applyColor() }
applyColor() constructor(context: Context, attrs: AttributeSet): super(context, attrs) { applyColor() }
} //constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) { applyColor() }
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){ private fun applyColor(){
super.setButtonTintList(ColorStateList.valueOf(ThemeColor.getThemeColor(context))) super.setButtonTintList(ColorStateList.valueOf(ThemeColor.getThemeColor(context)))
} }

View File

@ -14,12 +14,9 @@ import androidx.core.content.ContextCompat
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
class ColoredEditText: AppCompatEditText { class ColoredEditText: AppCompatEditText {
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) { applyColor() }
applyColor() constructor(context: Context, attrs: AttributeSet): super(context, attrs) { applyColor() }
} constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) { applyColor() }
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){ private fun applyColor(){
super.setBackgroundTintList(ColorStateList.valueOf(ThemeColor.getThemeColor(context))) super.setBackgroundTintList(ColorStateList.valueOf(ThemeColor.getThemeColor(context)))
} }

View File

@ -1,19 +1,18 @@
package sushi.hardcore.droidfs.widgets package sushi.hardcore.droidfs.widgets
import android.content.Context import android.content.Context
import android.content.res.ColorStateList
import android.util.AttributeSet import android.util.AttributeSet
import com.github.clans.fab.FloatingActionButton import androidx.core.content.ContextCompat
import com.google.android.material.floatingactionbutton.FloatingActionButton
class ColoredFAB: FloatingActionButton { class ColoredFAB: FloatingActionButton {
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) { applyColor() }
applyColor() constructor(context: Context, attrs: AttributeSet): super(context, attrs) { applyColor() }
} constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) { applyColor() }
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){ private fun applyColor(){
val themeColor = ThemeColor.getThemeColor(context) val themeColor = ThemeColor.getThemeColor(context)
super.setColorNormal(themeColor) backgroundTintList = ColorStateList.valueOf(themeColor)
super.setColorPressed(themeColor) setColorFilter(ContextCompat.getColor(context, android.R.color.white))
} }
} }

View File

@ -1,19 +0,0 @@
package sushi.hardcore.droidfs.widgets
import android.content.Context
import android.util.AttributeSet
import com.github.clans.fab.FloatingActionMenu
class ColoredFAM: FloatingActionMenu {
constructor(context: Context) : super(context) {
applyColor()
}
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){
val themeColor = ThemeColor.getThemeColor(context)
super.setMenuButtonColorNormal(themeColor)
super.setMenuButtonColorPressed(themeColor)
}
}

View File

@ -5,12 +5,9 @@ import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageButton import androidx.appcompat.widget.AppCompatImageButton
class ColoredImageButton: AppCompatImageButton { class ColoredImageButton: AppCompatImageButton {
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) { applyColor() }
applyColor() constructor(context: Context, attrs: AttributeSet): super(context, attrs) { applyColor() }
} constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) { applyColor() }
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){ private fun applyColor(){
super.setColorFilter(ThemeColor.getThemeColor(context)) super.setColorFilter(ThemeColor.getThemeColor(context))
} }

View File

@ -5,12 +5,9 @@ import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
class ColoredImageView : AppCompatImageView { class ColoredImageView : AppCompatImageView {
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) { applyColor() }
applyColor() constructor(context: Context, attrs: AttributeSet): super(context, attrs) { applyColor() }
} constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) { applyColor() }
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){ private fun applyColor(){
super.setColorFilter(ThemeColor.getThemeColor(context)) super.setColorFilter(ThemeColor.getThemeColor(context))
} }

View File

@ -1,21 +0,0 @@
package sushi.hardcore.droidfs.widgets
import android.content.Context
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatSeekBar
class ColoredSeekBar : AppCompatSeekBar {
constructor(context: Context) : super(context) {
applyColor()
}
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
applyColor()
}
private fun applyColor(){
val colorFilter = PorterDuffColorFilter(ThemeColor.getThemeColor(context), PorterDuff.Mode.SRC_IN)
super.getProgressDrawable().colorFilter = colorFilter
super.getThumb().colorFilter = colorFilter
}
}

View File

@ -7,17 +7,20 @@ import android.widget.ListAdapter
class NonScrollableColoredBorderListView: ColoredBorderListView { class NonScrollableColoredBorderListView: ColoredBorderListView {
constructor(context: Context) : super(context) constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet): super(context, attrs) constructor(context: Context, attrs: AttributeSet): super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr)
fun computeHeight(): Int {
var totalHeight = 0
for (i in 0 until adapter.count){
val item = adapter.getView(i, null, this)
item.measure(0, 0)
totalHeight += item.measuredHeight
}
return totalHeight + (dividerHeight * (adapter.count-1))
}
override fun setAdapter(adapter: ListAdapter?) { override fun setAdapter(adapter: ListAdapter?) {
super.setAdapter(adapter) super.setAdapter(adapter)
adapter?.let { layoutParams.height = computeHeight()
var totalHeight = 0
for (i in 0 until adapter.count){
val item = adapter.getView(i, null, this)
item.measure(0, 0)
totalHeight += item.measuredHeight
}
layoutParams.height = totalHeight + (dividerHeight * (adapter.count-1))
}
} }
} }

View File

@ -0,0 +1,27 @@
package sushi.hardcore.droidfs.widgets
import android.content.Context
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatImageView
class TakePhotoButton: AppCompatImageView {
constructor(context: Context) : super(context) { init() }
constructor(context: Context, attrs: AttributeSet): super(context, attrs) { init() }
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) { init() }
lateinit var onClick: ()->Unit
private fun init(){
setOnTouchListener{ _, event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> onClick()
MotionEvent.ACTION_UP -> isPressed = true
}
true
}
}
fun onPhotoTaken(){
isPressed = false
}
}

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/buttonBackgroundColor"/>
<corners android:radius="4dp"/>
</shape>
</item>
</selector>

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#666666"/>
<padding
android:left="16dp"
android:right="16dp"
android:top="6dp"
android:bottom="6dp"/>
<corners
android:radius="5dp"/>
</shape>

View File

@ -0,0 +1,6 @@
<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="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path android:fillColor="@android:color/white" android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#FFFFFF"
android:pathData="M20,40h-10v4h10v4l6,-6 -6,-6v4zM28,40v4h10v-4h-10zM34,0h-20c-2.21,0 -4,1.79 -4,4v28c0,2.21 1.79,4 4,4h20c2.21,0 4,-1.79 4,-4v-28c0,-2.21 -1.79,-4 -4,-4zM23.99,12c-2.21,0 -3.99,-1.79 -3.99,-4s1.78,-4 3.99,-4 4,1.79 4,4 -1.79,4 -4,4z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="48dp"
android:height="48dp"
android:viewportWidth="48"
android:viewportHeight="48">
<path
android:fillColor="#FFFFFF"
android:pathData="M20,40h-10v4h10v4l6,-6 -6,-6v4zM28,40v4h10v-4h-10zM24,16c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -3.99,1.79 -3.99,4c0.01,2.21 1.78,4 3.99,4zM34,0h-20c-2.21,0 -4,1.79 -4,4v28c0,2.21 1.79,4 4,4h20c2.21,0 4,-1.79 4,-4v-28c0,-2.21 -1.79,-4 -4,-4zM14,4h20v21c0,-3.33 -6.67,-5 -10,-5s-10,1.67 -10,5v-21z"/>
</vector>

View File

@ -1,11 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp" android:width="24dp"
android:height="24dp" android:height="24dp"
android:viewportWidth="500" android:viewportWidth="500"
android:viewportHeight="500"> android:viewportHeight="500">
<path
<path android:pathData="m131.889,118.111l0,63.597l-27.256,0c-20.079,0 -36.343,16.263 -36.343,36.342l0,181.711c0,20.078 16.264,36.34 36.343,36.34l290.734,0c20.078,0 36.345,-16.262 36.345,-36.34l0,-181.711c0,-20.079 -16.267,-36.342 -36.345,-36.342l-27.254,0l0,-63.597c0,-65.232 -52.882,-118.111 -118.112,-118.111s-118.112,52.878 -118.112,118.111zM177.317,181.708l0,-63.597c0,-40.157 32.525,-72.685 72.683,-72.685c40.158,0 72.685,32.528 72.685,72.685l0,63.597l-145.368,0zM213.658,281.649c0,-20.078 16.263,-36.341 36.342,-36.341s36.341,16.263 36.341,36.341c0,12.812 -6.634,24.079 -16.625,30.529c0,0 3.55,21.446 7.542,46.699c0,7.538 -6.087,13.625 -13.629,13.625l-27.258,0c-7.541,0 -13.627,-6.087 -13.627,-13.625l7.542,-46.699c-9.992,-6.45 -16.628,-17.718 -16.628,-30.529z"
android:fillColor="#FFFFFF" android:fillColor="#FFFFFF"
android:pathData="M131.889,150.061v63.597h-27.256 c-20.079,0-36.343,16.263-36.343,36.342v181.711c0,20.078,16.264,36.34,36.343,36.34h290.734c20.078,0,36.345-16.262,36.345-36.34 V250c0-20.079-16.267-36.342-36.345-36.342h-27.254v-63.597c0-65.232-52.882-118.111-118.112-118.111 S131.889,84.828,131.889,150.061z M177.317,213.658v-63.597c0-40.157,32.525-72.685,72.683-72.685 c40.158,0,72.685,32.528,72.685,72.685v63.597H177.317z M213.658,313.599c0-20.078,16.263-36.341,36.342-36.341 s36.341,16.263,36.341,36.341c0,12.812-6.634,24.079-16.625,30.529c0,0,3.55,21.446,7.542,46.699 c0,7.538-6.087,13.625-13.629,13.625h-27.258c-7.541,0-13.627-6.087-13.627-13.625l7.542-46.699 C220.294,337.678,213.658,326.41,213.658,313.599z" /> android:fillType="evenOdd"/>
</vector> </vector>

View 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="M3,2v12h3v9l7,-12L9,11l4,-9L3,2zM19,2h-2l-3.2,9h1.9l0.7,-2h3.2l0.7,2h1.9L19,2zM16.85,7.65L18,4l1.15,3.65h-2.3z"/>
</vector>

View 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="M3.27,3L2,4.27l5,5V13h3v9l3.58,-6.14L17.73,20 19,18.73 3.27,3zM17,10h-4l4,-8H7v2.18l8.46,8.46L17,10z"/>
</vector>

View 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="M7,2v11h3v9l7,-12h-4l4,-8z"/>
</vector>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<solid android:color="#CCCCCC" />
<size android:width="75dp" android:height="75dp" />
<stroke android:width="15dp" android:color="#444444"/>
</shape>
</item>
<item>
<shape android:shape="oval">
<solid android:color="#FFFFFF"/>
<size android:width="75dp" android:height="75dp" />
<stroke android:width="8dp" android:color="#444444"/>
</shape>
</item>
</selector>

View File

@ -0,0 +1,52 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".CameraActivity">
<com.otaliastudios.cameraview.CameraView
android:id="@+id/camera"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:cameraGesturePinch="zoom"
app:cameraPictureFormat="jpeg"
app:cameraAudio="off"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:layout_marginBottom="30dp">
<ImageView
android:id="@+id/image_flash"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/icon_flash_auto"
android:layout_alignEnd="@id/take_photo_button"
android:layout_marginEnd="120dp"
android:layout_centerVertical="true"
android:onClick="onClickFlash"/>
<sushi.hardcore.droidfs.widgets.TakePhotoButton
android:id="@+id/take_photo_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/take_photo_button"
android:layout_centerInParent="true"/>
<ImageView
android:id="@+id/image_camera_switch"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/icon_camera_front"
android:layout_alignStart="@id/take_photo_button"
android:layout_marginStart="120dp"
android:layout_centerVertical="true"
android:onClick="onClickCameraSwitch"/>
</RelativeLayout>
</RelativeLayout>

View File

@ -25,7 +25,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/volume_path" android:text="@string/volume_path"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_volume_path" android:id="@+id/edit_volume_path"
@ -54,7 +54,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/old_password" android:text="@string/old_password"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_old_password" android:id="@+id/edit_old_password"
@ -74,7 +74,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/new_password" android:text="@string/new_password"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_new_password" android:id="@+id/edit_new_password"
@ -94,7 +94,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/new_password_confirmation" android:text="@string/new_password_confirmation"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_new_password_confirm" android:id="@+id/edit_new_password_confirm"
@ -137,7 +137,7 @@
android:gravity="center" android:gravity="center"
android:text="@string/create_password_warning"/> android:text="@string/create_password_warning"/>
<Button <androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/action_activity_button_height" android:layout_height="@dimen/action_activity_button_height"
android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin" android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin"

View File

@ -25,7 +25,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/volume_path" android:text="@string/volume_path"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_volume_path" android:id="@+id/edit_volume_path"
@ -54,7 +54,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/password" android:text="@string/password"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_password" android:id="@+id/edit_password"
@ -74,7 +74,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/password_confirm" android:text="@string/password_confirm"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_password_confirm" android:id="@+id/edit_password_confirm"
@ -109,7 +109,7 @@
android:gravity="center" android:gravity="center"
android:text="@string/create_password_warning"/> android:text="@string/create_password_warning"/>
<Button <androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/action_activity_button_height" android:layout_height="@dimen/action_activity_button_height"
android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin" android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin"

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical" android:orientation="vertical"
@ -37,53 +36,14 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<sushi.hardcore.droidfs.widgets.ColoredFAM <sushi.hardcore.droidfs.widgets.ColoredFAB
android:id="@+id/fam_explorer"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_margin="15dp" android:layout_margin="15dp"
app:menu_labels_style="@style/fab_label"> android:src="@drawable/icon_add"
android:onClick="onClickFAB"/>
<sushi.hardcore.droidfs.widgets.ColoredFAB
android:id="@+id/fab_import_file_from_other_volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fab_size="mini"
app:fab_label="@string/import_from_other_volume"
android:src="@drawable/icon_transfert"
android:onClick="onClickAddFileFromOtherVolume"/>
<sushi.hardcore.droidfs.widgets.ColoredFAB
android:id="@+id/fab_import_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fab_size="mini"
app:fab_label="@string/import_files"
android:src="@drawable/icon_encrypt"
android:onClick="onClickAddFile"/>
<sushi.hardcore.droidfs.widgets.ColoredFAB
android:id="@+id/fab_add_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fab_size="mini"
app:fab_label="@string/new_file"
android:src="@drawable/icon_file_unknown"
android:onClick="onClickCreateFile"/>
<sushi.hardcore.droidfs.widgets.ColoredFAB
android:id="@+id/fab_add_folder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fab_size="mini"
app:fab_label="@string/mkdir"
android:src="@drawable/icon_folder"
android:onClick="onClickAddFolder"
tools:ignore="OnClick" />
</sushi.hardcore.droidfs.widgets.ColoredFAM>
</RelativeLayout> </RelativeLayout>

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:orientation="vertical"> android:orientation="vertical">
@ -35,25 +34,14 @@
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<sushi.hardcore.droidfs.widgets.ColoredFAM <sushi.hardcore.droidfs.widgets.ColoredFAB
android:id="@+id/fam_explorer"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_alignParentBottom="true" android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_margin="15dp" android:layout_margin="15dp"
app:menu_labels_style="@style/fab_label"> android:src="@drawable/icon_add"
android:onClick="onClickFAB"/>
<sushi.hardcore.droidfs.widgets.ColoredFAB
android:id="@+id/fab_add_folder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fab_size="mini"
app:fab_label="@string/mkdir"
android:src="@drawable/icon_folder"
android:onClick="onClickAddFolder"/>
</sushi.hardcore.droidfs.widgets.ColoredFAM>
</RelativeLayout> </RelativeLayout>

View File

@ -28,7 +28,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<Button <androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/main_activity_button_height" android:layout_height="@dimen/main_activity_button_height"
android:layout_marginHorizontal="@dimen/main_activity_button_hor_margin" android:layout_marginHorizontal="@dimen/main_activity_button_hor_margin"
@ -37,7 +37,7 @@
android:text="@string/open_volume" android:text="@string/open_volume"
style="@style/button"/> style="@style/button"/>
<Button <androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/main_activity_button_height" android:layout_height="@dimen/main_activity_button_height"
android:layout_marginHorizontal="@dimen/main_activity_button_hor_margin" android:layout_marginHorizontal="@dimen/main_activity_button_hor_margin"
@ -46,7 +46,7 @@
android:text="@string/create_volume" android:text="@string/create_volume"
style="@style/button"/> style="@style/button"/>
<Button <androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/main_activity_button_height" android:layout_height="@dimen/main_activity_button_height"
android:layout_marginHorizontal="@dimen/main_activity_button_hor_margin" android:layout_marginHorizontal="@dimen/main_activity_button_hor_margin"

View File

@ -25,7 +25,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/volume_path" android:text="@string/volume_path"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_volume_path" android:id="@+id/edit_volume_path"
@ -54,7 +54,7 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:gravity="center_vertical" android:gravity="center_vertical"
android:text="@string/password" android:text="@string/password"
android:textSize="@dimen/edit_text_label_size" /> android:textSize="@dimen/edit_text_label_text_size" />
<sushi.hardcore.droidfs.widgets.ColoredEditText <sushi.hardcore.droidfs.widgets.ColoredEditText
android:id="@+id/edit_password" android:id="@+id/edit_password"
@ -96,7 +96,7 @@
android:gravity="center" android:gravity="center"
android:text="@string/open_activity_warning"/> android:text="@string/open_activity_warning"/>
<Button <androidx.appcompat.widget.AppCompatButton
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="@dimen/action_activity_button_height" android:layout_height="@dimen/action_activity_button_height"
android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin" android:layout_marginHorizontal="@dimen/action_activity_button_horizontal_margin"

View File

@ -8,7 +8,8 @@
android:id="@+id/icon" android:id="@+id/icon"
android:layout_width="50dp" android:layout_width="50dp"
android:layout_height="50dp" android:layout_height="50dp"
android:layout_marginStart="20dp"/> android:layout_marginStart="20dp"
android:layout_marginEnd="5dp"/>
<TextView <TextView
android:id="@+id/text" android:id="@+id/text"

View File

@ -14,7 +14,7 @@
android:singleLine="true" android:singleLine="true"
android:layout_weight="1" android:layout_weight="1"
android:layout_marginStart="50dp" android:layout_marginStart="50dp"
android:textSize="15dp"/> android:textSize="15sp"/>
<TextView <TextView
android:id="@+id/total_size_text" android:id="@+id/total_size_text"
@ -23,6 +23,7 @@
android:layout_weight="1" android:layout_weight="1"
android:textAlignment="viewEnd" android:textAlignment="viewEnd"
android:layout_marginEnd="50dp" android:layout_marginEnd="50dp"
android:textSize="15dp"/> android:textSize="15sp"
android:text="@string/default_total_size"/>
</LinearLayout> </LinearLayout>

View File

@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<dimen name="main_activity_button_height">70dp</dimen> <dimen name="main_activity_button_height">60dp</dimen>
<dimen name="main_activity_button_hor_margin">50dp</dimen> <dimen name="main_activity_button_hor_margin">50dp</dimen>
<dimen name="main_activity_button_ver_margin">15dp</dimen> <dimen name="main_activity_button_ver_margin">20dp</dimen>
<dimen name="create_activity_label_width">100dp</dimen> <dimen name="create_activity_label_width">100dp</dimen>
<dimen name="edit_text_label_size">15sp</dimen> <dimen name="edit_text_label_text_size">15sp</dimen>
<dimen name="open_activity_label_width">90dp</dimen> <dimen name="open_activity_label_width">90dp</dimen>
<dimen name="change_password_activity_label_width">100dp</dimen> <dimen name="change_password_activity_label_width">100dp</dimen>
<dimen name="action_activity_button_horizontal_margin">60dp</dimen> <dimen name="action_activity_button_horizontal_margin">60dp</dimen>
<dimen name="action_activity_button_height">60dp</dimen> <dimen name="action_activity_button_height">50dp</dimen>
<dimen name="action_activity_listview_margin_horizontal">50dp</dimen> <dimen name="action_activity_listview_margin_horizontal">50dp</dimen>
<dimen name="action_activity_listview_margin_top">20dp</dimen> <dimen name="action_activity_listview_margin_top">20dp</dimen>
<dimen name="warning_msg_padding">20dp</dimen> <dimen name="warning_msg_padding">20dp</dimen>

View File

@ -6,8 +6,8 @@
<string name="password">Password:</string> <string name="password">Password:</string>
<string name="password_confirm">Password (confirmation):</string> <string name="password_confirm">Password (confirmation):</string>
<string name="volume_path">Volume Path:</string> <string name="volume_path">Volume Path:</string>
<string name="import_files">Import/Encrypt Files</string> <string name="import_files">Import/Encrypt files</string>
<string name="mkdir">Create Folder</string> <string name="mkdir">Create folder</string>
<string name="dir_empty">Directory Empty</string> <string name="dir_empty">Directory Empty</string>
<string name="warning">Warning !</string> <string name="warning">Warning !</string>
<string name="ask_close_volume">Are you sure you want to close this volume ?</string> <string name="ask_close_volume">Are you sure you want to close this volume ?</string>
@ -17,7 +17,7 @@
<string name="error">Error</string> <string name="error">Error</string>
<string name="error_filename_empty">Please enter a name</string> <string name="error_filename_empty">Please enter a name</string>
<string name="error_mkdir">Folder creation failed.</string> <string name="error_mkdir">Folder creation failed.</string>
<string name="success_import">Import Successful !</string> <string name="success_import">Import successful !</string>
<string name="success_import_msg">The selected files have been successfully imported.</string> <string name="success_import_msg">The selected files have been successfully imported.</string>
<string name="import_failed">Import of %1$s failed.</string> <string name="import_failed">Import of %1$s failed.</string>
<string name="export_failed">Export of %1$s failed.</string> <string name="export_failed">Export of %1$s failed.</string>
@ -119,7 +119,7 @@
<string name="discard">Discard</string> <string name="discard">Discard</string>
<string name="word_wrap">Word Wrap</string> <string name="word_wrap">Word Wrap</string>
<string name="outofmemoryerror_msg">OutOfMemoryError: This file is too large to be loaded in memory.</string> <string name="outofmemoryerror_msg">OutOfMemoryError: This file is too large to be loaded in memory.</string>
<string name="new_file">Create New File</string> <string name="new_file">Create new file</string>
<string name="enter_file_name">File name:</string> <string name="enter_file_name">File name:</string>
<string name="file_creation_failed">Failed to create the file.</string> <string name="file_creation_failed">Failed to create the file.</string>
<string name="loading">Loading…</string> <string name="loading">Loading…</string>
@ -139,4 +139,9 @@
<string name="copy_failed">Copy of %1$s failed.</string> <string name="copy_failed">Copy of %1$s failed.</string>
<string name="copy_success_msg">The selected items have been successfully copied.</string> <string name="copy_success_msg">The selected items have been successfully copied.</string>
<string name="copy_success">Copy successful !</string> <string name="copy_success">Copy successful !</string>
<string name="fab_dialog_title">Add</string>
<string name="take_photo">Take photo</string>
<string name="picture_save_success">Picture saved to %1$s</string>
<string name="picture_save_failed">Failed to save this picture.</string>
<string name="default_total_size">N//A</string>
</resources> </resources>

View File

@ -4,14 +4,11 @@
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="android:colorBackground">@color/backgroundColor</item> <item name="android:colorBackground">@color/backgroundColor</item>
<item name="android:textColor">@color/textColor</item> <item name="android:textColor">@color/textColor</item>
<item name="checkboxStyle">@style/checkbox</item> <!--<item name="checkboxStyle">@style/checkbox</item>-->
<!--<item name="actionOverflowMenuStyle">@style/menu_overflow</item>--> <!--<item name="actionOverflowMenuStyle">@style/menu_overflow</item>-->
</style> </style>
<style name="fab_label">
<item name="android:background">@drawable/fab_label_background</item>
</style>
<style name="button" parent="Widget.AppCompat.Button"> <style name="button" parent="Widget.AppCompat.Button">
<item name="android:backgroundTint">@color/buttonBackgroundColor</item> <item name="android:background">@drawable/button_background</item>
</style> </style>
<style name="listViewNoDivider"> <style name="listViewNoDivider">
<item name="android:divider">#000000</item> <item name="android:divider">#000000</item>