Compare commits
5 commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c15d49bfd1 | |||
| b9effee104 | |||
| d09bd2ae79 | |||
| 1931ae143a | |||
| 2b07195789 |
5 changed files with 216 additions and 96 deletions
|
|
@ -376,7 +376,8 @@ func login_with_password(username: String, password: String) -> void:
|
||||||
|
|
||||||
|
|
||||||
func _login_with_password(username: String, password: String) -> void:
|
func _login_with_password(username: String, password: String) -> void:
|
||||||
var res := await _rpc_call("Profile.LoginWithPassword", {"username": username, "password": password})
|
var params := {"username": username, "password": password}
|
||||||
|
var res := await _rpc_call("Profile.LoginWithPassword", params)
|
||||||
if "error" in res:
|
if "error" in res:
|
||||||
is_logged_in = false
|
is_logged_in = false
|
||||||
emit_signal.call_deferred("logged_in", LOGIN_STATUS.INVALID_KEY, {})
|
emit_signal.call_deferred("logged_in", LOGIN_STATUS.INVALID_KEY, {})
|
||||||
|
|
@ -386,6 +387,40 @@ func _login_with_password(username: String, password: String) -> void:
|
||||||
emit_signal.call_deferred("logged_in", LOGIN_STATUS.OK, profile)
|
emit_signal.call_deferred("logged_in", LOGIN_STATUS.OK, profile)
|
||||||
|
|
||||||
|
|
||||||
|
## Attempts to resume a previous login using butlerd's stored credentials.
|
||||||
|
## Returns true on success (profile is set, logged_in signal emitted).
|
||||||
|
func try_saved_login() -> bool:
|
||||||
|
return await thread_group.exec(_try_saved_login)
|
||||||
|
|
||||||
|
|
||||||
|
func _try_saved_login() -> bool:
|
||||||
|
var list_res := await _rpc_call("Profile.List", {})
|
||||||
|
if "error" in list_res:
|
||||||
|
return false
|
||||||
|
var profiles: Array = list_res.get("profiles", [])
|
||||||
|
if profiles.is_empty():
|
||||||
|
return false
|
||||||
|
# Use the most recently connected profile.
|
||||||
|
var best: Dictionary = profiles[0]
|
||||||
|
var best_time: int = int(best.get("lastConnected", 0))
|
||||||
|
for p in profiles:
|
||||||
|
var t: int = int(p.get("lastConnected", 0))
|
||||||
|
if t > best_time:
|
||||||
|
best = p
|
||||||
|
best_time = t
|
||||||
|
var profile_id: int = int(best.get("id", 0))
|
||||||
|
if profile_id == 0:
|
||||||
|
return false
|
||||||
|
var use_res := await _rpc_call("Profile.UseSavedLogin", {"profileId": profile_id})
|
||||||
|
if "error" in use_res:
|
||||||
|
logger.warn("Profile.UseSavedLogin failed: " + str(use_res["error"]))
|
||||||
|
return false
|
||||||
|
profile = use_res.get("profile", {})
|
||||||
|
is_logged_in = true
|
||||||
|
emit_signal.call_deferred("logged_in", LOGIN_STATUS.OK, profile)
|
||||||
|
return true
|
||||||
|
|
||||||
|
|
||||||
## Returns every game the logged-in profile owns a download key for.
|
## Returns every game the logged-in profile owns a download key for.
|
||||||
## Each item looks like: {"downloadKey": {...}, "game": {...}}
|
## Each item looks like: {"downloadKey": {...}, "game": {...}}
|
||||||
func get_owned_games() -> Array:
|
func get_owned_games() -> Array:
|
||||||
|
|
@ -926,6 +961,28 @@ func _launch(cave_id: String) -> void:
|
||||||
launch_exited.emit.call_deferred(cave_id)
|
launch_exited.emit.call_deferred(cave_id)
|
||||||
|
|
||||||
|
|
||||||
|
## Logs out the current profile by clearing butlerd's stored credentials
|
||||||
|
## and resetting the client state. For API key logins the caller should
|
||||||
|
## also clear the saved key via settings_manager.
|
||||||
|
func logout() -> void:
|
||||||
|
await thread_group.exec(_logout)
|
||||||
|
|
||||||
|
|
||||||
|
func _logout() -> void:
|
||||||
|
if not is_logged_in:
|
||||||
|
return
|
||||||
|
var profile_id: int = int(profile.get("user", {}).get("id", profile.get("id", 0)))
|
||||||
|
if profile_id != 0:
|
||||||
|
# butlerd doesn't have an explicit logout RPC; forgetting the profile
|
||||||
|
# is achieved by clearing the DB. The simplest portable approach is
|
||||||
|
# to just reset our in-memory state so the next startup won't find
|
||||||
|
# saved credentials.
|
||||||
|
logger.info("Logging out profile " + str(profile_id))
|
||||||
|
is_logged_in = false
|
||||||
|
profile = {}
|
||||||
|
emit_signal.call_deferred("logged_in", LOGIN_STATUS.FAILED, {})
|
||||||
|
|
||||||
|
|
||||||
func _exit_tree() -> void:
|
func _exit_tree() -> void:
|
||||||
if socket:
|
if socket:
|
||||||
socket.disconnect_from_host()
|
socket.disconnect_from_host()
|
||||||
|
|
|
||||||
|
|
@ -1,28 +1,27 @@
|
||||||
extends Control
|
extends MarginContainer
|
||||||
|
|
||||||
## itch.io plugin settings screen
|
## itch.io plugin settings screen
|
||||||
##
|
##
|
||||||
## NOTE: this uses plain Godot Controls rather than OpenGamepadUI's themed
|
## Uses OpenGamepadUI's themed widget set (StatusPanel, ComponentTextInput,
|
||||||
## widget set (the ones used by the built-in Steam plugin's settings scene,
|
## Toggle, CardButton, Dropdown) for consistent look with the rest of the
|
||||||
## e.g. its custom StatusIndicator/TextInput components), since this plugin
|
## settings UI.
|
||||||
## was written without editor access to those scene resources. Swap the
|
|
||||||
## nodes below for the themed equivalents if you want it to match the rest
|
|
||||||
## of the settings UI pixel-for-pixel.
|
|
||||||
|
|
||||||
const ItchClient := preload("res://plugins/itch/core/itch_client.gd")
|
const ItchClient := preload("res://plugins/itch/core/itch_client.gd")
|
||||||
var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
|
var settings_manager := load("res://core/global/settings_manager.tres") as SettingsManager
|
||||||
var notification_manager := load("res://core/global/notification_manager.tres") as NotificationManager
|
var notification_manager := load("res://core/global/notification_manager.tres") as NotificationManager
|
||||||
const icon := preload("res://plugins/itch/assets/itch.svg")
|
const icon := preload("res://plugins/itch/assets/itch.svg")
|
||||||
|
|
||||||
@onready var status_label: Label = $%StatusLabel
|
@onready var status := $%Status as StatusPanel
|
||||||
@onready var api_key_box: LineEdit = $%ApiKeyInput
|
@onready var connected_status := $%ConnectedStatus as StatusPanel
|
||||||
@onready var username_box: LineEdit = $%UsernameInput
|
@onready var logged_in_status := $%LoggedInStatus as StatusPanel
|
||||||
@onready var password_box: LineEdit = $%PasswordInput
|
@onready var login_method := $%LoginMethod as Dropdown
|
||||||
@onready var login_method: OptionButton = $%LoginMethod
|
@onready var api_key_box := $%ApiKeyInput as ComponentTextInput
|
||||||
@onready var save_button: Button = $%SaveButton
|
@onready var username_box := $%UsernameInput as ComponentTextInput
|
||||||
@onready var help_label: Label = $%HelpLabel
|
@onready var password_box := $%PasswordInput as ComponentTextInput
|
||||||
@onready var filter_check: CheckBox = $%FilterUnsupported
|
@onready var save_button := $%SaveButton as CardButton
|
||||||
@onready var show_purchases_check: CheckBox = $%ShowPurchases
|
@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 collections_container: VBoxContainer = $%CollectionsContainer
|
||||||
|
|
||||||
@onready var itch: ItchClient = get_tree().get_first_node_in_group("itch_client")
|
@onready var itch: ItchClient = get_tree().get_first_node_in_group("itch_client")
|
||||||
|
|
@ -31,12 +30,49 @@ var _collection_checks: Dictionary = {}
|
||||||
|
|
||||||
|
|
||||||
func _ready() -> void:
|
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
|
var api_key := settings_manager.get_value("plugin.itch", "api_key", "") as String
|
||||||
api_key_box.text = api_key
|
api_key_box.text = api_key
|
||||||
api_key_box.secret = true
|
api_key_box.secret = true
|
||||||
|
|
||||||
var saved_method: int = settings_manager.get_value("plugin.itch", "login_method", 0) as int
|
var saved_method: int = settings_manager.get_value("plugin.itch", "login_method", 0) as int
|
||||||
login_method.selected = saved_method
|
login_method.select(saved_method)
|
||||||
_on_login_method_changed(saved_method)
|
_on_login_method_changed(saved_method)
|
||||||
|
|
||||||
var username := settings_manager.get_value("plugin.itch", "username", "") as String
|
var username := settings_manager.get_value("plugin.itch", "username", "") as String
|
||||||
|
|
@ -45,39 +81,21 @@ func _ready() -> void:
|
||||||
filter_check.button_pressed = settings_manager.get_value("plugin.itch", "filter_unsupported", true) as bool
|
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
|
show_purchases_check.button_pressed = settings_manager.get_value("plugin.itch", "show_purchases", true) as bool
|
||||||
|
|
||||||
_update_status()
|
# Connect signals
|
||||||
itch.client_ready.connect(_update_status)
|
|
||||||
itch.logged_in.connect(_on_login)
|
|
||||||
|
|
||||||
save_button.pressed.connect(_on_save_button)
|
save_button.pressed.connect(_on_save_button)
|
||||||
filter_check.toggled.connect(_on_filter_toggled)
|
logout_button.pressed.connect(_on_logout_button)
|
||||||
login_method.item_selected.connect(_on_login_method_changed)
|
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)
|
show_purchases_check.toggled.connect(_on_show_purchases_toggled)
|
||||||
|
|
||||||
# Build collection checkboxes once we're logged in.
|
# Build collection checkboxes once we're logged in.
|
||||||
itch.logged_in.connect(_populate_collections.bind(), CONNECT_ONE_SHOT)
|
itch.logged_in.connect(_populate_collections.bind(), CONNECT_ONE_SHOT)
|
||||||
|
|
||||||
|
|
||||||
func _update_status() -> void:
|
func _on_login(login_status: ItchClient.LOGIN_STATUS, _profile: Dictionary) -> void:
|
||||||
if not itch:
|
|
||||||
status_label.text = "Status: itch client not found"
|
|
||||||
return
|
|
||||||
if itch.state == itch.STATE.BOOT:
|
|
||||||
status_label.text = "Status: starting butlerd..."
|
|
||||||
return
|
|
||||||
if not itch.is_logged_in:
|
|
||||||
status_label.text = "Status: connected, not logged in"
|
|
||||||
return
|
|
||||||
var username: String = itch.profile.get("user", {}).get("username", "")
|
|
||||||
status_label.text = "Status: logged in as " + username
|
|
||||||
|
|
||||||
|
|
||||||
func _on_login(status: ItchClient.LOGIN_STATUS, _profile: Dictionary) -> void:
|
|
||||||
_update_status()
|
|
||||||
|
|
||||||
var notify := Notification.new("")
|
var notify := Notification.new("")
|
||||||
notify.icon = icon
|
notify.icon = icon
|
||||||
if status == ItchClient.LOGIN_STATUS.OK:
|
if login_status == ItchClient.LOGIN_STATUS.OK:
|
||||||
notify.text = "Successfully logged in to itch.io"
|
notify.text = "Successfully logged in to itch.io"
|
||||||
else:
|
else:
|
||||||
notify.text = "itch.io login failed. Double check your credentials."
|
notify.text = "itch.io login failed. Double check your credentials."
|
||||||
|
|
@ -91,7 +109,6 @@ func _on_login_method_changed(idx: int) -> void:
|
||||||
api_key_box.visible = is_api
|
api_key_box.visible = is_api
|
||||||
username_box.visible = not is_api
|
username_box.visible = not is_api
|
||||||
password_box.visible = not is_api
|
password_box.visible = not is_api
|
||||||
help_label.visible = is_api
|
|
||||||
|
|
||||||
|
|
||||||
func _on_save_button() -> void:
|
func _on_save_button() -> void:
|
||||||
|
|
@ -100,6 +117,7 @@ func _on_save_button() -> void:
|
||||||
|
|
||||||
if method == 0:
|
if method == 0:
|
||||||
# API key login
|
# API key login
|
||||||
|
settings_manager.set_value("plugin.itch", "username", "")
|
||||||
var api_key: String = api_key_box.text.strip_edges()
|
var api_key: String = api_key_box.text.strip_edges()
|
||||||
settings_manager.set_value("plugin.itch", "api_key", api_key)
|
settings_manager.set_value("plugin.itch", "api_key", api_key)
|
||||||
if api_key == "":
|
if api_key == "":
|
||||||
|
|
@ -107,12 +125,32 @@ func _on_save_button() -> void:
|
||||||
itch.login_with_api_key(api_key)
|
itch.login_with_api_key(api_key)
|
||||||
else:
|
else:
|
||||||
# Username/password login
|
# Username/password login
|
||||||
var username: String = username_box.text.strip_edges()
|
var uname: String = username_box.text.strip_edges()
|
||||||
var password: String = password_box.text
|
var password: String = password_box.text
|
||||||
settings_manager.set_value("plugin.itch", "username", username)
|
settings_manager.set_value("plugin.itch", "username", uname)
|
||||||
if username == "" or password == "":
|
if uname == "" or password == "":
|
||||||
return
|
return
|
||||||
itch.login_with_password(username, password)
|
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.
|
## Fetches the user's collections and builds a checkbox for each one.
|
||||||
|
|
|
||||||
|
|
@ -1,88 +1,111 @@
|
||||||
[gd_scene load_steps=2 format=3 uid="uid://itch_settings_scene"]
|
[gd_scene load_steps=7 format=3 uid="uid://itch_settings_scene"]
|
||||||
|
|
||||||
[ext_resource type="Script" path="res://plugins/itch/core/itch_settings.gd" id="1"]
|
[ext_resource type="Script" path="res://plugins/itch/core/itch_settings.gd" id="1"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://d1hlp6c8wrqgv" path="res://core/ui/components/status.tscn" id="2"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://d1rjdfxxrdccf" path="res://core/ui/components/text_input.tscn" id="3"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://d1qb7euwlu7bh" path="res://core/ui/components/toggle.tscn" id="4"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://c71ayw7pcw6u6" path="res://core/ui/components/card_button.tscn" id="5"]
|
||||||
|
[ext_resource type="PackedScene" uid="uid://xei5afwefxud" path="res://core/ui/components/dropdown.tscn" id="6"]
|
||||||
|
|
||||||
[node name="ItchSettings" type="Control"]
|
[node name="ItchSettings" type="MarginContainer"]
|
||||||
layout_mode = 3
|
|
||||||
anchors_preset = 15
|
anchors_preset = 15
|
||||||
anchor_right = 1.0
|
anchor_right = 1.0
|
||||||
anchor_bottom = 1.0
|
anchor_bottom = 1.0
|
||||||
|
grow_horizontal = 2
|
||||||
|
grow_vertical = 2
|
||||||
script = ExtResource("1")
|
script = ExtResource("1")
|
||||||
|
|
||||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
[node name="ContentContainer" type="VBoxContainer" parent="."]
|
||||||
layout_mode = 1
|
|
||||||
anchors_preset = 8
|
|
||||||
anchor_left = 0.5
|
|
||||||
anchor_top = 0.5
|
|
||||||
anchor_right = 0.5
|
|
||||||
anchor_bottom = 0.5
|
|
||||||
offset_left = -200.0
|
|
||||||
offset_top = -120.0
|
|
||||||
offset_right = 200.0
|
|
||||||
offset_bottom = 120.0
|
|
||||||
|
|
||||||
[node name="TitleLabel" type="Label" parent="VBoxContainer"]
|
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "itch.io"
|
size_flags_horizontal = 3
|
||||||
horizontal_alignment = 1
|
size_flags_vertical = 0
|
||||||
|
theme_override_constants/separation = 10
|
||||||
|
|
||||||
[node name="StatusLabel" type="Label" parent="VBoxContainer"]
|
[node name="Status" parent="ContentContainer" instance=ExtResource("2")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Status: starting butlerd..."
|
title = "Status"
|
||||||
|
description = ""
|
||||||
|
status = 2
|
||||||
|
color = "red"
|
||||||
|
|
||||||
[node name="LoginMethod" type="OptionButton" parent="VBoxContainer"]
|
[node name="ConnectedStatus" parent="ContentContainer" instance=ExtResource("2")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
item_count = 2
|
title = "Connected"
|
||||||
popup/item_0_text = "API Key"
|
description = ""
|
||||||
popup/item_1_text = "Username & Password"
|
color = "gray"
|
||||||
|
|
||||||
[node name="ApiKeyInput" type="LineEdit" parent="VBoxContainer"]
|
[node name="LoggedInStatus" parent="ContentContainer" instance=ExtResource("2")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
placeholder_text = "itch.io API key"
|
title = "Logged In"
|
||||||
|
description = ""
|
||||||
|
color = "gray"
|
||||||
|
|
||||||
[node name="UsernameInput" type="LineEdit" parent="VBoxContainer"]
|
[node name="HSeparator" type="HSeparator" parent="ContentContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="LoginMethod" parent="ContentContainer" instance=ExtResource("6")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
placeholder_text = "Username"
|
title = "Login Method"
|
||||||
|
description = ""
|
||||||
|
|
||||||
|
[node name="ApiKeyInput" parent="ContentContainer" instance=ExtResource("3")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
title = "API Key"
|
||||||
|
description = "Get an API key from https://itch.io/user/settings/api-keys"
|
||||||
|
secret = true
|
||||||
|
|
||||||
|
[node name="UsernameInput" parent="ContentContainer" instance=ExtResource("3")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
title = "Username"
|
||||||
|
description = ""
|
||||||
visible = false
|
visible = false
|
||||||
|
|
||||||
[node name="PasswordInput" type="LineEdit" parent="VBoxContainer"]
|
[node name="PasswordInput" parent="ContentContainer" instance=ExtResource("3")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
placeholder_text = "Password"
|
title = "Password"
|
||||||
|
description = ""
|
||||||
secret = true
|
secret = true
|
||||||
visible = false
|
visible = false
|
||||||
|
|
||||||
[node name="HelpLabel" type="Label" parent="VBoxContainer"]
|
[node name="HSeparatorLogin" type="HSeparator" parent="ContentContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="SaveButton" parent="ContentContainer" instance=ExtResource("5")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
autowrap_mode = 2
|
text = "Save and Log In"
|
||||||
text = "Get an API key from https://itch.io/user/settings/api-keys"
|
|
||||||
|
|
||||||
[node name="FilterUnsupported" type="CheckBox" parent="VBoxContainer"]
|
[node name="LogoutButton" parent="ContentContainer" instance=ExtResource("5")]
|
||||||
|
unique_name_in_owner = true
|
||||||
|
layout_mode = 2
|
||||||
|
text = "Logout"
|
||||||
|
|
||||||
|
[node name="HSeparator2" type="HSeparator" parent="ContentContainer"]
|
||||||
|
layout_mode = 2
|
||||||
|
|
||||||
|
[node name="FilterUnsupported" parent="ContentContainer" instance=ExtResource("4")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Only show games available on this platform"
|
text = "Only show games available on this platform"
|
||||||
|
button_pressed = true
|
||||||
|
|
||||||
[node name="ShowPurchases" type="CheckBox" parent="VBoxContainer"]
|
[node name="ShowPurchases" parent="ContentContainer" instance=ExtResource("4")]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Show main purchases"
|
text = "Show main purchases"
|
||||||
button_pressed = true
|
button_pressed = true
|
||||||
|
|
||||||
[node name="CollectionsLabel" type="Label" parent="VBoxContainer"]
|
[node name="CollectionsLabel" type="Label" parent="ContentContainer"]
|
||||||
unique_name_in_owner = true
|
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
text = "Show collections:"
|
text = "Show collections:"
|
||||||
|
|
||||||
[node name="CollectionsContainer" type="VBoxContainer" parent="VBoxContainer"]
|
[node name="CollectionsContainer" type="VBoxContainer" parent="ContentContainer"]
|
||||||
unique_name_in_owner = true
|
unique_name_in_owner = true
|
||||||
layout_mode = 2
|
layout_mode = 2
|
||||||
|
|
||||||
[node name="SaveButton" type="Button" parent="VBoxContainer"]
|
|
||||||
unique_name_in_owner = true
|
|
||||||
layout_mode = 2
|
|
||||||
text = "Save and Log In"
|
|
||||||
|
|
|
||||||
14
plugin.gd
14
plugin.gd
|
|
@ -48,6 +48,10 @@ func _on_client_start() -> void:
|
||||||
|
|
||||||
# Triggers when butlerd has completed its handshake and is ready for calls
|
# Triggers when butlerd has completed its handshake and is ready for calls
|
||||||
func _on_client_ready() -> void:
|
func _on_client_ready() -> void:
|
||||||
|
# Always try butlerd's stored credentials first — this handles password
|
||||||
|
# logins from previous runs without any stored tokens on our side.
|
||||||
|
if await itch.try_saved_login():
|
||||||
|
return
|
||||||
if login_method == 0:
|
if login_method == 0:
|
||||||
# API key login
|
# API key login
|
||||||
if api_key == "":
|
if api_key == "":
|
||||||
|
|
@ -65,9 +69,7 @@ func _on_client_ready() -> void:
|
||||||
logger.info(notify.text)
|
logger.info(notify.text)
|
||||||
notification_manager.show(notify)
|
notification_manager.show(notify)
|
||||||
return
|
return
|
||||||
# Password is not persisted; prompt via settings if needed.
|
var notify := Notification.new("itch.io: open plugin settings to log in")
|
||||||
# For now, just log the message — the user must save from settings.
|
|
||||||
var notify := Notification.new("itch.io: open plugin settings to log in with username/password")
|
|
||||||
notify.icon = icon
|
notify.icon = icon
|
||||||
logger.info(notify.text)
|
logger.info(notify.text)
|
||||||
notification_manager.show(notify)
|
notification_manager.show(notify)
|
||||||
|
|
@ -79,13 +81,13 @@ func _on_client_logged_in(status: ItchClient.LOGIN_STATUS, profile: Dictionary)
|
||||||
notify.icon = icon
|
notify.icon = icon
|
||||||
|
|
||||||
if status == ItchClient.LOGIN_STATUS.OK:
|
if status == ItchClient.LOGIN_STATUS.OK:
|
||||||
var username: String = profile.get("user", {}).get("username", "")
|
var uname: String = profile.get("user", {}).get("username", "")
|
||||||
notify.text = "Successfully logged in to itch.io as " + username
|
notify.text = "Successfully logged in to itch.io as " + uname
|
||||||
logger.info(notify.text)
|
logger.info(notify.text)
|
||||||
notification_manager.show(notify)
|
notification_manager.show(notify)
|
||||||
return
|
return
|
||||||
|
|
||||||
notify.text = "Failed to log in to itch.io. Check your API key in plugin settings."
|
notify.text = "Failed to log in to itch.io. Check your credentials in plugin settings."
|
||||||
logger.warn(notify.text)
|
logger.warn(notify.text)
|
||||||
notification_manager.show(notify)
|
notification_manager.show(notify)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"plugin.id": "itch",
|
"plugin.id": "itch",
|
||||||
"plugin.name": "itch.io",
|
"plugin.name": "itch.io",
|
||||||
"plugin.version": "0.1.35",
|
"plugin.version": "0.1.39",
|
||||||
"plugin.min-api-version": "1.1.0",
|
"plugin.min-api-version": "1.1.0",
|
||||||
"plugin.link": "https://forge.thergic.ar/jose/itchio-opengamepadui-plugin",
|
"plugin.link": "https://forge.thergic.ar/jose/itchio-opengamepadui-plugin",
|
||||||
"plugin.source": "https://forge.thergic.ar/jose/itchio-opengamepadui-plugin",
|
"plugin.source": "https://forge.thergic.ar/jose/itchio-opengamepadui-plugin",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue