diff --git a/app/src/main/java/sushi/hardcore/droidfs/BaseActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/BaseActivity.kt index 760f4d4..f595c48 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/BaseActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/BaseActivity.kt @@ -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() - } - } } \ No newline at end of file diff --git a/app/src/main/java/sushi/hardcore/droidfs/CameraActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/CameraActivity.kt index 6ae7ec5..bd96e35 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/CameraActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/CameraActivity.kt @@ -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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt index 489261f..847a7c9 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/ChangePasswordActivity.kt @@ -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(this, themeValue, R.string.loading_msg_change_password) { + object : LoadingTask(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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/Constants.kt b/app/src/main/java/sushi/hardcore/droidfs/Constants.kt index 9e027a2..e18751d 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/Constants.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/Constants.kt @@ -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" diff --git a/app/src/main/java/sushi/hardcore/droidfs/FingerprintProtector.kt b/app/src/main/java/sushi/hardcore/droidfs/FingerprintProtector.kt index 9461886..3052e01 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/FingerprintProtector.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/FingerprintProtector.kt @@ -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) { _, _ -> diff --git a/app/src/main/java/sushi/hardcore/droidfs/LoadingTask.kt b/app/src/main/java/sushi/hardcore/droidfs/LoadingTask.kt index 74294d7..1839f7e 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/LoadingTask.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/LoadingTask.kt @@ -8,8 +8,8 @@ import kotlinx.coroutines.withContext import sushi.hardcore.droidfs.databinding.DialogLoadingBinding import sushi.hardcore.droidfs.widgets.CustomAlertDialogBuilder -abstract class LoadingTask(val activity: FragmentActivity, themeValue: String, loadingMessageResId: Int) { - private val dialogLoading = CustomAlertDialogBuilder(activity, themeValue) +abstract class LoadingTask(val activity: FragmentActivity, theme: Theme, loadingMessageResId: Int) { + private val dialogLoading = CustomAlertDialogBuilder(activity, theme) .setView( DialogLoadingBinding.inflate(activity.layoutInflater).apply { textMessage.text = activity.getString(loadingMessageResId) diff --git a/app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt index 67a2776..d20f49e 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/MainActivity.kt @@ -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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt index 29b0b2a..27840ff 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/SettingsActivity.kt @@ -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(Constants.THEME_VALUE_KEY)?.setOnPreferenceChangeListener { _, newValue -> - (activity as BaseActivity).onThemeChanged(newValue as String) + findPreference("color")?.setOnPreferenceChangeListener { _, _ -> + refreshTheme() + true + } + findPreference("black_theme")?.setOnPreferenceChangeListener { _, _ -> + refreshTheme() true } findPreference(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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/Theme.kt b/app/src/main/java/sushi/hardcore/droidfs/Theme.kt new file mode 100644 index 0000000..01d22bd --- /dev/null +++ b/app/src/main/java/sushi/hardcore/droidfs/Theme.kt @@ -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 { + override fun createFromParcel(parcel: Parcel) = Theme(parcel) + override fun newArray(size: Int) = arrayOfNulls(size) + } + + fun fromSharedPrefs(sharedPrefs: SharedPreferences): Theme { + val color = sharedPrefs.getString("color", "green")!! + val black = sharedPrefs.getBoolean("black_theme", false) + return Theme(color, black) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/sushi/hardcore/droidfs/VolumeOpener.kt b/app/src/main/java/sushi/hardcore/droidfs/VolumeOpener.kt index 678b268..5944635 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/VolumeOpener.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/VolumeOpener.kt @@ -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(activity, themeValue, R.string.loading_msg_open) { + object : LoadingTask(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(activity, themeValue, R.string.loading_msg_open) { + object : LoadingTask(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) { _, _ -> diff --git a/app/src/main/java/sushi/hardcore/droidfs/add_volume/AddVolumeActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/add_volume/AddVolumeActivity.kt index 1c14777..f45d46a 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/add_volume/AddVolumeActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/add_volume/AddVolumeActivity.kt @@ -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, diff --git a/app/src/main/java/sushi/hardcore/droidfs/add_volume/CreateVolumeFragment.kt b/app/src/main/java/sushi/hardcore/droidfs/add_volume/CreateVolumeFragment.kt index 2f3714d..8b2cd35 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/add_volume/CreateVolumeFragment.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/add_volume/CreateVolumeFragment.kt @@ -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(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(null) - object: LoadingTask(requireActivity() as AppCompatActivity, themeValue, R.string.loading_msg_create) { + object: LoadingTask(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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/add_volume/SelectPathFragment.kt b/app/src/main/java/sushi/hardcore/droidfs/add_volume/SelectPathFragment.kt index df0bd44..a1c6478 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/add_volume/SelectPathFragment.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/add_volume/SelectPathFragment.kt @@ -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") diff --git a/app/src/main/java/sushi/hardcore/droidfs/content_providers/ExternalProvider.kt b/app/src/main/java/sushi/hardcore/droidfs/content_providers/ExternalProvider.kt index 217d69b..2330b03 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/content_providers/ExternalProvider.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/content_providers/ExternalProvider.kt @@ -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) { + fun share(activity: AppCompatActivity, theme: Theme, encryptedVolume: EncryptedVolume, file_paths: List) { var contentType: String? = null val uris = ArrayList(file_paths.size) - object : LoadingTask(activity, themeValue, R.string.loading_msg_export) { + object : LoadingTask(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(activity, themeValue, R.string.loading_msg_export) { + fun open(activity: AppCompatActivity, theme: Theme, encryptedVolume: EncryptedVolume, file_path: String) { + object : LoadingTask(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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt index 8140946..05c8384 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/BaseExplorerActivity.kt @@ -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 diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt index da14a3c..22801a4 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivity.kt @@ -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, 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, callback: (List?) -> Unit) { for (item in items) { if (encryptedVolume.pathExists(item.dstPath!!) && !item.overwriteConfirmed) { - CustomAlertDialogBuilder(this, themeValue) + CustomAlertDialogBuilder(this, theme) .setTitle(R.string.warning) .setMessage( getString( diff --git a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt index 1e802d9..047ec1f 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/explorers/ExplorerActivityDrop.kt @@ -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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt index 6ddef20..1265264 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/FileViewerActivity.kt @@ -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() } diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/ImageViewer.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/ImageViewer.kt index e65d578..8e29916 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/ImageViewer.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/ImageViewer.kt @@ -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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/MediaPlayer.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/MediaPlayer.kt index a4be14b..a4513ee 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/MediaPlayer.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/MediaPlayer.kt @@ -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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt index 6bf1359..324aa0b 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/file_viewers/TextEditor.kt @@ -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) { _, _ -> diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/Compat.kt b/app/src/main/java/sushi/hardcore/droidfs/util/Compat.kt new file mode 100644 index 0000000..5addff5 --- /dev/null +++ b/app/src/main/java/sushi/hardcore/droidfs/util/Compat.kt @@ -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 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) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.kt b/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.kt index 27c9936..173b826 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/util/PathUtils.kt @@ -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, context: Context, themeValue: String) { + fun safePickDirectory(directoryPicker: ActivityResultLauncher, 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) diff --git a/app/src/main/java/sushi/hardcore/droidfs/widgets/CustomAlertDialogBuilder.kt b/app/src/main/java/sushi/hardcore/droidfs/widgets/CustomAlertDialogBuilder.kt index d018a98..d87b216 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/widgets/CustomAlertDialogBuilder.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/widgets/CustomAlertDialogBuilder.kt @@ -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 diff --git a/app/src/main/java/sushi/hardcore/droidfs/widgets/EditTextDialog.kt b/app/src/main/java/sushi/hardcore/droidfs/widgets/EditTextDialog.kt index cd1fb92..c82d9ed 100644 --- a/app/src/main/java/sushi/hardcore/droidfs/widgets/EditTextDialog.kt +++ b/app/src/main/java/sushi/hardcore/droidfs/widgets/EditTextDialog.kt @@ -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) { diff --git a/app/src/main/res/drawable/icon_night.xml b/app/src/main/res/drawable/icon_night.xml new file mode 100644 index 0000000..ccaf249 --- /dev/null +++ b/app/src/main/res/drawable/icon_night.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/values-ar/arrays.xml b/app/src/main/res/values-ar/arrays.xml index 263bfdc..8847479 100644 --- a/app/src/main/res/values-ar/arrays.xml +++ b/app/src/main/res/values-ar/arrays.xml @@ -27,21 +27,4 @@ حجم (وصف) تاريخ (وصف) - - - داكن أخضر - أسود أخضر - داكن أحمر - أسود أحمر - داكن أزرق - أسود أزرق - داكن أصفر - أسود أصفر - داكن برتقالي - أسود برتقالي - داكن بنفسجي - أسود بنفسجي - داكن زهري - أسود زهري - diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 663ba79..fb70504 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -79,7 +79,6 @@ الميزات غير الآمنة إدارة الميزات غير الآمنة تمكين / تعطيل الميزات غير الآمنة - الواجهة الرسومية يحاول DroidFS أن يكون آمنًا قدر الإمكان. ولكن غالبًا ما ينطوي الأمان على عدم الراحة. ولهذا السبب فإن DroidFS يقدم لك ميزات إضافية غير آمنة يمكنك تمكينها وتعطيلها وفقًا لاحتياجاتك. تحذير: يمكن أن تكون هذه الميزات غير آمنة. لا تستخدمها إلا إذا كنت تعرف بالضبط ما تفعله. نوصي بشدة بقراءة الوثائق قبل تمكينها. انظر الميزات غير الآمنة فتح ك @@ -174,7 +173,6 @@ تلقائي خوارزمية التشفير: سمة - تخصيص سمة التطبيق صور مصغرة عرض صور مصغرة للصور ومقاطع الفيديو +%d ثواني diff --git a/app/src/main/res/values-es/arrays.xml b/app/src/main/res/values-es/arrays.xml index 7a1bb37..c99ce5f 100644 --- a/app/src/main/res/values-es/arrays.xml +++ b/app/src/main/res/values-es/arrays.xml @@ -7,21 +7,4 @@ Tamaño (desc) Fecha (desc) - - - Verde Oscuro - Verde Negro - Rojo Oscuro - Rojo Negro - Azul Oscuro - Azul Negro - Amarillo Oscuro - Amarillo Negro - Naranja Oscuro - Naranja Negro - Morado Oscuro - Morado Negro - Dark Pink - Black Pink - \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index c29d311..040e5c6 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -79,7 +79,6 @@ Características inseguras Gestionar las características inseguras Activar/desactivar funciones inseguras - Interfaz 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. Ver características inseguras Abrir como @@ -174,7 +173,6 @@ Automático Cifrado de encriptación: Tema - Personalizar el tema de la aplicación Miniaturas Mostrar miniaturas de imágenes y vídeos +%d segundos diff --git a/app/src/main/res/values-pt-rBR/arrays.xml b/app/src/main/res/values-pt-rBR/arrays.xml index e9c8def..1a4509d 100644 --- a/app/src/main/res/values-pt-rBR/arrays.xml +++ b/app/src/main/res/values-pt-rBR/arrays.xml @@ -7,21 +7,4 @@ Tamanho (decres.) Data (decres.) - - - Verde escuro - Verde preto - Vermelho escuro - Vermelho preto - Azul escuro - Azul preto - Amarelo escuro - Amarelo preto - Laranja escuro - Laranja preto - Roxo escuro - Roxo preto - Dark Pink - Black Pink - diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index 776d40d..cca68de 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -79,7 +79,6 @@ Opções perigosas Gerenciar opções perigosas Alternar opções perigosas - IU 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. Ver opções perigosas Abrir como @@ -170,7 +169,6 @@ Autom Cipher de criptografia: Tema - Personalizar o tema do app Imagem em miniatura Mostrar imagens e vídeos em miniatura +%d segundos diff --git a/app/src/main/res/values-ru/arrays.xml b/app/src/main/res/values-ru/arrays.xml index f9659a7..4ebe713 100644 --- a/app/src/main/res/values-ru/arrays.xml +++ b/app/src/main/res/values-ru/arrays.xml @@ -8,20 +8,4 @@ Размер (по убыванию) Дата (по убыванию) - - Тёмно-зелёная - Чёрно-зелёная - Тёмно-красная - Чёрно-красная - Тёмно-синяя - Чёрно-синяя - Тёмно-жёлтая - Чёрно-жёлтая - Тёмно-оранжевая - Чёрно-оранжевая - Тёмно-фиолетовая - Чёрно-фиолетовая - Тёмно-розовая - Чёрно-розовая - diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ea20ff6..09bc126 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -76,7 +76,6 @@ Небезопасные функции Управление небезопасными функциями Включить/отключить небезопасные функции - Интерфейс DroidFS старается быть максимально безопасным, однако безопасность часто связана с появлением неудобств. Поэтому DroidFS предлагает дополнительные небезопасные функции, которые вы можете включить/отключить в соответствии со своими потребностями.\n\nПредупреждение: эти функции могут быть НЕБЕЗОПАСНЫМИ. Не используйте их, если не уверены в своих действиях. Настоятельно рекомендуется прочитать документацию перед их включением. Посмотреть небезопасные функции Открыть как @@ -168,7 +167,6 @@ Авто Шифр: Тема - Настройка темы приложения Эскизы Показывать эскизы изображений и видео +%d сек. diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 9a3b406..f20d0cc 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -28,21 +28,14 @@ Date (desc) - - Dark Green - Black Green - Dark Red - Black Red - Dark Blue - Black Blue - Dark Yellow - Black Yellow - Dark Orange - Black Orange - Dark Purple - Black Purple - Dark Pink - Black Pink + + Green + Red + Blue + Yellow + Orange + Purple + Pink @@ -55,20 +48,13 @@ date_desc - - dark_green - black_green - dark_red - black_red - dark_blue - black_blue - dark_yellow - black_yellow - dark_orange - black_orange - dark_purple - black_purple - dark_pink - black_pink + + green + red + blue + yellow + orange + purple + pink \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1d9b4a7..649089a 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -80,7 +80,6 @@ Unsafe Features Manage unsafe features Enable/Disable unsafe features - UI 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. See unsafe features Open as @@ -175,7 +174,6 @@ Auto Encryption cipher: Theme - Customize app theme Thumbnails Show images and videos thumbnails +%d seconds @@ -256,4 +254,8 @@ Volume unlocked Lock volume Lock + UX + Theme color + Change app theme color + Black theme diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 3643dfe..7df3298 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -1,37 +1,22 @@ - + - - - - + android:icon="@drawable/icon_night" + android:key="black_theme" + android:title="@string/black_theme"/> @@ -73,6 +58,31 @@ + + + + + + + + + + - +