Preferences with conductor (#792)
* Settings with conductor WIP * Add downloads preference controller. Implement source/track login * Improve settings controllers * Backup settings controller * Delete preferences xml * Remove keys from xml * PreferenceKeys is now an object * Remove now unused dependency
This commit is contained in:
@@ -1,120 +1,114 @@
|
||||
package eu.kanade.tachiyomi.data.preference
|
||||
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
||||
/**
|
||||
* This class stores the keys for the preferences in the application. Most of them are defined
|
||||
* in the file "keys.xml". By using this class we can define preferences in one place and get them
|
||||
* referenced here.
|
||||
*/
|
||||
@Suppress("HasPlatformType")
|
||||
class PreferenceKeys(context: Context) {
|
||||
|
||||
val theme = context.getString(R.string.pref_theme_key)
|
||||
|
||||
val rotation = context.getString(R.string.pref_rotation_type_key)
|
||||
|
||||
val enableTransitions = context.getString(R.string.pref_enable_transitions_key)
|
||||
|
||||
val showPageNumber = context.getString(R.string.pref_show_page_number_key)
|
||||
|
||||
val fullscreen = context.getString(R.string.pref_fullscreen_key)
|
||||
|
||||
val keepScreenOn = context.getString(R.string.pref_keep_screen_on_key)
|
||||
|
||||
val customBrightness = context.getString(R.string.pref_custom_brightness_key)
|
||||
|
||||
val customBrightnessValue = context.getString(R.string.pref_custom_brightness_value_key)
|
||||
|
||||
val colorFilter = context.getString(R.string.pref_color_filter_key)
|
||||
|
||||
val colorFilterValue = context.getString(R.string.pref_color_filter_value_key)
|
||||
|
||||
val defaultViewer = context.getString(R.string.pref_default_viewer_key)
|
||||
|
||||
val imageScaleType = context.getString(R.string.pref_image_scale_type_key)
|
||||
|
||||
val imageDecoder = context.getString(R.string.pref_image_decoder_key)
|
||||
|
||||
val zoomStart = context.getString(R.string.pref_zoom_start_key)
|
||||
|
||||
val readerTheme = context.getString(R.string.pref_reader_theme_key)
|
||||
|
||||
val cropBorders = context.getString(R.string.pref_crop_borders_key)
|
||||
|
||||
val readWithTapping = context.getString(R.string.pref_read_with_tapping_key)
|
||||
|
||||
val readWithVolumeKeys = context.getString(R.string.pref_read_with_volume_keys_key)
|
||||
|
||||
val portraitColumns = context.getString(R.string.pref_library_columns_portrait_key)
|
||||
|
||||
val landscapeColumns = context.getString(R.string.pref_library_columns_landscape_key)
|
||||
|
||||
val updateOnlyNonCompleted = context.getString(R.string.pref_update_only_non_completed_key)
|
||||
|
||||
val autoUpdateTrack = context.getString(R.string.pref_auto_update_manga_sync_key)
|
||||
|
||||
val askUpdateTrack = context.getString(R.string.pref_ask_update_manga_sync_key)
|
||||
|
||||
val lastUsedCatalogueSource = context.getString(R.string.pref_last_catalogue_source_key)
|
||||
|
||||
val lastUsedCategory = context.getString(R.string.pref_last_used_category_key)
|
||||
|
||||
val catalogueAsList = context.getString(R.string.pref_display_catalogue_as_list)
|
||||
|
||||
val enabledLanguages = context.getString(R.string.pref_source_languages)
|
||||
|
||||
val backupDirectory = context.getString(R.string.pref_backup_directory_key)
|
||||
|
||||
val downloadsDirectory = context.getString(R.string.pref_download_directory_key)
|
||||
|
||||
val downloadThreads = context.getString(R.string.pref_download_slots_key)
|
||||
|
||||
val downloadOnlyOverWifi = context.getString(R.string.pref_download_only_over_wifi_key)
|
||||
|
||||
val numberOfBackups = context.getString(R.string.pref_backup_slots_key)
|
||||
|
||||
val backupInterval = context.getString(R.string.pref_backup_interval_key)
|
||||
|
||||
val removeAfterReadSlots = context.getString(R.string.pref_remove_after_read_slots_key)
|
||||
|
||||
val removeAfterMarkedAsRead = context.getString(R.string.pref_remove_after_marked_as_read_key)
|
||||
|
||||
val libraryUpdateInterval = context.getString(R.string.pref_library_update_interval_key)
|
||||
|
||||
val libraryUpdateRestriction = context.getString(R.string.pref_library_update_restriction_key)
|
||||
|
||||
val libraryUpdateCategories = context.getString(R.string.pref_library_update_categories_key)
|
||||
|
||||
val filterDownloaded = context.getString(R.string.pref_filter_downloaded_key)
|
||||
|
||||
val filterUnread = context.getString(R.string.pref_filter_unread_key)
|
||||
|
||||
val librarySortingMode = context.getString(R.string.pref_library_sorting_mode_key)
|
||||
|
||||
val automaticUpdates = context.getString(R.string.pref_enable_automatic_updates_key)
|
||||
|
||||
val startScreen = context.getString(R.string.pref_start_screen_key)
|
||||
|
||||
val downloadNew = context.getString(R.string.pref_download_new_key)
|
||||
|
||||
val downloadNewCategories = context.getString(R.string.pref_download_new_categories_key)
|
||||
|
||||
fun sourceUsername(sourceId: Long) = "pref_source_username_$sourceId"
|
||||
|
||||
fun sourcePassword(sourceId: Long) = "pref_source_password_$sourceId"
|
||||
|
||||
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
|
||||
|
||||
fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId"
|
||||
|
||||
fun trackToken(syncId: Int) = "track_token_$syncId"
|
||||
|
||||
val libraryAsList = context.getString(R.string.pref_display_library_as_list)
|
||||
|
||||
val lang = context.getString(R.string.pref_language_key)
|
||||
|
||||
val defaultCategory = context.getString(R.string.default_category_key)
|
||||
|
||||
}
|
||||
package eu.kanade.tachiyomi.data.preference
|
||||
|
||||
/**
|
||||
* This class stores the keys for the preferences in the application.
|
||||
*/
|
||||
object PreferenceKeys {
|
||||
|
||||
const val theme = "pref_theme_key"
|
||||
|
||||
const val rotation = "pref_rotation_type_key"
|
||||
|
||||
const val enableTransitions = "pref_enable_transitions_key"
|
||||
|
||||
const val showPageNumber = "pref_show_page_number_key"
|
||||
|
||||
const val fullscreen = "fullscreen"
|
||||
|
||||
const val keepScreenOn = "pref_keep_screen_on_key"
|
||||
|
||||
const val customBrightness = "pref_custom_brightness_key"
|
||||
|
||||
const val customBrightnessValue = "custom_brightness_value"
|
||||
|
||||
const val colorFilter = "pref_color_filter_key"
|
||||
|
||||
const val colorFilterValue = "color_filter_value"
|
||||
|
||||
const val defaultViewer = "pref_default_viewer_key"
|
||||
|
||||
const val imageScaleType = "pref_image_scale_type_key"
|
||||
|
||||
const val imageDecoder = "image_decoder"
|
||||
|
||||
const val zoomStart = "pref_zoom_start_key"
|
||||
|
||||
const val readerTheme = "pref_reader_theme_key"
|
||||
|
||||
const val cropBorders = "crop_borders"
|
||||
|
||||
const val readWithTapping = "reader_tap"
|
||||
|
||||
const val readWithVolumeKeys = "reader_volume_keys"
|
||||
|
||||
const val portraitColumns = "pref_library_columns_portrait_key"
|
||||
|
||||
const val landscapeColumns = "pref_library_columns_landscape_key"
|
||||
|
||||
const val updateOnlyNonCompleted = "pref_update_only_non_completed_key"
|
||||
|
||||
const val autoUpdateTrack = "pref_auto_update_manga_sync_key"
|
||||
|
||||
const val askUpdateTrack = "pref_ask_update_manga_sync_key"
|
||||
|
||||
const val lastUsedCatalogueSource = "last_catalogue_source"
|
||||
|
||||
const val lastUsedCategory = "last_used_category"
|
||||
|
||||
const val catalogueAsList = "pref_display_catalogue_as_list"
|
||||
|
||||
const val enabledLanguages = "source_languages"
|
||||
|
||||
const val backupDirectory = "backup_directory"
|
||||
|
||||
const val downloadsDirectory = "download_directory"
|
||||
|
||||
const val downloadThreads = "pref_download_slots_key"
|
||||
|
||||
const val downloadOnlyOverWifi = "pref_download_only_over_wifi_key"
|
||||
|
||||
const val numberOfBackups = "backup_slots"
|
||||
|
||||
const val backupInterval = "backup_interval"
|
||||
|
||||
const val removeAfterReadSlots = "remove_after_read_slots"
|
||||
|
||||
const val removeAfterMarkedAsRead = "pref_remove_after_marked_as_read_key"
|
||||
|
||||
const val libraryUpdateInterval = "pref_library_update_interval_key"
|
||||
|
||||
const val libraryUpdateRestriction = "library_update_restriction"
|
||||
|
||||
const val libraryUpdateCategories = "library_update_categories"
|
||||
|
||||
const val filterDownloaded = "pref_filter_downloaded_key"
|
||||
|
||||
const val filterUnread = "pref_filter_unread_key"
|
||||
|
||||
const val librarySortingMode = "library_sorting_mode"
|
||||
|
||||
const val automaticUpdates = "automatic_updates"
|
||||
|
||||
const val startScreen = "start_screen"
|
||||
|
||||
const val downloadNew = "download_new"
|
||||
|
||||
const val downloadNewCategories = "download_new_categories"
|
||||
|
||||
const val libraryAsList = "pref_display_library_as_list"
|
||||
|
||||
const val lang = "app_language"
|
||||
|
||||
const val defaultCategory = "default_category"
|
||||
|
||||
fun sourceUsername(sourceId: Long) = "pref_source_username_$sourceId"
|
||||
|
||||
fun sourcePassword(sourceId: Long) = "pref_source_password_$sourceId"
|
||||
|
||||
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
|
||||
|
||||
fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId"
|
||||
|
||||
fun trackToken(syncId: Int) = "track_token_$syncId"
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.source.Source
|
||||
import java.io.File
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
||||
|
||||
fun <T> Preference<T>.getOrDefault(): T = get() ?: defaultValue()!!
|
||||
|
||||
@@ -17,8 +18,6 @@ fun Preference<Boolean>.invert(): Boolean = getOrDefault().let { set(!it); !it }
|
||||
|
||||
class PreferencesHelper(val context: Context) {
|
||||
|
||||
val keys = PreferenceKeys(context)
|
||||
|
||||
private val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||
private val rxPrefs = RxSharedPreferences.create(prefs)
|
||||
|
||||
@@ -30,134 +29,134 @@ class PreferencesHelper(val context: Context) {
|
||||
File(Environment.getExternalStorageDirectory().absolutePath + File.separator +
|
||||
context.getString(R.string.app_name), "backup"))
|
||||
|
||||
fun startScreen() = prefs.getInt(keys.startScreen, 1)
|
||||
fun startScreen() = prefs.getInt(Keys.startScreen, 1)
|
||||
|
||||
fun clear() = prefs.edit().clear().apply()
|
||||
|
||||
fun theme() = prefs.getInt(keys.theme, 1)
|
||||
fun theme() = prefs.getInt(Keys.theme, 1)
|
||||
|
||||
fun rotation() = rxPrefs.getInteger(keys.rotation, 1)
|
||||
fun rotation() = rxPrefs.getInteger(Keys.rotation, 1)
|
||||
|
||||
fun pageTransitions() = rxPrefs.getBoolean(keys.enableTransitions, true)
|
||||
fun pageTransitions() = rxPrefs.getBoolean(Keys.enableTransitions, true)
|
||||
|
||||
fun showPageNumber() = rxPrefs.getBoolean(keys.showPageNumber, true)
|
||||
fun showPageNumber() = rxPrefs.getBoolean(Keys.showPageNumber, true)
|
||||
|
||||
fun fullscreen() = rxPrefs.getBoolean(keys.fullscreen, true)
|
||||
fun fullscreen() = rxPrefs.getBoolean(Keys.fullscreen, true)
|
||||
|
||||
fun keepScreenOn() = rxPrefs.getBoolean(keys.keepScreenOn, true)
|
||||
fun keepScreenOn() = rxPrefs.getBoolean(Keys.keepScreenOn, true)
|
||||
|
||||
fun customBrightness() = rxPrefs.getBoolean(keys.customBrightness, false)
|
||||
fun customBrightness() = rxPrefs.getBoolean(Keys.customBrightness, false)
|
||||
|
||||
fun customBrightnessValue() = rxPrefs.getInteger(keys.customBrightnessValue, 0)
|
||||
fun customBrightnessValue() = rxPrefs.getInteger(Keys.customBrightnessValue, 0)
|
||||
|
||||
fun colorFilter() = rxPrefs.getBoolean(keys.colorFilter, false)
|
||||
fun colorFilter() = rxPrefs.getBoolean(Keys.colorFilter, false)
|
||||
|
||||
fun colorFilterValue() = rxPrefs.getInteger(keys.colorFilterValue, 0)
|
||||
fun colorFilterValue() = rxPrefs.getInteger(Keys.colorFilterValue, 0)
|
||||
|
||||
fun defaultViewer() = prefs.getInt(keys.defaultViewer, 1)
|
||||
fun defaultViewer() = prefs.getInt(Keys.defaultViewer, 1)
|
||||
|
||||
fun imageScaleType() = rxPrefs.getInteger(keys.imageScaleType, 1)
|
||||
fun imageScaleType() = rxPrefs.getInteger(Keys.imageScaleType, 1)
|
||||
|
||||
fun imageDecoder() = rxPrefs.getInteger(keys.imageDecoder, 0)
|
||||
fun imageDecoder() = rxPrefs.getInteger(Keys.imageDecoder, 0)
|
||||
|
||||
fun zoomStart() = rxPrefs.getInteger(keys.zoomStart, 1)
|
||||
fun zoomStart() = rxPrefs.getInteger(Keys.zoomStart, 1)
|
||||
|
||||
fun readerTheme() = rxPrefs.getInteger(keys.readerTheme, 0)
|
||||
fun readerTheme() = rxPrefs.getInteger(Keys.readerTheme, 0)
|
||||
|
||||
fun cropBorders() = rxPrefs.getBoolean(keys.cropBorders, false)
|
||||
fun cropBorders() = rxPrefs.getBoolean(Keys.cropBorders, false)
|
||||
|
||||
fun readWithTapping() = rxPrefs.getBoolean(keys.readWithTapping, true)
|
||||
fun readWithTapping() = rxPrefs.getBoolean(Keys.readWithTapping, true)
|
||||
|
||||
fun readWithVolumeKeys() = rxPrefs.getBoolean(keys.readWithVolumeKeys, false)
|
||||
fun readWithVolumeKeys() = rxPrefs.getBoolean(Keys.readWithVolumeKeys, false)
|
||||
|
||||
fun portraitColumns() = rxPrefs.getInteger(keys.portraitColumns, 0)
|
||||
fun portraitColumns() = rxPrefs.getInteger(Keys.portraitColumns, 0)
|
||||
|
||||
fun landscapeColumns() = rxPrefs.getInteger(keys.landscapeColumns, 0)
|
||||
fun landscapeColumns() = rxPrefs.getInteger(Keys.landscapeColumns, 0)
|
||||
|
||||
fun updateOnlyNonCompleted() = prefs.getBoolean(keys.updateOnlyNonCompleted, false)
|
||||
fun updateOnlyNonCompleted() = prefs.getBoolean(Keys.updateOnlyNonCompleted, false)
|
||||
|
||||
fun autoUpdateTrack() = prefs.getBoolean(keys.autoUpdateTrack, true)
|
||||
fun autoUpdateTrack() = prefs.getBoolean(Keys.autoUpdateTrack, true)
|
||||
|
||||
fun askUpdateTrack() = prefs.getBoolean(keys.askUpdateTrack, false)
|
||||
fun askUpdateTrack() = prefs.getBoolean(Keys.askUpdateTrack, false)
|
||||
|
||||
fun lastUsedCatalogueSource() = rxPrefs.getLong(keys.lastUsedCatalogueSource, -1)
|
||||
fun lastUsedCatalogueSource() = rxPrefs.getLong(Keys.lastUsedCatalogueSource, -1)
|
||||
|
||||
fun lastUsedCategory() = rxPrefs.getInteger(keys.lastUsedCategory, 0)
|
||||
fun lastUsedCategory() = rxPrefs.getInteger(Keys.lastUsedCategory, 0)
|
||||
|
||||
fun lastVersionCode() = rxPrefs.getInteger("last_version_code", 0)
|
||||
|
||||
fun catalogueAsList() = rxPrefs.getBoolean(keys.catalogueAsList, false)
|
||||
fun catalogueAsList() = rxPrefs.getBoolean(Keys.catalogueAsList, false)
|
||||
|
||||
fun enabledLanguages() = rxPrefs.getStringSet(keys.enabledLanguages, setOf("en"))
|
||||
fun enabledLanguages() = rxPrefs.getStringSet(Keys.enabledLanguages, setOf("en"))
|
||||
|
||||
fun sourceUsername(source: Source) = prefs.getString(keys.sourceUsername(source.id), "")
|
||||
fun sourceUsername(source: Source) = prefs.getString(Keys.sourceUsername(source.id), "")
|
||||
|
||||
fun sourcePassword(source: Source) = prefs.getString(keys.sourcePassword(source.id), "")
|
||||
fun sourcePassword(source: Source) = prefs.getString(Keys.sourcePassword(source.id), "")
|
||||
|
||||
fun setSourceCredentials(source: Source, username: String, password: String) {
|
||||
prefs.edit()
|
||||
.putString(keys.sourceUsername(source.id), username)
|
||||
.putString(keys.sourcePassword(source.id), password)
|
||||
.putString(Keys.sourceUsername(source.id), username)
|
||||
.putString(Keys.sourcePassword(source.id), password)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun trackUsername(sync: TrackService) = prefs.getString(keys.trackUsername(sync.id), "")
|
||||
fun trackUsername(sync: TrackService) = prefs.getString(Keys.trackUsername(sync.id), "")
|
||||
|
||||
fun trackPassword(sync: TrackService) = prefs.getString(keys.trackPassword(sync.id), "")
|
||||
fun trackPassword(sync: TrackService) = prefs.getString(Keys.trackPassword(sync.id), "")
|
||||
|
||||
fun setTrackCredentials(sync: TrackService, username: String, password: String) {
|
||||
prefs.edit()
|
||||
.putString(keys.trackUsername(sync.id), username)
|
||||
.putString(keys.trackPassword(sync.id), password)
|
||||
.putString(Keys.trackUsername(sync.id), username)
|
||||
.putString(Keys.trackPassword(sync.id), password)
|
||||
.apply()
|
||||
}
|
||||
|
||||
fun trackToken(sync: TrackService) = rxPrefs.getString(keys.trackToken(sync.id), "")
|
||||
fun trackToken(sync: TrackService) = rxPrefs.getString(Keys.trackToken(sync.id), "")
|
||||
|
||||
fun anilistScoreType() = rxPrefs.getInteger("anilist_score_type", 0)
|
||||
|
||||
fun backupsDirectory() = rxPrefs.getString(keys.backupDirectory, defaultBackupDir.toString())
|
||||
fun backupsDirectory() = rxPrefs.getString(Keys.backupDirectory, defaultBackupDir.toString())
|
||||
|
||||
fun downloadsDirectory() = rxPrefs.getString(keys.downloadsDirectory, defaultDownloadsDir.toString())
|
||||
fun downloadsDirectory() = rxPrefs.getString(Keys.downloadsDirectory, defaultDownloadsDir.toString())
|
||||
|
||||
fun downloadThreads() = rxPrefs.getInteger(keys.downloadThreads, 1)
|
||||
fun downloadThreads() = rxPrefs.getInteger(Keys.downloadThreads, 1)
|
||||
|
||||
fun downloadOnlyOverWifi() = prefs.getBoolean(keys.downloadOnlyOverWifi, true)
|
||||
fun downloadOnlyOverWifi() = prefs.getBoolean(Keys.downloadOnlyOverWifi, true)
|
||||
|
||||
fun numberOfBackups() = rxPrefs.getInteger(keys.numberOfBackups, 1)
|
||||
fun numberOfBackups() = rxPrefs.getInteger(Keys.numberOfBackups, 1)
|
||||
|
||||
fun backupInterval() = rxPrefs.getInteger(keys.backupInterval, 0)
|
||||
fun backupInterval() = rxPrefs.getInteger(Keys.backupInterval, 0)
|
||||
|
||||
fun removeAfterReadSlots() = prefs.getInt(keys.removeAfterReadSlots, -1)
|
||||
fun removeAfterReadSlots() = prefs.getInt(Keys.removeAfterReadSlots, -1)
|
||||
|
||||
fun removeAfterMarkedAsRead() = prefs.getBoolean(keys.removeAfterMarkedAsRead, false)
|
||||
fun removeAfterMarkedAsRead() = prefs.getBoolean(Keys.removeAfterMarkedAsRead, false)
|
||||
|
||||
fun libraryUpdateInterval() = rxPrefs.getInteger(keys.libraryUpdateInterval, 0)
|
||||
fun libraryUpdateInterval() = rxPrefs.getInteger(Keys.libraryUpdateInterval, 0)
|
||||
|
||||
fun libraryUpdateRestriction() = prefs.getStringSet(keys.libraryUpdateRestriction, emptySet())
|
||||
fun libraryUpdateRestriction() = prefs.getStringSet(Keys.libraryUpdateRestriction, emptySet())
|
||||
|
||||
fun libraryUpdateCategories() = rxPrefs.getStringSet(keys.libraryUpdateCategories, emptySet())
|
||||
fun libraryUpdateCategories() = rxPrefs.getStringSet(Keys.libraryUpdateCategories, emptySet())
|
||||
|
||||
fun libraryAsList() = rxPrefs.getBoolean(keys.libraryAsList, false)
|
||||
fun libraryAsList() = rxPrefs.getBoolean(Keys.libraryAsList, false)
|
||||
|
||||
fun filterDownloaded() = rxPrefs.getBoolean(keys.filterDownloaded, false)
|
||||
fun filterDownloaded() = rxPrefs.getBoolean(Keys.filterDownloaded, false)
|
||||
|
||||
fun filterUnread() = rxPrefs.getBoolean(keys.filterUnread, false)
|
||||
fun filterUnread() = rxPrefs.getBoolean(Keys.filterUnread, false)
|
||||
|
||||
fun librarySortingMode() = rxPrefs.getInteger(keys.librarySortingMode, 0)
|
||||
fun librarySortingMode() = rxPrefs.getInteger(Keys.librarySortingMode, 0)
|
||||
|
||||
fun librarySortingAscending() = rxPrefs.getBoolean("library_sorting_ascending", true)
|
||||
|
||||
fun automaticUpdates() = prefs.getBoolean(keys.automaticUpdates, false)
|
||||
fun automaticUpdates() = prefs.getBoolean(Keys.automaticUpdates, false)
|
||||
|
||||
fun hiddenCatalogues() = rxPrefs.getStringSet("hidden_catalogues", emptySet())
|
||||
|
||||
fun downloadNew() = rxPrefs.getBoolean(keys.downloadNew, false)
|
||||
fun downloadNew() = rxPrefs.getBoolean(Keys.downloadNew, false)
|
||||
|
||||
fun downloadNewCategories() = rxPrefs.getStringSet(keys.downloadNewCategories, emptySet())
|
||||
fun downloadNewCategories() = rxPrefs.getStringSet(Keys.downloadNewCategories, emptySet())
|
||||
|
||||
fun lang() = prefs.getString(keys.lang, "")
|
||||
fun lang() = prefs.getString(Keys.lang, "")
|
||||
|
||||
fun defaultCategory() = prefs.getInt(keys.defaultCategory, -1)
|
||||
fun defaultCategory() = prefs.getInt(Keys.defaultCategory, -1)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user