diff --git a/project.godot b/project.godot index b42ec21b..940bd51b 100644 --- a/project.godot +++ b/project.godot @@ -11,7 +11,7 @@ config_version=5 [application] config/name="GodSVG" -config/version="v1.0-alpha3" +config/version="1.0-alpha3" config/tags=PackedStringArray("project") run/main_scene="res://src/ui_parts/main_scene.tscn" config/use_custom_user_dir=true diff --git a/src/ui_parts/about_menu.gd b/src/ui_parts/about_menu.gd index 849e52bc..53fcd8a5 100644 --- a/src/ui_parts/about_menu.gd +++ b/src/ui_parts/about_menu.gd @@ -7,8 +7,7 @@ extends PanelContainer @onready var version_label: Label = %VersionLabel func _ready() -> void: - version_label.text = "GodSVG " + ProjectSettings.get_setting( - "application/config/version", "Version information unavailable") + version_label.text = "GodSVG v" + ProjectSettings.get_setting("application/config/version") project_founder_list.items = AppInfo.project_founder_and_manager project_founder_list.setup() authors_list.items = AppInfo.authors diff --git a/src/ui_parts/display.gd b/src/ui_parts/display.gd index 0f1a4f2b..60c3210f 100644 --- a/src/ui_parts/display.gd +++ b/src/ui_parts/display.gd @@ -7,6 +7,7 @@ signal snap_settings_updated(snap_enabled: bool, snap_amount: float) const settings_menu = preload("settings_menu.tscn") const about_menu = preload("about_menu.tscn") const donate_menu = preload("res://src/ui_parts/donate_menu.tscn") +const update_menu = preload("res://src/ui_parts/update_menu.tscn") const NumberEditType = preload("res://src/ui_elements/number_edit.gd") const BetterToggleButtonType = preload("res://src/ui_elements/BetterToggleButton.gd") @@ -109,10 +110,12 @@ func _on_more_options_pressed() -> void: Utils.create_btn(tr("GodSVG Repository"), open_godsvg_repo, false, load("res://visual/icons/Link.svg")), Utils.create_btn(tr("GodSVG Website"), open_godsvg_website, false, - load("res://visual/icons/Link.svg")) + load("res://visual/icons/Link.svg")), + Utils.create_btn(tr("Check for Updates"), open_update_checker, false, + load("res://visual/icons/Reload.svg")) ] - var separator_indices: Array[int] = [2] - + var separator_indices: Array[int] = [2,4] + var more_popup := ContextPopup.new() more_popup.setup(buttons_arr, true, -1, separator_indices) HandlerGUI.popup_under_rect_center(more_popup, more_button.get_global_rect(), @@ -132,6 +135,10 @@ func open_sponsor() -> void: var donate_menu_instance := donate_menu.instantiate() HandlerGUI.add_overlay(donate_menu_instance) +func open_update_checker() -> void: + var update_menu_instance := update_menu.instantiate() + HandlerGUI.add_overlay(update_menu_instance) + func toggle_grid_visuals() -> void: grid_visuals.visible = not grid_visuals.visible diff --git a/src/ui_parts/update_menu.gd b/src/ui_parts/update_menu.gd new file mode 100644 index 00000000..56eb85a5 --- /dev/null +++ b/src/ui_parts/update_menu.gd @@ -0,0 +1,83 @@ +extends PanelContainer + +@onready var status_label: RichTextLabel = %Status +@onready var check_button: Button = %Check +#@onready var prereleases_checkbox: CheckBox = %IncludePrereleases +@onready var http: HTTPRequest = %HTTPRequest + + +func _ready() -> void: + status_label.text = "Current Version: " + ProjectSettings.get_setting("application/config/version") + +func _on_check_pressed() -> void: + check_button.disabled = true + status_label.text = "Checking..." + + var err := http.request( + "https://api.github.com/repos/MewPurPur/GodSVG/releases", + ["User-Agent: MewPurPur/GodSVG"] + ) + + if err: + _failed(error_string(err)) + + +func _on_request_completed(result: HTTPRequest.Result, response_code: int, +_headers: PackedStringArray, body: PackedByteArray) -> void: + match result: + http.RESULT_SUCCESS: + if not response_code == 200: + _failed("Response code "+str(response_code)) + return + + var json = JSON.parse_string(body.get_string_from_utf8()) + if not json: + _failed("Failed to decode JSON") + return + + # Always enabled as long as there is no stable GodSVG release yet. + var include_prereleases := true # prereleases_checkbox.button_pressed + var latest_ver := "" + var latest_url := "" + var latest_timestamp := 0 + + for release: Dictionary in json: + var is_prerelease := release["prerelease"] as bool + if is_prerelease and not include_prereleases: + continue + + var timestamp := Time.get_unix_time_from_datetime_string(release["created_at"] as String) + + if timestamp > latest_timestamp: + latest_timestamp = timestamp + latest_ver = release["name"] + latest_url = release["html_url"] + + var current_ver := ProjectSettings.get_setting("application/config/version") as String + + if latest_ver == current_ver: + status_label.text = "No new version available." + else: + status_label.parse_bbcode("New version available! %s\n[url=%s]Open GitHub page[/url]" % [latest_ver, latest_url]) + + check_button.disabled = false + + http.RESULT_TIMEOUT: + _failed("Request timed out ("+str(http.timeout)+"s)") + return + _: + _failed("Error code "+str(result)) + return + + +func _failed(msg: String) -> void: + status_label.text = "Failed to check for updates:\n"+msg + check_button.disabled = false + + +func _on_close_pressed() -> void: + HandlerGUI.remove_overlay() + + +func _on_status_label_link_clicked(meta: Variant) -> void: + OS.shell_open(meta) diff --git a/src/ui_parts/update_menu.tscn b/src/ui_parts/update_menu.tscn new file mode 100644 index 00000000..3f04c89a --- /dev/null +++ b/src/ui_parts/update_menu.tscn @@ -0,0 +1,90 @@ +[gd_scene load_steps=4 format=3 uid="uid://dtyn8imbyo2rg"] + +[ext_resource type="Script" path="res://src/ui_parts/update_menu.gd" id="1_up0ed"] + +[sub_resource type="LabelSettings" id="LabelSettings_h3pgq"] +font_size = 12 +font_color = Color(0.6875, 0.6875, 0.6875, 1) + +[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_nqy1r"] + +[node name="UpdateMenu" type="PanelContainer"] +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -2.0 +offset_top = -2.0 +offset_right = 2.0 +offset_bottom = 2.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_type_variation = &"OverlayPanel" +script = ExtResource("1_up0ed") + +[node name="HTTPRequest" type="HTTPRequest" parent="."] +unique_name_in_owner = true +download_chunk_size = 32768 +timeout = 10.0 + +[node name="VBoxContainer" type="VBoxContainer" parent="."] +layout_mode = 2 +theme_override_constants/separation = 12 + +[node name="Label" type="Label" parent="VBoxContainer"] +layout_mode = 2 +text = "Update Menu" +horizontal_alignment = 1 + +[node name="PanelContainer" type="PanelContainer" parent="VBoxContainer"] +layout_mode = 2 +theme_type_variation = &"OverlayPanel" + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/PanelContainer"] +layout_mode = 2 +theme_override_constants/separation = 8 + +[node name="VBoxContainer" type="VBoxContainer" parent="VBoxContainer/PanelContainer/VBoxContainer"] +layout_mode = 2 +theme_override_constants/separation = 2 + +[node name="Check" type="Button" parent="VBoxContainer/PanelContainer/VBoxContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +text = "Check for Updates" + +[node name="Hint" type="Label" parent="VBoxContainer/PanelContainer/VBoxContainer/VBoxContainer"] +layout_mode = 2 +text = "This will connect to the Internet." +label_settings = SubResource("LabelSettings_h3pgq") +horizontal_alignment = 1 + +[node name="IncludePrereleases" type="CheckBox" parent="VBoxContainer/PanelContainer/VBoxContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +theme_override_styles/focus = SubResource("StyleBoxEmpty_nqy1r") +button_pressed = true +text = "Include Prereleases" + +[node name="Status" type="RichTextLabel" parent="VBoxContainer/PanelContainer/VBoxContainer"] +unique_name_in_owner = true +layout_mode = 2 +bbcode_enabled = true +fit_content = true +scroll_active = false +autowrap_mode = 0 + +[node name="Close" type="Button" parent="VBoxContainer"] +layout_mode = 2 +size_flags_horizontal = 4 +size_flags_vertical = 8 +focus_mode = 0 +mouse_default_cursor_shape = 2 +text = "Close" + +[connection signal="request_completed" from="HTTPRequest" to="." method="_on_request_completed"] +[connection signal="pressed" from="VBoxContainer/PanelContainer/VBoxContainer/VBoxContainer/Check" to="." method="_on_check_pressed"] +[connection signal="meta_clicked" from="VBoxContainer/PanelContainer/VBoxContainer/Status" to="." method="_on_status_label_link_clicked"] +[connection signal="pressed" from="VBoxContainer/Close" to="." method="_on_close_pressed"]