mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-02-27 07:16:54 +00:00
Mark stable classes and enable Compose Compiler reports (#4775)
* Enable stabilityConfigurationFile and reportsDestination https://developer.android.com/develop/ui/compose/performance/stability/fix#configuration-file * Remove org.jetbrains.kotlinx:kotlinx-collections-immutable
This commit is contained in:
@@ -318,6 +318,11 @@ androidComponents {
|
||||
}
|
||||
}
|
||||
|
||||
composeCompiler {
|
||||
stabilityConfigurationFile = layout.projectDirectory.file("compose_compiler_config.conf")
|
||||
reportsDestination = layout.buildDirectory.dir("compose_build_reports")
|
||||
}
|
||||
|
||||
addFrameworkJar('framework-14.jar')
|
||||
|
||||
dependencies {
|
||||
@@ -360,7 +365,6 @@ dependencies {
|
||||
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1'
|
||||
implementation 'org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.2'
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-collections-immutable:0.3.8"
|
||||
implementation 'com.github.ChickenHook:RestrictionBypass:2.2'
|
||||
implementation 'dev.rikka.tools.refine:runtime:4.4.0'
|
||||
|
||||
|
||||
8
compose_compiler_config.conf
Normal file
8
compose_compiler_config.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
androidx.collection.*
|
||||
|
||||
java.nio.file.Path
|
||||
|
||||
kotlin.collections.*
|
||||
kotlin.time.Duration
|
||||
|
||||
kotlinx.coroutines.CoroutineScope
|
||||
@@ -6,7 +6,6 @@ import androidx.annotation.LayoutRes
|
||||
import androidx.annotation.StringRes
|
||||
import app.lawnchair.util.isPackageInstalledAndEnabled
|
||||
import com.android.launcher3.R
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
|
||||
sealed class SmartspaceMode(
|
||||
@StringRes val nameResourceId: Int,
|
||||
@@ -23,7 +22,7 @@ sealed class SmartspaceMode(
|
||||
/**
|
||||
* @return The list of all smartspace options
|
||||
*/
|
||||
fun values() = persistentListOf(
|
||||
fun values() = listOf(
|
||||
LawnchairSmartspace,
|
||||
GoogleSmartspace,
|
||||
GoogleSearchSmartspace,
|
||||
|
||||
@@ -4,8 +4,6 @@ import androidx.annotation.StringRes
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import app.lawnchair.ui.preferences.components.controls.ListPreferenceEntry
|
||||
import com.android.launcher3.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
enum class ColorMode(
|
||||
@StringRes val labelResourceId: Int,
|
||||
@@ -30,8 +28,8 @@ enum class ColorMode(
|
||||
|
||||
fun fromString(string: String) = values().firstOrNull { it.toString() == string }
|
||||
|
||||
fun entries(): ImmutableList<ListPreferenceEntry<ColorMode>> = values().map {
|
||||
fun entries(): List<ListPreferenceEntry<ColorMode>> = values().map {
|
||||
ListPreferenceEntry(value = it) { stringResource(id = it.labelResourceId) }
|
||||
}.toPersistentList()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ import app.lawnchair.ui.preferences.data.liveinfo.model.Announcement
|
||||
import app.lawnchair.ui.util.addIf
|
||||
import com.android.launcher3.BuildConfig
|
||||
import com.android.launcher3.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
fun AnnouncementPreference() {
|
||||
@@ -56,14 +55,14 @@ fun AnnouncementPreference() {
|
||||
|
||||
if (enabled && showAnnouncements) {
|
||||
AnnouncementPreference(
|
||||
announcements = liveInformation.announcementsImmutable,
|
||||
announcements = liveInformation.announcements,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun AnnouncementPreference(
|
||||
announcements: ImmutableList<Announcement>,
|
||||
announcements: List<Announcement>,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(
|
||||
|
||||
@@ -19,7 +19,6 @@ import app.lawnchair.ui.preferences.components.controls.ListPreference
|
||||
import app.lawnchair.ui.preferences.components.controls.ListPreferenceEntry
|
||||
import com.android.launcher3.R
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
data class ProviderInfo(
|
||||
val name: String,
|
||||
@@ -49,7 +48,7 @@ fun getEntries(context: Context) = getProviders(context).map {
|
||||
},
|
||||
label = { it.name },
|
||||
)
|
||||
}.toPersistentList()
|
||||
}.toList()
|
||||
|
||||
@Composable
|
||||
fun FeedPreference(
|
||||
|
||||
@@ -7,7 +7,6 @@ import app.lawnchair.preferences2.preferenceManager2
|
||||
import app.lawnchair.ui.preferences.components.controls.ListPreference
|
||||
import app.lawnchair.ui.preferences.components.controls.ListPreferenceEntry
|
||||
import com.android.launcher3.R
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
object HiddenAppsInSearch {
|
||||
const val NEVER = "off"
|
||||
@@ -20,13 +19,12 @@ val hiddenAppsInSearchEntries = sequenceOf(
|
||||
ListPreferenceEntry(HiddenAppsInSearch.IF_NAME_TYPED) { stringResource(R.string.hidden_apps_show_name_typed) },
|
||||
ListPreferenceEntry(HiddenAppsInSearch.ALWAYS) { stringResource(R.string.always_choice) },
|
||||
)
|
||||
.toPersistentList()
|
||||
|
||||
@Composable
|
||||
fun HiddenAppsInSearchPreference() {
|
||||
ListPreference(
|
||||
adapter = preferenceManager2().hiddenAppsInSearch.getAdapter(),
|
||||
entries = hiddenAppsInSearchEntries,
|
||||
entries = hiddenAppsInSearchEntries.toList(),
|
||||
label = stringResource(R.string.show_hidden_apps_in_search_results),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ import app.lawnchair.ui.preferences.components.controls.ListPreference
|
||||
import app.lawnchair.ui.preferences.components.controls.ListPreferenceEntry
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
object ThemeChoice {
|
||||
const val LIGHT = "light"
|
||||
@@ -28,7 +27,7 @@ val themeEntries = sequenceOf(
|
||||
ThemeChoice.SYSTEM -> Utilities.ATLEAST_O_MR1
|
||||
else -> true
|
||||
}
|
||||
}.toPersistentList()
|
||||
}.toList()
|
||||
|
||||
@Composable
|
||||
fun ThemePreference() {
|
||||
|
||||
@@ -17,8 +17,6 @@ import app.lawnchair.ui.preferences.components.controls.ListPreferenceEntry
|
||||
import app.lawnchair.ui.preferences.components.layout.Chip
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
|
||||
import com.android.launcher3.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
@Composable
|
||||
fun WebSearchProvider(
|
||||
@@ -31,7 +29,7 @@ fun WebSearchProvider(
|
||||
value = mode,
|
||||
label = { stringResource(id = mode.label) },
|
||||
)
|
||||
}.toPersistentList()
|
||||
}
|
||||
}
|
||||
|
||||
ListPreferenceChips(
|
||||
@@ -45,7 +43,7 @@ fun WebSearchProvider(
|
||||
@Composable
|
||||
fun <T> ListPreferenceChips(
|
||||
adapter: PreferenceAdapter<T>,
|
||||
entries: ImmutableList<ListPreferenceEntry<T>>,
|
||||
entries: List<ListPreferenceEntry<T>>,
|
||||
label: String,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
@@ -62,7 +60,7 @@ fun <T> ListPreferenceChips(
|
||||
|
||||
@Composable
|
||||
fun <T> ListPreferenceChips(
|
||||
entries: ImmutableList<ListPreferenceEntry<T>>,
|
||||
entries: List<ListPreferenceEntry<T>>,
|
||||
value: T,
|
||||
onValueChange: (T) -> Unit,
|
||||
label: String,
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package app.lawnchair.ui.preferences.components.colorpreference
|
||||
|
||||
import app.lawnchair.theme.color.ColorOption
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
val staticColors: ImmutableList<ColorPreferenceEntry<ColorOption>> = sequenceOf(
|
||||
val staticColors: List<ColorPreferenceEntry<ColorOption>> = sequenceOf(
|
||||
ColorOption.CustomColor(0xFFF32020),
|
||||
ColorOption.CustomColor(0xFFF20D69),
|
||||
ColorOption.CustomColor(0xFF7452FF),
|
||||
@@ -17,13 +15,13 @@ val staticColors: ImmutableList<ColorPreferenceEntry<ColorOption>> = sequenceOf(
|
||||
ColorOption.CustomColor(0xFFFF9800),
|
||||
ColorOption.CustomColor(0xFF7C5445),
|
||||
ColorOption.CustomColor(0xFF67818E),
|
||||
).map(ColorOption::colorPreferenceEntry).toPersistentList()
|
||||
).map(ColorOption::colorPreferenceEntry).toList()
|
||||
|
||||
val dynamicColors: ImmutableList<ColorPreferenceEntry<ColorOption>> =
|
||||
val dynamicColors: List<ColorPreferenceEntry<ColorOption>> =
|
||||
sequenceOf(ColorOption.SystemAccent, ColorOption.WallpaperPrimary)
|
||||
.filter(ColorOption::isSupported)
|
||||
.map(ColorOption::colorPreferenceEntry)
|
||||
.toPersistentList()
|
||||
.toList()
|
||||
|
||||
val dynamicColorsWithDefault: ImmutableList<ColorPreferenceEntry<ColorOption>> =
|
||||
(dynamicColors.asSequence() + ColorOption.Default.colorPreferenceEntry).toPersistentList()
|
||||
val dynamicColorsWithDefault: List<ColorPreferenceEntry<ColorOption>> =
|
||||
(dynamicColors.asSequence() + ColorOption.Default.colorPreferenceEntry).toList()
|
||||
|
||||
@@ -4,10 +4,9 @@ import androidx.annotation.StringRes
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import app.lawnchair.theme.color.ColorOption
|
||||
import com.patrykmichalik.opto.domain.Preference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
data class ColorPreferenceModel(
|
||||
val prefObject: Preference<ColorOption, String, Preferences.Key<String>>,
|
||||
@StringRes val labelRes: Int,
|
||||
val dynamicEntries: ImmutableList<ColorPreferenceEntry<ColorOption>>,
|
||||
val dynamicEntries: List<ColorPreferenceEntry<ColorOption>>,
|
||||
)
|
||||
|
||||
@@ -32,7 +32,6 @@ import app.lawnchair.ui.preferences.components.layout.Chip
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
|
||||
import com.android.launcher3.R
|
||||
import com.patrykmichalik.opto.domain.Preference
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Composable
|
||||
@@ -40,8 +39,8 @@ fun ColorSelection(
|
||||
label: String,
|
||||
preference: Preference<ColorOption, String, *>,
|
||||
modifier: Modifier = Modifier,
|
||||
dynamicEntries: ImmutableList<ColorPreferenceEntry<ColorOption>> = dynamicColors,
|
||||
staticEntries: ImmutableList<ColorPreferenceEntry<ColorOption>> = staticColors,
|
||||
dynamicEntries: List<ColorPreferenceEntry<ColorOption>> = dynamicColors,
|
||||
staticEntries: List<ColorPreferenceEntry<ColorOption>> = staticColors,
|
||||
) {
|
||||
val adapter = preference.getAdapter()
|
||||
val appliedColor = adapter.state.value
|
||||
|
||||
@@ -16,11 +16,10 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceDivider
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
|
||||
import com.android.launcher3.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
fun PresetsList(
|
||||
dynamicEntries: ImmutableList<ColorPreferenceEntry<ColorOption>>,
|
||||
dynamicEntries: List<ColorPreferenceEntry<ColorOption>>,
|
||||
onPresetClick: (ColorOption) -> Unit,
|
||||
isPresetSelected: (ColorOption) -> Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
|
||||
@@ -29,7 +29,6 @@ import app.lawnchair.ui.preferences.components.colorpreference.ColorPreferenceEn
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
|
||||
import app.lawnchair.ui.theme.isSelectedThemeDark
|
||||
import com.android.launcher3.R
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
object SwatchGridDefaults {
|
||||
val GutterSize = 12.dp
|
||||
@@ -39,7 +38,7 @@ object SwatchGridDefaults {
|
||||
|
||||
@Composable
|
||||
fun <T> SwatchGrid(
|
||||
entries: ImmutableList<ColorPreferenceEntry<T>>,
|
||||
entries: List<ColorPreferenceEntry<T>>,
|
||||
onSwatchClick: (T) -> Unit,
|
||||
isSwatchSelected: (T) -> Boolean,
|
||||
modifier: Modifier = Modifier,
|
||||
|
||||
@@ -35,12 +35,11 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceDivider
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceTemplate
|
||||
import app.lawnchair.ui.util.addIf
|
||||
import app.lawnchair.ui.util.bottomSheetHandler
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
@Composable
|
||||
fun <T> ListPreference(
|
||||
adapter: PreferenceAdapter<T>,
|
||||
entries: ImmutableList<ListPreferenceEntry<T>>,
|
||||
entries: List<ListPreferenceEntry<T>>,
|
||||
label: String,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
@@ -61,7 +60,7 @@ fun <T> ListPreference(
|
||||
|
||||
@Composable
|
||||
fun <T> ListPreference(
|
||||
entries: ImmutableList<ListPreferenceEntry<T>>,
|
||||
entries: List<ListPreferenceEntry<T>>,
|
||||
value: T,
|
||||
onValueChange: (T) -> Unit,
|
||||
label: String,
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
package app.lawnchair.ui.preferences.data.liveinfo.model
|
||||
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
import kotlinx.collections.immutable.toImmutableList
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class LiveInformation(
|
||||
private val version: Int = 1,
|
||||
private val announcements: List<Announcement>,
|
||||
val announcements: List<Announcement>,
|
||||
) {
|
||||
|
||||
val announcementsImmutable: ImmutableList<Announcement>
|
||||
get() = announcements.toImmutableList()
|
||||
|
||||
companion object {
|
||||
val default = LiveInformation(
|
||||
version = 1,
|
||||
|
||||
@@ -41,7 +41,6 @@ import app.lawnchair.ui.preferences.components.layout.ExpandAndShrink
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceGroup
|
||||
import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
|
||||
import com.android.launcher3.R
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
object DockRoutes {
|
||||
const val SEARCH_PROVIDER = "searchProvider"
|
||||
@@ -143,7 +142,7 @@ private fun HotseatModePreference(
|
||||
label = { stringResource(id = mode.nameResourceId) },
|
||||
enabled = mode.isAvailable(context = context),
|
||||
)
|
||||
}.toPersistentList()
|
||||
}
|
||||
}
|
||||
|
||||
ListPreference(
|
||||
|
||||
@@ -51,7 +51,6 @@ import app.lawnchair.ui.preferences.components.notificationDotsEnabled
|
||||
import app.lawnchair.ui.preferences.components.notificationServiceEnabled
|
||||
import com.android.launcher3.R
|
||||
import com.android.launcher3.Utilities
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
object GeneralRoutes {
|
||||
const val ICON_PACK = "iconPack"
|
||||
@@ -220,7 +219,7 @@ private fun ColorStylePreference(
|
||||
value = mode,
|
||||
label = { stringResource(id = mode.nameResourceId) },
|
||||
)
|
||||
}.toPersistentList()
|
||||
}
|
||||
}
|
||||
|
||||
ListPreference(
|
||||
|
||||
@@ -40,8 +40,6 @@ import app.lawnchair.util.appComparator
|
||||
import app.lawnchair.util.appsState
|
||||
import com.android.launcher3.R
|
||||
import java.util.Comparator.comparing
|
||||
import kotlinx.collections.immutable.ImmutableSet
|
||||
import kotlinx.collections.immutable.toPersistentSet
|
||||
|
||||
@Composable
|
||||
fun HiddenAppsPreferences(
|
||||
@@ -55,7 +53,7 @@ fun HiddenAppsPreferences(
|
||||
} else {
|
||||
stringResource(id = R.string.hidden_apps_label_with_count, hiddenApps.size)
|
||||
}
|
||||
val apps by appsState(comparator = hiddenAppsComparator(hiddenApps.toPersistentSet()))
|
||||
val apps by appsState(comparator = hiddenAppsComparator(hiddenApps))
|
||||
val state = rememberLazyListState()
|
||||
PreferenceScaffold(
|
||||
label = pageTitle,
|
||||
@@ -109,7 +107,7 @@ fun HiddenAppsPreferences(
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun hiddenAppsComparator(hiddenApps: ImmutableSet<String>): Comparator<App> = remember {
|
||||
fun hiddenAppsComparator(hiddenApps: Set<String>): Comparator<App> = remember {
|
||||
comparing<App, Int> {
|
||||
if (hiddenApps.contains(it.key.toString())) 0 else 1
|
||||
}.then(appComparator)
|
||||
|
||||
@@ -79,7 +79,6 @@ import app.lawnchair.util.getThemedIconPacksInstalled
|
||||
import app.lawnchair.util.isPackageInstalled
|
||||
import com.android.launcher3.R
|
||||
import com.google.accompanist.drawablepainter.rememberDrawablePainter
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
data class IconPackInfo(
|
||||
@@ -227,7 +226,7 @@ fun IconPackPreferences(
|
||||
value = it,
|
||||
label = { stringResource(id = it.labelResourceId) },
|
||||
)
|
||||
}.toPersistentList(),
|
||||
},
|
||||
value = ThemedIconsState.getForSettings(
|
||||
themedIcons = themedIconsAdapter.state.value,
|
||||
drawerThemedIcons = drawerThemedIconsEnabled,
|
||||
|
||||
@@ -37,7 +37,6 @@ import app.lawnchair.util.filesAndStorageGranted
|
||||
import com.android.launcher3.R
|
||||
import com.google.accompanist.permissions.ExperimentalPermissionsApi
|
||||
import com.google.accompanist.permissions.rememberPermissionState
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
@Composable
|
||||
fun SearchPreferences() {
|
||||
@@ -138,7 +137,8 @@ private fun ASISearchSettings(prefs: PreferenceManager) {
|
||||
private fun SearchProvider(
|
||||
context: Context,
|
||||
) {
|
||||
val searchAlgorithmEntries = sequenceOf(
|
||||
val searchAlgorithmEntries = remember {
|
||||
sequenceOf(
|
||||
ListPreferenceEntry(LawnchairSearchAlgorithm.APP_SEARCH) { stringResource(R.string.search_algorithm_app_search) },
|
||||
ListPreferenceEntry(LawnchairSearchAlgorithm.LOCAL_SEARCH) { stringResource(R.string.search_algorithm_global_search_on_device) },
|
||||
ListPreferenceEntry(LawnchairSearchAlgorithm.ASI_SEARCH) { stringResource(R.string.search_algorithm_global_search_via_asi) },
|
||||
@@ -147,7 +147,8 @@ private fun SearchProvider(
|
||||
LawnchairSearchAlgorithm.ASI_SEARCH -> LawnchairSearchAlgorithm.isASISearchEnabled(context)
|
||||
else -> true
|
||||
}
|
||||
}.toPersistentList()
|
||||
}.toList()
|
||||
}
|
||||
|
||||
ListPreference(
|
||||
adapter = preferenceManager2().searchAlgorithm.getAdapter(),
|
||||
|
||||
@@ -41,7 +41,6 @@ import app.lawnchair.ui.preferences.components.layout.PreferenceLayout
|
||||
import app.lawnchair.ui.theme.isSelectedThemeDark
|
||||
import com.android.launcher3.R
|
||||
import com.kieronquinn.app.smartspacer.sdk.SmartspacerConstants
|
||||
import kotlinx.collections.immutable.toPersistentList
|
||||
|
||||
@Composable
|
||||
fun SmartspacePreferences(
|
||||
@@ -136,7 +135,7 @@ fun SmartspaceProviderPreference(
|
||||
label = { stringResource(id = mode.nameResourceId) },
|
||||
enabled = mode.isAvailable(context = context),
|
||||
)
|
||||
}.toPersistentList()
|
||||
}.toList()
|
||||
}
|
||||
|
||||
ListPreference(
|
||||
@@ -244,7 +243,7 @@ fun SmartspaceTimeFormatPreference(
|
||||
|
||||
ListPreference(
|
||||
adapter = adapter,
|
||||
entries = entries.toPersistentList(),
|
||||
entries = entries,
|
||||
label = stringResource(id = R.string.smartspace_time_format),
|
||||
modifier = modifier,
|
||||
)
|
||||
@@ -257,7 +256,7 @@ fun SmartspaceCalendarPreference(
|
||||
val entries = remember {
|
||||
SmartspaceCalendar.values().map { calendar ->
|
||||
ListPreferenceEntry(calendar) { stringResource(id = calendar.nameResourceId) }
|
||||
}.toPersistentList()
|
||||
}
|
||||
}
|
||||
|
||||
val adapter = preferenceManager2().smartspaceCalendar.getAdapter()
|
||||
|
||||
Reference in New Issue
Block a user