extends Control const SERVER_STATUS_TEXT: Dictionary = { "RUNNING": "Server is running!", "NOT_RUNNING": "Server is not running." } const ACCEPTED_FILE_FORMATS := ["md"] # server should ignore these file types when adding endpoints enum ContextMenuOptions { MOVE_UP, MOVE_DOWN, } onready var server_path_label := $"%ServerPathLabel" onready var port_spin_box := $"%PortSpinBox" onready var server_status_label := $"%ServerStatusLabel" onready var document_title_lineedit := $"%DocTitleLineEdit" onready var document_date_lineedit := $"%DocDateLineEdit" onready var file_tree := $"%FileTree" onready var file_tree_context_menu := $"%FileTreeContextMenu" onready var document_input_textedit := $"%DocInputTextEdit" onready var content_preview_richtextlabel := $"%ContentPreviewRichTextLabel" onready var server_folder_dialog := $"%ServerFolderDialog" signal server_folder_changed(new_path) # new_path: String signal server_port_changed(new_port) # new_port: int signal start_server_button_pressed(port) # port: int signal open_browser_button_pressed(port) # port: int signal files_selection_changed(new_files) # new_files: Array var server_dir: String setget set_server_dir var is_server_running: bool = false setget set_server_running var working_files: Array = [] # Array var current_file: FileDef = null func _ready() -> void: # TODO: put this in a config file if !OS.has_feature("editor"): self.server_dir = OS.get_executable_path().get_base_dir() else: self.server_dir = ProjectSettings.globalize_path("res://") func set_server_dir(dir: String) -> void: server_dir = dir server_path_label.text = dir file_tree.clear() working_files.clear() var root: TreeItem = file_tree.create_item() root.set_text(0, "Server files") var directory := Directory.new() if directory.open(dir) == OK: directory.list_dir_begin() var file_name: String = directory.get_next() while file_name != "": if !directory.current_is_dir() && (file_name.get_extension() in ACCEPTED_FILE_FORMATS): var fd = FileDef(file_name, false) working_files.append(fd) var in_filestxt := _is_file_in_filestxt(file_name) var item: TreeItem = file_tree.create_item(root) item.set_cell_mode(0, TreeItem.CELL_MODE_CHECK) item.set_metadata(0, fd) item.set_editable(0, true) item.set_text(0, file_name) item.set_checked(0, in_filestxt) fd.include_in_filestxt = in_filestxt file_name = directory.get_next() directory.list_dir_end() func _on_FileTree_item_edited() -> void: var item: TreeItem = file_tree.get_edited() var fd: FileDef = item.get_metadata(0) fd.include_in_filestxt = item.is_checked(0) func _on_FileTree_item_selected() -> void: var item: TreeItem = file_tree.get_selected() current_file = item.get_metadata(0) as FileDef if !current_file.dirty: var file_metadata := _get_file_metadata(current_file.file_path) current_file.title = file_metadata["title"] current_file.date = file_metadata["date"] current_file.content = file_metadata["content"] document_input_textedit.text = current_file.content document_date_lineedit.text = current_file.date document_title_lineedit.text = current_file.title func _on_FileTree_item_rmb_selected(position: Vector2) -> void: # var item: TreeItem = file_tree.get_selected() file_tree_context_menu.rect_position = position + file_tree.rect_global_position file_tree_context_menu.popup() func _on_OpenServerFolderButton_pressed() -> void: server_folder_dialog.popup() func set_server_running(running: bool) -> void: is_server_running = running # TODO: logic for disabling and enabling certain nodes func _generate_filestxt() -> String: var files := "" for file in working_files: file = file as FileDef if file.include_in_filestxt: files += "%s %s %s\n" % [file.file_path, file.date, file.title] return files func _is_file_in_filestxt(path: String) -> bool: var f := File.new() if f.open(server_dir.plus_file("files.txt"), File.READ) == OK: var text := f.get_as_text() return path in text else: return false func _get_file_metadata(path: String) -> Dictionary: var f := File.new() var res = {} if f.open(server_dir.plus_file("files.txt"), File.READ) == OK: var text := f.get_as_text() var lines := text.split("\n") for line in lines: line = line as String if line.empty(): res = {} var def = line.split(" ", true, 2) if def[0] == path: res["file_path"] = def[0] res["date"] = def[1] if def.size() > 1 else "" res["title"] = def[2] if def.size() > 2 else "" break if f.open(server_dir.plus_file(path), File.READ) == OK: res["content"] = f.get_as_text() return res func _on_DocTitleLineEdit_text_changed(new_text: String) -> void: if current_file: current_file.title = new_text current_file.dirty = true func _on_DocDateLineEdit_text_changed(new_text: String) -> void: if current_file: current_file.date = new_text current_file.dirty = true func _on_DocInputTextEdit_text_changed() -> void: if current_file: var new_text: String = document_input_textedit.text current_file.content = new_text current_file.dirty = true func FileDef( file_path: String, include_in_filestxt: bool, title: String = "", date: String = "") -> FileDef: var fd := FileDef.new() fd.file_path = file_path fd.include_in_filestxt = include_in_filestxt fd.title = title fd.date = date return fd class FileDef: var file_path: String # relative var include_in_filestxt: bool = true var title: String # optional var date: String # optional, YYYY-MM-DD var dirty: bool = false var content: String