mirror of
https://github.com/Orama-Interactive/Pixelorama.git
synced 2025-01-31 15:39:49 +00:00
f43f80cee0
* Integration of ExtensionExplorer --------- Co-authored-by: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Co-authored-by: Emmanouil Papadeas <manoschool@yahoo.gr>
215 lines
7.1 KiB
GDScript
215 lines
7.1 KiB
GDScript
extends Window
|
|
|
|
## Usage:
|
|
## Change the "STORE_NAME" and "STORE_LINK"
|
|
## Don't touch anything else
|
|
|
|
const STORE_NAME := "Extension Explorer"
|
|
# gdlint: ignore=max-line-length
|
|
const STORE_LINK := "https://raw.githubusercontent.com/Orama-Interactive/Pixelorama/master/src/UI/ExtensionExplorer/store_info.md"
|
|
## File that will contain information about extensions available for download
|
|
const STORE_INFORMATION_FILE := STORE_NAME + ".md"
|
|
const EXTENSION_ENTRY_TSCN := preload("res://src/UI/ExtensionExplorer/Entry/ExtensionEntry.tscn")
|
|
|
|
# Variables placed here due to their frequent use
|
|
var extension_container: VBoxContainer
|
|
var extension_path: String ## The path where extensions will be stored (obtained from pixelorama)
|
|
var custom_links_remaining: int ## Remaining custom links to be processed
|
|
var redirects: Array[String]
|
|
var faulty_custom_links: Array[String]
|
|
|
|
# node references used in this script
|
|
@onready var content: VBoxContainer = $"%Content"
|
|
@onready var store_info_downloader: HTTPRequest = %StoreInformationDownloader
|
|
@onready var main_store_link: LineEdit = %MainStoreLink
|
|
@onready var custom_store_links: VBoxContainer = %CustomStoreLinks
|
|
@onready var search_manager: LineEdit = %SearchManager
|
|
@onready var tab_container: TabContainer = %TabContainer
|
|
@onready var progress_bar: ProgressBar = %ProgressBar
|
|
@onready var update_timer: Timer = %UpdateTimer
|
|
@onready var faulty_links_label: Label = %FaultyLinks
|
|
@onready var custom_link_error: AcceptDialog = %ErrorCustom
|
|
@onready var error_get_info: AcceptDialog = %Error
|
|
|
|
|
|
func _ready() -> void:
|
|
# Basic setup
|
|
extension_container = Global.preferences_dialog.find_child("Extensions")
|
|
main_store_link.text = STORE_LINK
|
|
# Get the path that pixelorama uses to store extensions
|
|
extension_path = ProjectSettings.globalize_path(extension_container.EXTENSIONS_PATH)
|
|
# tell the downloader where to download the store information
|
|
store_info_downloader.download_file = extension_path.path_join(STORE_INFORMATION_FILE)
|
|
|
|
|
|
func _on_Store_about_to_show() -> void:
|
|
# Clear old tags
|
|
search_manager.available_tags = PackedStringArray()
|
|
for tag in search_manager.tag_list.get_children():
|
|
tag.queue_free()
|
|
# Clear old entries
|
|
for entry in content.get_children():
|
|
entry.queue_free()
|
|
faulty_custom_links.clear()
|
|
custom_links_remaining = custom_store_links.custom_links.size()
|
|
fetch_info(STORE_LINK)
|
|
|
|
|
|
func _on_close_requested() -> void:
|
|
hide()
|
|
|
|
|
|
func fetch_info(link: String) -> void:
|
|
if extension_path != "": # Did everything went smoothly in _ready() function?
|
|
# everything is ready, now request the store information
|
|
# so that available extensions could be displayed
|
|
var error := store_info_downloader.request(link)
|
|
if error == OK:
|
|
prepare_progress()
|
|
else:
|
|
printerr("Unable to get info from remote repository.")
|
|
error_getting_info(error)
|
|
|
|
|
|
## When downloading is finished
|
|
func _on_StoreInformation_request_completed(
|
|
result: int, _response_code: int, _headers: PackedStringArray, _body: PackedByteArray
|
|
) -> void:
|
|
if result == HTTPRequest.RESULT_SUCCESS:
|
|
# process the info contained in the file
|
|
var file := FileAccess.open(
|
|
extension_path.path_join(STORE_INFORMATION_FILE), FileAccess.READ
|
|
)
|
|
while not file.eof_reached():
|
|
process_line(file.get_line())
|
|
file.close()
|
|
|
|
DirAccess.remove_absolute(extension_path.path_join(STORE_INFORMATION_FILE))
|
|
# Hide the progress bar because it's no longer required
|
|
close_progress()
|
|
else:
|
|
printerr("Unable to get info from remote repository...")
|
|
error_getting_info(result)
|
|
|
|
|
|
func close_progress() -> void:
|
|
progress_bar.get_parent().visible = false
|
|
tab_container.visible = true
|
|
update_timer.stop()
|
|
if redirects.size() > 0:
|
|
var next_link := redirects.pop_front() as String
|
|
fetch_info(next_link)
|
|
else:
|
|
# no more redirects, jump to the next store
|
|
custom_links_remaining -= 1
|
|
if custom_links_remaining >= 0:
|
|
var next_link: String = custom_store_links.custom_links[custom_links_remaining]
|
|
fetch_info(next_link)
|
|
else:
|
|
if faulty_custom_links.size() > 0: # manage custom faulty links
|
|
faulty_links_label.text = ""
|
|
for link in faulty_custom_links:
|
|
faulty_links_label.text += str(link, "\n")
|
|
custom_link_error.popup_centered()
|
|
|
|
|
|
## Signal connected from StoreButton.tscn
|
|
func _on_explore_pressed() -> void:
|
|
popup_centered()
|
|
|
|
|
|
## Function related to error dialog
|
|
func _on_CopyCommand_pressed() -> void:
|
|
DisplayServer.clipboard_set(
|
|
"sudo flatpak override com.orama_interactive.Pixelorama --share=network"
|
|
)
|
|
|
|
|
|
## Adds a new extension entry to the "content"
|
|
func add_entry(info: Dictionary) -> void:
|
|
var entry := EXTENSION_ENTRY_TSCN.instantiate()
|
|
entry.extension_container = extension_container
|
|
content.add_child(entry)
|
|
entry.set_info(info, extension_path)
|
|
|
|
|
|
## Gets called when data couldn't be fetched from remote repository
|
|
func error_getting_info(result: int) -> void:
|
|
# Shows a popup if error is from main link (i-e MainStore)
|
|
# Popups for errors in custom_links are handled in close_progress()
|
|
if custom_links_remaining == custom_store_links.custom_links.size():
|
|
error_get_info.popup_centered()
|
|
error_get_info.title = error_string(result)
|
|
else:
|
|
faulty_custom_links.append(custom_store_links.custom_links[custom_links_remaining])
|
|
close_progress()
|
|
|
|
|
|
## Progress bar method
|
|
func prepare_progress() -> void:
|
|
progress_bar.get_parent().visible = true
|
|
tab_container.visible = false
|
|
progress_bar.value = 0
|
|
update_timer.start()
|
|
|
|
|
|
## Progress bar method
|
|
func update_progress() -> void:
|
|
var down := store_info_downloader.get_downloaded_bytes()
|
|
var total := store_info_downloader.get_body_size()
|
|
progress_bar.value = (float(down) / float(total)) * 100.0
|
|
|
|
|
|
## Progress bar method
|
|
func _on_UpdateTimer_timeout() -> void:
|
|
update_progress()
|
|
|
|
|
|
# DATA PROCESSORS
|
|
func process_line(line: String):
|
|
# If the line isn't a comment, we will check data type
|
|
var raw_data
|
|
line = line.strip_edges()
|
|
if !line.begins_with("#") and !line.begins_with("//") and line != "":
|
|
# attempting to convert to a variable other than a string
|
|
raw_data = str_to_var(line)
|
|
if !raw_data: # attempt failed, using it as string
|
|
raw_data = line
|
|
|
|
# Determine action based on data type
|
|
match typeof(raw_data):
|
|
TYPE_ARRAY:
|
|
var extension_data: Dictionary = parse_extension_data(raw_data)
|
|
add_entry(extension_data)
|
|
TYPE_STRING:
|
|
# it's most probably a store link
|
|
var link: String = raw_data.strip_edges()
|
|
if !link in redirects:
|
|
redirects.append(link)
|
|
|
|
|
|
func parse_extension_data(raw_data: Array) -> Dictionary:
|
|
DirAccess.make_dir_recursive_absolute(str(extension_path, "Download/"))
|
|
var result := {}
|
|
# Check for non-compulsory things if they exist
|
|
for item in raw_data:
|
|
if typeof(item) == TYPE_ARRAY:
|
|
# first array element should always be an identifier text type
|
|
var identifier = item.pop_front()
|
|
if typeof(identifier) == TYPE_STRING and item.size() > 0:
|
|
match identifier:
|
|
"name":
|
|
result["name"] = item[0]
|
|
"version":
|
|
result["version"] = item[0]
|
|
"description":
|
|
result["description"] = item[0]
|
|
"thumbnail":
|
|
result["thumbnail"] = item[0]
|
|
"download_link":
|
|
result["download_link"] = item[0]
|
|
"tags": # (this should remain as an array)
|
|
result["tags"] = item
|
|
search_manager.add_new_tags(item)
|
|
return result
|