extends MarginContainer ## itch.io plugin settings screen ## ## Uses OpenGamepadUI's themed widget set (StatusPanel, ComponentTextInput, ## Toggle, CardButton, Dropdown) for consistent look with the rest of the ## settings UI. const ItchClient := preload("res://plugins/itch/core/itch_client.gd") var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager var notification_manager := load("res://core/global/notification_manager.tres") as NotificationManager const icon := preload("res://plugins/itch/assets/itch.svg") @onready var status := $%Status as StatusPanel @onready var connected_status := $%ConnectedStatus as StatusPanel @onready var logged_in_status := $%LoggedInStatus as StatusPanel @onready var login_method := $%LoginMethod as Dropdown @onready var api_key_box := $%ApiKeyInput as ComponentTextInput @onready var username_box := $%UsernameInput as ComponentTextInput @onready var password_box := $%PasswordInput as ComponentTextInput @onready var save_button := $%SaveButton as CardButton @onready var logout_button := $%LogoutButton as CardButton @onready var filter_check := $%FilterUnsupported as Toggle @onready var show_purchases_check := $%ShowPurchases as Toggle @onready var collections_container: VBoxContainer = $%CollectionsContainer @onready var itch: ItchClient = get_tree().get_first_node_in_group("itch_client") var _collection_checks: Dictionary = {} func _ready() -> void: # Configure status indicators status.status = status.STATUS.CANCELLED status.color = "red" var set_running := func(): if not itch.client_started: return status.status = status.STATUS.ACTIVE status.color = "green" if itch.client_started: set_running.call() itch.bootstrap_finished.connect(set_running) # Configure connected status connected_status.status = connected_status.STATUS.ACTIVE if itch.state != itch.STATE.BOOT: connected_status.color = "green" itch.client_ready.connect(func(): connected_status.color = "green" ) # Configure login status var update_login_status := func(login_status: ItchClient.LOGIN_STATUS): if login_status != ItchClient.LOGIN_STATUS.OK: logged_in_status.status = logged_in_status.STATUS.ACTIVE logged_in_status.color = "gray" return logged_in_status.status = logged_in_status.STATUS.CLOSED logged_in_status.color = "green" itch.logged_in.connect(update_login_status) itch.logged_in.connect(_on_login) # Configure login method dropdown login_method.add_item("API Key", 0) login_method.add_item("Username & Password", 1) login_method.selected = 0 # Load saved settings var api_key := settings_manager.get_value("plugin.itch", "api_key", "") as String api_key_box.text = api_key api_key_box.secret = true var saved_method: int = settings_manager.get_value("plugin.itch", "login_method", 0) as int login_method.select(saved_method) _on_login_method_changed(saved_method) var username := settings_manager.get_value("plugin.itch", "username", "") as String username_box.text = username filter_check.button_pressed = settings_manager.get_value("plugin.itch", "filter_unsupported", true) as bool show_purchases_check.button_pressed = settings_manager.get_value("plugin.itch", "show_purchases", true) as bool # Connect signals save_button.pressed.connect(_on_save_button) logout_button.pressed.connect(_on_logout_button) login_method.item_selected.connect(_on_login_method_changed) filter_check.toggled.connect(_on_filter_toggled) show_purchases_check.toggled.connect(_on_show_purchases_toggled) # Build collection checkboxes once we're logged in. itch.logged_in.connect(_populate_collections.bind(), CONNECT_ONE_SHOT) func _on_login(login_status: ItchClient.LOGIN_STATUS, _profile: Dictionary) -> void: var notify := Notification.new("") notify.icon = icon if login_status == ItchClient.LOGIN_STATUS.OK: notify.text = "Successfully logged in to itch.io" else: notify.text = "itch.io login failed. Double check your credentials." notification_manager.show(notify) func _on_login_method_changed(idx: int) -> void: # API key mode: show API key input, hide user/pass. # Password mode: show user/pass, hide API key. var is_api := idx == 0 api_key_box.visible = is_api username_box.visible = not is_api password_box.visible = not is_api func _on_save_button() -> void: var method: int = login_method.selected settings_manager.set_value("plugin.itch", "login_method", method) if method == 0: # API key login settings_manager.set_value("plugin.itch", "username", "") var api_key: String = api_key_box.text.strip_edges() settings_manager.set_value("plugin.itch", "api_key", api_key) if api_key == "": return itch.login_with_api_key(api_key) else: # Username/password login var uname: String = username_box.text.strip_edges() var password: String = password_box.text settings_manager.set_value("plugin.itch", "username", uname) if uname == "" or password == "": return itch.login_with_password(uname, password) func _on_logout_button() -> void: var method: int = login_method.selected # Clear saved credentials if method == 0: settings_manager.set_value("plugin.itch", "api_key", "") api_key_box.text = "" else: settings_manager.set_value("plugin.itch", "username", "") username_box.text = "" password_box.text = "" # Logout from butlerd itch.logout() var notify := Notification.new("Logged out of itch.io") notify.icon = icon notification_manager.show(notify) ## Fetches the user's collections and builds a checkbox for each one. func _populate_collections(_status: ItchClient.LOGIN_STATUS, _profile: Dictionary) -> void: if not itch.is_logged_in: return var profile_id: int = itch.profile.get("user", {}).get("id", itch.profile.get("id", 0)) var res := await itch._rpc_call("Fetch.ProfileCollections", {"profileId": profile_id}) if "error" in res: return var collections: Array = res.get("items", []) # Load saved visibility state. var hidden: Dictionary = settings_manager.get_value("plugin.itch", "hidden_collections", {}) as Dictionary # Clear old checkboxes. for child in collections_container.get_children(): child.queue_free() _collection_checks.clear() for c in collections: var collection: Dictionary = c var col_name: String = collection.get("title", "Collection " + str(collection.get("id", ""))) var col_id: String = str(collection.get("id", 0)) var check := CheckBox.new() check.text = col_name check.button_pressed = not hidden.has(col_id) check.toggled.connect(_on_collection_toggled.bind(col_id)) collections_container.add_child(check) _collection_checks[col_id] = check func _on_collection_toggled(pressed: bool, col_id: String) -> void: var hidden: Dictionary = settings_manager.get_value("plugin.itch", "hidden_collections", {}) as Dictionary if pressed: hidden.erase(col_id) else: hidden[col_id] = true settings_manager.set_value("plugin.itch", "hidden_collections", hidden) func _on_show_purchases_toggled(pressed: bool) -> void: settings_manager.set_value("plugin.itch", "show_purchases", pressed) ## Persists the platform filter and reloads the itch.io library so the ## change applies without restarting. The setting is read back by ## library_itch.gd on every library load, so toggling just re-filters. func _on_filter_toggled(pressed: bool) -> void: settings_manager.set_value("plugin.itch", "filter_unsupported", pressed) var library_manager := load("res://core/global/library_manager.tres") as LibraryManager if library_manager: library_manager.load_library("itch")