Reader grayscale filter (closes #2822)
This commit is contained in:
parent
fe373a95a2
commit
908c9bc624
@ -49,6 +49,8 @@ object PreferenceKeys {
|
||||
|
||||
const val colorFilterMode = "color_filter_mode"
|
||||
|
||||
const val grayscale = "pref_grayscale"
|
||||
|
||||
const val defaultReadingMode = "pref_default_reading_mode_key"
|
||||
|
||||
const val defaultOrientationType = "pref_default_orientation_type_key"
|
||||
|
@ -121,6 +121,8 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun colorFilterMode() = flowPrefs.getInt(Keys.colorFilterMode, 0)
|
||||
|
||||
fun grayscale() = flowPrefs.getBoolean(Keys.grayscale, false)
|
||||
|
||||
fun defaultReadingMode() = prefs.getInt(Keys.defaultReadingMode, ReadingModeType.RIGHT_TO_LEFT.flagValue)
|
||||
|
||||
fun defaultOrientationType() = prefs.getInt(Keys.defaultOrientationType, OrientationType.FREE.flagValue)
|
||||
|
@ -8,12 +8,16 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.graphics.Bitmap
|
||||
import android.graphics.Color
|
||||
import android.graphics.ColorMatrix
|
||||
import android.graphics.ColorMatrixColorFilter
|
||||
import android.graphics.Paint
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.view.KeyEvent
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.MotionEvent
|
||||
import android.view.View.LAYER_TYPE_HARDWARE
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
@ -789,6 +793,16 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||
*/
|
||||
private inner class ReaderConfig {
|
||||
|
||||
private val grayscalePaint by lazy {
|
||||
Paint().apply {
|
||||
colorFilter = ColorMatrixColorFilter(
|
||||
ColorMatrix().apply {
|
||||
setSaturation(0f)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the reader subscriptions.
|
||||
*/
|
||||
@ -827,6 +841,10 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||
preferences.colorFilterMode().asFlow()
|
||||
.onEach { setColorFilter(preferences.colorFilter().get()) }
|
||||
.launchIn(lifecycleScope)
|
||||
|
||||
preferences.grayscale().asFlow()
|
||||
.onEach { setGrayscale(it) }
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -934,5 +952,10 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||
binding.colorOverlay.isVisible = true
|
||||
binding.colorOverlay.setFilterColor(value, preferences.colorFilterMode().get())
|
||||
}
|
||||
|
||||
private fun setGrayscale(enabled: Boolean) {
|
||||
val paint = if (enabled) grayscalePaint else null
|
||||
binding.viewerContainer.setLayerType(LAYER_TYPE_HARDWARE, paint)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import androidx.lifecycle.lifecycleScope
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.databinding.ReaderColorFilterSettingsBinding
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
|
||||
import eu.kanade.tachiyomi.util.preference.bindToPreference
|
||||
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
@ -63,20 +63,10 @@ class ReaderColorFilterSettings @JvmOverloads constructor(context: Context, attr
|
||||
binding.seekbarColorFilterBlue.progress = argb[3]
|
||||
|
||||
// Set listeners
|
||||
binding.switchColorFilter.isChecked = preferences.colorFilter().get()
|
||||
binding.switchColorFilter.setOnCheckedChangeListener { _, isChecked ->
|
||||
preferences.colorFilter().set(isChecked)
|
||||
}
|
||||
|
||||
binding.customBrightness.isChecked = preferences.customBrightness().get()
|
||||
binding.customBrightness.setOnCheckedChangeListener { _, isChecked ->
|
||||
preferences.customBrightness().set(isChecked)
|
||||
}
|
||||
|
||||
binding.colorFilterMode.onItemSelectedListener = IgnoreFirstSpinnerListener { position ->
|
||||
preferences.colorFilterMode().set(position)
|
||||
}
|
||||
binding.colorFilterMode.setSelection(preferences.colorFilterMode().get(), false)
|
||||
binding.switchColorFilter.bindToPreference(preferences.colorFilter())
|
||||
binding.customBrightness.bindToPreference(preferences.customBrightness())
|
||||
binding.colorFilterMode.bindToPreference(preferences.colorFilterMode())
|
||||
binding.grayscale.bindToPreference(preferences.grayscale())
|
||||
|
||||
binding.seekbarColorFilterAlpha.setOnSeekBarChangeListener(
|
||||
object : SimpleSeekBarListener() {
|
||||
|
@ -3,8 +3,7 @@
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
@ -17,12 +16,25 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pref_custom_color_filter"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- Red filter -->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_red_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:text="@string/color_filter_r_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar_color_filter_red"
|
||||
android:layout_width="0dp"
|
||||
@ -30,33 +42,36 @@
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:max="255"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_red_value"
|
||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/switch_color_filter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_red_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_r_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_red_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red" />
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red"
|
||||
tools:text="255" />
|
||||
|
||||
<!-- Green filter -->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_green_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:text="@string/color_filter_g_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar_color_filter_green"
|
||||
android:layout_width="0dp"
|
||||
@ -64,33 +79,36 @@
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:max="255"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_green_value"
|
||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_red" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_green_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_g_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_green_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green" />
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green"
|
||||
tools:text="255" />
|
||||
|
||||
<!-- Blue filter -->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_blue_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_b_value"
|
||||
android:paddingStart="16dp"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar_color_filter_blue"
|
||||
android:layout_width="0dp"
|
||||
@ -98,33 +116,36 @@
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:max="255"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_blue_value"
|
||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_blue_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_b_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_blue_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue" />
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue"
|
||||
tools:text="255" />
|
||||
|
||||
<!-- Alpha filter -->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_alpha_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:text="@string/color_filter_a_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha" />
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar_color_filter_alpha"
|
||||
android:layout_width="0dp"
|
||||
@ -132,51 +153,45 @@
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:max="255"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_alpha_value"
|
||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_blue" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_alpha_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_a_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_alpha_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha" />
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha"
|
||||
tools:text="255" />
|
||||
|
||||
<!-- Filter mode -->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/color_filter_mode_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pref_color_filter_mode"
|
||||
app:layout_constraintBaseline_toBaselineOf="@id/color_filter_mode"
|
||||
app:layout_constraintEnd_toStartOf="@id/color_filter_mode"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
<eu.kanade.tachiyomi.widget.MaterialSpinnerView
|
||||
android:id="@+id/color_filter_mode"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:entries="@array/color_filter_modes"
|
||||
app:layout_constraintEnd_toStartOf="@id/spinner_end"
|
||||
app:layout_constraintStart_toEndOf="@id/verticalcenter"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_alpha" />
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||
app:title="@string/pref_color_filter_mode" />
|
||||
|
||||
<!-- Grayscale -->
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/grayscale"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:text="@string/pref_grayscale"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:layout_constraintTop_toBottomOf="@id/color_filter_mode" />
|
||||
|
||||
<!-- Brightness -->
|
||||
|
||||
@ -185,11 +200,25 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:text="@string/pref_custom_brightness"
|
||||
app:layout_constraintTop_toBottomOf="@id/color_filter_mode_text" />
|
||||
app:layout_constraintTop_toBottomOf="@id/grayscale" />
|
||||
|
||||
<!-- Brightness value -->
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/txt_brightness_seekbar_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
android:tint="?attr/colorOnBackground"
|
||||
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/brightness_seekbar"
|
||||
app:srcCompat="@drawable/ic_brightness_5_24dp" />
|
||||
|
||||
<eu.kanade.tachiyomi.widget.NegativeSeekBar
|
||||
android:id="@+id/brightness_seekbar"
|
||||
android:layout_width="0dp"
|
||||
@ -203,25 +232,16 @@
|
||||
app:max_seek="100"
|
||||
app:min_seek="-75" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/txt_brightness_seekbar_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
android:tint="?attr/colorOnBackground"
|
||||
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/brightness_seekbar"
|
||||
app:srcCompat="@drawable/ic_brightness_5_24dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_brightness_seekbar_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/brightness_seekbar" />
|
||||
app:layout_constraintTop_toTopOf="@id/brightness_seekbar"
|
||||
tools:text="50" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/color_filter_symbols_barrier"
|
||||
@ -230,20 +250,6 @@
|
||||
app:barrierDirection="end"
|
||||
app:constraint_referenced_ids="txt_color_filter_alpha_symbol,txt_color_filter_blue_symbol,txt_color_filter_red_symbol,txt_color_filter_green_symbol" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/verticalcenter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<android.widget.Space
|
||||
android:id="@+id/spinner_end"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintStart_toEndOf="parent"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
@ -271,6 +271,7 @@
|
||||
<string name="pref_true_color_summary">Reduces banding, but impacts performance</string>
|
||||
<string name="pref_crop_borders">Crop borders</string>
|
||||
<string name="pref_custom_brightness">Custom brightness</string>
|
||||
<string name="pref_grayscale">Grayscale</string>
|
||||
<string name="pref_custom_color_filter">Custom color filter</string>
|
||||
<string name="pref_color_filter_mode">Color filter blend mode</string>
|
||||
<string name="filter_mode_default">Default</string>
|
||||
|
Loading…
Reference in New Issue
Block a user