Files

184 lines
6.0 KiB
GDScript

class_name ReportModal
extends Control
## In-game reporting modal (Trust & Safety).
##
## Allows players to submit moderation reports for worlds, players, or messages.
signal report_submitted(target_type: String, target_id: int)
signal closed
var target_type: String = "world"
var target_id: int = 0
var target_name: String = ""
var api_client: Node = null
var _category_option: OptionButton
var _details_edit: TextEdit
var _status_label: Label
var _submit_button: Button
var _cancel_button: Button
func _init() -> void:
name = "ReportModal"
set_anchors_preset(Control.PRESET_FULL_RECT)
func setup_report(p_type: String, p_id: int, p_name: String) -> void:
target_type = p_type
target_id = p_id
target_name = p_name
func _ready() -> void:
mouse_filter = Control.MOUSE_FILTER_STOP
var overlay := ColorRect.new()
overlay.color = Color(0, 0, 0, 0.8)
overlay.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(overlay)
var center := CenterContainer.new()
center.set_anchors_preset(Control.PRESET_FULL_RECT)
add_child(center)
var panel := PanelContainer.new()
panel.custom_minimum_size = Vector2(460, 0)
var style := StyleBoxFlat.new()
style.bg_color = Color(0.16, 0.16, 0.2, 1.0)
style.border_color = Color(0.9, 0.35, 0.35, 1.0)
style.set_border_width_all(2)
style.set_corner_radius_all(10)
style.content_margin_left = 20
style.content_margin_right = 20
style.content_margin_top = 18
style.content_margin_bottom = 18
panel.add_theme_stylebox_override("panel", style)
center.add_child(panel)
var vbox := VBoxContainer.new()
vbox.add_theme_constant_override("separation", 10)
panel.add_child(vbox)
var title := Label.new()
title.text = "🚩 Submit Report"
title.add_theme_font_size_override("font_size", 18)
title.add_theme_color_override("font_color", Color(1.0, 0.5, 0.5))
title.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
vbox.add_child(title)
var target_lbl := Label.new()
target_lbl.name = "TargetLabel"
target_lbl.text = "Reporting %s: \"%s\" (ID: %d)" % [target_type.capitalize(), target_name, target_id]
target_lbl.add_theme_font_size_override("font_size", 12)
target_lbl.add_theme_color_override("font_color", Color(0.8, 0.8, 0.8))
vbox.add_child(target_lbl)
var cat_lbl := Label.new()
cat_lbl.text = "Category:"
cat_lbl.add_theme_font_size_override("font_size", 12)
vbox.add_child(cat_lbl)
_category_option = OptionButton.new()
_category_option.name = "CategoryOption"
_category_option.add_item("Inappropriate Content / Behavior", 0)
_category_option.set_item_metadata(0, "inappropriate_content")
_category_option.add_item("Harassment / Toxicity", 1)
_category_option.set_item_metadata(1, "harassment")
_category_option.add_item("World Rules Violation", 2)
_category_option.set_item_metadata(2, "rules_violation")
_category_option.add_item("Misleading Tags / Content", 3)
_category_option.set_item_metadata(3, "misleading")
_category_option.add_item("Spam / Exploiting", 4)
_category_option.set_item_metadata(4, "spam")
_category_option.add_item("Other Safety Concern", 5)
_category_option.set_item_metadata(5, "other")
vbox.add_child(_category_option)
var det_lbl := Label.new()
det_lbl.text = "Details / Explanation:"
det_lbl.add_theme_font_size_override("font_size", 12)
vbox.add_child(det_lbl)
_details_edit = TextEdit.new()
_details_edit.name = "DetailsEdit"
_details_edit.custom_minimum_size = Vector2(0, 80)
_details_edit.placeholder_text = "Please describe what happened..."
vbox.add_child(_details_edit)
_status_label = Label.new()
_status_label.name = "StatusLabel"
_status_label.text = ""
_status_label.add_theme_font_size_override("font_size", 11)
vbox.add_child(_status_label)
var btn_row := HBoxContainer.new()
btn_row.alignment = BoxContainer.ALIGNMENT_END
btn_row.add_theme_constant_override("separation", 10)
_cancel_button = Button.new()
_cancel_button.name = "CancelButton"
_cancel_button.text = "Cancel"
_cancel_button.pressed.connect(_on_cancel_pressed)
btn_row.add_child(_cancel_button)
_submit_button = Button.new()
_submit_button.name = "SubmitButton"
_submit_button.text = "Submit Report"
_submit_button.add_theme_color_override("font_color", Color(1.0, 0.4, 0.4))
_submit_button.pressed.connect(_on_submit_pressed)
btn_row.add_child(_submit_button)
vbox.add_child(btn_row)
func _on_cancel_pressed() -> void:
closed.emit()
queue_free()
func _on_submit_pressed() -> void:
var details := _details_edit.text.strip_edges()
if details.is_empty():
_status_label.text = "Please provide details explaining your report."
_status_label.add_theme_color_override("font_color", Color(1.0, 0.4, 0.4))
return
var cat_meta: String = _category_option.get_item_metadata(_category_option.selected)
_submit_button.disabled = true
_cancel_button.disabled = true
_status_label.text = "Submitting report..."
_status_label.add_theme_color_override("font_color", Color(0.8, 0.8, 0.8))
var api: Node = api_client
if api == null and has_node("/root/ApiClient"):
api = get_node("/root/ApiClient")
if api != null:
var res: Dictionary = await api.submit_moderation_report(target_type, target_id, details, cat_meta)
if res.get("ok", false) or res.get("status", 0) == 201:
_status_label.text = "Report submitted to moderation queue. Thank you."
_status_label.add_theme_color_override("font_color", Color(0.4, 1.0, 0.5))
report_submitted.emit(target_type, target_id)
await get_tree().create_timer(1.2).timeout
queue_free()
return
else:
_status_label.text = "Failed to submit: %s" % str(res.get("detail", "Error"))
_status_label.add_theme_color_override("font_color", Color(1.0, 0.4, 0.4))
_submit_button.disabled = false
_cancel_button.disabled = false
else:
_status_label.text = "Report recorded locally."
_status_label.add_theme_color_override("font_color", Color(0.4, 1.0, 0.5))
report_submitted.emit(target_type, target_id)
await get_tree().create_timer(1.0).timeout
queue_free()
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel"):
get_viewport().set_input_as_handled()
closed.emit()
queue_free()