148 lines
4.1 KiB
GDScript
148 lines
4.1 KiB
GDScript
extends Node
|
|
|
|
signal mail_updated
|
|
signal unread_count_changed(count: int)
|
|
|
|
var mails: Array = []
|
|
var claimed_ids: Array = []
|
|
var read_ids: Array = []
|
|
|
|
var _is_fetching: bool = false
|
|
|
|
func _ready() -> void:
|
|
if UserProfileManager:
|
|
UserProfileManager.profile_loaded.connect(_on_profile_loaded)
|
|
|
|
func _on_profile_loaded(_profile: Dictionary) -> void:
|
|
fetch_mails()
|
|
|
|
func fetch_mails() -> void:
|
|
if _is_fetching or not NakamaManager.session: return
|
|
_is_fetching = true
|
|
|
|
var result = await BackendService.get_mail()
|
|
_is_fetching = false
|
|
|
|
if result.get("success", false) == false:
|
|
push_error("[MailManager] Failed to fetch mails: " + str(result.get("error", "")))
|
|
return
|
|
|
|
var payload = result.get("data", {})
|
|
if payload and payload is Dictionary:
|
|
var raw_mails = payload.get("mails", [])
|
|
if typeof(raw_mails) == TYPE_ARRAY:
|
|
mails = raw_mails
|
|
elif typeof(raw_mails) == TYPE_DICTIONARY:
|
|
mails = raw_mails.values()
|
|
else:
|
|
mails = []
|
|
var state = payload.get("state", {})
|
|
if typeof(state) != TYPE_DICTIONARY:
|
|
state = {}
|
|
var raw_claimed_ids = state.get("claimed_ids", [])
|
|
var raw_read_ids = state.get("read_ids", [])
|
|
claimed_ids = raw_claimed_ids if typeof(raw_claimed_ids) == TYPE_ARRAY else []
|
|
read_ids = raw_read_ids if typeof(raw_read_ids) == TYPE_ARRAY else []
|
|
|
|
# Sort by date descending
|
|
mails.sort_custom(func(a, b):
|
|
return a.get("date", "") > b.get("date", "")
|
|
)
|
|
|
|
mail_updated.emit()
|
|
_update_unread_count()
|
|
|
|
func _update_unread_count() -> void:
|
|
var count = 0
|
|
for m in mails:
|
|
if m.id not in read_ids:
|
|
count += 1
|
|
unread_count_changed.emit(count)
|
|
|
|
func claim_reward(mail_id: String) -> bool:
|
|
var result = await BackendService.claim_mail_reward(mail_id)
|
|
if result.get("success", false) == false:
|
|
push_error("[MailManager] Claim failed: " + str(result.get("error", "")))
|
|
return false
|
|
|
|
var payload = result.get("data", {})
|
|
if payload and payload.get("success"):
|
|
claimed_ids = payload.get("claimed_ids", claimed_ids)
|
|
if mail_id not in read_ids:
|
|
read_ids.append(mail_id)
|
|
mail_updated.emit()
|
|
_update_unread_count()
|
|
|
|
# Refresh wallet
|
|
UserProfileManager.load_profile()
|
|
return true
|
|
return false
|
|
|
|
func delete_mail(mail_id: String) -> bool:
|
|
var result = await BackendService.delete_mail(mail_id)
|
|
if result.get("success", false) == false:
|
|
push_error("[MailManager] Delete failed: " + str(result.get("error", "")))
|
|
return false
|
|
|
|
var payload = result.get("data", {})
|
|
if payload and payload.get("success"):
|
|
var deleted_ids = payload.get("deleted_ids", [])
|
|
# Remove from local array
|
|
for i in range(mails.size() - 1, -1, -1):
|
|
if mails[i].id in deleted_ids:
|
|
mails.remove_at(i)
|
|
if mail_id not in read_ids:
|
|
read_ids.append(mail_id)
|
|
mail_updated.emit()
|
|
_update_unread_count()
|
|
return true
|
|
return false
|
|
|
|
func mark_as_read(mail_id: String) -> void:
|
|
if mail_id in read_ids: return
|
|
read_ids.append(mail_id)
|
|
_update_unread_count()
|
|
# Persist read state to server via delete_mail RPC pattern (just saves state)
|
|
_save_inbox_state()
|
|
|
|
func _save_inbox_state() -> void:
|
|
if not NakamaManager.session: return
|
|
var state_payload = {
|
|
"claimed_ids": claimed_ids,
|
|
"deleted_ids": [],
|
|
"read_ids": read_ids
|
|
}
|
|
var result = await BackendService.api_rpc_async("save_mail_state", JSON.stringify(state_payload))
|
|
if result.get("success", false) == false:
|
|
push_warning("[MailManager] Could not save mail state: " + str(result.get("error", "")))
|
|
|
|
func read_all_and_claim_all() -> void:
|
|
"""Mark all mails as read and claim all unclaimed rewards."""
|
|
if mails.is_empty(): return
|
|
|
|
# Mark all as read
|
|
for mail in mails:
|
|
var mid = mail.get("id", "")
|
|
if mid not in read_ids:
|
|
read_ids.append(mid)
|
|
|
|
# Claim all unclaimed rewards
|
|
var to_claim: Array = []
|
|
for mail in mails:
|
|
var mid = mail.get("id", "")
|
|
if mid in claimed_ids: continue
|
|
var rewards = mail.get("rewards", [])
|
|
var has_rewards = false
|
|
if typeof(rewards) == TYPE_DICTIONARY:
|
|
has_rewards = rewards.get("star", 0) > 0 or rewards.get("gold", 0) > 0
|
|
elif typeof(rewards) == TYPE_ARRAY:
|
|
has_rewards = rewards.size() > 0
|
|
if has_rewards:
|
|
to_claim.append(mid)
|
|
|
|
for mid in to_claim:
|
|
await claim_reward(mid)
|
|
|
|
_update_unread_count()
|
|
mail_updated.emit()
|