diff --git a/src/Preferences/HandleExtensions.gd b/src/Preferences/HandleExtensions.gd index 6e441f6e4..ea27bb525 100644 --- a/src/Preferences/HandleExtensions.gd +++ b/src/Preferences/HandleExtensions.gd @@ -1,6 +1,10 @@ extends Control +enum UninstallMode { KEEP_FILE, FILE_TO_BIN, REMOVE_PERMANENT } + const EXTENSIONS_PATH := "user://extensions" +const BUG_EXTENSIONS_PATH := "user://give_in_bug_report" +const BIN_ACTION := "trash" var extensions := {} ## Extension name: Extension class var extension_selected := -1 @@ -10,6 +14,7 @@ var damaged_extension: String @onready var enable_button: Button = $HBoxContainer/EnableButton @onready var uninstall_button: Button = $HBoxContainer/UninstallButton @onready var extension_parent: Node = Global.control.get_node("Extensions") +@onready var delete_confirmation: ConfirmationDialog = %DeleteConfirmation class Extension: @@ -40,6 +45,7 @@ class Extension: func _ready() -> void: + delete_confirmation.add_button(tr("Move to Trash"), false, BIN_ACTION) if OS.get_name() == "Web": $HBoxContainer/AddExtensionButton.disabled = true $HBoxContainer/OpenFolderButton.visible = false @@ -74,9 +80,18 @@ func install_extension(path: String) -> void: _add_extension(file_name) -func _uninstall_extension(file_name := "", remove_file := true, item := extension_selected) -> void: - if remove_file: - var err := DirAccess.remove_absolute(EXTENSIONS_PATH.path_join(file_name)) +func _uninstall_extension( + file_name := "", remove_mode := UninstallMode.REMOVE_PERMANENT, item := extension_selected +) -> void: + var err := OK + match remove_mode: + UninstallMode.FILE_TO_BIN: + err = OS.move_to_trash( + ProjectSettings.globalize_path(EXTENSIONS_PATH).path_join(file_name) + ) + UninstallMode.REMOVE_PERMANENT: + err = DirAccess.remove_absolute(EXTENSIONS_PATH.path_join(file_name)) + if remove_mode != UninstallMode.KEEP_FILE: if err != OK: print(err) return @@ -94,16 +109,21 @@ func _uninstall_extension(file_name := "", remove_file := true, item := extensio func _add_extension(file_name: String) -> void: var tester_file: FileAccess # For testing and deleting damaged extensions - var remover_directory := DirAccess.open(EXTENSIONS_PATH) # Remove any extension that was proven guilty before this extension is loaded - if remover_directory.file_exists(EXTENSIONS_PATH.path_join("Faulty.txt")): + if FileAccess.file_exists(EXTENSIONS_PATH.path_join("Faulty.txt")): # This code will only run if pixelorama crashed var faulty_path := EXTENSIONS_PATH.path_join("Faulty.txt") tester_file = FileAccess.open(faulty_path, FileAccess.READ) damaged_extension = tester_file.get_as_text() tester_file.close() - remover_directory.remove(EXTENSIONS_PATH.path_join(damaged_extension)) - remover_directory.remove(EXTENSIONS_PATH.path_join("Faulty.txt")) + # don't delete the extension permanently + # (so that it may be given to the developer in the bug report) + DirAccess.make_dir_recursive_absolute(BUG_EXTENSIONS_PATH) + DirAccess.rename_absolute( + EXTENSIONS_PATH.path_join(damaged_extension), + BUG_EXTENSIONS_PATH.path_join(damaged_extension) + ) + DirAccess.remove_absolute(EXTENSIONS_PATH.path_join("Faulty.txt")) # Don't load a deleted extension if damaged_extension == file_name: @@ -125,7 +145,7 @@ func _add_extension(file_name: String) -> void: if item == -1: print("Failed to find %s" % file_name) return - _uninstall_extension(file_name, false, item) + _uninstall_extension(file_name, UninstallMode.KEEP_FILE, item) # Wait two frames so the previous nodes can get freed await get_tree().process_frame await get_tree().process_frame @@ -134,11 +154,14 @@ func _add_extension(file_name: String) -> void: var file_path := EXTENSIONS_PATH.path_join(file_name) var success := ProjectSettings.load_resource_pack(file_path) if !success: - print("Failed loading resource pack.") - var dir := DirAccess.open(EXTENSIONS_PATH) - dir.remove(file_path) + # Don't delete the extension + # Context: pixelorama deletes v0.11.x extensions when you open v1.0, this will prevent it. +# OS.move_to_trash(file_path) + print("EXTENSION ERROR: Failed loading resource pack %s." % file_name) + print(" There may be errors in extension code or extension is incompatible") + # Delete the faulty.txt, (it's fate has already been decided) + DirAccess.remove_absolute(EXTENSIONS_PATH.path_join("Faulty.txt")) return - var extension_path := "res://src/Extensions/%s/" % file_name_no_ext var extension_config_file_path := extension_path.path_join("extension.json") var extension_config_file := FileAccess.open(extension_config_file_path, FileAccess.READ) @@ -176,7 +199,7 @@ func _add_extension(file_name: String) -> void: Global.dialog_open(true) print("Incompatible API") # Don't put it in faulty, (it's merely incompatible) - remover_directory.remove(EXTENSIONS_PATH.path_join("Faulty.txt")) + DirAccess.remove_absolute(EXTENSIONS_PATH.path_join("Faulty.txt")) return var extension := Extension.new() @@ -192,7 +215,7 @@ func _add_extension(file_name: String) -> void: # If an extension doesn't crash pixelorama then it is proven innocent # And we should now delete its "Faulty.txt" file - remover_directory.remove(EXTENSIONS_PATH.path_join("Faulty.txt")) + DirAccess.remove_absolute(EXTENSIONS_PATH.path_join("Faulty.txt")) func _enable_extension(extension: Extension, save_to_config := true) -> void: @@ -259,7 +282,7 @@ func _on_EnableButton_pressed() -> void: func _on_UninstallButton_pressed() -> void: - _uninstall_extension(extension_list.get_item_metadata(extension_selected)) + delete_confirmation.popup_centered() func _on_OpenFolderButton_pressed() -> void: @@ -269,3 +292,15 @@ func _on_OpenFolderButton_pressed() -> void: func _on_AddExtensionFileDialog_files_selected(paths: PackedStringArray) -> void: for path in paths: install_extension(path) + + +func _on_delete_confirmation_custom_action(action: StringName) -> void: + if action == BIN_ACTION: + _uninstall_extension( + extension_list.get_item_metadata(extension_selected), UninstallMode.FILE_TO_BIN + ) + delete_confirmation.hide() + + +func _on_delete_confirmation_confirmed() -> void: + _uninstall_extension(extension_list.get_item_metadata(extension_selected)) diff --git a/src/Preferences/PreferencesDialog.tscn b/src/Preferences/PreferencesDialog.tscn index 0ea68fdb5..bd35a8e70 100644 --- a/src/Preferences/PreferencesDialog.tscn +++ b/src/Preferences/PreferencesDialog.tscn @@ -23,11 +23,11 @@ anchor_bottom = 1.0 offset_left = 8.0 offset_top = 8.0 offset_right = -8.0 -offset_bottom = -36.0 +offset_bottom = -49.0 size_flags_horizontal = 3 theme_override_constants/separation = 20 theme_override_constants/autohide = 0 -split_offset = 1 +split_offset = 150 [node name="List" type="ItemList" parent="HSplitContainer"] custom_minimum_size = Vector2(85, 0) @@ -1300,6 +1300,21 @@ access = 2 filters = PackedStringArray("*.pck ; Godot Resource Pack File", "*.zip ;") show_hidden_files = true +[node name="DeleteConfirmation" type="ConfirmationDialog" parent="."] +unique_name_in_owner = true +position = Vector2i(0, 36) +size = Vector2i(500, 100) +ok_button_text = "Delete Permanently" + +[node name="Label" type="Label" parent="DeleteConfirmation"] +offset_left = 8.0 +offset_top = 8.0 +offset_right = 492.0 +offset_bottom = 51.0 +text = "Delete Extension?" +horizontal_alignment = 1 +vertical_alignment = 1 + [connection signal="about_to_popup" from="." to="." method="_on_PreferencesDialog_about_to_show"] [connection signal="visibility_changed" from="." to="." method="_on_PreferencesDialog_visibility_changed"] [connection signal="item_selected" from="HSplitContainer/List" to="." method="_on_List_item_selected"] @@ -1312,3 +1327,5 @@ show_hidden_files = true [connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/HBoxContainer/UninstallButton" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_UninstallButton_pressed"] [connection signal="pressed" from="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions/HBoxContainer/OpenFolderButton" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_OpenFolderButton_pressed"] [connection signal="files_selected" from="Popups/AddExtensionFileDialog" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_AddExtensionFileDialog_files_selected"] +[connection signal="confirmed" from="DeleteConfirmation" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_delete_confirmation_confirmed"] +[connection signal="custom_action" from="DeleteConfirmation" to="HSplitContainer/VBoxContainer/ScrollContainer/RightSide/Extensions" method="_on_delete_confirmation_custom_action"]