Separate color selection & black theme

This commit is contained in:
Matéo Duparc 2023-02-28 22:50:59 +01:00
parent 1a1d3ea570
commit 5090a7aa03
Signed by: hardcoresushi
GPG Key ID: AFE384344A45E13A
38 changed files with 298 additions and 285 deletions

View File

@ -8,41 +8,17 @@ import androidx.appcompat.app.AppCompatActivity
open class BaseActivity: AppCompatActivity() { open class BaseActivity: AppCompatActivity() {
protected lateinit var sharedPrefs: SharedPreferences protected lateinit var sharedPrefs: SharedPreferences
protected var applyCustomTheme: Boolean = true protected var applyCustomTheme: Boolean = true
lateinit var themeValue: String lateinit var theme: Theme
private var shouldCheckTheme = true
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
sharedPrefs = (application as VolumeManagerApp).sharedPreferences
themeValue = sharedPrefs.getString(Constants.THEME_VALUE_KEY, Constants.DEFAULT_THEME_VALUE)!!
if (shouldCheckTheme && applyCustomTheme) {
when (themeValue) {
"black_green" -> setTheme(R.style.BlackGreen)
"dark_red" -> setTheme(R.style.DarkRed)
"black_red" -> setTheme(R.style.BlackRed)
"dark_blue" -> setTheme(R.style.DarkBlue)
"black_blue" -> setTheme(R.style.BlackBlue)
"dark_yellow" -> setTheme(R.style.DarkYellow)
"black_yellow" -> setTheme(R.style.BlackYellow)
"dark_orange" -> setTheme(R.style.DarkOrange)
"black_orange" -> setTheme(R.style.BlackOrange)
"dark_purple" -> setTheme(R.style.DarkPurple)
"black_purple" -> setTheme(R.style.BlackPurple)
"dark_pink" -> setTheme(R.style.DarkPink)
"black_pink" -> setTheme(R.style.BlackPink)
}
}
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
sharedPrefs = (application as VolumeManagerApp).sharedPreferences
theme = Theme.fromSharedPrefs(sharedPrefs)
if (applyCustomTheme) {
setTheme(theme.toResourceId())
}
if (!sharedPrefs.getBoolean("usf_screenshot", false)) { if (!sharedPrefs.getBoolean("usf_screenshot", false)) {
window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE)
} }
} }
// must not be called if applyCustomTheme is false
fun onThemeChanged(newThemeValue: String) {
if (newThemeValue != themeValue) {
themeValue = newThemeValue
shouldCheckTheme = false
recreate()
}
}
} }

View File

@ -123,7 +123,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
} else { } else {
1 1
} }
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.camera_optimization) .setTitle(R.string.camera_optimization)
.setSingleChoiceItems(arrayOf(getString(R.string.maximize_quality), getString(R.string.minimize_latency)), currentIndex) { dialog, which -> .setSingleChoiceItems(arrayOf(getString(R.string.maximize_quality), getString(R.string.minimize_latency)), currentIndex) { dialog, which ->
val resId: Int val resId: Int
@ -150,7 +150,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
} }
binding.imageRatio.setOnClickListener { binding.imageRatio.setOnClickListener {
resolutions?.let { resolutions?.let {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.choose_resolution) .setTitle(R.string.choose_resolution)
.setSingleChoiceItems(it.map { size -> size.toString() }.toTypedArray(), currentResolutionIndex) { dialog, which -> .setSingleChoiceItems(it.map { size -> size.toString() }.toTypedArray(), currentResolutionIndex) { dialog, which ->
currentResolution = resolutions!![which] currentResolution = resolutions!![which]
@ -283,7 +283,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
permissionsGranted = true permissionsGranted = true
setupCamera() setupCamera()
} else { } else {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.camera_perm_needed) .setMessage(R.string.camera_perm_needed)
.setCancelable(false) .setCancelable(false)
@ -410,7 +410,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
if (encryptedVolume.importFile(ByteArrayInputStream(outputBuff.toByteArray()), outputPath)) { if (encryptedVolume.importFile(ByteArrayInputStream(outputBuff.toByteArray()), outputPath)) {
Toast.makeText(applicationContext, getString(R.string.picture_save_success, outputPath), Toast.LENGTH_SHORT).show() Toast.makeText(applicationContext, getString(R.string.picture_save_success, outputPath), Toast.LENGTH_SHORT).show()
} else { } else {
CustomAlertDialogBuilder(this@CameraActivity, themeValue) CustomAlertDialogBuilder(this@CameraActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.picture_save_failed) .setMessage(R.string.picture_save_failed)
.setCancelable(false) .setCancelable(false)

View File

@ -42,7 +42,7 @@ class ChangePasswordActivity: BaseActivity() {
volumeDatabase = VolumeDatabase(this) volumeDatabase = VolumeDatabase(this)
usfFingerprint = sharedPrefs.getBoolean("usf_fingerprint", false) usfFingerprint = sharedPrefs.getBoolean("usf_fingerprint", false)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
fingerprintProtector = FingerprintProtector.new(this, themeValue, volumeDatabase) fingerprintProtector = FingerprintProtector.new(this, theme, volumeDatabase)
if (fingerprintProtector != null && volume.encryptedHash != null) { if (fingerprintProtector != null && volume.encryptedHash != null) {
binding.fingerprintSwitchContainer.visibility = View.VISIBLE binding.fingerprintSwitchContainer.visibility = View.VISIBLE
} }
@ -139,7 +139,7 @@ class ChangePasswordActivity: BaseActivity() {
} else { } else {
null null
} }
object : LoadingTask<Boolean>(this, themeValue, R.string.loading_msg_change_password) { object : LoadingTask<Boolean>(this, theme, R.string.loading_msg_change_password) {
override suspend fun doTask(): Boolean { override suspend fun doTask(): Boolean {
val success = if (volume.type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE) { val success = if (volume.type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE) {
GocryptfsVolume.changePassword( GocryptfsVolume.changePassword(
@ -199,7 +199,7 @@ class ChangePasswordActivity: BaseActivity() {
finish() finish()
} }
} else { } else {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.change_password_failed) .setMessage(R.string.change_password_failed)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@ -11,7 +11,6 @@ object Constants {
const val IO_BUFF_SIZE = 16384 const val IO_BUFF_SIZE = 16384
const val SLIDESHOW_DELAY: Long = 4000 const val SLIDESHOW_DELAY: Long = 4000
const val DEFAULT_THEME_VALUE = "dark_green" const val DEFAULT_THEME_VALUE = "dark_green"
const val THEME_VALUE_KEY = "theme"
const val DEFAULT_VOLUME_KEY = "default_volume" const val DEFAULT_VOLUME_KEY = "default_volume"
const val REMEMBER_VOLUME_KEY = "remember_volume" const val REMEMBER_VOLUME_KEY = "remember_volume"
const val THUMBNAIL_MAX_SIZE_KEY = "thumbnail_max_size" const val THUMBNAIL_MAX_SIZE_KEY = "thumbnail_max_size"

View File

@ -22,7 +22,7 @@ import javax.crypto.spec.GCMParameterSpec
@RequiresApi(Build.VERSION_CODES.M) @RequiresApi(Build.VERSION_CODES.M)
class FingerprintProtector private constructor( class FingerprintProtector private constructor(
private val activity: FragmentActivity, private val activity: FragmentActivity,
private val themeValue: String, private val theme: Theme,
private val volumeDatabase: VolumeDatabase, private val volumeDatabase: VolumeDatabase,
) { ) {
@ -54,11 +54,11 @@ class FingerprintProtector private constructor(
fun new( fun new(
activity: FragmentActivity, activity: FragmentActivity,
themeValue: String, theme: Theme,
volumeDatabase: VolumeDatabase, volumeDatabase: VolumeDatabase,
): FingerprintProtector? { ): FingerprintProtector? {
return if (canAuthenticate(activity) == 0) return if (canAuthenticate(activity) == 0)
FingerprintProtector(activity, themeValue, volumeDatabase) FingerprintProtector(activity, theme, volumeDatabase)
else else
null null
} }
@ -98,7 +98,7 @@ class FingerprintProtector private constructor(
listener.onPasswordHashDecrypted(plainText) listener.onPasswordHashDecrypted(plainText)
} catch (e: AEADBadTagException) { } catch (e: AEADBadTagException) {
listener.onFailed(true) listener.onFailed(true)
CustomAlertDialogBuilder(activity, themeValue) CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.MAC_verification_failed) .setMessage(R.string.MAC_verification_failed)
.setPositiveButton(R.string.reset_hash_storage) { _, _ -> .setPositiveButton(R.string.reset_hash_storage) { _, _ ->
@ -112,7 +112,7 @@ class FingerprintProtector private constructor(
} }
} catch (e: IllegalBlockSizeException) { } catch (e: IllegalBlockSizeException) {
listener.onFailed(true) listener.onFailed(true)
CustomAlertDialogBuilder(activity, themeValue) CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.illegal_block_size_exception) .setTitle(R.string.illegal_block_size_exception)
.setMessage(R.string.illegal_block_size_exception_msg) .setMessage(R.string.illegal_block_size_exception_msg)
.setPositiveButton(R.string.reset_hash_storage) { _, _ -> .setPositiveButton(R.string.reset_hash_storage) { _, _ ->
@ -159,7 +159,7 @@ class FingerprintProtector private constructor(
keyStore.getKey(KEY_ALIAS, null) as SecretKey keyStore.getKey(KEY_ALIAS, null) as SecretKey
} catch (e: UnrecoverableKeyException) { } catch (e: UnrecoverableKeyException) {
listener.onFailed(true) listener.onFailed(true)
CustomAlertDialogBuilder(activity, themeValue) CustomAlertDialogBuilder(activity, theme)
.setTitle(activity.getString(R.string.unrecoverable_key_exception)) .setTitle(activity.getString(R.string.unrecoverable_key_exception))
.setMessage(activity.getString(R.string.unrecoverable_key_exception_msg, e.localizedMessage)) .setMessage(activity.getString(R.string.unrecoverable_key_exception_msg, e.localizedMessage))
.setPositiveButton(R.string.reset_hash_storage) { _, _ -> .setPositiveButton(R.string.reset_hash_storage) { _, _ ->
@ -196,7 +196,7 @@ class FingerprintProtector private constructor(
private fun alertKeyPermanentlyInvalidatedException() { private fun alertKeyPermanentlyInvalidatedException() {
listener.onFailed(true) listener.onFailed(true)
CustomAlertDialogBuilder(activity, themeValue) CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.key_permanently_invalidated_exception) .setTitle(R.string.key_permanently_invalidated_exception)
.setMessage(R.string.key_permanently_invalidated_exception_msg) .setMessage(R.string.key_permanently_invalidated_exception_msg)
.setPositiveButton(R.string.reset_hash_storage) { _, _ -> .setPositiveButton(R.string.reset_hash_storage) { _, _ ->

View File

@ -8,8 +8,8 @@ import kotlinx.coroutines.withContext
import sushi.hardcore.droidfs.databinding.DialogLoadingBinding import sushi.hardcore.droidfs.databinding.DialogLoadingBinding
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
abstract class LoadingTask<T>(val activity: FragmentActivity, themeValue: String, loadingMessageResId: Int) { abstract class LoadingTask<T>(val activity: FragmentActivity, theme: Theme, loadingMessageResId: Int) {
private val dialogLoading = CustomAlertDialogBuilder(activity, themeValue) private val dialogLoading = CustomAlertDialogBuilder(activity, theme)
.setView( .setView(
DialogLoadingBinding.inflate(activity.layoutInflater).apply { DialogLoadingBinding.inflate(activity.layoutInflater).apply {
textMessage.text = activity.getString(loadingMessageResId) textMessage.text = activity.getString(loadingMessageResId)

View File

@ -62,7 +62,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
if (sharedPrefs.getBoolean("applicationFirstOpening", true)) { if (sharedPrefs.getBoolean("applicationFirstOpening", true)) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setMessage(R.string.usf_home_warning_msg) .setMessage(R.string.usf_home_warning_msg)
.setCancelable(false) .setCancelable(false)
@ -140,10 +140,11 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
// refresh theme if changed in SettingsActivity // check if theme was changed (by SettingsActivity)
val newThemeValue = sharedPrefs.getString(Constants.THEME_VALUE_KEY, Constants.DEFAULT_THEME_VALUE)!! val newTheme = Theme.fromSharedPrefs(sharedPrefs)
onThemeChanged(newThemeValue) if (newTheme != theme) {
volumeOpener.themeValue = newThemeValue recreate()
} else {
volumeAdapter.refresh() volumeAdapter.refresh()
if (volumeAdapter.volumes.isNotEmpty()) { if (volumeAdapter.volumes.isNotEmpty()) {
binding.textNoVolumes.visibility = View.GONE binding.textNoVolumes.visibility = View.GONE
@ -151,6 +152,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
// refresh this in case another instance of MainActivity changes its value // refresh this in case another instance of MainActivity changes its value
volumeOpener.defaultVolumeName = sharedPrefs.getString(DEFAULT_VOLUME_KEY, null) volumeOpener.defaultVolumeName = sharedPrefs.getString(DEFAULT_VOLUME_KEY, null)
} }
}
override fun onSaveInstanceState(outState: Bundle) { override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState) super.onSaveInstanceState(outState)
@ -206,7 +208,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
break break
} }
} }
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setView(dialogBinding.root) .setView(dialogBinding.root)
.setPositiveButton(R.string.forget_only) { _, _ -> .setPositiveButton(R.string.forget_only) { _, _ ->
@ -305,10 +307,10 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
val volume = volumeAdapter.volumes[position] val volume = volumeAdapter.volumes[position]
when { when {
volume.isHidden -> { volume.isHidden -> {
PathUtils.safePickDirectory(pickDirectory, this, themeValue) PathUtils.safePickDirectory(pickDirectory, this, theme)
} }
File(filesDir, volume.shortName).exists() -> { File(filesDir, volume.shortName).exists() -> {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.hidden_volume_already_exists) .setMessage(R.string.hidden_volume_already_exists)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -381,7 +383,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
unselect(position) unselect(position)
val dstDocumentFile = DocumentFile.fromTreeUri(this, uri) val dstDocumentFile = DocumentFile.fromTreeUri(this, uri)
if (dstDocumentFile == null) { if (dstDocumentFile == null) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.path_error) .setMessage(R.string.path_error)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -427,7 +429,7 @@ class MainActivity : BaseActivity(), VolumeAdapter.Listener {
} }
} }
else -> { else -> {
CustomAlertDialogBuilder(this@MainActivity, themeValue) CustomAlertDialogBuilder(this@MainActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.copy_failed, result.taskResult.failedItem.name)) .setMessage(getString(R.string.copy_failed, result.taskResult.failedItem.name))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@ -1,5 +1,6 @@
package sushi.hardcore.droidfs package sushi.hardcore.droidfs
import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
@ -79,11 +80,23 @@ class SettingsActivity : BaseActivity() {
} }
} }
private fun refreshTheme() {
with(requireActivity()) {
startActivity(Intent(this, SettingsActivity::class.java))
finish()
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out)
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey) setPreferencesFromResource(R.xml.root_preferences, rootKey)
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(requireContext()) sharedPrefs = PreferenceManager.getDefaultSharedPreferences(requireContext())
findPreference<ListPreference>(Constants.THEME_VALUE_KEY)?.setOnPreferenceChangeListener { _, newValue -> findPreference<ListPreference>("color")?.setOnPreferenceChangeListener { _, _ ->
(activity as BaseActivity).onThemeChanged(newValue as String) refreshTheme()
true
}
findPreference<SwitchPreferenceCompat>("black_theme")?.setOnPreferenceChangeListener { _, _ ->
refreshTheme()
true true
} }
findPreference<Preference>(Constants.THUMBNAIL_MAX_SIZE_KEY)?.let { findPreference<Preference>(Constants.THUMBNAIL_MAX_SIZE_KEY)?.let {
@ -126,7 +139,7 @@ class SettingsActivity : BaseActivity() {
if (errorMsg == null) { if (errorMsg == null) {
true true
} else { } else {
CustomAlertDialogBuilder(requireContext(), (requireActivity() as BaseActivity).themeValue) CustomAlertDialogBuilder(requireContext(), (requireActivity() as BaseActivity).theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(errorMsg) .setMessage(errorMsg)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@ -0,0 +1,68 @@
package sushi.hardcore.droidfs
import android.content.SharedPreferences
import android.os.Parcel
import android.os.Parcelable
class Theme(var color: String, var black: Boolean) : Parcelable {
constructor(parcel: Parcel) : this(
parcel.readString()!!,
parcel.readByte() != 0.toByte(),
)
fun toResourceId(): Int {
return if (black) {
when (color) {
"red" -> R.style.BlackRed
"blue" -> R.style.BlackBlue
"yellow" -> R.style.BlackYellow
"orange" -> R.style.BlackOrange
"purple" -> R.style.BlackPurple
"pink" -> R.style.BlackPink
else -> R.style.BlackGreen
}
} else {
when (color) {
"red" -> R.style.DarkRed
"blue" -> R.style.DarkBlue
"yellow" -> R.style.DarkYellow
"orange" -> R.style.DarkOrange
"purple" -> R.style.DarkPurple
"pink" -> R.style.DarkPink
else -> R.style.BaseTheme
}
}
}
override fun equals(other: Any?): Boolean {
if (other !is Theme) {
return false
}
return other.color == color && other.black == black
}
override fun describeContents(): Int = 0
override fun writeToParcel(dest: Parcel, flags: Int) {
with(dest) {
writeString(color)
writeByte(if (black) 1 else 0)
}
}
companion object {
@JvmField
val CREATOR = object : Parcelable.Creator<Theme> {
override fun createFromParcel(parcel: Parcel) = Theme(parcel)
override fun newArray(size: Int) = arrayOfNulls<Theme>(size)
}
fun fromSharedPrefs(sharedPrefs: SharedPreferences): Theme {
val color = sharedPrefs.getString("color", "green")!!
val black = sharedPrefs.getBoolean("black_theme", false)
return Theme(color, black)
}
}
}

View File

@ -28,14 +28,14 @@ class VolumeOpener(
private val volumeDatabase = VolumeDatabase(activity) private val volumeDatabase = VolumeDatabase(activity)
private var fingerprintProtector: FingerprintProtector? = null private var fingerprintProtector: FingerprintProtector? = null
private val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(activity) private val sharedPrefs = PreferenceManager.getDefaultSharedPreferences(activity)
var themeValue = sharedPrefs.getString(Constants.THEME_VALUE_KEY, Constants.DEFAULT_THEME_VALUE)!! private val theme = (activity as BaseActivity).theme
var defaultVolumeName: String? = sharedPrefs.getString(DEFAULT_VOLUME_KEY, null) var defaultVolumeName: String? = sharedPrefs.getString(DEFAULT_VOLUME_KEY, null)
private var dialogBinding: DialogOpenVolumeBinding? = null private var dialogBinding: DialogOpenVolumeBinding? = null
private val volumeManager = (activity.application as VolumeManagerApp).volumeManager private val volumeManager = (activity.application as VolumeManagerApp).volumeManager
init { init {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
fingerprintProtector = FingerprintProtector.new(activity, themeValue, volumeDatabase) fingerprintProtector = FingerprintProtector.new(activity, theme, volumeDatabase)
} }
} }
@ -60,7 +60,7 @@ class VolumeOpener(
callbacks.onHashStorageReset() callbacks.onHashStorageReset()
} }
override fun onPasswordHashDecrypted(hash: ByteArray) { override fun onPasswordHashDecrypted(hash: ByteArray) {
object : LoadingTask<EncryptedVolume?>(activity, themeValue, R.string.loading_msg_open) { object : LoadingTask<EncryptedVolume?>(activity, theme, R.string.loading_msg_open) {
override suspend fun doTask(): EncryptedVolume? { override suspend fun doTask(): EncryptedVolume? {
val encryptedVolume = EncryptedVolume.init(volume, activity.filesDir.path, null, hash, null) val encryptedVolume = EncryptedVolume.init(volume, activity.filesDir.path, null, hash, null)
Arrays.fill(hash, 0) Arrays.fill(hash, 0)
@ -68,7 +68,7 @@ class VolumeOpener(
} }
}.startTask(activity.lifecycleScope) { encryptedVolume -> }.startTask(activity.lifecycleScope) { encryptedVolume ->
if (encryptedVolume == null) { if (encryptedVolume == null) {
CustomAlertDialogBuilder(activity, themeValue) CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.open_volume_failed) .setTitle(R.string.open_volume_failed)
.setMessage(R.string.open_failed_hash_msg) .setMessage(R.string.open_failed_hash_msg)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -140,7 +140,7 @@ class VolumeOpener(
dialogBinding!!.checkboxSavePassword.visibility = View.GONE dialogBinding!!.checkboxSavePassword.visibility = View.GONE
dialogBinding!!.checkboxDefaultOpen.visibility = View.GONE dialogBinding!!.checkboxDefaultOpen.visibility = View.GONE
} }
val dialog = CustomAlertDialogBuilder(activity, themeValue) val dialog = CustomAlertDialogBuilder(activity, theme)
.setTitle(activity.getString(R.string.open_dialog_title, volume.shortName)) .setTitle(activity.getString(R.string.open_dialog_title, volume.shortName))
.setView(dialogBinding!!.root) .setView(dialogBinding!!.root)
.setNegativeButton(R.string.cancel, null) .setNegativeButton(R.string.cancel, null)
@ -168,7 +168,7 @@ class VolumeOpener(
} else { } else {
null null
} }
object : LoadingTask<EncryptedVolume?>(activity, themeValue, R.string.loading_msg_open) { object : LoadingTask<EncryptedVolume?>(activity, theme, R.string.loading_msg_open) {
override suspend fun doTask(): EncryptedVolume? { override suspend fun doTask(): EncryptedVolume? {
val encryptedVolume = EncryptedVolume.init(volume, activity.filesDir.path, password, null, returnedHash) val encryptedVolume = EncryptedVolume.init(volume, activity.filesDir.path, password, null, returnedHash)
Arrays.fill(password, 0) Arrays.fill(password, 0)
@ -176,7 +176,7 @@ class VolumeOpener(
} }
}.startTask(activity.lifecycleScope) { encryptedVolume -> }.startTask(activity.lifecycleScope) { encryptedVolume ->
if (encryptedVolume == null) { if (encryptedVolume == null) {
CustomAlertDialogBuilder(activity, themeValue) CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.open_volume_failed) .setTitle(R.string.open_volume_failed)
.setMessage(R.string.open_volume_failed_msg) .setMessage(R.string.open_volume_failed_msg)
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->

View File

@ -29,7 +29,7 @@ class AddVolumeActivity: BaseActivity() {
.beginTransaction() .beginTransaction()
.add( .add(
R.id.fragment_container, R.id.fragment_container,
SelectPathFragment.newInstance(themeValue, explorerRouter.pickMode), SelectPathFragment.newInstance(theme, explorerRouter.pickMode),
) )
.commit() .commit()
} }
@ -85,7 +85,7 @@ class AddVolumeActivity: BaseActivity() {
.beginTransaction() .beginTransaction()
.replace( .replace(
R.id.fragment_container, CreateVolumeFragment.newInstance( R.id.fragment_container, CreateVolumeFragment.newInstance(
themeValue, theme,
volumePath, volumePath,
isHidden, isHidden,
rememberVolume, rememberVolume,

View File

@ -18,6 +18,7 @@ import sushi.hardcore.droidfs.databinding.FragmentCreateVolumeBinding
import sushi.hardcore.droidfs.filesystems.CryfsVolume import sushi.hardcore.droidfs.filesystems.CryfsVolume
import sushi.hardcore.droidfs.filesystems.EncryptedVolume import sushi.hardcore.droidfs.filesystems.EncryptedVolume
import sushi.hardcore.droidfs.filesystems.GocryptfsVolume import sushi.hardcore.droidfs.filesystems.GocryptfsVolume
import sushi.hardcore.droidfs.util.Compat
import sushi.hardcore.droidfs.util.ObjRef import sushi.hardcore.droidfs.util.ObjRef
import sushi.hardcore.droidfs.util.WidgetUtil import sushi.hardcore.droidfs.util.WidgetUtil
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
@ -34,7 +35,7 @@ class CreateVolumeFragment: Fragment() {
private const val KEY_USF_FINGERPRINT = "fingerprint" private const val KEY_USF_FINGERPRINT = "fingerprint"
fun newInstance( fun newInstance(
themeValue: String, theme: Theme,
volumePath: String, volumePath: String,
isHidden: Boolean, isHidden: Boolean,
rememberVolume: Boolean, rememberVolume: Boolean,
@ -43,7 +44,7 @@ class CreateVolumeFragment: Fragment() {
): CreateVolumeFragment { ): CreateVolumeFragment {
return CreateVolumeFragment().apply { return CreateVolumeFragment().apply {
arguments = Bundle().apply { arguments = Bundle().apply {
putString(KEY_THEME_VALUE, themeValue) putParcelable(KEY_THEME_VALUE, theme)
putString(KEY_VOLUME_PATH, volumePath) putString(KEY_VOLUME_PATH, volumePath)
putBoolean(KEY_IS_HIDDEN, isHidden) putBoolean(KEY_IS_HIDDEN, isHidden)
putBoolean(KEY_REMEMBER_VOLUME, rememberVolume) putBoolean(KEY_REMEMBER_VOLUME, rememberVolume)
@ -55,7 +56,7 @@ class CreateVolumeFragment: Fragment() {
} }
private lateinit var binding: FragmentCreateVolumeBinding private lateinit var binding: FragmentCreateVolumeBinding
private var themeValue = Constants.DEFAULT_THEME_VALUE private lateinit var theme: Theme
private val volumeTypes = ArrayList<String>(2) private val volumeTypes = ArrayList<String>(2)
private lateinit var volumePath: String private lateinit var volumePath: String
private var isHiddenVolume: Boolean = false private var isHiddenVolume: Boolean = false
@ -76,7 +77,7 @@ class CreateVolumeFragment: Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val pinPasswords = requireArguments().let { arguments -> val pinPasswords = requireArguments().let { arguments ->
arguments.getString(KEY_THEME_VALUE)?.let { themeValue = it } theme = Compat.getParcelable(arguments, KEY_THEME_VALUE)!!
volumePath = arguments.getString(KEY_VOLUME_PATH)!! volumePath = arguments.getString(KEY_VOLUME_PATH)!!
isHiddenVolume = arguments.getBoolean(KEY_IS_HIDDEN) isHiddenVolume = arguments.getBoolean(KEY_IS_HIDDEN)
rememberVolume = arguments.getBoolean(KEY_REMEMBER_VOLUME) rememberVolume = arguments.getBoolean(KEY_REMEMBER_VOLUME)
@ -85,7 +86,7 @@ class CreateVolumeFragment: Fragment() {
} }
volumeDatabase = VolumeDatabase(requireContext()) volumeDatabase = VolumeDatabase(requireContext())
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
fingerprintProtector = FingerprintProtector.new(requireActivity(), themeValue, volumeDatabase) fingerprintProtector = FingerprintProtector.new(requireActivity(), theme, volumeDatabase)
} }
if (!rememberVolume || !usfFingerprint || fingerprintProtector == null) { if (!rememberVolume || !usfFingerprint || fingerprintProtector == null) {
binding.checkboxSavePassword.visibility = View.GONE binding.checkboxSavePassword.visibility = View.GONE
@ -159,7 +160,7 @@ class CreateVolumeFragment: Fragment() {
null null
} }
val encryptedVolume = ObjRef<EncryptedVolume?>(null) val encryptedVolume = ObjRef<EncryptedVolume?>(null)
object: LoadingTask<Byte>(requireActivity() as AppCompatActivity, themeValue, R.string.loading_msg_create) { object: LoadingTask<Byte>(requireActivity() as AppCompatActivity, theme, R.string.loading_msg_create) {
private fun generateResult(success: Boolean, volumeType: Byte): Byte { private fun generateResult(success: Boolean, volumeType: Byte): Byte {
return if (success) { return if (success) {
volumeType volumeType
@ -203,7 +204,7 @@ class CreateVolumeFragment: Fragment() {
} }
}.startTask(lifecycleScope) { result -> }.startTask(lifecycleScope) { result ->
if (result.compareTo(-1) == 0) { if (result.compareTo(-1) == 0) {
CustomAlertDialogBuilder(requireContext(), themeValue) CustomAlertDialogBuilder(requireContext(), theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.create_volume_failed) .setMessage(R.string.create_volume_failed)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@ -22,12 +22,14 @@ import androidx.fragment.app.Fragment
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import sushi.hardcore.droidfs.Constants import sushi.hardcore.droidfs.Constants
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.Theme
import sushi.hardcore.droidfs.VolumeData import sushi.hardcore.droidfs.VolumeData
import sushi.hardcore.droidfs.VolumeDatabase import sushi.hardcore.droidfs.VolumeDatabase
import sushi.hardcore.droidfs.VolumeManagerApp import sushi.hardcore.droidfs.VolumeManagerApp
import sushi.hardcore.droidfs.databinding.DialogSdcardErrorBinding import sushi.hardcore.droidfs.databinding.DialogSdcardErrorBinding
import sushi.hardcore.droidfs.databinding.FragmentSelectPathBinding import sushi.hardcore.droidfs.databinding.FragmentSelectPathBinding
import sushi.hardcore.droidfs.filesystems.EncryptedVolume import sushi.hardcore.droidfs.filesystems.EncryptedVolume
import sushi.hardcore.droidfs.util.Compat
import sushi.hardcore.droidfs.util.PathUtils import sushi.hardcore.droidfs.util.PathUtils
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import java.io.File import java.io.File
@ -37,10 +39,10 @@ class SelectPathFragment: Fragment() {
private const val KEY_THEME_VALUE = "theme" private const val KEY_THEME_VALUE = "theme"
private const val KEY_PICK_MODE = "pick" private const val KEY_PICK_MODE = "pick"
fun newInstance(themeValue: String, pickMode: Boolean): SelectPathFragment { fun newInstance(theme: Theme, pickMode: Boolean): SelectPathFragment {
return SelectPathFragment().apply { return SelectPathFragment().apply {
arguments = Bundle().apply { arguments = Bundle().apply {
putString(KEY_THEME_VALUE, themeValue) putParcelable(KEY_THEME_VALUE, theme)
putBoolean(KEY_PICK_MODE, pickMode) putBoolean(KEY_PICK_MODE, pickMode)
} }
} }
@ -52,7 +54,7 @@ class SelectPathFragment: Fragment() {
if (result[Manifest.permission.READ_EXTERNAL_STORAGE] == true && result[Manifest.permission.WRITE_EXTERNAL_STORAGE] == true) if (result[Manifest.permission.READ_EXTERNAL_STORAGE] == true && result[Manifest.permission.WRITE_EXTERNAL_STORAGE] == true)
launchPickDirectory() launchPickDirectory()
else else
CustomAlertDialogBuilder(requireContext(), themeValue) CustomAlertDialogBuilder(requireContext(), theme)
.setTitle(R.string.storage_perm_denied) .setTitle(R.string.storage_perm_denied)
.setMessage(R.string.storage_perm_denied_msg) .setMessage(R.string.storage_perm_denied_msg)
.setCancelable(false) .setCancelable(false)
@ -64,7 +66,7 @@ class SelectPathFragment: Fragment() {
onDirectoryPicked(uri) onDirectoryPicked(uri)
} }
private lateinit var app: VolumeManagerApp private lateinit var app: VolumeManagerApp
private var themeValue = Constants.DEFAULT_THEME_VALUE private lateinit var theme: Theme
private lateinit var volumeDatabase: VolumeDatabase private lateinit var volumeDatabase: VolumeDatabase
private lateinit var filesDir: String private lateinit var filesDir: String
private lateinit var sharedPrefs: SharedPreferences private lateinit var sharedPrefs: SharedPreferences
@ -88,7 +90,7 @@ class SelectPathFragment: Fragment() {
originalRememberVolume = sharedPrefs.getBoolean(Constants.REMEMBER_VOLUME_KEY, true) originalRememberVolume = sharedPrefs.getBoolean(Constants.REMEMBER_VOLUME_KEY, true)
binding.switchRemember.isChecked = originalRememberVolume binding.switchRemember.isChecked = originalRememberVolume
arguments?.let { arguments -> arguments?.let { arguments ->
arguments.getString(KEY_THEME_VALUE)?.let { themeValue = it } theme = Compat.getParcelable(arguments, KEY_THEME_VALUE)!!
pickMode = arguments.getBoolean(KEY_PICK_MODE) pickMode = arguments.getBoolean(KEY_PICK_MODE)
} }
if (pickMode) { if (pickMode) {
@ -155,7 +157,7 @@ class SelectPathFragment: Fragment() {
private fun launchPickDirectory() { private fun launchPickDirectory() {
app.isStartingExternalApp = true app.isStartingExternalApp = true
PathUtils.safePickDirectory(pickDirectory, requireContext(), themeValue) PathUtils.safePickDirectory(pickDirectory, requireContext(), theme)
} }
private fun showRightSection() { private fun showRightSection() {
@ -217,7 +219,7 @@ class SelectPathFragment: Fragment() {
if (path != null) if (path != null)
binding.editVolumeName.setText(path) binding.editVolumeName.setText(path)
else else
CustomAlertDialogBuilder(requireContext(), themeValue) CustomAlertDialogBuilder(requireContext(), theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.path_error) .setMessage(R.string.path_error)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -250,7 +252,7 @@ class SelectPathFragment: Fragment() {
} else if (isHidden && currentVolumeValue.contains(PathUtils.SEPARATOR)) { } else if (isHidden && currentVolumeValue.contains(PathUtils.SEPARATOR)) {
Toast.makeText(requireContext(), R.string.error_slash_in_name, Toast.LENGTH_SHORT).show() Toast.makeText(requireContext(), R.string.error_slash_in_name, Toast.LENGTH_SHORT).show()
} else if (isHidden && volumeAction == Action.CREATE) { } else if (isHidden && volumeAction == Action.CREATE) {
CustomAlertDialogBuilder(requireContext(), themeValue) CustomAlertDialogBuilder(requireContext(), theme)
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setMessage(R.string.hidden_volume_warning) .setMessage(R.string.hidden_volume_warning)
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
@ -302,13 +304,13 @@ class SelectPathFragment: Fragment() {
Action.ADD -> { Action.ADD -> {
val volumeType = EncryptedVolume.getVolumeType(volumePath) val volumeType = EncryptedVolume.getVolumeType(volumePath)
if (volumeType < 0) { if (volumeType < 0) {
CustomAlertDialogBuilder(requireContext(), themeValue) CustomAlertDialogBuilder(requireContext(), theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.error_not_a_volume) .setMessage(R.string.error_not_a_volume)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
.show() .show()
} else if (!File(volumePath).canWrite()) { } else if (!File(volumePath).canWrite()) {
val dialog = CustomAlertDialogBuilder(requireContext(), themeValue) val dialog = CustomAlertDialogBuilder(requireContext(), theme)
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setCancelable(false) .setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> addVolume(if (isHidden) currentVolumeValue else volumePath, isHidden, volumeType) } .setPositiveButton(R.string.ok) { _, _ -> addVolume(if (isHidden) currentVolumeValue else volumePath, isHidden, volumeType) }
@ -332,7 +334,7 @@ class SelectPathFragment: Fragment() {
// called when the user tries to create a volume in a non-writable directory // called when the user tries to create a volume in a non-writable directory
private fun errorDirectoryNotWritable(volumePath: String) { private fun errorDirectoryNotWritable(volumePath: String) {
val dialog = CustomAlertDialogBuilder(requireContext(), themeValue) val dialog = CustomAlertDialogBuilder(requireContext(), theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@SuppressLint("InflateParams") @SuppressLint("InflateParams")

View File

@ -11,6 +11,7 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import sushi.hardcore.droidfs.LoadingTask import sushi.hardcore.droidfs.LoadingTask
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.Theme
import sushi.hardcore.droidfs.filesystems.EncryptedVolume import sushi.hardcore.droidfs.filesystems.EncryptedVolume
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import java.io.File import java.io.File
@ -45,10 +46,10 @@ object ExternalProvider {
return Pair(null, null) return Pair(null, null)
} }
fun share(activity: AppCompatActivity, themeValue: String, encryptedVolume: EncryptedVolume, file_paths: List<String>) { fun share(activity: AppCompatActivity, theme: Theme, encryptedVolume: EncryptedVolume, file_paths: List<String>) {
var contentType: String? = null var contentType: String? = null
val uris = ArrayList<Uri>(file_paths.size) val uris = ArrayList<Uri>(file_paths.size)
object : LoadingTask<String?>(activity, themeValue, R.string.loading_msg_export) { object : LoadingTask<String?>(activity, theme, R.string.loading_msg_export) {
override suspend fun doTask(): String? { override suspend fun doTask(): String? {
for (path in file_paths) { for (path in file_paths) {
val result = exportFile(activity, encryptedVolume, path, contentType) val result = exportFile(activity, encryptedVolume, path, contentType)
@ -74,7 +75,7 @@ object ExternalProvider {
} }
activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_chooser))) activity.startActivity(Intent.createChooser(shareIntent, activity.getString(R.string.share_chooser)))
} else { } else {
CustomAlertDialogBuilder(activity, themeValue) CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(activity.getString(R.string.export_failed, failedItem)) .setMessage(activity.getString(R.string.export_failed, failedItem))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -83,8 +84,8 @@ object ExternalProvider {
} }
} }
fun open(activity: AppCompatActivity, themeValue: String, encryptedVolume: EncryptedVolume, file_path: String) { fun open(activity: AppCompatActivity, theme: Theme, encryptedVolume: EncryptedVolume, file_path: String) {
object : LoadingTask<Intent?>(activity, themeValue, R.string.loading_msg_export) { object : LoadingTask<Intent?>(activity, theme, R.string.loading_msg_export) {
override suspend fun doTask(): Intent? { override suspend fun doTask(): Intent? {
val result = exportFile(activity, encryptedVolume, file_path, null) val result = exportFile(activity, encryptedVolume, file_path, null)
return if (result.first != null) { return if (result.first != null) {
@ -98,7 +99,7 @@ object ExternalProvider {
} }
}.startTask(activity.lifecycleScope) { openIntent -> }.startTask(activity.lifecycleScope) { openIntent ->
if (openIntent == null) { if (openIntent == null) {
CustomAlertDialogBuilder(activity, themeValue) CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(activity.getString(R.string.export_failed, file_path)) .setMessage(activity.getString(R.string.export_failed, file_path))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@ -191,12 +191,12 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
private fun openWithExternalApp(fullPath: String) { private fun openWithExternalApp(fullPath: String) {
app.isStartingExternalApp = true app.isStartingExternalApp = true
ExternalProvider.open(this, themeValue, encryptedVolume, fullPath) ExternalProvider.open(this, theme, encryptedVolume, fullPath)
} }
private fun showOpenAsDialog(path: String) { private fun showOpenAsDialog(path: String) {
val adapter = OpenAsDialogAdapter(this, usf_open) val adapter = OpenAsDialogAdapter(this, usf_open)
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setSingleChoiceItems(adapter, -1) { dialog, which -> .setSingleChoiceItems(adapter, -1) { dialog, which ->
when (adapter.getItem(which)) { when (adapter.getItem(which)) {
"image" -> startFileViewer(ImageViewer::class.java, path) "image" -> startFileViewer(ImageViewer::class.java, path)
@ -341,7 +341,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
} }
private fun askLockVolume() { private fun askLockVolume() {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setMessage(R.string.ask_lock_volume) .setMessage(R.string.ask_lock_volume)
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
@ -357,7 +357,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
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 {
if (!encryptedVolume.mkdir(PathUtils.pathJoin(currentDirectoryPath, folderName))) { if (!encryptedVolume.mkdir(PathUtils.pathJoin(currentDirectoryPath, folderName))) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.error_mkdir) .setMessage(R.string.error_mkdir)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -394,7 +394,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
} }
} }
if (!ready){ if (!ready){
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setMessage(getString( .setMessage(getString(
if (items[i].isDirectory) { if (items[i].isDirectory) {
@ -444,7 +444,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
for (uri in uris) { for (uri in uris) {
val fileName = PathUtils.getFilenameFromURI(this, uri) val fileName = PathUtils.getFilenameFromURI(this, uri)
if (fileName == null) { if (fileName == null) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.error_retrieving_filename, uri)) .setMessage(getString(R.string.error_retrieving_filename, uri))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -476,7 +476,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
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 {
if (!encryptedVolume.rename(PathUtils.pathJoin(currentDirectoryPath, old_name), PathUtils.pathJoin(currentDirectoryPath, new_name))) { if (!encryptedVolume.rename(PathUtils.pathJoin(currentDirectoryPath, old_name), PathUtils.pathJoin(currentDirectoryPath, new_name))) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.rename_failed, old_name)) .setMessage(getString(R.string.rename_failed, old_name))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -532,7 +532,7 @@ open class BaseExplorerActivity : BaseActivity(), ExplorerElementAdapter.Listene
true true
} }
R.id.sort -> { R.id.sort -> {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.sort_order) .setTitle(R.string.sort_order)
.setSingleChoiceItems(sortOrderEntries, currentSortOrderIndex) { dialog, which -> .setSingleChoiceItems(sortOrderEntries, currentSortOrderIndex) { dialog, which ->
currentSortOrderIndex = which currentSortOrderIndex = which

View File

@ -69,7 +69,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (failedItem == null) { if (failedItem == null) {
Toast.makeText(this@ExplorerActivity, R.string.success_import, Toast.LENGTH_SHORT).show() Toast.makeText(this@ExplorerActivity, R.string.success_import, Toast.LENGTH_SHORT).show()
} else { } else {
CustomAlertDialogBuilder(this@ExplorerActivity, themeValue) CustomAlertDialogBuilder(this@ExplorerActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.import_failed, failedItem)) .setMessage(getString(R.string.import_failed, failedItem))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -99,7 +99,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (result.failedItem == null) { if (result.failedItem == null) {
Toast.makeText(this@ExplorerActivity, R.string.success_export, Toast.LENGTH_SHORT).show() Toast.makeText(this@ExplorerActivity, R.string.success_export, Toast.LENGTH_SHORT).show()
} else { } else {
CustomAlertDialogBuilder(this@ExplorerActivity, themeValue) CustomAlertDialogBuilder(this@ExplorerActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.export_failed, result.failedItem)) .setMessage(getString(R.string.export_failed, result.failedItem))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -131,7 +131,7 @@ class ExplorerActivity : BaseExplorerActivity() {
private fun onImportComplete(failedItem: String?, urisToWipe: List<Uri>, rootFile: DocumentFile? = null) { private fun onImportComplete(failedItem: String?, urisToWipe: List<Uri>, rootFile: DocumentFile? = null) {
if (failedItem == null){ if (failedItem == null){
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.success_import) .setTitle(R.string.success_import)
.setMessage(""" .setMessage("""
${getString(R.string.success_import_msg)} ${getString(R.string.success_import_msg)}
@ -143,7 +143,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (errorMsg == null) { if (errorMsg == null) {
Toast.makeText(this@ExplorerActivity, R.string.wipe_successful, Toast.LENGTH_SHORT).show() Toast.makeText(this@ExplorerActivity, R.string.wipe_successful, Toast.LENGTH_SHORT).show()
} else { } else {
CustomAlertDialogBuilder(this@ExplorerActivity, themeValue) CustomAlertDialogBuilder(this@ExplorerActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.wipe_failed, errorMsg)) .setMessage(getString(R.string.wipe_failed, errorMsg))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -154,7 +154,7 @@ class ExplorerActivity : BaseExplorerActivity() {
.setNegativeButton(R.string.no, null) .setNegativeButton(R.string.no, null)
.show() .show()
} else { } else {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.import_failed, failedItem)) .setMessage(getString(R.string.import_failed, failedItem))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -188,7 +188,7 @@ class ExplorerActivity : BaseExplorerActivity() {
listOf("createFolder", R.string.mkdir, R.drawable.icon_create_new_folder), listOf("createFolder", R.string.mkdir, R.drawable.icon_create_new_folder),
listOf("camera", R.string.camera, R.drawable.icon_photo) listOf("camera", R.string.camera, R.drawable.icon_photo)
) )
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setSingleChoiceItems(adapter, -1){ thisDialog, which -> .setSingleChoiceItems(adapter, -1){ thisDialog, which ->
when (adapter.getItem(which)){ when (adapter.getItem(which)){
"importFromOtherVolumes" -> { "importFromOtherVolumes" -> {
@ -243,7 +243,7 @@ class ExplorerActivity : BaseExplorerActivity() {
val filePath = PathUtils.pathJoin(currentDirectoryPath, fileName) val filePath = PathUtils.pathJoin(currentDirectoryPath, fileName)
val handleID = encryptedVolume.openFile(filePath) val handleID = encryptedVolume.openFile(filePath)
if (handleID == -1L) { if (handleID == -1L) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.file_creation_failed) .setMessage(R.string.file_creation_failed)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -332,7 +332,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (failedItem == null) { if (failedItem == null) {
Toast.makeText(this@ExplorerActivity, R.string.copy_success, Toast.LENGTH_SHORT).show() Toast.makeText(this@ExplorerActivity, R.string.copy_success, Toast.LENGTH_SHORT).show()
} else { } else {
CustomAlertDialogBuilder(this@ExplorerActivity, themeValue) CustomAlertDialogBuilder(this@ExplorerActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.copy_failed, failedItem)) .setMessage(getString(R.string.copy_failed, failedItem))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -362,7 +362,7 @@ class ExplorerActivity : BaseExplorerActivity() {
if (failedItem == null) { if (failedItem == null) {
Toast.makeText(this@ExplorerActivity, R.string.move_success, Toast.LENGTH_SHORT).show() Toast.makeText(this@ExplorerActivity, R.string.move_success, Toast.LENGTH_SHORT).show()
} else { } else {
CustomAlertDialogBuilder(this@ExplorerActivity, themeValue) CustomAlertDialogBuilder(this@ExplorerActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.move_failed, failedItem)) .setMessage(getString(R.string.move_failed, failedItem))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -378,12 +378,12 @@ class ExplorerActivity : BaseExplorerActivity() {
} }
R.id.delete -> { R.id.delete -> {
val size = explorerAdapter.selectedItems.size val size = explorerAdapter.selectedItems.size
val dialog = CustomAlertDialogBuilder(this, themeValue) val dialog = CustomAlertDialogBuilder(this, theme)
dialog.setTitle(R.string.warning) dialog.setTitle(R.string.warning)
dialog.setPositiveButton(R.string.ok) { _, _ -> dialog.setPositiveButton(R.string.ok) { _, _ ->
taskScope.launch { taskScope.launch {
fileOperationService.removeElements(explorerAdapter.selectedItems.map { i -> explorerElements[i] })?.let { failedItem -> fileOperationService.removeElements(explorerAdapter.selectedItems.map { i -> explorerElements[i] })?.let { failedItem ->
CustomAlertDialogBuilder(this@ExplorerActivity, themeValue) CustomAlertDialogBuilder(this@ExplorerActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.remove_failed, failedItem)) .setMessage(getString(R.string.remove_failed, failedItem))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -411,7 +411,7 @@ class ExplorerActivity : BaseExplorerActivity() {
paths.add(explorerElements[i].fullPath) paths.add(explorerElements[i].fullPath)
} }
app.isStartingExternalApp = true app.isStartingExternalApp = true
ExternalProvider.share(this, themeValue, encryptedVolume, paths) ExternalProvider.share(this, theme, encryptedVolume, paths)
unselectAll() unselectAll()
true true
} }
@ -432,7 +432,7 @@ class ExplorerActivity : BaseExplorerActivity() {
private fun checkMoveOverwrite(items: List<OperationFile>, callback: (List<OperationFile>?) -> Unit) { private fun checkMoveOverwrite(items: List<OperationFile>, callback: (List<OperationFile>?) -> Unit) {
for (item in items) { for (item in items) {
if (encryptedVolume.pathExists(item.dstPath!!) && !item.overwriteConfirmed) { if (encryptedVolume.pathExists(item.dstPath!!) && !item.overwriteConfirmed) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setMessage( .setMessage(
getString( getString(

View File

@ -61,7 +61,7 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
getString(R.string.share_intent_parsing_failed) getString(R.string.share_intent_parsing_failed)
} }
errorMsg?.let { errorMsg?.let {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(it) .setMessage(it)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)
@ -76,7 +76,7 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
private fun onImported(failedItem: String?){ private fun onImported(failedItem: String?){
setCurrentPath(currentDirectoryPath) setCurrentPath(currentDirectoryPath)
if (failedItem == null) { if (failedItem == null) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.success_import) .setTitle(R.string.success_import)
.setMessage(R.string.success_import_msg) .setMessage(R.string.success_import_msg)
.setCancelable(false) .setCancelable(false)
@ -85,7 +85,7 @@ class ExplorerActivityDrop : BaseExplorerActivity() {
} }
.show() .show()
} else { } else {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.import_failed, failedItem)) .setMessage(getString(R.string.import_failed, failedItem))
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@ -84,7 +84,7 @@ abstract class FileViewerActivity: BaseActivity() {
if (result.second == 0) { if (result.second == 0) {
callback(result.first!!) callback(result.first!!)
} else { } else {
val dialog = CustomAlertDialogBuilder(this@FileViewerActivity, themeValue) val dialog = CustomAlertDialogBuilder(this@FileViewerActivity, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setCancelable(false) .setCancelable(false)
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer() } .setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer() }

View File

@ -91,7 +91,7 @@ class ImageViewer: FileViewerActivity() {
} }
}) })
binding.imageDelete.setOnClickListener { binding.imageDelete.setOnClickListener {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.keepFullScreen() .keepFullScreen()
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
@ -105,7 +105,7 @@ class ImageViewer: FileViewerActivity() {
loadImage() loadImage()
} }
} else { } else {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.keepFullScreen() .keepFullScreen()
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.remove_failed, fileName)) .setMessage(getString(R.string.remove_failed, fileName))
@ -222,7 +222,7 @@ class ImageViewer: FileViewerActivity() {
private fun askSaveRotation(callback: () -> Unit){ private fun askSaveRotation(callback: () -> Unit){
if (rotationAngle.mod(360f) != originalOrientation && !slideshowActive) { if (rotationAngle.mod(360f) != originalOrientation && !slideshowActive) {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.keepFullScreen() .keepFullScreen()
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setMessage(R.string.ask_save_img_rotated) .setMessage(R.string.ask_save_img_rotated)
@ -241,7 +241,7 @@ class ImageViewer: FileViewerActivity() {
Toast.makeText(this, R.string.image_saved_successfully, Toast.LENGTH_SHORT).show() Toast.makeText(this, R.string.image_saved_successfully, Toast.LENGTH_SHORT).show()
callback() callback()
} else { } else {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.keepFullScreen() .keepFullScreen()
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.file_write_failed) .setMessage(R.string.file_write_failed)
@ -249,7 +249,7 @@ class ImageViewer: FileViewerActivity() {
.show() .show()
} }
} else { } else {
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.keepFullScreen() .keepFullScreen()
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.bitmap_compress_failed) .setMessage(R.string.bitmap_compress_failed)

View File

@ -45,7 +45,7 @@ abstract class MediaPlayer: FileViewerActivity() {
onVideoSizeChanged(videoSize.width, videoSize.height) onVideoSizeChanged(videoSize.width, videoSize.height)
} }
override fun onPlayerError(error: PlaybackException) { override fun onPlayerError(error: PlaybackException) {
CustomAlertDialogBuilder(this@MediaPlayer, themeValue) CustomAlertDialogBuilder(this@MediaPlayer, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(getString(R.string.playing_failed, error.errorCodeName)) .setMessage(getString(R.string.playing_failed, error.errorCodeName))
.setCancelable(false) .setCancelable(false)

View File

@ -34,7 +34,7 @@ class TextEditor: FileViewerActivity() {
checkSaveAndExit() checkSaveAndExit()
} }
} catch (e: OutOfMemoryError){ } catch (e: OutOfMemoryError){
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.outofmemoryerror_msg) .setMessage(R.string.outofmemoryerror_msg)
.setCancelable(false) .setCancelable(false)
@ -87,7 +87,7 @@ class TextEditor: FileViewerActivity() {
private fun checkSaveAndExit(){ private fun checkSaveAndExit(){
if (changedSinceLastSave){ if (changedSinceLastSave){
CustomAlertDialogBuilder(this, themeValue) CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.warning) .setTitle(R.string.warning)
.setMessage(R.string.ask_save) .setMessage(R.string.ask_save)
.setPositiveButton(R.string.save) { _, _ -> .setPositiveButton(R.string.save) { _, _ ->

View File

@ -0,0 +1,16 @@
package sushi.hardcore.droidfs.util
import android.os.Build
import android.os.Bundle
import android.os.Parcelable
object Compat {
inline fun <reified T: Parcelable> getParcelable(bundle: Bundle, name: String): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
bundle.getParcelable(name, T::class.java)
} else {
@Suppress("Deprecation")
bundle.getParcelable(name)
}
}
}

View File

@ -11,6 +11,7 @@ import android.util.Log
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.Theme
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import java.io.File import java.io.File
import java.text.DecimalFormat import java.text.DecimalFormat
@ -226,11 +227,11 @@ object PathUtils {
return rootDirectory.delete() return rootDirectory.delete()
} }
fun safePickDirectory(directoryPicker: ActivityResultLauncher<Uri?>, context: Context, themeValue: String) { fun safePickDirectory(directoryPicker: ActivityResultLauncher<Uri?>, context: Context, theme: Theme) {
try { try {
directoryPicker.launch(null) directoryPicker.launch(null)
} catch (e: ActivityNotFoundException) { } catch (e: ActivityNotFoundException) {
CustomAlertDialogBuilder(context, themeValue) CustomAlertDialogBuilder(context, theme)
.setTitle(R.string.error) .setTitle(R.string.error)
.setMessage(R.string.open_tree_failed) .setMessage(R.string.open_tree_failed)
.setPositiveButton(R.string.ok, null) .setPositiveButton(R.string.ok, null)

View File

@ -7,24 +7,30 @@ import androidx.appcompat.app.AlertDialog
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.WindowInsetsControllerCompat
import sushi.hardcore.droidfs.R import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.Theme
open class CustomAlertDialogBuilder(context: Context, theme: String) : AlertDialog.Builder( open class CustomAlertDialogBuilder(context: Context, theme: Theme) : AlertDialog.Builder(
context, when (theme) { context, if (theme.black) {
"black_green" -> R.style.BlackGreenDialog when (theme.color) {
"dark_red" -> R.style.DarkRedDialog "red" -> R.style.BlackRedDialog
"black_red" -> R.style.BlackRedDialog "blue" -> R.style.BlackBlueDialog
"dark_blue" -> R.style.DarkBlueDialog "yellow" -> R.style.BlackYellowDialog
"black_blue" -> R.style.BlackBlueDialog "orange" -> R.style.BlackOrangeDialog
"dark_yellow" -> R.style.DarkYellowDialog "purple" -> R.style.BlackPurpleDialog
"black_yellow" -> R.style.BlackYellowDialog "pink" -> R.style.BlackPinkDialog
"dark_orange" -> R.style.DarkOrangeDialog else -> R.style.BlackGreenDialog
"black_orange" -> R.style.BlackOrangeDialog }
"dark_purple" -> R.style.DarkPurpleDialog } else {
"black_purple" -> R.style.BlackPurpleDialog when (theme.color) {
"dark_pink" -> R.style.DarkPinkDialog "red" -> R.style.DarkRedDialog
"black_pink" -> R.style.BlackPinkDialog "blue" -> R.style.DarkBlueDialog
"yellow" -> R.style.DarkYellowDialog
"orange" -> R.style.DarkOrangeDialog
"purple" -> R.style.DarkPurpleDialog
"pink" -> R.style.DarkPinkDialog
else -> R.style.DarkGreenDialog else -> R.style.DarkGreenDialog
} }
}
) { ) {
private var keepFullScreen = false private var keepFullScreen = false

View File

@ -10,7 +10,7 @@ class EditTextDialog(
activity: BaseActivity, activity: BaseActivity,
private val titleId: Int, private val titleId: Int,
private val callback: (String) -> Unit, private val callback: (String) -> Unit,
): CustomAlertDialogBuilder(activity, activity.themeValue) { ): CustomAlertDialogBuilder(activity, activity.theme) {
val binding = DialogEditTextBinding.inflate(activity.layoutInflater) val binding = DialogEditTextBinding.inflate(activity.layoutInflater)
fun setSelectedText(text: CharSequence) { fun setSelectedText(text: CharSequence) {

View File

@ -0,0 +1,5 @@
<vector android:height="24dp"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/colorAccent" android:pathData="M12,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9s9,-4.03 9,-9c0,-0.46 -0.04,-0.92 -0.1,-1.36c-0.98,1.37 -2.58,2.26 -4.4,2.26c-2.98,0 -5.4,-2.42 -5.4,-5.4c0,-1.81 0.89,-3.42 2.26,-4.4C12.92,3.04 12.46,3 12,3L12,3z"/>
</vector>

View File

@ -27,21 +27,4 @@
<item>حجم (وصف)</item> <item>حجم (وصف)</item>
<item>تاريخ (وصف)</item> <item>تاريخ (وصف)</item>
</string-array> </string-array>
<string-array name="themes_entries">
<item>داكن أخضر</item>
<item>أسود أخضر</item>
<item>داكن أحمر</item>
<item>أسود أحمر</item>
<item>داكن أزرق</item>
<item>أسود أزرق</item>
<item>داكن أصفر</item>
<item>أسود أصفر</item>
<item>داكن برتقالي</item>
<item>أسود برتقالي</item>
<item>داكن بنفسجي</item>
<item>أسود بنفسجي</item>
<item>داكن زهري</item>
<item>أسود زهري</item>
</string-array>
</resources> </resources>

View File

@ -79,7 +79,6 @@
<string name="unsafe_features">الميزات غير الآمنة</string> <string name="unsafe_features">الميزات غير الآمنة</string>
<string name="manage_unsafe_features">إدارة الميزات غير الآمنة</string> <string name="manage_unsafe_features">إدارة الميزات غير الآمنة</string>
<string name="manage_unsafe_features_summary">تمكين / تعطيل الميزات غير الآمنة</string> <string name="manage_unsafe_features_summary">تمكين / تعطيل الميزات غير الآمنة</string>
<string name="ui">الواجهة الرسومية</string>
<string name="usf_home_warning_msg">يحاول DroidFS أن يكون آمنًا قدر الإمكان. ولكن غالبًا ما ينطوي الأمان على عدم الراحة. ولهذا السبب فإن DroidFS يقدم لك ميزات إضافية غير آمنة يمكنك تمكينها وتعطيلها وفقًا لاحتياجاتك. تحذير: يمكن أن تكون هذه الميزات غير آمنة. لا تستخدمها إلا إذا كنت تعرف بالضبط ما تفعله. نوصي بشدة بقراءة الوثائق قبل تمكينها.</string> <string name="usf_home_warning_msg">يحاول DroidFS أن يكون آمنًا قدر الإمكان. ولكن غالبًا ما ينطوي الأمان على عدم الراحة. ولهذا السبب فإن DroidFS يقدم لك ميزات إضافية غير آمنة يمكنك تمكينها وتعطيلها وفقًا لاحتياجاتك. تحذير: يمكن أن تكون هذه الميزات غير آمنة. لا تستخدمها إلا إذا كنت تعرف بالضبط ما تفعله. نوصي بشدة بقراءة الوثائق قبل تمكينها.</string>
<string name="see_unsafe_features">انظر الميزات غير الآمنة</string> <string name="see_unsafe_features">انظر الميزات غير الآمنة</string>
<string name="open_as">فتح ك</string> <string name="open_as">فتح ك</string>
@ -174,7 +173,6 @@
<string name="auto">تلقائي</string> <string name="auto">تلقائي</string>
<string name="encryption_cipher_label">خوارزمية التشفير:</string> <string name="encryption_cipher_label">خوارزمية التشفير:</string>
<string name="theme">سمة</string> <string name="theme">سمة</string>
<string name="theme_summary">تخصيص سمة التطبيق</string>
<string name="thumbnails">صور مصغرة</string> <string name="thumbnails">صور مصغرة</string>
<string name="thumbnails_summary">عرض صور مصغرة للصور ومقاطع الفيديو</string> <string name="thumbnails_summary">عرض صور مصغرة للصور ومقاطع الفيديو</string>
<string name="seek_seconds_forward">+%d ثواني</string> <string name="seek_seconds_forward">+%d ثواني</string>

View File

@ -7,21 +7,4 @@
<item>Tamaño (desc)</item> <item>Tamaño (desc)</item>
<item>Fecha (desc)</item> <item>Fecha (desc)</item>
</string-array> </string-array>
<string-array name="themes_entries">
<item>Verde Oscuro</item>
<item>Verde Negro</item>
<item>Rojo Oscuro</item>
<item>Rojo Negro</item>
<item>Azul Oscuro</item>
<item>Azul Negro</item>
<item>Amarillo Oscuro</item>
<item>Amarillo Negro</item>
<item>Naranja Oscuro</item>
<item>Naranja Negro</item>
<item>Morado Oscuro</item>
<item>Morado Negro</item>
<item>Dark Pink</item>
<item>Black Pink</item>
</string-array>
</resources> </resources>

View File

@ -79,7 +79,6 @@
<string name="unsafe_features">Características inseguras</string> <string name="unsafe_features">Características inseguras</string>
<string name="manage_unsafe_features">Gestionar las características inseguras</string> <string name="manage_unsafe_features">Gestionar las características inseguras</string>
<string name="manage_unsafe_features_summary">Activar/desactivar funciones inseguras</string> <string name="manage_unsafe_features_summary">Activar/desactivar funciones inseguras</string>
<string name="ui">Interfaz</string>
<string name="usf_home_warning_msg">DroidFS intenta ser lo más seguro posible. Sin embargo, la seguridad a menudo implica la falta de comodidad. Es por eso que DroidFS te ofrece características inseguras adicionales que puedes activar/desactivar de acuerdo a tus necesidades.\n\nAdvertencia: estas funciones pueden ser inseguras. No las utilices a menos que sepas exactamente lo que estás haciendo. Es muy recomendable leer la documentación antes de activarlas.</string> <string name="usf_home_warning_msg">DroidFS intenta ser lo más seguro posible. Sin embargo, la seguridad a menudo implica la falta de comodidad. Es por eso que DroidFS te ofrece características inseguras adicionales que puedes activar/desactivar de acuerdo a tus necesidades.\n\nAdvertencia: estas funciones pueden ser inseguras. No las utilices a menos que sepas exactamente lo que estás haciendo. Es muy recomendable leer la documentación antes de activarlas.</string>
<string name="see_unsafe_features">Ver características inseguras</string> <string name="see_unsafe_features">Ver características inseguras</string>
<string name="open_as">Abrir como</string> <string name="open_as">Abrir como</string>
@ -174,7 +173,6 @@
<string name="auto">Automático</string> <string name="auto">Automático</string>
<string name="encryption_cipher_label">Cifrado de encriptación:</string> <string name="encryption_cipher_label">Cifrado de encriptación:</string>
<string name="theme">Tema</string> <string name="theme">Tema</string>
<string name="theme_summary">Personalizar el tema de la aplicación</string>
<string name="thumbnails">Miniaturas</string> <string name="thumbnails">Miniaturas</string>
<string name="thumbnails_summary">Mostrar miniaturas de imágenes y vídeos</string> <string name="thumbnails_summary">Mostrar miniaturas de imágenes y vídeos</string>
<string name="seek_seconds_forward">+%d segundos</string> <string name="seek_seconds_forward">+%d segundos</string>

View File

@ -7,21 +7,4 @@
<item>Tamanho (decres.)</item> <item>Tamanho (decres.)</item>
<item>Data (decres.)</item> <item>Data (decres.)</item>
</string-array> </string-array>
<string-array name="themes_entries">
<item>Verde escuro</item>
<item>Verde preto</item>
<item>Vermelho escuro</item>
<item>Vermelho preto</item>
<item>Azul escuro</item>
<item>Azul preto</item>
<item>Amarelo escuro</item>
<item>Amarelo preto</item>
<item>Laranja escuro</item>
<item>Laranja preto</item>
<item>Roxo escuro</item>
<item>Roxo preto</item>
<item>Dark Pink</item>
<item>Black Pink</item>
</string-array>
</resources> </resources>

View File

@ -79,7 +79,6 @@
<string name="unsafe_features">Opções perigosas</string> <string name="unsafe_features">Opções perigosas</string>
<string name="manage_unsafe_features">Gerenciar opções perigosas</string> <string name="manage_unsafe_features">Gerenciar opções perigosas</string>
<string name="manage_unsafe_features_summary">Alternar opções perigosas</string> <string name="manage_unsafe_features_summary">Alternar opções perigosas</string>
<string name="ui">IU</string>
<string name="usf_home_warning_msg">DroidFS tenta ser o mais seguro possível. No entanto, a segurança muitas vezes resulta em falta de conforto. Por isso o DroidFS oferece opções adicionais que você pode alternar de acordo com as suas necessidades.\n\nAviso: estas opções podem ser PERIGOSAS. Não as utilize a menos que você saiba o que está fazendo. É altamente recomendável ler a documentação antes de ativá-las.</string> <string name="usf_home_warning_msg">DroidFS tenta ser o mais seguro possível. No entanto, a segurança muitas vezes resulta em falta de conforto. Por isso o DroidFS oferece opções adicionais que você pode alternar de acordo com as suas necessidades.\n\nAviso: estas opções podem ser PERIGOSAS. Não as utilize a menos que você saiba o que está fazendo. É altamente recomendável ler a documentação antes de ativá-las.</string>
<string name="see_unsafe_features">Ver opções perigosas</string> <string name="see_unsafe_features">Ver opções perigosas</string>
<string name="open_as">Abrir como</string> <string name="open_as">Abrir como</string>
@ -170,7 +169,6 @@
<string name="auto">Autom</string> <string name="auto">Autom</string>
<string name="encryption_cipher_label">Cipher de criptografia:</string> <string name="encryption_cipher_label">Cipher de criptografia:</string>
<string name="theme">Tema</string> <string name="theme">Tema</string>
<string name="theme_summary">Personalizar o tema do app</string>
<string name="thumbnails">Imagem em miniatura</string> <string name="thumbnails">Imagem em miniatura</string>
<string name="thumbnails_summary">Mostrar imagens e vídeos em miniatura</string> <string name="thumbnails_summary">Mostrar imagens e vídeos em miniatura</string>
<string name="seek_seconds_forward">+%d segundos</string> <string name="seek_seconds_forward">+%d segundos</string>

View File

@ -8,20 +8,4 @@
<item>Размер (по убыванию)</item> <item>Размер (по убыванию)</item>
<item>Дата (по убыванию)</item> <item>Дата (по убыванию)</item>
</string-array> </string-array>
<string-array name="themes_entries">
<item>Тёмно-зелёная</item>
<item>Чёрно-зелёная</item>
<item>Тёмно-красная</item>
<item>Чёрно-красная</item>
<item>Тёмно-синяя</item>
<item>Чёрно-синяя</item>
<item>Тёмно-жёлтая</item>
<item>Чёрно-жёлтая</item>
<item>Тёмно-оранжевая</item>
<item>Чёрно-оранжевая</item>
<item>Тёмно-фиолетовая</item>
<item>Чёрно-фиолетовая</item>
<item>Тёмно-розовая</item>
<item>Чёрно-розовая</item>
</string-array>
</resources> </resources>

View File

@ -76,7 +76,6 @@
<string name="unsafe_features">Небезопасные функции</string> <string name="unsafe_features">Небезопасные функции</string>
<string name="manage_unsafe_features">Управление небезопасными функциями</string> <string name="manage_unsafe_features">Управление небезопасными функциями</string>
<string name="manage_unsafe_features_summary">Включить/отключить небезопасные функции</string> <string name="manage_unsafe_features_summary">Включить/отключить небезопасные функции</string>
<string name="ui">Интерфейс</string>
<string name="usf_home_warning_msg">DroidFS старается быть максимально безопасным, однако безопасность часто связана с появлением неудобств. Поэтому DroidFS предлагает дополнительные небезопасные функции, которые вы можете включить/отключить в соответствии со своими потребностями.\n\nПредупреждение: эти функции могут быть НЕБЕЗОПАСНЫМИ. Не используйте их, если не уверены в своих действиях. Настоятельно рекомендуется прочитать документацию перед их включением.</string> <string name="usf_home_warning_msg">DroidFS старается быть максимально безопасным, однако безопасность часто связана с появлением неудобств. Поэтому DroidFS предлагает дополнительные небезопасные функции, которые вы можете включить/отключить в соответствии со своими потребностями.\n\nПредупреждение: эти функции могут быть НЕБЕЗОПАСНЫМИ. Не используйте их, если не уверены в своих действиях. Настоятельно рекомендуется прочитать документацию перед их включением.</string>
<string name="see_unsafe_features">Посмотреть небезопасные функции</string> <string name="see_unsafe_features">Посмотреть небезопасные функции</string>
<string name="open_as">Открыть как</string> <string name="open_as">Открыть как</string>
@ -168,7 +167,6 @@
<string name="auto">Авто</string> <string name="auto">Авто</string>
<string name="encryption_cipher_label">Шифр:</string> <string name="encryption_cipher_label">Шифр:</string>
<string name="theme">Тема</string> <string name="theme">Тема</string>
<string name="theme_summary">Настройка темы приложения</string>
<string name="thumbnails">Эскизы</string> <string name="thumbnails">Эскизы</string>
<string name="thumbnails_summary">Показывать эскизы изображений и видео</string> <string name="thumbnails_summary">Показывать эскизы изображений и видео</string>
<string name="seek_seconds_forward">+%d сек.</string> <string name="seek_seconds_forward">+%d сек.</string>

View File

@ -28,21 +28,14 @@
<item>Date (desc)</item> <item>Date (desc)</item>
</string-array> </string-array>
<string-array name="themes_entries"> <string-array name="color_names">
<item>Dark Green</item> <item>Green</item>
<item>Black Green</item> <item>Red</item>
<item>Dark Red</item> <item>Blue</item>
<item>Black Red</item> <item>Yellow</item>
<item>Dark Blue</item> <item>Orange</item>
<item>Black Blue</item> <item>Purple</item>
<item>Dark Yellow</item> <item>Pink</item>
<item>Black Yellow</item>
<item>Dark Orange</item>
<item>Black Orange</item>
<item>Dark Purple</item>
<item>Black Purple</item>
<item>Dark Pink</item>
<item>Black Pink</item>
</string-array> </string-array>
<!-- don't translate the following otherwise the app will crash --> <!-- don't translate the following otherwise the app will crash -->
@ -55,20 +48,13 @@
<item>date_desc</item> <item>date_desc</item>
</string-array> </string-array>
<string-array name="themes_values"> <string-array name="color_values">
<item>dark_green</item> <item>green</item>
<item>black_green</item> <item>red</item>
<item>dark_red</item> <item>blue</item>
<item>black_red</item> <item>yellow</item>
<item>dark_blue</item> <item>orange</item>
<item>black_blue</item> <item>purple</item>
<item>dark_yellow</item> <item>pink</item>
<item>black_yellow</item>
<item>dark_orange</item>
<item>black_orange</item>
<item>dark_purple</item>
<item>black_purple</item>
<item>dark_pink</item>
<item>black_pink</item>
</string-array> </string-array>
</resources> </resources>

View File

@ -80,7 +80,6 @@
<string name="unsafe_features">Unsafe Features</string> <string name="unsafe_features">Unsafe Features</string>
<string name="manage_unsafe_features">Manage unsafe features</string> <string name="manage_unsafe_features">Manage unsafe features</string>
<string name="manage_unsafe_features_summary">Enable/Disable unsafe features</string> <string name="manage_unsafe_features_summary">Enable/Disable unsafe features</string>
<string name="ui">UI</string>
<string name="usf_home_warning_msg">DroidFS try to be as secure as possible. However, security often involves lack of comfort. This is why DroidFS offer you additional unsafe features that you can enable/disable according to your needs.\n\nWarning: this features can be UNSAFE. Do not use them unless you know exactly what you are doing. It is highly recommended to read the documentation before enabling them.</string> <string name="usf_home_warning_msg">DroidFS try to be as secure as possible. However, security often involves lack of comfort. This is why DroidFS offer you additional unsafe features that you can enable/disable according to your needs.\n\nWarning: this features can be UNSAFE. Do not use them unless you know exactly what you are doing. It is highly recommended to read the documentation before enabling them.</string>
<string name="see_unsafe_features">See unsafe features</string> <string name="see_unsafe_features">See unsafe features</string>
<string name="open_as">Open as</string> <string name="open_as">Open as</string>
@ -175,7 +174,6 @@
<string name="auto">Auto</string> <string name="auto">Auto</string>
<string name="encryption_cipher_label">Encryption cipher:</string> <string name="encryption_cipher_label">Encryption cipher:</string>
<string name="theme">Theme</string> <string name="theme">Theme</string>
<string name="theme_summary">Customize app theme</string>
<string name="thumbnails">Thumbnails</string> <string name="thumbnails">Thumbnails</string>
<string name="thumbnails_summary">Show images and videos thumbnails</string> <string name="thumbnails_summary">Show images and videos thumbnails</string>
<string name="seek_seconds_forward">+%d seconds</string> <string name="seek_seconds_forward">+%d seconds</string>
@ -256,4 +254,8 @@
<string name="volume_unlocked">Volume unlocked</string> <string name="volume_unlocked">Volume unlocked</string>
<string name="lock_volume">Lock volume</string> <string name="lock_volume">Lock volume</string>
<string name="lock">Lock</string> <string name="lock">Lock</string>
<string name="ux">UX</string>
<string name="theme_color">Theme color</string>
<string name="theme_color_summary">Change app theme color</string>
<string name="black_theme">Black theme</string>
</resources> </resources>

View File

@ -1,37 +1,22 @@
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto" <PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"> xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/ui"> <PreferenceCategory android:title="@string/theme">
<ListPreference <ListPreference
android:defaultValue="dark_green" android:defaultValue="green"
android:entries="@array/themes_entries" android:entries="@array/color_names"
android:entryValues="@array/themes_values" android:entryValues="@array/color_values"
android:key="theme" android:key="color"
android:title="@string/theme" android:title="@string/theme_color"
android:summary="@string/theme_summary" android:summary="@string/theme_color_summary"
android:icon="@drawable/icon_palette"/> android:icon="@drawable/icon_palette"/>
<SwitchPreferenceCompat <SwitchPreferenceCompat
android:title="@string/auto_fit_title"
android:summary="@string/auto_fit_summary"
android:key="autoFit"
android:defaultValue="false" android:defaultValue="false"
android:icon="@drawable/icon_screen_rotation"/> android:icon="@drawable/icon_night"
android:key="black_theme"
<SwitchPreferenceCompat android:title="@string/black_theme"/>
android:title="@string/legacy_mod_title"
android:summary="@string/legacy_mod_summary"
android:key="legacyMod"
android:defaultValue="false"
android:icon="@drawable/icon_mod"/>
<SwitchPreferenceCompat
android:title="@string/pin_passwords_title"
android:summary="@string/pin_passwords_summary"
android:key="pin_passwords"
android:defaultValue="false"
android:icon="@drawable/icon_num_pad"/>
</PreferenceCategory> </PreferenceCategory>
@ -73,6 +58,31 @@
</PreferenceCategory> </PreferenceCategory>
<PreferenceCategory android:title="@string/ux">
<SwitchPreferenceCompat
android:title="@string/auto_fit_title"
android:summary="@string/auto_fit_summary"
android:key="autoFit"
android:defaultValue="false"
android:icon="@drawable/icon_screen_rotation"/>
<SwitchPreferenceCompat
android:title="@string/legacy_mod_title"
android:summary="@string/legacy_mod_summary"
android:key="legacyMod"
android:defaultValue="false"
android:icon="@drawable/icon_mod"/>
<SwitchPreferenceCompat
android:title="@string/pin_passwords_title"
android:summary="@string/pin_passwords_summary"
android:key="pin_passwords"
android:defaultValue="false"
android:icon="@drawable/icon_num_pad"/>
</PreferenceCategory>
<PreferenceCategory android:title="@string/unsafe_features"> <PreferenceCategory android:title="@string/unsafe_features">
<Preference <Preference

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/ui"> <PreferenceCategory android:title="@string/ux">
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="false"