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() {
protected lateinit var sharedPrefs: SharedPreferences
protected var applyCustomTheme: Boolean = true
lateinit var themeValue: String
private var shouldCheckTheme = true
lateinit var theme: Theme
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)
if (!sharedPrefs.getBoolean("usf_screenshot", false)){
sharedPrefs = (application as VolumeManagerApp).sharedPreferences
theme = Theme.fromSharedPrefs(sharedPrefs)
if (applyCustomTheme) {
setTheme(theme.toResourceId())
}
if (!sharedPrefs.getBoolean("usf_screenshot", false)) {
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 {
1
}
CustomAlertDialogBuilder(this, themeValue)
CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.camera_optimization)
.setSingleChoiceItems(arrayOf(getString(R.string.maximize_quality), getString(R.string.minimize_latency)), currentIndex) { dialog, which ->
val resId: Int
@ -150,7 +150,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
}
binding.imageRatio.setOnClickListener {
resolutions?.let {
CustomAlertDialogBuilder(this, themeValue)
CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.choose_resolution)
.setSingleChoiceItems(it.map { size -> size.toString() }.toTypedArray(), currentResolutionIndex) { dialog, which ->
currentResolution = resolutions!![which]
@ -283,7 +283,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
permissionsGranted = true
setupCamera()
} else {
CustomAlertDialogBuilder(this, themeValue)
CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error)
.setMessage(R.string.camera_perm_needed)
.setCancelable(false)
@ -410,7 +410,7 @@ class CameraActivity : BaseActivity(), SensorOrientationListener.Listener {
if (encryptedVolume.importFile(ByteArrayInputStream(outputBuff.toByteArray()), outputPath)) {
Toast.makeText(applicationContext, getString(R.string.picture_save_success, outputPath), Toast.LENGTH_SHORT).show()
} else {
CustomAlertDialogBuilder(this@CameraActivity, themeValue)
CustomAlertDialogBuilder(this@CameraActivity, theme)
.setTitle(R.string.error)
.setMessage(R.string.picture_save_failed)
.setCancelable(false)

View File

@ -42,7 +42,7 @@ class ChangePasswordActivity: BaseActivity() {
volumeDatabase = VolumeDatabase(this)
usfFingerprint = sharedPrefs.getBoolean("usf_fingerprint", false)
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) {
binding.fingerprintSwitchContainer.visibility = View.VISIBLE
}
@ -139,7 +139,7 @@ class ChangePasswordActivity: BaseActivity() {
} else {
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 {
val success = if (volume.type == EncryptedVolume.GOCRYPTFS_VOLUME_TYPE) {
GocryptfsVolume.changePassword(
@ -199,7 +199,7 @@ class ChangePasswordActivity: BaseActivity() {
finish()
}
} else {
CustomAlertDialogBuilder(this, themeValue)
CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error)
.setMessage(R.string.change_password_failed)
.setPositiveButton(R.string.ok, null)

View File

@ -11,7 +11,6 @@ object Constants {
const val IO_BUFF_SIZE = 16384
const val SLIDESHOW_DELAY: Long = 4000
const val DEFAULT_THEME_VALUE = "dark_green"
const val THEME_VALUE_KEY = "theme"
const val DEFAULT_VOLUME_KEY = "default_volume"
const val REMEMBER_VOLUME_KEY = "remember_volume"
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)
class FingerprintProtector private constructor(
private val activity: FragmentActivity,
private val themeValue: String,
private val theme: Theme,
private val volumeDatabase: VolumeDatabase,
) {
@ -54,11 +54,11 @@ class FingerprintProtector private constructor(
fun new(
activity: FragmentActivity,
themeValue: String,
theme: Theme,
volumeDatabase: VolumeDatabase,
): FingerprintProtector? {
return if (canAuthenticate(activity) == 0)
FingerprintProtector(activity, themeValue, volumeDatabase)
FingerprintProtector(activity, theme, volumeDatabase)
else
null
}
@ -98,7 +98,7 @@ class FingerprintProtector private constructor(
listener.onPasswordHashDecrypted(plainText)
} catch (e: AEADBadTagException) {
listener.onFailed(true)
CustomAlertDialogBuilder(activity, themeValue)
CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.error)
.setMessage(R.string.MAC_verification_failed)
.setPositiveButton(R.string.reset_hash_storage) { _, _ ->
@ -112,7 +112,7 @@ class FingerprintProtector private constructor(
}
} catch (e: IllegalBlockSizeException) {
listener.onFailed(true)
CustomAlertDialogBuilder(activity, themeValue)
CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.illegal_block_size_exception)
.setMessage(R.string.illegal_block_size_exception_msg)
.setPositiveButton(R.string.reset_hash_storage) { _, _ ->
@ -159,7 +159,7 @@ class FingerprintProtector private constructor(
keyStore.getKey(KEY_ALIAS, null) as SecretKey
} catch (e: UnrecoverableKeyException) {
listener.onFailed(true)
CustomAlertDialogBuilder(activity, themeValue)
CustomAlertDialogBuilder(activity, theme)
.setTitle(activity.getString(R.string.unrecoverable_key_exception))
.setMessage(activity.getString(R.string.unrecoverable_key_exception_msg, e.localizedMessage))
.setPositiveButton(R.string.reset_hash_storage) { _, _ ->
@ -196,7 +196,7 @@ class FingerprintProtector private constructor(
private fun alertKeyPermanentlyInvalidatedException() {
listener.onFailed(true)
CustomAlertDialogBuilder(activity, themeValue)
CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.key_permanently_invalidated_exception)
.setMessage(R.string.key_permanently_invalidated_exception_msg)
.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.widgets.CustomAlertDialogBuilder
abstract class LoadingTask<T>(val activity: FragmentActivity, themeValue: String, loadingMessageResId: Int) {
private val dialogLoading = CustomAlertDialogBuilder(activity, themeValue)
abstract class LoadingTask<T>(val activity: FragmentActivity, theme: Theme, loadingMessageResId: Int) {
private val dialogLoading = CustomAlertDialogBuilder(activity, theme)
.setView(
DialogLoadingBinding.inflate(activity.layoutInflater).apply {
textMessage.text = activity.getString(loadingMessageResId)

View File

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

View File

@ -1,5 +1,6 @@
package sushi.hardcore.droidfs
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
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?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(requireContext())
findPreference<ListPreference>(Constants.THEME_VALUE_KEY)?.setOnPreferenceChangeListener { _, newValue ->
(activity as BaseActivity).onThemeChanged(newValue as String)
findPreference<ListPreference>("color")?.setOnPreferenceChangeListener { _, _ ->
refreshTheme()
true
}
findPreference<SwitchPreferenceCompat>("black_theme")?.setOnPreferenceChangeListener { _, _ ->
refreshTheme()
true
}
findPreference<Preference>(Constants.THUMBNAIL_MAX_SIZE_KEY)?.let {
@ -126,7 +139,7 @@ class SettingsActivity : BaseActivity() {
if (errorMsg == null) {
true
} else {
CustomAlertDialogBuilder(requireContext(), (requireActivity() as BaseActivity).themeValue)
CustomAlertDialogBuilder(requireContext(), (requireActivity() as BaseActivity).theme)
.setTitle(R.string.error)
.setMessage(errorMsg)
.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 var fingerprintProtector: FingerprintProtector? = null
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)
private var dialogBinding: DialogOpenVolumeBinding? = null
private val volumeManager = (activity.application as VolumeManagerApp).volumeManager
init {
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()
}
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? {
val encryptedVolume = EncryptedVolume.init(volume, activity.filesDir.path, null, hash, null)
Arrays.fill(hash, 0)
@ -68,7 +68,7 @@ class VolumeOpener(
}
}.startTask(activity.lifecycleScope) { encryptedVolume ->
if (encryptedVolume == null) {
CustomAlertDialogBuilder(activity, themeValue)
CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.open_volume_failed)
.setMessage(R.string.open_failed_hash_msg)
.setPositiveButton(R.string.ok, null)
@ -140,7 +140,7 @@ class VolumeOpener(
dialogBinding!!.checkboxSavePassword.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))
.setView(dialogBinding!!.root)
.setNegativeButton(R.string.cancel, null)
@ -168,7 +168,7 @@ class VolumeOpener(
} else {
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? {
val encryptedVolume = EncryptedVolume.init(volume, activity.filesDir.path, password, null, returnedHash)
Arrays.fill(password, 0)
@ -176,7 +176,7 @@ class VolumeOpener(
}
}.startTask(activity.lifecycleScope) { encryptedVolume ->
if (encryptedVolume == null) {
CustomAlertDialogBuilder(activity, themeValue)
CustomAlertDialogBuilder(activity, theme)
.setTitle(R.string.open_volume_failed)
.setMessage(R.string.open_volume_failed_msg)
.setPositiveButton(R.string.ok) { _, _ ->

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -34,7 +34,7 @@ class TextEditor: FileViewerActivity() {
checkSaveAndExit()
}
} catch (e: OutOfMemoryError){
CustomAlertDialogBuilder(this, themeValue)
CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.error)
.setMessage(R.string.outofmemoryerror_msg)
.setCancelable(false)
@ -87,7 +87,7 @@ class TextEditor: FileViewerActivity() {
private fun checkSaveAndExit(){
if (changedSinceLastSave){
CustomAlertDialogBuilder(this, themeValue)
CustomAlertDialogBuilder(this, theme)
.setTitle(R.string.warning)
.setMessage(R.string.ask_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.core.content.ContextCompat
import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.Theme
import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder
import java.io.File
import java.text.DecimalFormat
@ -226,11 +227,11 @@ object PathUtils {
return rootDirectory.delete()
}
fun safePickDirectory(directoryPicker: ActivityResultLauncher<Uri?>, context: Context, themeValue: String) {
fun safePickDirectory(directoryPicker: ActivityResultLauncher<Uri?>, context: Context, theme: Theme) {
try {
directoryPicker.launch(null)
} catch (e: ActivityNotFoundException) {
CustomAlertDialogBuilder(context, themeValue)
CustomAlertDialogBuilder(context, theme)
.setTitle(R.string.error)
.setMessage(R.string.open_tree_failed)
.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.WindowInsetsControllerCompat
import sushi.hardcore.droidfs.R
import sushi.hardcore.droidfs.Theme
open class CustomAlertDialogBuilder(context: Context, theme: String) : AlertDialog.Builder(
context, when (theme) {
"black_green" -> R.style.BlackGreenDialog
"dark_red" -> R.style.DarkRedDialog
"black_red" -> R.style.BlackRedDialog
"dark_blue" -> R.style.DarkBlueDialog
"black_blue" -> R.style.BlackBlueDialog
"dark_yellow" -> R.style.DarkYellowDialog
"black_yellow" -> R.style.BlackYellowDialog
"dark_orange" -> R.style.DarkOrangeDialog
"black_orange" -> R.style.BlackOrangeDialog
"dark_purple" -> R.style.DarkPurpleDialog
"black_purple" -> R.style.BlackPurpleDialog
"dark_pink" -> R.style.DarkPinkDialog
"black_pink" -> R.style.BlackPinkDialog
else -> R.style.DarkGreenDialog
}
open class CustomAlertDialogBuilder(context: Context, theme: Theme) : AlertDialog.Builder(
context, if (theme.black) {
when (theme.color) {
"red" -> R.style.BlackRedDialog
"blue" -> R.style.BlackBlueDialog
"yellow" -> R.style.BlackYellowDialog
"orange" -> R.style.BlackOrangeDialog
"purple" -> R.style.BlackPurpleDialog
"pink" -> R.style.BlackPinkDialog
else -> R.style.BlackGreenDialog
}
} else {
when (theme.color) {
"red" -> R.style.DarkRedDialog
"blue" -> R.style.DarkBlueDialog
"yellow" -> R.style.DarkYellowDialog
"orange" -> R.style.DarkOrangeDialog
"purple" -> R.style.DarkPurpleDialog
"pink" -> R.style.DarkPinkDialog
else -> R.style.DarkGreenDialog
}
}
) {
private var keepFullScreen = false

View File

@ -10,7 +10,7 @@ class EditTextDialog(
activity: BaseActivity,
private val titleId: Int,
private val callback: (String) -> Unit,
): CustomAlertDialogBuilder(activity, activity.themeValue) {
): CustomAlertDialogBuilder(activity, activity.theme) {
val binding = DialogEditTextBinding.inflate(activity.layoutInflater)
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>
</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>

View File

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

View File

@ -7,21 +7,4 @@
<item>Tamaño (desc)</item>
<item>Fecha (desc)</item>
</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>

View File

@ -79,7 +79,6 @@
<string name="unsafe_features">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="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="see_unsafe_features">Ver características inseguras</string>
<string name="open_as">Abrir como</string>
@ -174,7 +173,6 @@
<string name="auto">Automático</string>
<string name="encryption_cipher_label">Cifrado de encriptación:</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_summary">Mostrar miniaturas de imágenes y vídeos</string>
<string name="seek_seconds_forward">+%d segundos</string>

View File

@ -7,21 +7,4 @@
<item>Tamanho (decres.)</item>
<item>Data (decres.)</item>
</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>

View File

@ -79,7 +79,6 @@
<string name="unsafe_features">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="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="see_unsafe_features">Ver opções perigosas</string>
<string name="open_as">Abrir como</string>
@ -170,7 +169,6 @@
<string name="auto">Autom</string>
<string name="encryption_cipher_label">Cipher de criptografia:</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_summary">Mostrar imagens e vídeos em miniatura</string>
<string name="seek_seconds_forward">+%d segundos</string>

View File

@ -8,20 +8,4 @@
<item>Размер (по убыванию)</item>
<item>Дата (по убыванию)</item>
</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>

View File

@ -76,7 +76,6 @@
<string name="unsafe_features">Небезопасные функции</string>
<string name="manage_unsafe_features">Управление небезопасными функциями</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="see_unsafe_features">Посмотреть небезопасные функции</string>
<string name="open_as">Открыть как</string>
@ -168,7 +167,6 @@
<string name="auto">Авто</string>
<string name="encryption_cipher_label">Шифр:</string>
<string name="theme">Тема</string>
<string name="theme_summary">Настройка темы приложения</string>
<string name="thumbnails">Эскизы</string>
<string name="thumbnails_summary">Показывать эскизы изображений и видео</string>
<string name="seek_seconds_forward">+%d сек.</string>

View File

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

View File

@ -80,7 +80,6 @@
<string name="unsafe_features">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="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="see_unsafe_features">See unsafe features</string>
<string name="open_as">Open as</string>
@ -175,7 +174,6 @@
<string name="auto">Auto</string>
<string name="encryption_cipher_label">Encryption cipher:</string>
<string name="theme">Theme</string>
<string name="theme_summary">Customize app theme</string>
<string name="thumbnails">Thumbnails</string>
<string name="thumbnails_summary">Show images and videos thumbnails</string>
<string name="seek_seconds_forward">+%d seconds</string>
@ -256,4 +254,8 @@
<string name="volume_unlocked">Volume unlocked</string>
<string name="lock_volume">Lock volume</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>

View File

@ -1,37 +1,22 @@
<PreferenceScreen xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<PreferenceCategory android:title="@string/ui">
<PreferenceCategory android:title="@string/theme">
<ListPreference
android:defaultValue="dark_green"
android:entries="@array/themes_entries"
android:entryValues="@array/themes_values"
android:key="theme"
android:title="@string/theme"
android:summary="@string/theme_summary"
android:defaultValue="green"
android:entries="@array/color_names"
android:entryValues="@array/color_values"
android:key="color"
android:title="@string/theme_color"
android:summary="@string/theme_color_summary"
android:icon="@drawable/icon_palette"/>
<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"/>
android:icon="@drawable/icon_night"
android:key="black_theme"
android:title="@string/black_theme"/>
</PreferenceCategory>
@ -73,6 +58,31 @@
</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">
<Preference

View File

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