163 lines
5.4 KiB
GDScript
163 lines
5.4 KiB
GDScript
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
|
|
var saved_status_timer: Timer
|
|
|
|
|
|
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)
|
|
saved_status_timer = Timer.new()
|
|
saved_status_timer.one_shot = true
|
|
saved_status_timer.wait_time = 2.0
|
|
saved_status_timer.timeout.connect(_clear_saved_status)
|
|
add_child(saved_status_timer)
|
|
|
|
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)
|
|
notes_service.save_succeeded.connect(_on_save_succeeded)
|
|
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()
|
|
if notes_service.state != "saved":
|
|
saved_status_timer.stop()
|
|
|
|
|
|
func _refresh_from_service() -> void:
|
|
_on_service_content_changed(notes_service.content)
|
|
|
|
|
|
func _refresh_metadata() -> void:
|
|
if status_label.text != "Saved" or saved_status_timer.time_left <= 0.0:
|
|
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 == "conflict" else Brand.muted_color(theme_service.is_dark_mode()))
|
|
|
|
|
|
func _on_save_succeeded() -> void:
|
|
status_label.text = "Saved"
|
|
saved_status_timer.start()
|
|
|
|
|
|
func _clear_saved_status() -> void:
|
|
if status_label.text == "Saved":
|
|
status_label.text = ""
|
|
|
|
|
|
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()
|