diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ae19ee4..df3ad3a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ ### Changed - RPC client is rewritten to use OkHttp library instead of Qt +- All torrent adding parameters are now remembered together with download directory ## [2.9.1] - 2023-03-26 ### Fixed diff --git a/app/src/main/kotlin/org/equeim/tremotesf/ui/Settings.kt b/app/src/main/kotlin/org/equeim/tremotesf/ui/Settings.kt index 702ff4ee..824f5236 100644 --- a/app/src/main/kotlin/org/equeim/tremotesf/ui/Settings.kt +++ b/app/src/main/kotlin/org/equeim/tremotesf/ui/Settings.kt @@ -27,6 +27,7 @@ import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.equeim.tremotesf.R import org.equeim.tremotesf.TremotesfApplication +import org.equeim.tremotesf.torrentfile.rpc.requests.torrentproperties.TorrentLimits import org.equeim.tremotesf.ui.Settings.Property import org.equeim.tremotesf.ui.torrentslistfragment.TorrentsListFragmentViewModel import timber.log.Timber @@ -106,31 +107,58 @@ object Settings { putString(colorTheme.key, newValue) } } + context.getString(R.string.deprecated_prefs_remember_download_directory_key) + .let { deprecatedRememberDownloadDirectoryKey -> + if (preferences.contains(deprecatedRememberDownloadDirectoryKey)) { + preferences.edit { + putBoolean( + rememberAddTorrentParameters.key, + preferences.getBoolean(deprecatedRememberDownloadDirectoryKey, false) + ) + remove(deprecatedRememberDownloadDirectoryKey) + } + } + } migrated = true } } } + private class EnumPrefsMapper>( + private val enumClass: Class, + @StringRes private val keyResId: Int, + @StringRes private val defaultValueResId: Int, + val enumToPrefsValue: (T) -> String, + ) { + private val enumValues = requireNotNull(enumClass.enumConstants) + + fun prefsValueToEnum(prefsValue: String): T { + enumValues.find { enumToPrefsValue(it) == prefsValue }?.let { return it } + val key = context.getString(keyResId) + Timber.e("Unknown prefs value $prefsValue for key $key and enum $enumClass") + val defaultPrefsValue = context.getString(defaultValueResId) + return enumValues.find { enumToPrefsValue(it) == defaultPrefsValue } + ?: throw IllegalStateException("Did not find value of enum $enumClass for default prefs value $defaultPrefsValue and key $key") + } + } + + private inline fun > EnumPrefsMapper( + @StringRes keyResId: Int, + @StringRes defaultValueResId: Int, + noinline enumToPrefsValue: (T) -> String, + ): EnumPrefsMapper = + EnumPrefsMapper(T::class.java, keyResId, defaultValueResId, enumToPrefsValue) + private interface MappedPrefsEnum { val prefsValue: String - - companion object { - inline fun fromPrefsValueProvider( - @StringRes keyResId: Int, - @StringRes defaultValueResId: Int, - ): (String) -> T where T : MappedPrefsEnum, T : Enum { - val values = enumValues() - return { prefsValue -> - values.find { it.prefsValue == prefsValue } ?: run { - Timber.e("Unknown value $prefsValue for key ${context.getString(keyResId)}") - val defaultPrefsValue = context.getString(defaultValueResId) - values.single { it.prefsValue == defaultPrefsValue } - } - } - } - } } + private inline fun EnumPrefsMapper( + @StringRes keyResId: Int, + @StringRes defaultValueResId: Int, + ): EnumPrefsMapper where T : MappedPrefsEnum, T : Enum = + EnumPrefsMapper(T::class.java, keyResId, defaultValueResId, MappedPrefsEnum::prefsValue) + enum class ColorTheme( @StringRes prefsValueResId: Int, @StyleRes val activityThemeResId: Int = 0, @@ -140,20 +168,15 @@ object Settings { Teal(R.string.prefs_color_theme_value_teal, R.style.AppTheme_Teal); override val prefsValue = context.getString(prefsValueResId) - - companion object { - val fromPrefsValue = MappedPrefsEnum.fromPrefsValueProvider( - R.string.prefs_color_theme_key, - R.string.prefs_color_theme_default_value - ) - } } + private val colorThemeMapper = + EnumPrefsMapper(R.string.prefs_color_theme_key, R.string.prefs_color_theme_default_value) val colorTheme: MutableProperty = mutableProperty( R.string.prefs_color_theme_key, R.string.prefs_color_theme_default_value ).map( - transformGetter = ColorTheme.fromPrefsValue, + transformGetter = colorThemeMapper::prefsValueToEnum, transformSetter = { it.prefsValue } ) @@ -171,20 +194,17 @@ object Settings { Off(R.string.prefs_dark_theme_mode_value_off, AppCompatDelegate.MODE_NIGHT_NO); override val prefsValue = context.getString(prefsValueResId) - - companion object { - val fromPrefsValue = MappedPrefsEnum.fromPrefsValueProvider( - R.string.prefs_dark_theme_mode_key, - R.string.prefs_dark_theme_mode_default_value - ) - } } + private val darkThemeModeMapper = EnumPrefsMapper( + R.string.prefs_dark_theme_mode_key, + R.string.prefs_dark_theme_mode_default_value + ) val darkThemeMode: Property = property( R.string.prefs_dark_theme_mode_key, R.string.prefs_dark_theme_mode_default_value - ).map(DarkThemeMode.fromPrefsValue) + ).map(darkThemeModeMapper::prefsValueToEnum) val torrentCompactView: Property = property( R.string.prefs_torrent_compact_view_key, @@ -247,8 +267,47 @@ object Settings { val fillTorrentLinkFromKeyboard: Property = property(R.string.prefs_link_from_clipboard_key, R.bool.prefs_link_from_clipboard_default_value) - val rememberDownloadDirectory: Property = - property(R.string.prefs_remember_download_directory_key, R.bool.prefs_remember_download_directory_default_value) + val rememberAddTorrentParameters: Property = + property( + R.string.prefs_remember_add_torrent_parameters_key, + R.bool.prefs_remember_add_torrent_parameters_default_value + ) + + enum class StartTorrentAfterAdding(override val prefsValue: String) : MappedPrefsEnum { + Start("start"), + DontStart("dont_start"), + Unknown("unknown") + } + + private val startTorrentAfterAddingMapper = EnumPrefsMapper( + R.string.prefs_last_add_torrent_start_after_adding_key, + R.string.prefs_last_add_torrent_start_after_adding_default_value + ) + val lastAddTorrentStartAfterAdding: MutableProperty = mutableProperty( + R.string.prefs_last_add_torrent_start_after_adding_key, + R.string.prefs_last_add_torrent_start_after_adding_default_value + ).map( + transformGetter = startTorrentAfterAddingMapper::prefsValueToEnum, + transformSetter = startTorrentAfterAddingMapper.enumToPrefsValue + ) + + private val bandwidthPriorityMapper = EnumPrefsMapper( + R.string.prefs_last_add_torrent_priority_key, + R.string.prefs_last_add_torrent_priority_default_value + ) { + when (it) { + TorrentLimits.BandwidthPriority.Low -> "low" + TorrentLimits.BandwidthPriority.Normal -> "normal" + TorrentLimits.BandwidthPriority.High -> "high" + } + } + val lastAddTorrentPriority: MutableProperty = mutableProperty( + R.string.prefs_last_add_torrent_priority_key, + R.string.prefs_last_add_torrent_priority_default_value + ).map( + transformGetter = bandwidthPriorityMapper::prefsValueToEnum, + transformSetter = bandwidthPriorityMapper.enumToPrefsValue + ) val torrentsSortMode: MutableProperty = mutableProperty( diff --git a/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/AddTorrentFileFragment.kt b/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/AddTorrentFileFragment.kt index e7db950c..732dad96 100644 --- a/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/AddTorrentFileFragment.kt +++ b/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/AddTorrentFileFragment.kt @@ -70,7 +70,7 @@ class AddTorrentFileFragment : AddTorrentFragment( 0 ) { private val args: AddTorrentFileFragmentArgs by navArgs() - val model: AddTorrentFileModel by viewModels { + val model: AddTorrentFileModelImpl by viewModels { viewModelFactory { initializer { AddTorrentFileModelImpl( @@ -323,15 +323,14 @@ class AddTorrentFileFragment : AddTorrentFragment( if (model.shouldSetInitialRpcInputs) { val downloadingSettings = it.downloadingSettings.response downloadDirectoryLayout.downloadDirectoryEdit.setText( - model.getInitialDownloadDirectory( - downloadingSettings - ) + model.getInitialDownloadDirectory(downloadingSettings) ) - startDownloadingCheckBox.isChecked = downloadingSettings.startAddedTorrents + startDownloadingCheckBox.isChecked = model.getInitialStartAfterAdding(downloadingSettings) model.shouldSetInitialRpcInputs = false } if (model.shouldSetInitialLocalInputs) { - priorityView.setText(R.string.normal_priority) + val parent = requireParentFragment() as AddTorrentFileFragment + priorityView.setText(parent.priorityItems[parent.priorityItemEnums.indexOf(model.getInitialPriority())]) model.shouldSetInitialLocalInputs = false } } diff --git a/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/AddTorrentLinkFragment.kt b/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/AddTorrentLinkFragment.kt index b13fc6a7..998a8ff7 100644 --- a/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/AddTorrentLinkFragment.kt +++ b/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/AddTorrentLinkFragment.kt @@ -203,12 +203,12 @@ class AddTorrentLinkFragment : AddTorrentFragment( private suspend fun showView(downloadingSettings: DownloadingServerSettings) = with(binding) { if (model.shouldSetInitialRpcInputs) { downloadDirectoryLayout.downloadDirectoryEdit.setText(model.getInitialDownloadDirectory(downloadingSettings)) - startDownloadingCheckBox.isChecked = downloadingSettings.startAddedTorrents + startDownloadingCheckBox.isChecked = model.getInitialStartAfterAdding(downloadingSettings) model.shouldSetInitialRpcInputs = false } if (model.shouldSetInitialLocalInputs) { torrentLinkEdit.setText(model.getInitialTorrentLink()) - priorityView.setText(R.string.normal_priority) + priorityView.setText(priorityItems[priorityItemEnums.indexOf(model.getInitialPriority())]) model.shouldSetInitialLocalInputs = false } scrollView.isVisible = true diff --git a/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/BaseAddTorrentModel.kt b/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/BaseAddTorrentModel.kt index fd713cfb..3cb7a333 100644 --- a/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/BaseAddTorrentModel.kt +++ b/app/src/main/kotlin/org/equeim/tremotesf/ui/addtorrent/BaseAddTorrentModel.kt @@ -19,6 +19,7 @@ import org.equeim.tremotesf.torrentfile.rpc.requests.FileSize import org.equeim.tremotesf.torrentfile.rpc.requests.getFreeSpaceInDirectory import org.equeim.tremotesf.torrentfile.rpc.requests.serversettings.DownloadingServerSettings import org.equeim.tremotesf.torrentfile.rpc.requests.serversettings.getDownloadingServerSettings +import org.equeim.tremotesf.torrentfile.rpc.requests.torrentproperties.TorrentLimits import org.equeim.tremotesf.torrentfile.rpc.stateIn import org.equeim.tremotesf.torrentfile.rpc.toNativeSeparators import org.equeim.tremotesf.ui.Settings @@ -34,7 +35,7 @@ abstract class BaseAddTorrentModel(application: Application) : AndroidViewModel( .stateIn(GlobalRpcClient, viewModelScope) suspend fun getInitialDownloadDirectory(settings: DownloadingServerSettings): String { - return if (Settings.rememberDownloadDirectory.get()) { + return if (Settings.rememberAddTorrentParameters.get()) { GlobalServers.serversState.value.currentServer ?.lastDownloadDirectory ?.takeIf { it.isNotEmpty() } @@ -45,6 +46,24 @@ abstract class BaseAddTorrentModel(application: Application) : AndroidViewModel( }.toNativeSeparators() } + suspend fun getInitialStartAfterAdding(settings: DownloadingServerSettings): Boolean = + if (Settings.rememberAddTorrentParameters.get()) { + when (Settings.lastAddTorrentStartAfterAdding.get()) { + Settings.StartTorrentAfterAdding.Start -> true + Settings.StartTorrentAfterAdding.DontStart -> false + Settings.StartTorrentAfterAdding.Unknown -> settings.startAddedTorrents + } + } else { + settings.startAddedTorrents + } + + suspend fun getInitialPriority(): TorrentLimits.BandwidthPriority = + if (Settings.rememberAddTorrentParameters.get()) { + Settings.lastAddTorrentPriority.get() + } else { + TorrentLimits.BandwidthPriority.Normal + } + suspend fun getFreeSpace(directory: String): FileSize? = try { GlobalRpcClient.getFreeSpaceInDirectory(directory) } catch (e: RpcRequestError) { diff --git a/app/src/main/res/values-de-rDE/strings.xml b/app/src/main/res/values-de-rDE/strings.xml index 1b14b284..06b9b2db 100644 --- a/app/src/main/res/values-de-rDE/strings.xml +++ b/app/src/main/res/values-de-rDE/strings.xml @@ -416,7 +416,7 @@ SPDX-License-Identifier: GPL-3.0-or-later Lösche Dateien auf der Festplatte, wenn der Torrent gelöscht wird Beim Hinzufügen eines Torrent-Links automatisch den Link aus der Zwischenablage ausfüllen - Letztes Download-Verzeichnis merken + Letztes Download-Verzeichnis merken Alternative Geschwindigkeitslimitierungen diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 5c9dc8d1..486c4dfd 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -419,7 +419,7 @@ SPDX-License-Identifier: GPL-3.0-or-later Supprimer les fichiers du disque lors de la suppression du torrent Remplir automatiquement le lien depuis le presse-papiers lors de l\'ajout d\'un lien torrent - Se souvenir du dernier répertoire de téléchargement + Se souvenir du dernier répertoire de téléchargement Limites de vitesse alternatives diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 703375f0..a7967e7d 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -446,7 +446,7 @@ SPDX-License-Identifier: GPL-3.0-or-later Удалять файлы на жестком диске при удалении торрента Автоматически копировать ссылку из буфера обмена при добавлении ссылки на торрент - Запоминать последний каталог загрузки + Запоминать последний каталог загрузки Альтернативные ограничения скорости diff --git a/app/src/main/res/values/prefs_constants.xml b/app/src/main/res/values/prefs_constants.xml index 3b09ae04..10f44860 100644 --- a/app/src/main/res/values/prefs_constants.xml +++ b/app/src/main/res/values/prefs_constants.xml @@ -95,6 +95,14 @@ SPDX-License-Identifier: GPL-3.0-or-later notificationPermission - rememberDownloadDirectory - true + rememberDownloadDirectory + + rememberAddTorrentParameters + true + + lastAddTorrentStartAfterAdding + unknown + + lastAddTorrentPriority + normal \ 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 97120e95..db15fcf4 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -474,7 +474,7 @@ SPDX-License-Identifier: GPL-3.0-or-later Delete files on the hard disk when removing torrent Automatically fill link from clipboard when adding torrent link - Remember last download directory + Remember parameters of last added torrent Alternative speed limits diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index 26962d6e..aab65be3 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -55,9 +55,9 @@ SPDX-License-Identifier: GPL-3.0-or-later app:singleLineTitle="false" />