class_name KeetFile
extends Node
## File manager for Keet room files — list, preview, download, subscribe.
## Follows same patterns as KeetChat and KeetRoom.
signal files_loaded(room_id: String, files: Array)
signal file_info_loaded(room_id: String, file_entry: Dictionary)
signal file_preview_loaded(room_id: String, file_id: String, preview_data: Dictionary)
signal download_started(room_id: String, file_id: String)
signal download_progress(room_id: String, file_id: String, progress: Dictionary)
signal file_update(room_id: String, data: Dictionary)
signal error_occurred(message: String)
var client: KeetUdsClient
var _subscribed_room: String = ""
## List files in a room.
func list_files(room_id: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("file.list", {"roomId": room_id}, func(result, err):
if err != null:
error_occurred.emit("list_files: %s" % str(err))
return
var files: Array = result if result is Array else []
files_loaded.emit(room_id, files)
if callback.is_valid():
callback.call(files)
)
## Get detailed info for a single file.
func get_file_info(room_id: String, file_id: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("file.info", {"roomId": room_id, "fileId": file_id}, func(result, err):
if err != null:
error_occurred.emit("file_info: %s" % str(err))
return
var entry: Dictionary = result if result is Dictionary else {}
file_info_loaded.emit(room_id, entry)
if callback.is_valid():
callback.call(entry)
)
## Get preview data for a file (base64 WebP).
func get_preview(room_id: String, file_id: String, size: String = "small", callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("file.preview", {"roomId": room_id, "fileId": file_id, "size": size}, func(result, err):
if err != null:
error_occurred.emit("preview: %s" % str(err))
return
var data: Dictionary = result if result is Dictionary else {}
file_preview_loaded.emit(room_id, file_id, data)
if callback.is_valid():
callback.call(data)
)
## Get local filesystem path of a downloaded file.
func get_file_path(room_id: String, file_id: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("file.path", {"roomId": room_id, "fileId": file_id}, func(result, err):
if err != null:
error_occurred.emit("file_path: %s" % str(err))
return
if callback.is_valid():
callback.call(result if result is Dictionary else {})
)
## Start downloading a file.
func start_download(room_id: String, file_id: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("file.download", {"roomId": room_id, "fileId": file_id}, func(result, err):
if err != null:
error_occurred.emit("download: %s" % str(err))
return
download_started.emit(room_id, file_id)
if callback.is_valid():
callback.call(result)
)
## Cancel an active download.
func cancel_download(room_id: String, file_id: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("file.cancel", {"roomId": room_id, "fileId": file_id}, func(result, err):
if err != null:
error_occurred.emit("cancel: %s" % str(err))
return
if callback.is_valid():
callback.call(result)
)
## Send a file from a local path to a room.
func send_file(room_id: String, file_path: String, callback: Callable = Callable()) -> void:
_require_client()
client.call_rpc("file.sendFromPath", {
"roomId": room_id,
"filePath": file_path
}, func(result, err):
if err != null:
error_occurred.emit("send_file: %s" % str(err))
if callback.is_valid():
callback.call(null)
return
if callback.is_valid():
callback.call(result)
)
## Subscribe to file events for a room (new files, progress updates).
func subscribe_files(room_id: String) -> void:
if _subscribed_room != "" and _subscribed_room != room_id:
unsubscribe_files()
_subscribed_room = room_id
_require_client()
if not client.event_received.is_connected(_on_push_event):
client.event_received.connect(_on_push_event)
client.call_rpc("file.subscribe", {"roomId": room_id}, func(_result, err):
if err != null:
error_occurred.emit("file.subscribe: %s" % str(err))
)
## Unsubscribe from file events.
func unsubscribe_files() -> void:
if _subscribed_room != "" and client != null and client.is_connected:
client.call_rpc("file.unsubscribe", {"roomId": _subscribed_room})
_subscribed_room = ""
func _on_push_event(event_name: String, data: Dictionary) -> void:
if event_name == "file_update":
var event_room: String = data.get("roomId", "")
if event_room != "" and event_room != _subscribed_room:
return
file_update.emit(_subscribed_room, data)
elif event_name == "file_progress":
var event_room: String = data.get("roomId", "")
if event_room != "" and event_room != _subscribed_room:
return
var file_id: String = data.get("fileId", "")
download_progress.emit(_subscribed_room, file_id, data)
func _require_client() -> void:
if client == null:
push_error("KeetFile: client not set")