OverviewFilesCommitsIssuesDocsReleasesPeers

godot-keet / addons / keet_social / keet_file.gd

155 lines · gd ref:
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")