1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-31 15:39:49 +00:00
Pixelorama/src/UI/ExtensionExplorer/Store.gd
Variable f43f80cee0
Integrate Extension Explorer (#910)
* Integration of ExtensionExplorer

---------

Co-authored-by: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com>
Co-authored-by: Emmanouil Papadeas <manoschool@yahoo.gr>
2024-01-23 03:25:37 +02:00

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