extends VBoxContainer const Brand := preload("res://scripts/ui/medmind_style.gd") var editor: TextEdit var status_label: Label var count_label: Label var conflict_panel: PanelContainer var applying_content := false var notes_service: Node var theme_service: Node func _ready() -> void: notes_service = get_node("/root/NotesService") theme_service = get_node("/root/UIThemeService") size_flags_horizontal = Control.SIZE_EXPAND_FILL size_flags_vertical = Control.SIZE_EXPAND_FILL add_theme_constant_override("separation", 10) var metadata_row := HBoxContainer.new() metadata_row.add_theme_constant_override("separation", 12) add_child(metadata_row) status_label = Label.new() status_label.size_flags_horizontal = Control.SIZE_EXPAND_FILL Brand.apply_font(status_label) metadata_row.add_child(status_label) count_label = Label.new() Brand.apply_font(count_label) metadata_row.add_child(count_label) editor = TextEdit.new() editor.placeholder_text = "Write notes..." editor.wrap_mode = TextEdit.LINE_WRAPPING_BOUNDARY editor.size_flags_horizontal = Control.SIZE_EXPAND_FILL editor.size_flags_vertical = Control.SIZE_EXPAND_FILL editor.custom_minimum_size = Vector2(0, 260) editor.add_theme_font_override("font", Brand.font) editor.add_theme_font_size_override("font_size", 17) editor.text_changed.connect(_on_text_changed) add_child(editor) conflict_panel = PanelContainer.new() conflict_panel.visible = false add_child(conflict_panel) var conflict_content := VBoxContainer.new() conflict_content.add_theme_constant_override("separation", 8) conflict_panel.add_child(conflict_content) var conflict_message := Label.new() conflict_message.text = "This note changed on another device. Choose which version to keep." conflict_message.autowrap_mode = TextServer.AUTOWRAP_WORD_SMART Brand.apply_font(conflict_message) conflict_content.add_child(conflict_message) var conflict_actions := HBoxContainer.new() conflict_actions.add_theme_constant_override("separation", 8) conflict_content.add_child(conflict_actions) var keep_draft := Button.new() keep_draft.text = "Keep my draft" keep_draft.pressed.connect(notes_service.resolve_conflict_keep_draft) conflict_actions.add_child(keep_draft) var use_synced := Button.new() use_synced.text = "Use synced version" use_synced.pressed.connect(notes_service.resolve_conflict_use_synced) conflict_actions.add_child(use_synced) notes_service.content_changed.connect(_on_service_content_changed) notes_service.state_changed.connect(_on_service_state_changed) theme_service.theme_changed.connect(_on_theme_changed) _refresh_from_service() _apply_theme() func activate() -> void: notes_service.ensure_loaded() _refresh_from_service() func focus_editor() -> void: editor.grab_focus() func _on_text_changed() -> void: if applying_content: return if editor.text.length() > notes_service.MAX_CONTENT_LENGTH: var caret_line := editor.get_caret_line() var caret_column := editor.get_caret_column() applying_content = true editor.text = editor.text.left(NotesService.MAX_CONTENT_LENGTH) editor.set_caret_line(mini(caret_line, editor.get_line_count() - 1)) editor.set_caret_column(caret_column) applying_content = false notes_service.set_content(editor.text) _refresh_metadata() func _on_service_content_changed(value: String) -> void: if editor.text != value: applying_content = true editor.text = value applying_content = false _refresh_metadata() func _on_service_state_changed(_new_state: String) -> void: _refresh_metadata() func _refresh_from_service() -> void: _on_service_content_changed(notes_service.content) func _refresh_metadata() -> void: status_label.text = notes_service.status_text() count_label.text = "%s / %s" % [ _format_count(editor.text.length()), _format_count(notes_service.MAX_CONTENT_LENGTH) ] conflict_panel.visible = notes_service.conflict_active status_label.add_theme_color_override( "font_color", Brand.AMBER if notes_service.state in ["dirty", "offline", "conflict"] else Brand.muted_color(theme_service.is_dark_mode())) func _format_count(value: int) -> String: return "%d,%03d" % [int(floor(float(value) / 1000.0)), value % 1000] if value >= 1000 else str(value) func _on_theme_changed(_dark: bool) -> void: _apply_theme() func _apply_theme() -> void: var dark: bool = theme_service.is_dark_mode() editor.add_theme_color_override("font_color", Brand.text_color(dark)) editor.add_theme_color_override("font_placeholder_color", Brand.muted_color(dark)) editor.add_theme_color_override("caret_color", Brand.SKY_BLUE if dark else Brand.ROYAL_BLUE) editor.add_theme_color_override("selection_color", Color(Brand.ROYAL_BLUE, 0.32)) editor.add_theme_stylebox_override("normal", Brand.field_box(dark)) editor.add_theme_stylebox_override("focus", Brand.field_box(dark, true)) conflict_panel.add_theme_stylebox_override("panel", Brand.content_card_box(dark, true, Brand.AMBER)) _refresh_metadata()