neon-sprawl/client/addons/gdUnit4/src/update/GdUnitUpdateNotify.gd

207 lines
7.2 KiB
GDScript

@tool
extends MarginContainer
#signal request_completed(response)
const GdMarkDownReader = preload("res://addons/gdUnit4/src/update/GdMarkDownReader.gd")
const GdUnitUpdateClient = preload("res://addons/gdUnit4/src/update/GdUnitUpdateClient.gd")
const GdUnitUpdateProgress = preload("res://addons/gdUnit4/src/update/GdUnitUpdate.gd")
@onready var _md_reader: GdMarkDownReader = GdMarkDownReader.new()
@onready var _update_client: GdUnitUpdateClient = $GdUnitUpdateClient
@onready var _header: Label = $Panel/GridContainer/PanelContainer/header
@onready var _update_button: Button = $Panel/GridContainer/Panel/HBoxContainer/update
@onready var _content: RichTextLabel = $Panel/GridContainer/PanelContainer2/ScrollContainer/MarginContainer/content
@onready var _update_progress :GdUnitUpdateProgress = %update_banner
var _debug_mode := false
var _patcher := GdUnitPatcher.new()
var _current_version := GdUnit4Version.current()
func _ready() -> void:
_update_button.set_disabled(false)
_md_reader.set_http_client(_update_client)
@warning_ignore("return_value_discarded")
#GdUnitFonts.init_fonts(_content)
_update_progress.set_visible(false)
_update_progress.hidden.connect(func() -> void:
_update_button.set_disabled(false)
)
func request_releases() -> bool:
if _debug_mode:
_update_progress._debug_mode = _debug_mode
_header.text = "A new version 'v4.4.4' is available"
_update_button.set_disabled(false)
return true
var response :GdUnitUpdateClient.HttpResponse = await _update_client.request_latest_version()
if response.status() != 200:
_header.text = "Update information cannot be retrieved from GitHub!"
message_h4("\n\nError: %s" % response.response(), Color.INDIAN_RED)
return false
var latest_version := _update_client.extract_latest_version(response)
# if same version exit here no update need
if latest_version.is_greater(_current_version):
_patcher.scan(_current_version)
_header.text = "A new version '%s' is available" % latest_version
var download_zip_url := extract_zip_url(response)
_update_progress.setup(_update_client, download_zip_url)
_update_button.set_disabled(false)
return true
else:
_header.text = "No update is available."
_update_button.set_disabled(true)
return false
func _colored(message_: String, color: Color) -> String:
return "[color=#%s]%s[/color]" % [color.to_html(), message_]
func message_h4(message_: String, color: Color, clear := true) -> void:
if clear:
_content.clear()
_content.append_text("[font_size=16]%s[/font_size]" % _colored(message_, color))
func message(message_: String, color: Color) -> void:
_content.clear()
_content.append_text(_colored(message_, color))
func _process(_delta: float) -> void:
if _content != null and _content.is_visible_in_tree():
_content.queue_redraw()
func show_update() -> void:
if not GdUnitSettings.is_update_notification_enabled():
_header.text = "No update is available."
message_h4("The search for updates is deactivated.", Color.CORNFLOWER_BLUE)
_update_button.set_disabled(true)
return
if not await request_releases():
return
_update_button.set_disabled(true)
prints("Scan for GdUnit4 Update ...")
message_h4("\n\n\nRequest release infos ... ", Color.SNOW)
_content.add_image(GdUnitUiTools.get_spinner(), 32, 32)
var content: String
if _debug_mode:
await get_tree().create_timer(.2).timeout
var template := FileAccess.open("res://addons/gdUnit4/test/update/resources/http_response_releases.txt", FileAccess.READ).get_as_text()
content = await _md_reader.to_bbcode(template)
else:
var response :GdUnitUpdateClient.HttpResponse = await _update_client.request_releases()
if response.status() == 200:
content = await extract_releases(response, _current_version)
else:
message_h4("\n\n\nError checked request available releases!", Color.INDIAN_RED)
return
# finally force rescan to import images as textures
if Engine.is_editor_hint():
await rescan()
message(content, Color.CADET_BLUE)
_update_button.set_disabled(false)
func extract_zip_url(response: GdUnitUpdateClient.HttpResponse) -> String:
var body :Array = response.response()
return body[0]["zipball_url"]
func extract_releases(response: GdUnitUpdateClient.HttpResponse, current_version: GdUnit4Version) -> String:
await get_tree().process_frame
var result := ""
for release :Dictionary in response.response():
var release_version := str(release["tag_name"])
if GdUnit4Version.parse(release_version).equals(current_version):
break
var release_description := _colored("<h1>GdUnit Release %s</h1>" % release_version, Color.CORNFLOWER_BLUE)
release_description += "\n"
release_description += release["body"]
release_description += "\n\n"
result += await _md_reader.to_bbcode(release_description)
return result
func rescan() -> void:
if Engine.is_editor_hint():
if OS.is_stdout_verbose():
prints(".. reimport release resources")
var fs := EditorInterface.get_resource_filesystem()
fs.scan()
while fs.is_scanning():
if OS.is_stdout_verbose():
progressBar(fs.get_scanning_progress() * 100 as int)
await get_tree().process_frame
await get_tree().process_frame
await get_tree().create_timer(1).timeout
func progressBar(p_progress: int) -> void:
if p_progress < 0:
p_progress = 0
if p_progress > 100:
p_progress = 100
printraw("scan [%-50s] %-3d%%\r" % ["".lpad(int(p_progress/2.0), "#").rpad(50, "-"), p_progress])
@warning_ignore("return_value_discarded")
func _on_update_pressed() -> void:
_update_button.set_disabled(true)
# close all opend scripts before start the update
if not _debug_mode:
ScriptEditorControls.close_open_editor_scripts()
# copy update source to a temp because the update is deleting the whole gdUnit folder
DirAccess.make_dir_absolute("res://addons/.gdunit_update")
DirAccess.copy_absolute("res://addons/gdUnit4/src/update/GdUnitUpdate.tscn", "res://addons/.gdunit_update/GdUnitUpdate.tscn")
DirAccess.copy_absolute("res://addons/gdUnit4/src/update/GdUnitUpdate.gd", "res://addons/.gdunit_update/GdUnitUpdate.gd")
var source := FileAccess.open("res://addons/gdUnit4/src/update/GdUnitUpdate.tscn", FileAccess.READ)
var content := source.get_as_text().replace("res://addons/gdUnit4/src/update/GdUnitUpdate.gd", "res://addons/.gdunit_update/GdUnitUpdate.gd")
var dest := FileAccess.open("res://addons/.gdunit_update/GdUnitUpdate.tscn", FileAccess.WRITE)
dest.store_string(content)
_update_progress.set_visible(true)
func _on_show_next_toggled(enabled: bool) -> void:
GdUnitSettings.set_update_notification(enabled)
func _on_cancel_pressed() -> void:
hide()
func _on_content_meta_clicked(meta: String) -> void:
var properties: Dictionary = str_to_var(meta)
if properties.has("url"):
@warning_ignore("return_value_discarded")
OS.shell_open(str(properties.get("url")))
func _on_content_meta_hover_started(meta: String) -> void:
var properties: Dictionary = str_to_var(meta)
if properties.has("tool_tip"):
_content.set_tooltip_text(str(properties.get("tool_tip")))
@warning_ignore("unused_parameter")
func _on_content_meta_hover_ended(meta: String) -> void:
_content.set_tooltip_text("")
func _on_visibility_changed() -> void:
if not is_visible_in_tree():
return
if _update_progress != null:
_update_progress.set_visible(false)
await show_update()