Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added auto-updater #134

Merged
merged 1 commit into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions addons/pandora/plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func _init() -> void:


func _enter_tree() -> void:
Engine.set_meta("PandoraEditorPlugin", self)
_exporter = PandoraExportPlugin.new()
add_autoload_singleton("Pandora", "res://addons/pandora/api.gd")
add_export_plugin(_exporter)
Expand Down
88 changes: 88 additions & 0 deletions addons/pandora/ui/components/update_button/update_button.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
@tool
extends Button

const RELEASE_URL: String = "https://github.com/gitapi/repos/bitbrain/pandora/releases"

@onready var http_request: HTTPRequest = %HTTPRequest
@onready var updater_window: AcceptDialog = $UpdaterWindow
@onready var updater: Control = $UpdaterWindow/UpdaterControl
@onready var post_update_window: ConfirmationDialog = $PostUpdateWindow

func _ready() -> void:
self.hide()
check_for_updates()

func get_version() -> String:
var plugin_config:ConfigFile = ConfigFile.new()
plugin_config.load("res://addons/pandora/plugin.cfg")
return plugin_config.get_value("plugin", "version")

func check_for_updates() -> void:
http_request.request(RELEASE_URL)

func version_to_number(ver: String) -> int:
ver = ver.lstrip("v")
ver = ver.split("+")[0]

var parts = ver.split("-")
var release_ver = parts[0]
parts.remove_at(0)

var phase = null
if parts.size() > 0: phase = "-".join(parts)

var nums = release_ver.split(".")
var size = nums.size()
var offset = 0 if phase == null else 1
var value = 0

for idx in range(size):
var item = nums[idx]
if item.is_valid_int():
value += item.to_int() * (100 ** (size + offset - idx))

# If the release is stable, add 75 to be greater than alpha, beta & rc
if phase == null && idx == size - 1:
value += 75

# The lstrip is done seperately so it works even if the "." is not present
if phase != null:
if phase.begins_with("alpha"):
value += phase.lstrip("alpha").lstrip(".").to_int()
elif phase.begins_with("beta"):
value += 25 + phase.lstrip("beta").lstrip(".").to_int()
elif phase.begins_with("rc"):
value += 50 + phase.lstrip("rc").lstrip(".").to_int()

return value

func _on_http_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS: return

var res = JSON.parse_string(body.get_string_from_utf8())
if typeof(res) != TYPE_ARRAY: return

var curr_version_num = version_to_number(get_version())

var new_versions: Array = (res as Array).filter(func(release):
return version_to_number(release.tag_name) > curr_version_num
)

if new_versions.size() > 0:
self.show()
updater.releases = new_versions

func _on_update_button_pressed() -> void:
updater_window.show()

func _on_updater_update_done(success: bool) -> void:
if success:
post_update_window.set_text("Updated Pandora successfully!\nRestart editor?")
else:
post_update_window.set_text("Could not update Pandora!\nRestart editor?")

post_update_window.show()

func _on_post_update_window_confirmed() -> void:
var plugin: EditorPlugin = Engine.get_meta("PandoraEditorPlugin")
plugin.get_editor_interface().restart_editor(true)
34 changes: 34 additions & 0 deletions addons/pandora/ui/components/update_button/update_button.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
[gd_scene load_steps=3 format=3 uid="uid://dy4xl20q2nq7q"]

[ext_resource type="Script" path="res://addons/pandora/ui/components/update_button/update_button.gd" id="1_0iteh"]
[ext_resource type="PackedScene" uid="uid://dtwiql0cpn5hu" path="res://addons/pandora/ui/components/updater/updater.tscn" id="2_lifbu"]

[node name="UpdateButton" type="Button"]
visible = false
text = "Update"
script = ExtResource("1_0iteh")

[node name="HTTPRequest" type="HTTPRequest" parent="."]
unique_name_in_owner = true

[node name="UpdaterWindow" type="AcceptDialog" parent="."]
title = "Update Pandora"
initial_position = 2
size = Vector2i(600, 450)
unresizable = true
ok_button_text = "Close"

[node name="UpdaterControl" parent="UpdaterWindow" instance=ExtResource("2_lifbu")]

[node name="PostUpdateWindow" type="ConfirmationDialog" parent="."]
title = "Pandora Updater"
initial_position = 2
size = Vector2i(343, 109)
ok_button_text = "Restart"
dialog_text = "Updated Pandora successfully!
Restart editor?"

[connection signal="pressed" from="." to="." method="_on_update_button_pressed"]
[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_completed"]
[connection signal="update_done" from="UpdaterWindow/UpdaterControl" to="." method="_on_updater_update_done"]
[connection signal="confirmed" from="PostUpdateWindow" to="." method="_on_post_update_window_confirmed"]
77 changes: 77 additions & 0 deletions addons/pandora/ui/components/updater/updater.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
@tool
extends Control

signal update_done(success: bool)

const TEMP_FILE_NAME: String = "user://temp.zip"

@onready var http_request: HTTPRequest = $HTTPRequest
@onready var release_text: TextEdit = $VBoxContainer/ReleaseText
@onready var release_link: LinkButton = $VBoxContainer/CenterContainer2/LinkButton
@onready var download_btn: Button = $VBoxContainer/CenterContainer/DownloadButton
@onready var version_text: Label = $VBoxContainer/VersionText

var releases: Array = []:
set(value):
releases = value
_update_ui()
get:
return releases

func _update_ui() -> void:
if releases.is_empty(): return

var release_notes_text = ""
for release in releases:
release_notes_text += "Release " + release.tag_name + "\n" + release.body + "\n\n"
release_notes_text = release_notes_text.rstrip("\n")
release_text.set_text(release_notes_text)

version_text.set_text("Latest version: " + releases[0].tag_name)
release_link.set_uri(releases[0].html_url)

func _on_download_button_pressed() -> void:
if releases.is_empty():
self.update_done.emit(false)
self.hide()
return

if FileAccess.file_exists("res://examples/inventory/inventory_example.gd"):
prints("You can't update the addon from within itself.")
return

http_request.request(releases[0].zipball_url)
download_btn.disabled = true
download_btn.set_text("Downloading")

func _on_http_request_request_completed(result: int, response_code: int, headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS:
self.update_done.emit(false)
self.hide()
return

var zip_file: FileAccess = FileAccess.open(TEMP_FILE_NAME, FileAccess.WRITE)
zip_file.store_buffer(body)
zip_file.close()

OS.move_to_trash(ProjectSettings.globalize_path("res://addons/pandora"))

var zip_reader: ZIPReader = ZIPReader.new()
zip_reader.open(TEMP_FILE_NAME)
var files: PackedStringArray = zip_reader.get_files()

var base_path = files[1]

for path in files:
var new_file_path: String = path.replace(base_path, "")
if path.ends_with("/"):
DirAccess.make_dir_recursive_absolute("res://addons/%s" % new_file_path)
else:
var file: FileAccess = FileAccess.open("res://addons/%s" % new_file_path, FileAccess.WRITE)
file.store_buffer(zip_reader.read_file(path))

zip_reader.close()
DirAccess.remove_absolute(TEMP_FILE_NAME)

self.update_done.emit(true)
self.hide()
73 changes: 73 additions & 0 deletions addons/pandora/ui/components/updater/updater.tscn
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
[gd_scene load_steps=3 format=3 uid="uid://dtwiql0cpn5hu"]

[ext_resource type="Script" path="res://addons/pandora/ui/components/updater/updater.gd" id="1_e18b4"]
[ext_resource type="Texture2D" uid="uid://crgjwaubao8pj" path="res://addons/pandora/icons/icon.png" id="1_jpf8m"]

[node name="UpdaterControl" type="Control"]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 8.0
offset_top = 8.0
offset_right = -8.0
offset_bottom = -49.0
grow_horizontal = 2
grow_vertical = 2
script = ExtResource("1_e18b4")

[node name="HTTPRequest" type="HTTPRequest" parent="."]

[node name="VBoxContainer" type="VBoxContainer" parent="."]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
theme_override_constants/separation = 8

[node name="ReleaseNotesText" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "Release Notes"

[node name="ReleaseText" type="TextEdit" parent="VBoxContainer"]
custom_minimum_size = Vector2(256, 256)
layout_mode = 2
editable = false
context_menu_enabled = false
shortcut_keys_enabled = false
deselect_on_focus_loss_enabled = false
drag_and_drop_selection_enabled = false
virtual_keyboard_enabled = false
middle_mouse_paste_enabled = false

[node name="TextureRect" type="TextureRect" parent="VBoxContainer"]
visible = false
custom_minimum_size = Vector2(128, 128)
layout_mode = 2
texture = ExtResource("1_jpf8m")
expand_mode = 1
stretch_mode = 5

[node name="VersionText" type="Label" parent="VBoxContainer"]
layout_mode = 2
text = "Latest version: vx.y.-alphaZ"
horizontal_alignment = 1

[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer"]
layout_mode = 2

[node name="DownloadButton" type="Button" parent="VBoxContainer/CenterContainer"]
layout_mode = 2
text = "Download and install"

[node name="CenterContainer2" type="CenterContainer" parent="VBoxContainer"]
layout_mode = 2

[node name="LinkButton" type="LinkButton" parent="VBoxContainer/CenterContainer2"]
layout_mode = 2
text = "Release Notes"

[connection signal="request_completed" from="HTTPRequest" to="." method="_on_http_request_request_completed"]
[connection signal="pressed" from="VBoxContainer/CenterContainer/DownloadButton" to="." method="_on_download_button_pressed"]
6 changes: 5 additions & 1 deletion addons/pandora/ui/editor/pandora_editor.tscn
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[gd_scene load_steps=16 format=3 uid="uid://0bxxjjroysub"]
[gd_scene load_steps=17 format=3 uid="uid://0bxxjjroysub"]

[ext_resource type="Script" path="res://addons/pandora/ui/editor/pandora_editor.gd" id="1_bowve"]
[ext_resource type="Texture2D" uid="uid://dojpd3ptnta4m" path="res://addons/pandora/icons/Object.svg" id="2_aj8uc"]
Expand All @@ -14,6 +14,7 @@
[ext_resource type="Texture2D" uid="uid://3w10txrbpwmx" path="res://addons/pandora/icons/Import.svg" id="7_2mwyl"]
[ext_resource type="PackedScene" uid="uid://dibfkp6i5uvgi" path="res://addons/pandora/ui/components/progress_bar/progress_bar.tscn" id="10_xf8wv"]
[ext_resource type="Texture2D" uid="uid://cjqnk0xjuxycs" path="res://docs/assets/logo.svg" id="11_4qjpy"]
[ext_resource type="PackedScene" uid="uid://dy4xl20q2nq7q" path="res://addons/pandora/ui/components/update_button/update_button.tscn" id="11_cva2e"]
[ext_resource type="PackedScene" uid="uid://ceboo5esbe2ld" path="res://addons/pandora/ui/editor/import_dialog/import_dialog.tscn" id="15_umv0u"]

[node name="PandoraEditor" type="MarginContainer"]
Expand Down Expand Up @@ -134,6 +135,9 @@ horizontal_alignment = 2
vertical_alignment = 1
justification_flags = 0

[node name="UpdateButton" parent="Contents/HeaderBar/Links" instance=ExtResource("11_cva2e")]
layout_mode = 2

[node name="DataContent" type="HBoxContainer" parent="Contents"]
unique_name_in_owner = true
clip_contents = true
Expand Down