mirror of
https://github.com/yairm210/Unciv.git
synced 2025-07-08 23:08:35 +07:00
Cosmetic: Convenience shortcuts, some linting (#4067)
This commit is contained in:
@ -514,6 +514,7 @@ Disband unit =
|
||||
Explore =
|
||||
Stop exploration =
|
||||
Pillage =
|
||||
Are you sure you want to pillage this [improvement]? =
|
||||
Do you really want to disband this unit? =
|
||||
Disband this unit for [goldAmount] gold? =
|
||||
Create [improvement] =
|
||||
|
@ -665,8 +665,8 @@ class CivilizationInfo {
|
||||
fun getProtectorCivs() : List<CivilizationInfo> {
|
||||
if(this.isMajorCiv()) return emptyList()
|
||||
return diplomacy.values
|
||||
.filter{!it.otherCiv().isDefeated() && it.diplomaticStatus == DiplomaticStatus.Protector}
|
||||
.map{it->it.otherCiv()}
|
||||
.filter{ !it.otherCiv().isDefeated() && it.diplomaticStatus == DiplomaticStatus.Protector }
|
||||
.map{ it.otherCiv() }
|
||||
}
|
||||
|
||||
fun addProtectorCiv(otherCiv: CivilizationInfo) {
|
||||
|
@ -42,6 +42,12 @@ class Nation : INamed {
|
||||
var uniqueText = ""
|
||||
var innerColor: List<Int>? = null
|
||||
var startBias = ArrayList<String>()
|
||||
|
||||
/* Properties present in json but not yet implemented:
|
||||
var adjective = ArrayList<String>()
|
||||
var startIntroPart1 = ""
|
||||
var startIntroPart2 = ""
|
||||
*/
|
||||
|
||||
@Transient
|
||||
private lateinit var outerColorObject: Color
|
||||
@ -71,8 +77,8 @@ class Nation : INamed {
|
||||
fun setTransients() {
|
||||
outerColorObject = colorFromRGB(outerColor)
|
||||
|
||||
if (innerColor == null) innerColorObject = Color.BLACK
|
||||
else innerColorObject = colorFromRGB(innerColor!!)
|
||||
innerColorObject = if (innerColor == null) Color.BLACK
|
||||
else colorFromRGB(innerColor!!)
|
||||
|
||||
forestsAndJunglesAreRoads = uniques.contains("All units move through Forest and Jungle Tiles in friendly territory as if they have roads. These tiles can be used to establish City Connections upon researching the Wheel.")
|
||||
ignoreHillMovementCost = uniques.contains("Units ignore terrain costs when moving into any tile with Hills")
|
||||
@ -184,4 +190,4 @@ class Nation : INamed {
|
||||
textList += " " + unique.tr()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class CityScreenCityPickerTable(private val cityScreen: CityScreen) : Table() {
|
||||
textArea.alignment = Align.center
|
||||
editCityNamePopup.add(textArea).colspan(2).row()
|
||||
//editCityNamePopup.name = "CityNamePopup" // debug help
|
||||
editCityNamePopup.addButtonInRow("Save", '\r') {
|
||||
editCityNamePopup.addButtonInRow("Save", KeyCharAndCode.RETURN) {
|
||||
city.name = textArea.text
|
||||
cityScreen.game.setScreen(CityScreen(city))
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ class MapEditorMenuPopup(var mapEditorScreen: MapEditorScreen): Popup(mapEditorS
|
||||
|
||||
add(ScrollPane(checkboxTable)).maxHeight(mapEditorScreen.stage.height * 0.8f).colspan(2).row()
|
||||
|
||||
addButtonInRow("Save", '\r') {
|
||||
addButtonInRow("Save", KeyCharAndCode.RETURN) {
|
||||
val incompatibilities = HashSet<String>()
|
||||
for (set in mapEditorScreen.tileMap.values.map { it.getRulesetIncompatibility(ruleset) })
|
||||
incompatibilities.addAll(set)
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.unciv.ui.mapeditor
|
||||
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.math.Vector2
|
||||
import com.badlogic.gdx.scenes.scene2d.InputEvent
|
||||
@ -68,7 +67,7 @@ class MapEditorScreen(): CameraStageBaseScreen() {
|
||||
}
|
||||
val optionsMenuButton = "Menu".toTextButton()
|
||||
optionsMenuButton.onClick(openOptionsMenu)
|
||||
keyPressDispatcher[Input.Keys.BACK] = openOptionsMenu
|
||||
keyPressDispatcher[KeyCharAndCode.BACK] = openOptionsMenu
|
||||
optionsMenuButton.label.setFontSize(24)
|
||||
optionsMenuButton.labelCell.pad(20f)
|
||||
optionsMenuButton.pack()
|
||||
|
@ -7,7 +7,6 @@ import com.badlogic.gdx.scenes.scene2d.ui.Table
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton
|
||||
import com.badlogic.gdx.scenes.scene2d.ui.TextField
|
||||
import com.badlogic.gdx.utils.Json
|
||||
import com.badlogic.gdx.Input
|
||||
import com.unciv.logic.MapSaver
|
||||
import com.unciv.logic.map.MapType
|
||||
import com.unciv.logic.map.TileMap
|
||||
@ -71,7 +70,7 @@ class SaveAndLoadMapScreen(mapToSave: TileMap?, save:Boolean = false, previousSc
|
||||
}
|
||||
}
|
||||
rightSideButton.onClick(rightSideButtonAction)
|
||||
keyPressDispatcher['\r'] = rightSideButtonAction
|
||||
keyPressDispatcher[KeyCharAndCode.RETURN] = rightSideButtonAction
|
||||
|
||||
topTable.add(ScrollPane(mapsTable)).maxWidth(stage.width / 2)
|
||||
|
||||
|
@ -15,7 +15,7 @@ import com.unciv.ui.utils.*
|
||||
import kotlin.math.max
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class CityOverviewTable(val viewingPlayer: CivilizationInfo, val overviewScreen: EmpireOverviewScreen): Table() {
|
||||
class CityOverviewTable(private val viewingPlayer: CivilizationInfo, private val overviewScreen: EmpireOverviewScreen): Table() {
|
||||
|
||||
companion object {
|
||||
const val iconSize = 50f //if you set this too low, there is a chance that the tables will be misaligned
|
||||
@ -52,7 +52,7 @@ class CityOverviewTable(val viewingPlayer: CivilizationInfo, val overviewScreen:
|
||||
|
||||
// Prepare top third: cityInfoTableIcons
|
||||
cityInfoTableIcons.defaults()
|
||||
.pad(paddingVert, paddingHorz, paddingVert, paddingHorz)
|
||||
.pad(paddingVert, paddingHorz)
|
||||
.align(Align.center)
|
||||
cityInfoTableIcons.add("Cities".toLabel(fontSize = 24)).colspan(numHeaderCells).align(Align.center).row()
|
||||
val citySortIcon: IconCircleGroup = ImageGetter.getUnitIcon("Settler").surroundWithCircle(iconSize)
|
||||
@ -65,7 +65,7 @@ class CityOverviewTable(val viewingPlayer: CivilizationInfo, val overviewScreen:
|
||||
|
||||
// Prepare middle third: cityInfoScrollPane (a ScrollPane containing cityInfoTableDetails)
|
||||
cityInfoTableDetails.defaults()
|
||||
.pad(paddingVert, paddingHorz, paddingVert, paddingHorz)
|
||||
.pad(paddingVert, paddingHorz)
|
||||
.minWidth(iconSize) //we need the min width so we can align the different tables
|
||||
.align(Align.left)
|
||||
|
||||
@ -83,7 +83,7 @@ class CityOverviewTable(val viewingPlayer: CivilizationInfo, val overviewScreen:
|
||||
|
||||
// Prepare bottom third: cityInfoTableTotal
|
||||
cityInfoTableTotal.defaults()
|
||||
.pad(paddingVert, paddingHorz, paddingVert, paddingHorz)
|
||||
.pad(paddingVert, paddingHorz)
|
||||
.minWidth(iconSize) //we need the min width so we can align the different tables
|
||||
|
||||
cityInfoTableTotal.add("Total".toLabel())
|
||||
@ -109,8 +109,9 @@ class CityOverviewTable(val viewingPlayer: CivilizationInfo, val overviewScreen:
|
||||
}
|
||||
|
||||
private fun getStatOfCity(cityInfo: CityInfo, stat: Stat): Int {
|
||||
if (stat == Stat.Happiness) return cityInfo.cityStats.happinessList.values.sum().roundToInt()
|
||||
else return cityInfo.cityStats.currentCityStats.get(stat).roundToInt()
|
||||
return if (stat == Stat.Happiness)
|
||||
cityInfo.cityStats.happinessList.values.sum().roundToInt()
|
||||
else cityInfo.cityStats.currentCityStats.get(stat).roundToInt()
|
||||
}
|
||||
|
||||
private fun fillCitiesTable(citiesTable: Table, sortType: String, descending: Boolean) {
|
||||
|
@ -18,7 +18,7 @@ import com.unciv.ui.utils.AutoScrollPane as ScrollPane
|
||||
|
||||
|
||||
class SaveGameScreen(val gameInfo: GameInfo) : PickerScreen(disableScroll = true) {
|
||||
val gameNameTextField = TextField("", skin)
|
||||
private val gameNameTextField = TextField("", skin)
|
||||
val currentSaves = Table()
|
||||
|
||||
init {
|
||||
@ -30,7 +30,7 @@ class SaveGameScreen(val gameInfo: GameInfo) : PickerScreen(disableScroll = true
|
||||
topTable.add(ScrollPane(currentSaves))
|
||||
|
||||
val newSave = Table()
|
||||
newSave.defaults().pad(5f, 10f, 5f, 10f)
|
||||
newSave.defaults().pad(5f, 10f)
|
||||
val defaultSaveName = gameInfo.currentPlayer + " - " + gameInfo.turns + " turns"
|
||||
gameNameTextField.text = defaultSaveName
|
||||
|
||||
@ -100,7 +100,7 @@ class SaveGameScreen(val gameInfo: GameInfo) : PickerScreen(disableScroll = true
|
||||
}
|
||||
}
|
||||
|
||||
fun updateShownSaves(showAutosaves: Boolean) {
|
||||
private fun updateShownSaves(showAutosaves: Boolean) {
|
||||
currentSaves.clear()
|
||||
val saves = GameSaver.getSaves()
|
||||
.sortedByDescending { it.lastModified() }
|
||||
|
@ -116,8 +116,8 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
}
|
||||
|
||||
val protectors = otherCiv.getProtectorCivs()
|
||||
if (protectors.size > 0) {
|
||||
val protectorString = "{Protected by}: " + protectors.map{it.civName}.joinToString(", ")
|
||||
if (protectors.isNotEmpty()) {
|
||||
val protectorString = "{Protected by}: " + protectors.joinToString(", ") { it.civName }
|
||||
diplomacyTable.add(protectorString.toLabel()).row()
|
||||
}
|
||||
|
||||
@ -164,28 +164,28 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
if (viewingCiv.gold < giftAmount || isNotPlayersTurn()) giftButton.disable()
|
||||
|
||||
if (otherCivDiplomacyManager.diplomaticStatus == DiplomaticStatus.Protector){
|
||||
val RevokeProtectionButton = "Revoke Protection".toTextButton()
|
||||
RevokeProtectionButton.onClick{
|
||||
YesNoPopup("Revoke protection for [${otherCiv.civName}]?".tr(), {
|
||||
val revokeProtectionButton = "Revoke Protection".toTextButton()
|
||||
revokeProtectionButton.onClick {
|
||||
YesNoPopup("Revoke protection for [${otherCiv.civName}]?", {
|
||||
otherCiv.removeProtectorCiv(viewingCiv)
|
||||
updateLeftSideTable()
|
||||
updateRightSide(otherCiv)
|
||||
}, this).open()
|
||||
}
|
||||
diplomacyTable.add(RevokeProtectionButton).row()
|
||||
diplomacyTable.add(revokeProtectionButton).row()
|
||||
} else {
|
||||
val ProtectionButton = "Pledge to protect".toTextButton()
|
||||
ProtectionButton.onClick{
|
||||
YesNoPopup("Declare Protection of [${otherCiv.civName}]?".tr(), {
|
||||
val protectionButton = "Pledge to protect".toTextButton()
|
||||
protectionButton.onClick {
|
||||
YesNoPopup("Declare Protection of [${otherCiv.civName}]?", {
|
||||
otherCiv.addProtectorCiv(viewingCiv)
|
||||
updateLeftSideTable()
|
||||
updateRightSide(otherCiv)
|
||||
}, this).open()
|
||||
}
|
||||
if(viewingCiv.isAtWarWith(otherCiv)) {
|
||||
ProtectionButton.disable()
|
||||
protectionButton.disable()
|
||||
}
|
||||
diplomacyTable.add(ProtectionButton).row()
|
||||
diplomacyTable.add(protectionButton).row()
|
||||
}
|
||||
|
||||
val diplomacyManager = viewingCiv.getDiplomacyManager(otherCiv)
|
||||
@ -193,7 +193,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
if (viewingCiv.isAtWarWith(otherCiv)) {
|
||||
val peaceButton = "Negotiate Peace".toTextButton()
|
||||
peaceButton.onClick {
|
||||
YesNoPopup("Peace with [${otherCiv.civName}]?".tr(), {
|
||||
YesNoPopup("Peace with [${otherCiv.civName}]?", {
|
||||
val tradeLogic = TradeLogic(viewingCiv, otherCiv)
|
||||
tradeLogic.currentTrade.ourOffers.add(TradeOffer(Constants.peaceTreaty, TradeType.Treaty))
|
||||
tradeLogic.currentTrade.theirOffers.add(TradeOffer(Constants.peaceTreaty, TradeType.Treaty))
|
||||
@ -457,7 +457,7 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
declareWarButton.setText(declareWarButton.text.toString() + " ($turnsToPeaceTreaty${Fonts.turn})")
|
||||
}
|
||||
declareWarButton.onClick {
|
||||
YesNoPopup("Declare war on [${otherCiv.civName}]?".tr(), {
|
||||
YesNoPopup("Declare war on [${otherCiv.civName}]?", {
|
||||
diplomacyManager.declareWar()
|
||||
setRightSideFlavorText(otherCiv, otherCiv.nation.attacked, "Very well.")
|
||||
updateLeftSideTable()
|
||||
@ -466,6 +466,8 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
return declareWarButton
|
||||
}
|
||||
|
||||
// response currently always gets "Very Well.", but that may expand in the future.
|
||||
@Suppress("SameParameterValue")
|
||||
private fun setRightSideFlavorText(otherCiv: CivilizationInfo, flavorText: String, response: String) {
|
||||
val diplomacyTable = Table()
|
||||
diplomacyTable.defaults().pad(10f)
|
||||
@ -481,4 +483,4 @@ class DiplomacyScreen(val viewingCiv:CivilizationInfo):CameraStageBaseScreen() {
|
||||
rightSideTable.add(diplomacyTable)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ class TutorialRender(private val screen: CameraStageBaseScreen) {
|
||||
|
||||
tutorialPopup.addGoodSizedLabel(texts[0]).row()
|
||||
|
||||
tutorialPopup.addCloseButton(additionalKey = KeyCharAndCode(' ')) {
|
||||
tutorialPopup.addCloseButton(additionalKey = KeyCharAndCode.SPACE) {
|
||||
tutorialPopup.remove()
|
||||
texts.removeIndex(0)
|
||||
showDialog(tutorialName, texts, closeAction)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.unciv.ui.utils
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.Screen
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.graphics.GL20
|
||||
@ -95,8 +94,7 @@ open class CameraStageBaseScreen : Screen {
|
||||
}
|
||||
|
||||
fun onBackButtonClicked(action: () -> Unit) {
|
||||
keyPressDispatcher[Input.Keys.BACK] = action
|
||||
keyPressDispatcher['\u001B'] = action
|
||||
keyPressDispatcher[KeyCharAndCode.BACK] = action
|
||||
}
|
||||
|
||||
fun isPortrait() = stage.viewport.screenHeight > stage.viewport.screenWidth
|
||||
|
@ -111,6 +111,11 @@ fun <T : Actor> Table.addCell(actor: T): Table {
|
||||
return this
|
||||
}
|
||||
|
||||
/** Shortcut for [Cell].[pad][com.badlogic.gdx.scenes.scene2d.ui.Cell.pad] with top=bottom and left=right */
|
||||
fun <T : Actor> Cell<T>.pad(vertical: Float, horizontal: Float): Cell<T> {
|
||||
return pad(vertical, horizontal, vertical, horizontal)
|
||||
}
|
||||
|
||||
/** Gets a clone of an [ArrayList] with an additional item
|
||||
*
|
||||
* Solves concurrent modification problems - everyone who had a reference to the previous arrayList can keep using it because it hasn't changed
|
||||
|
@ -146,10 +146,10 @@ object Fonts {
|
||||
}
|
||||
|
||||
|
||||
const val turn = '⏳'
|
||||
const val strength = '†'
|
||||
const val rangedStrength = '‡'
|
||||
const val movement = '➡'
|
||||
const val range = '…'
|
||||
const val production = '⚙'
|
||||
const val turn = '⏳' // U+23F3 'hourglass'
|
||||
const val strength = '†' // U+2020 'dagger'
|
||||
const val rangedStrength = '‡' // U+2021 'double dagger'
|
||||
const val movement = '➡' // U+27A1 'black rightwards arrow'
|
||||
const val range = '…' // U+2026 'horizontal ellipsis'
|
||||
const val production = '⚙' // U+2699 'gear'
|
||||
}
|
||||
|
@ -39,11 +39,20 @@ data class KeyCharAndCode(val char: Char, val code: Int) {
|
||||
// debug helper
|
||||
return when {
|
||||
char == Char.MIN_VALUE -> Input.Keys.toString(code)
|
||||
char == '\u001B' -> "ESC"
|
||||
this == ESC -> "ESC"
|
||||
char < ' ' -> "Ctrl-" + (char.toInt()+64).toChar()
|
||||
else -> "\"$char\""
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience shortcuts for frequently used constants
|
||||
companion object {
|
||||
val BACK = KeyCharAndCode(Input.Keys.BACK)
|
||||
val ESC = KeyCharAndCode('\u001B')
|
||||
val RETURN = KeyCharAndCode('\r')
|
||||
val NEWLINE = KeyCharAndCode('\n')
|
||||
val SPACE = KeyCharAndCode(' ')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -86,19 +95,19 @@ class KeyPressDispatcher(val name: String? = null) : HashMap<KeyCharAndCode, (()
|
||||
operator fun set(key: KeyCharAndCode, action: () -> Unit) {
|
||||
super.put(key, action)
|
||||
// On Android the Enter key will fire with Ascii code `Linefeed`, on desktop as `Carriage Return`
|
||||
if (key == KeyCharAndCode('\r'))
|
||||
super.put(KeyCharAndCode('\n'), action)
|
||||
if (key == KeyCharAndCode.RETURN)
|
||||
super.put(KeyCharAndCode.NEWLINE, action)
|
||||
// Likewise always match Back to ESC
|
||||
if (key == KeyCharAndCode(Input.Keys.BACK))
|
||||
super.put(KeyCharAndCode('\u001B'), action)
|
||||
if (key == KeyCharAndCode.BACK)
|
||||
super.put(KeyCharAndCode.ESC, action)
|
||||
checkInstall()
|
||||
}
|
||||
override fun remove(key: KeyCharAndCode): (() -> Unit)? {
|
||||
val result = super.remove(key)
|
||||
if (key == KeyCharAndCode('\r'))
|
||||
super.remove(KeyCharAndCode('\n'))
|
||||
if (key == KeyCharAndCode(Input.Keys.BACK))
|
||||
super.remove(KeyCharAndCode('\u001B'))
|
||||
if (key == KeyCharAndCode.RETURN)
|
||||
super.remove(KeyCharAndCode.NEWLINE)
|
||||
if (key == KeyCharAndCode.BACK)
|
||||
super.remove(KeyCharAndCode.ESC)
|
||||
checkInstall()
|
||||
return result
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.unciv.ui.utils
|
||||
|
||||
import com.badlogic.gdx.Input
|
||||
import com.badlogic.gdx.graphics.Color
|
||||
import com.badlogic.gdx.scenes.scene2d.Actor
|
||||
import com.badlogic.gdx.scenes.scene2d.Touchable
|
||||
@ -137,7 +136,7 @@ open class Popup(val screen: CameraStageBaseScreen): Table(CameraStageBaseScreen
|
||||
action: (()->Unit)? = null
|
||||
): Cell<TextButton> {
|
||||
val closeAction = { close(); if(action!=null) action() }
|
||||
keyPressDispatcher[Input.Keys.BACK] = closeAction
|
||||
keyPressDispatcher[KeyCharAndCode.BACK] = closeAction
|
||||
return addButton(text, additionalKey, closeAction)
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
package com.unciv.ui.utils
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.Input
|
||||
import com.unciv.UncivGame
|
||||
|
||||
/** Variant of [Popup] pre-populated with one label, plus yes and no buttons
|
||||
@ -23,8 +22,8 @@ open class YesNoPopup (
|
||||
add(question.toLabel()).colspan(2).row()
|
||||
addButtonInRow("Yes", 'y', yes)
|
||||
addButtonInRow("No", 'n', no)
|
||||
keyPressDispatcher['\r'] = yes
|
||||
keyPressDispatcher[Input.Keys.BACK] = no
|
||||
keyPressDispatcher[KeyCharAndCode.RETURN] = yes
|
||||
keyPressDispatcher[KeyCharAndCode.BACK] = no
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,12 +7,13 @@ import com.badlogic.gdx.utils.Align
|
||||
import com.unciv.logic.map.MapUnit
|
||||
import com.unciv.ui.utils.ImageGetter
|
||||
import com.unciv.ui.utils.onClick
|
||||
import com.unciv.ui.utils.pad
|
||||
import com.unciv.ui.worldscreen.WorldMapHolder
|
||||
|
||||
class IdleUnitButton (
|
||||
internal val unitTable: UnitTable,
|
||||
val tileMapHolder: WorldMapHolder,
|
||||
val previous:Boolean
|
||||
internal val unitTable: UnitTable,
|
||||
private val tileMapHolder: WorldMapHolder,
|
||||
val previous:Boolean
|
||||
) : Table() {
|
||||
|
||||
val image = ImageGetter.getImage("OtherIcons/BackArrow")
|
||||
@ -26,7 +27,7 @@ class IdleUnitButton (
|
||||
image.setOrigin(Align.center)
|
||||
image.rotateBy(180f)
|
||||
}
|
||||
add(image).size(imageSize).pad(10f,20f,10f,20f)
|
||||
add(image).size(imageSize).pad(10f,20f)
|
||||
enable()
|
||||
onClick {
|
||||
|
||||
@ -61,4 +62,3 @@ class IdleUnitButton (
|
||||
touchable=Touchable.disabled
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user