Reach nodes by unique name instead of long paths
Nodes a script uses through a path of several nodes are marked unique in their scene and found with %Name. The search list is renamed SearchResults, and the player row's nodes get their real types.
This commit is contained in:
1 parent
390da577d7
commit
674604425f
17 files changed
+54
-24
No files matched your search
@@ -74,6 +74,7 @@ text = "Statistics"
|
|||||||
horizontal_alignment = 1
|
horizontal_alignment = 1
|
||||||
|
|
||||||
[node name="StatisticsLabel" type="Label" parent="StatisticsPopupPanel" unique_id=58226477]
|
[node name="StatisticsLabel" type="Label" parent="StatisticsPopupPanel" unique_id=58226477]
|
||||||
|
unique_name_in_owner = true
|
||||||
offset_left = 4.0
|
offset_left = 4.0
|
||||||
offset_top = 4.0
|
offset_top = 4.0
|
||||||
offset_right = 446.0
|
offset_right = 446.0
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ follow_focus = true
|
|||||||
script = ExtResource("7_dj026")
|
script = ExtResource("7_dj026")
|
||||||
|
|
||||||
[node name="MusicList" type="VBoxContainer" parent="ScrollContainer" unique_id=373398568]
|
[node name="MusicList" type="VBoxContainer" parent="ScrollContainer" unique_id=373398568]
|
||||||
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 3
|
size_flags_vertical = 3
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ layout_mode = 2
|
|||||||
size_flags_vertical = 4
|
size_flags_vertical = 4
|
||||||
|
|
||||||
[node name="PlayTextureButton" type="TextureButton" parent="PlayerBar/MusicPlayerContainer"]
|
[node name="PlayTextureButton" type="TextureButton" parent="PlayerBar/MusicPlayerContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(32, 32)
|
custom_minimum_size = Vector2(32, 32)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_mode = 0
|
focus_mode = 0
|
||||||
@@ -66,6 +67,7 @@ ignore_texture_size = true
|
|||||||
stretch_mode = 0
|
stretch_mode = 0
|
||||||
|
|
||||||
[node name="RestartTextureButton" type="TextureButton" parent="PlayerBar/MusicPlayerContainer"]
|
[node name="RestartTextureButton" type="TextureButton" parent="PlayerBar/MusicPlayerContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(32, 32)
|
custom_minimum_size = Vector2(32, 32)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_mode = 0
|
focus_mode = 0
|
||||||
@@ -77,16 +79,19 @@ stretch_mode = 0
|
|||||||
flip_h = true
|
flip_h = true
|
||||||
|
|
||||||
[node name="MusicPlayerSlider" type="HSlider" parent="PlayerBar/MusicPlayerContainer"]
|
[node name="MusicPlayerSlider" type="HSlider" parent="PlayerBar/MusicPlayerContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 4
|
size_flags_vertical = 4
|
||||||
scrollable = false
|
scrollable = false
|
||||||
|
|
||||||
[node name="MusicTimeLabel" type="Label" parent="PlayerBar/MusicPlayerContainer"]
|
[node name="MusicTimeLabel" type="Label" parent="PlayerBar/MusicPlayerContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "0:00 / 0:00"
|
text = "0:00 / 0:00"
|
||||||
|
|
||||||
[node name="VolumeSlider" parent="PlayerBar/MusicPlayerContainer" instance=ExtResource("5_iifuj")]
|
[node name="VolumeSlider" parent="PlayerBar/MusicPlayerContainer" instance=ExtResource("5_iifuj")]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(100, 0)
|
custom_minimum_size = Vector2(100, 0)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_vertical = 4
|
size_flags_vertical = 4
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ layout_mode = 2
|
|||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_821k2")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_821k2")
|
||||||
|
|
||||||
[node name="Name" type="Label" parent="HBoxContainer"]
|
[node name="Name" type="Label" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(130, 40)
|
custom_minimum_size = Vector2(130, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
@@ -57,6 +58,7 @@ layout_mode = 2
|
|||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_w10e8")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_w10e8")
|
||||||
|
|
||||||
[node name="Character" type="TextureButton" parent="HBoxContainer"]
|
[node name="Character" type="TextureButton" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(80, 40)
|
custom_minimum_size = Vector2(80, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_mode = 0
|
focus_mode = 0
|
||||||
@@ -71,6 +73,7 @@ layout_mode = 2
|
|||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_78a8g")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_78a8g")
|
||||||
|
|
||||||
[node name="AddPoint" type="Button" parent="HBoxContainer"]
|
[node name="AddPoint" type="Button" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(40, 40)
|
custom_minimum_size = Vector2(40, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_mode = 0
|
focus_mode = 0
|
||||||
@@ -83,6 +86,7 @@ layout_mode = 2
|
|||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_i56hb")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_i56hb")
|
||||||
|
|
||||||
[node name="RemovePoint" type="Button" parent="HBoxContainer"]
|
[node name="RemovePoint" type="Button" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(40, 40)
|
custom_minimum_size = Vector2(40, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_mode = 0
|
focus_mode = 0
|
||||||
@@ -95,6 +99,7 @@ layout_mode = 2
|
|||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_b2crt")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_b2crt")
|
||||||
|
|
||||||
[node name="RemovePlayer" type="TextureButton" parent="HBoxContainer"]
|
[node name="RemovePlayer" type="TextureButton" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(40, 40)
|
custom_minimum_size = Vector2(40, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
focus_mode = 0
|
focus_mode = 0
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ horizontal_alignment = 1
|
|||||||
vertical_alignment = 1
|
vertical_alignment = 1
|
||||||
|
|
||||||
[node name="AddPlayersButton" type="TextureButton" parent="VBoxContainer/HBoxContainer" unique_id=634410148]
|
[node name="AddPlayersButton" type="TextureButton" parent="VBoxContainer/HBoxContainer" unique_id=634410148]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(2.08165e-12, 40)
|
custom_minimum_size = Vector2(2.08165e-12, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 8
|
size_flags_horizontal = 8
|
||||||
@@ -51,6 +52,7 @@ shortcut = SubResource("Shortcut_jafqj")
|
|||||||
texture_normal = ExtResource("5_31tjv")
|
texture_normal = ExtResource("5_31tjv")
|
||||||
|
|
||||||
[node name="AddPlayerContainer" type="HBoxContainer" parent="VBoxContainer" unique_id=1371948739]
|
[node name="AddPlayerContainer" type="HBoxContainer" parent="VBoxContainer" unique_id=1371948739]
|
||||||
|
unique_name_in_owner = true
|
||||||
visible = false
|
visible = false
|
||||||
custom_minimum_size = Vector2(2.08165e-12, 40)
|
custom_minimum_size = Vector2(2.08165e-12, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -61,6 +63,7 @@ size_flags_horizontal = 3
|
|||||||
theme_override_styles/panel = SubResource("StyleBoxFlat_qk7sj")
|
theme_override_styles/panel = SubResource("StyleBoxFlat_qk7sj")
|
||||||
|
|
||||||
[node name="PlayerNameField" type="TextEdit" parent="VBoxContainer/AddPlayerContainer" unique_id=332535327]
|
[node name="PlayerNameField" type="TextEdit" parent="VBoxContainer/AddPlayerContainer" unique_id=332535327]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(2.08165e-12, 40)
|
custom_minimum_size = Vector2(2.08165e-12, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
@@ -68,6 +71,7 @@ placeholder_text = "Player name"
|
|||||||
script = ExtResource("7_qsdfy")
|
script = ExtResource("7_qsdfy")
|
||||||
|
|
||||||
[node name="AddPlayerButton" type="Button" parent="VBoxContainer/AddPlayerContainer" unique_id=245001313]
|
[node name="AddPlayerButton" type="Button" parent="VBoxContainer/AddPlayerContainer" unique_id=245001313]
|
||||||
|
unique_name_in_owner = true
|
||||||
custom_minimum_size = Vector2(2.08165e-12, 40)
|
custom_minimum_size = Vector2(2.08165e-12, 40)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Add"
|
text = "Add"
|
||||||
@@ -84,6 +88,7 @@ size_flags_vertical = 15
|
|||||||
horizontal_scroll_mode = 0
|
horizontal_scroll_mode = 0
|
||||||
|
|
||||||
[node name="PlayersListVBoxContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer" unique_id=1000000002]
|
[node name="PlayersListVBoxContainer" type="VBoxContainer" parent="VBoxContainer/ScrollContainer" unique_id=1000000002]
|
||||||
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
size_flags_vertical = 15
|
size_flags_vertical = 15
|
||||||
@@ -22,6 +22,7 @@ offset_right = 450.0
|
|||||||
offset_bottom = 520.0
|
offset_bottom = 520.0
|
||||||
|
|
||||||
[node name="QRCodeRect" type="TextureRect" parent="QRPanel" unique_id=1054378438]
|
[node name="QRCodeRect" type="TextureRect" parent="QRPanel" unique_id=1054378438]
|
||||||
|
unique_name_in_owner = true
|
||||||
layout_mode = 0
|
layout_mode = 0
|
||||||
offset_left = 20.0
|
offset_left = 20.0
|
||||||
offset_top = 20.0
|
offset_top = 20.0
|
||||||
|
|||||||
+2
-1
@@ -47,6 +47,7 @@ offset_right = 576.0
|
|||||||
offset_bottom = 384.0
|
offset_bottom = 384.0
|
||||||
scale = Vector2(2, 2)
|
scale = Vector2(2, 2)
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="ScrollContainer" unique_id=1567403144]
|
[node name="SearchResults" type="VBoxContainer" parent="ScrollContainer" unique_id=1567403144]
|
||||||
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_horizontal = 3
|
size_flags_horizontal = 3
|
||||||
@@ -17,6 +17,7 @@ layout_mode = 2
|
|||||||
size_flags_vertical = 0
|
size_flags_vertical = 0
|
||||||
|
|
||||||
[node name="SongListLabel" type="Label" parent="HBoxContainer"]
|
[node name="SongListLabel" type="Label" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
texture_filter = 2
|
texture_filter = 2
|
||||||
custom_minimum_size = Vector2(865, 28)
|
custom_minimum_size = Vector2(865, 28)
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
@@ -34,6 +35,7 @@ size_flags_horizontal = 3
|
|||||||
size_flags_vertical = 0
|
size_flags_vertical = 0
|
||||||
|
|
||||||
[node name="SongListPlayers" type="HBoxContainer" parent="HBoxContainer"]
|
[node name="SongListPlayers" type="HBoxContainer" parent="HBoxContainer"]
|
||||||
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
size_flags_vertical = 0
|
size_flags_vertical = 0
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -33,7 +33,7 @@ var log_popup: LogPopup = %LogPopup
|
|||||||
var statistic_popup: PopupPanel = $StatisticsPopupPanel
|
var statistic_popup: PopupPanel = $StatisticsPopupPanel
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var statistic_label: Label = $StatisticsPopupPanel/StatisticsLabel
|
var statistic_label: Label = %StatisticsLabel
|
||||||
|
|
||||||
## Dims the window behind an open popup and keeps clicks from reaching the buttons under it.
|
## Dims the window behind an open popup and keeps clicks from reaching the buttons under it.
|
||||||
var popup_backdrop: PopupBackdrop
|
var popup_backdrop: PopupBackdrop
|
||||||
|
|||||||
+1
-1
@@ -8,7 +8,7 @@ signal song_clicked(song_no: int)
|
|||||||
var _song_list_object: PackedScene = preload("res://SongRow.tscn")
|
var _song_list_object: PackedScene = preload("res://SongRow.tscn")
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var _rows: VBoxContainer = $ScrollContainer/MusicList
|
var _rows: VBoxContainer = %MusicList
|
||||||
|
|
||||||
|
|
||||||
## Shows the songs in the playlist again, so it shows their latest state.
|
## Shows the songs in the playlist again, so it shows their latest state.
|
||||||
|
|||||||
+5
-5
@@ -7,10 +7,10 @@ extends Control
|
|||||||
# LOC 12/6-24: 170
|
# LOC 12/6-24: 170
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var play_button: TextureButton = $PlayerBar/MusicPlayerContainer/PlayTextureButton
|
var play_button: TextureButton = %PlayTextureButton
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var restart_button: TextureButton = $PlayerBar/MusicPlayerContainer/RestartTextureButton
|
var restart_button: TextureButton = %RestartTextureButton
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var audio_player: AudioStreamPlayer = $AudioStreamPlayer
|
var audio_player: AudioStreamPlayer = $AudioStreamPlayer
|
||||||
@@ -22,13 +22,13 @@ var sound_player: AudioStreamPlayer = $AudioSoundPlayer
|
|||||||
var sound_effect_player: AudioStreamPlayer = $AudioSoundEffectPlayer
|
var sound_effect_player: AudioStreamPlayer = $AudioSoundEffectPlayer
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var progress_slider: HSlider = $PlayerBar/MusicPlayerContainer/MusicPlayerSlider
|
var progress_slider: HSlider = %MusicPlayerSlider
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var volume_slider: VolumeSlider = $PlayerBar/MusicPlayerContainer/VolumeSlider
|
var volume_slider: VolumeSlider = %VolumeSlider
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var music_time_label: Label = $PlayerBar/MusicPlayerContainer/MusicTimeLabel
|
var music_time_label: Label = %MusicTimeLabel
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var auto_repeat_button: CheckButton = $RepeatSongCheckButton
|
var auto_repeat_button: CheckButton = $RepeatSongCheckButton
|
||||||
|
|||||||
+5
-5
@@ -2,19 +2,19 @@ class_name PlayerRow
|
|||||||
extends Control
|
extends Control
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var player_name_field := $HBoxContainer/Name
|
var player_name_field: Label = %Name
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var add_button := $HBoxContainer/AddPoint
|
var add_button: Button = %AddPoint
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var minus_button := $HBoxContainer/RemovePoint
|
var minus_button: Button = %RemovePoint
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var character := $HBoxContainer/Character
|
var character: TextureButton = %Character
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var remove_player := $HBoxContainer/RemovePlayer
|
var remove_player: TextureButton = %RemovePlayer
|
||||||
|
|
||||||
signal change_character_clicked
|
signal change_character_clicked
|
||||||
signal player_removed
|
signal player_removed
|
||||||
|
|||||||
+5
-5
@@ -18,19 +18,19 @@ signal change_character_requested(row: PlayerRow, player_name: String)
|
|||||||
var _player_row: PackedScene = preload("res://PlayerRow.tscn")
|
var _player_row: PackedScene = preload("res://PlayerRow.tscn")
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var add_players_button: TextureButton = $VBoxContainer/HBoxContainer/AddPlayersButton
|
var add_players_button: TextureButton = %AddPlayersButton
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var add_player_container: HBoxContainer = $VBoxContainer/AddPlayerContainer
|
var add_player_container: HBoxContainer = %AddPlayerContainer
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var add_player_button: Button = $VBoxContainer/AddPlayerContainer/AddPlayerButton
|
var add_player_button: Button = %AddPlayerButton
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var new_player_name_field: TextEdit = $VBoxContainer/AddPlayerContainer/PlayerNameField
|
var new_player_name_field: TextEdit = %PlayerNameField
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var players_list_container: VBoxContainer = $VBoxContainer/ScrollContainer/PlayersListVBoxContainer
|
var players_list_container: VBoxContainer = %PlayersListVBoxContainer
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
|||||||
+2
-2
@@ -5,10 +5,10 @@ extends BasePopup
|
|||||||
var qr_panel: Panel = $QRPanel
|
var qr_panel: Panel = $QRPanel
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var qr_code_rect: QRCodeRect = $QRPanel/QRCodeRect
|
var qr_code_rect: QRCodeRect = %QRCodeRect
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var url_label: Label = $QRPanel/URLLabel
|
var url_label: Label = %URLLabel
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
func _ready() -> void:
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@ class_name SearchPopup
|
|||||||
extends BasePopup
|
extends BasePopup
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var search_list: VBoxContainer = $ScrollContainer/VBoxContainer
|
var search_list: VBoxContainer = %SearchResults
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var search_panel: Panel = %SearchPanel
|
var search_panel: Panel = %SearchPanel
|
||||||
|
|||||||
+2
-2
@@ -2,10 +2,10 @@ class_name SongRow
|
|||||||
extends PanelContainer
|
extends PanelContainer
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var song_list_label: Label = $HBoxContainer/SongListLabel
|
var song_list_label: Label = %SongListLabel
|
||||||
|
|
||||||
@onready
|
@onready
|
||||||
var song_list_players: HBoxContainer = $HBoxContainer/SongListPlayers
|
var song_list_players: HBoxContainer = %SongListPlayers
|
||||||
|
|
||||||
var song_object: SongObject
|
var song_object: SongObject
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,11 @@ const RENAMED_SCENES: Dictionary = {
|
|||||||
"Player": "PlayerRow",
|
"Player": "PlayerRow",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
## Nodes renamed inside a popup: old path from the main window, and new path.
|
||||||
|
const RENAMED_PATHS: Dictionary = {
|
||||||
|
"SearchPopup/ScrollContainer/VBoxContainer": "SearchPopup/ScrollContainer/SearchResults",
|
||||||
|
}
|
||||||
|
|
||||||
## How far a node may be from its old place, in pixels.
|
## How far a node may be from its old place, in pixels.
|
||||||
const TOLERANCE: float = 0.5
|
const TOLERANCE: float = 0.5
|
||||||
|
|
||||||
@@ -96,7 +101,11 @@ static func new_path(old_path: String) -> String:
|
|||||||
parts[i] = RENAMED_SCENES.get(parts[i], parts[i])
|
parts[i] = RENAMED_SCENES.get(parts[i], parts[i])
|
||||||
var first: String = parts[0]
|
var first: String = parts[0]
|
||||||
parts[0] = MOVED.get(first, first)
|
parts[0] = MOVED.get(first, first)
|
||||||
return "/".join(parts)
|
var path: String = "/".join(parts)
|
||||||
|
for renamed: String in RENAMED_PATHS:
|
||||||
|
if path == renamed || path.begins_with(renamed + "/"):
|
||||||
|
return RENAMED_PATHS[renamed] + path.trim_prefix(renamed)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
func _baseline() -> Dictionary:
|
func _baseline() -> Dictionary:
|
||||||
|
|||||||
Reference in new issue
Block a user