class_name SyncPopup extends BasePopup ## Asks the server to sync its soundtracks with the music folder, shows the progress, ## and then lists what was added, changed or removed. ## Emitted when the server has started syncing. signal sync_started ## Emitted when the sync is done and its result is shown. signal sync_finished var changes: bool = false var has_synced: bool = false @onready var sync_panel: Panel = %SyncPanel @onready var sync_title_label: Label = %SyncTitleLabel @onready var no_changes_label: Label = %NoChangesLabel @onready var progress_hbox: HBoxContainer = %ProgressHBoxContainer @onready var sync_hbox: HBoxContainer = %SyncHBoxContainer @onready var sync_progress_bar: AnimatedProgressBar = %SyncProgressBar @onready var soundtracks_added_vbox: VBoxContainer = %SoundtracksAddedVBox @onready var soundtracks_added_separator: VSeparator = %SoundtracksAddedSeparator @onready var soundtracks_readded_vbox: VBoxContainer = %SoundtracksReAddedVBox @onready var soundtracks_readded_separator: VSeparator = %SoundtracksReAddedSeparator @onready var soundtracks_changed_title_vbox: VBoxContainer = %SoundtracksChangedTitleVBox @onready var soundtracks_changed_title_separator: VSeparator = %SoundtracksChangedTitleSeparator @onready var soundtracks_changed_content_vbox: VBoxContainer = %SoundtracksChangedContentVBox @onready var soundtracks_changed_content_separator: VSeparator = %SoundtracksChangedContentSeparator @onready var soundtracks_removed_vbox: VBoxContainer = %SoundtracksRemovedVBox @onready var soundtracks_removed_separator: VSeparator = %SoundtracksRemovedSeparator @onready var caught_errors_vbox: VBoxContainer = %CaughtErrorsVBox @onready var sync_time: Label = %SyncTime @onready var sync_timer: Timer = %SyncTimer @onready var restart_sync_button: Button = %RestartSyncButton func _ready() -> void: sync_timer.timeout.connect(_on_sync_timeout) restart_sync_button.pressed.connect(start_sync) restart_sync_button.visible = false ## Lists [param data] under [param header_text] in [param vbox] and returns true, or hides ## the column and its separator when there is nothing to list. func show_section_if_has_data(data: Variant, vbox: VBoxContainer, separator: VSeparator, header_text: String) -> bool: if data != null && data.size() > 0: vbox.visible = true make_list(data, vbox, header_text) return true else: vbox.visible = false separator.visible = false return false func start_sync() -> void: GameLog.debug("start_sync") open() if has_synced: # Already synced, just show the results show_sync_result() return var sync_request_sent: Callable = func sync_request_sent() -> void: sync_timer.start(0.75) Settings.currently_syncing = true sync_started.emit() show_sync_progress() if !Settings.currently_syncing: MusicServerClient.start_sync(sync_request_sent) func _on_sync_timeout() -> void: GameLog.debug("_on_sync_timeout!") var get_progress: Callable = func get_progress(data_received: Dictionary) -> void: GameLog.debug("get_progress") GameLog.debug("data_received: ", data_received) if data_received != null: if data_received.has("progress"): sync_progress_bar.move_to(int(data_received.progress)) sync_time.text = data_received.time_spent if data_received.has("time_spent") else "" else: _finish_progress(data_received) MusicServerClient.fetch_sync_progress(get_progress) # Fills the bar and lets it pop before the result takes its place func _finish_progress(data_received: Dictionary) -> void: sync_timer.stop() if Anim.enabled() && progress_hbox.visible: sync_progress_bar.move_to(sync_progress_bar.max_value) await get_tree().create_timer(Anim.SLOW).timeout Anim.pop(sync_progress_bar, 1.04, Anim.SLOW) await get_tree().create_timer(Anim.SLOW).timeout on_sync_finished(data_received) func on_sync_finished(data_received: Dictionary) -> void: has_synced = true reset_sync_result() if show_section_if_has_data(data_received.soundtracks_added, soundtracks_added_vbox, soundtracks_added_separator, "Added"): changes = true if show_section_if_has_data(data_received.soundtracks_re_added, soundtracks_readded_vbox, soundtracks_readded_separator, "Re-added"): changes = true var changed_titles: Variant = data_received.soundtracks_changed_title if changed_titles != null && changed_titles.size() > 0: changes = true Settings.delete_children(soundtracks_changed_title_vbox) make_header_label(soundtracks_changed_title_vbox, "Changed Title") var row: int = 0 for old_soundtrack_title: String in changed_titles: var new_soundtrack_title: String = changed_titles[old_soundtrack_title] soundtracks_changed_title_vbox.add_child(make_soundtrack_row( old_soundtrack_title + "\nchanged title to\n" + new_soundtrack_title, row)) row += 1 soundtracks_changed_title_vbox.visible = true if show_section_if_has_data(data_received.soundtracks_changed_content, soundtracks_changed_content_vbox, soundtracks_changed_content_separator, "Changed Content"): changes = true if show_section_if_has_data(data_received.soundtracks_removed, soundtracks_removed_vbox, soundtracks_removed_separator, "Removed"): changes = true # The server's name for the errors it caught if data_received.catched_errors != null && data_received.catched_errors.size() > 0: caught_errors_vbox.visible = true make_list(data_received.catched_errors, caught_errors_vbox, "Errors") # Separators go only between visible columns, not after the last one var visible_sections: Array = [] if soundtracks_added_vbox.visible: visible_sections.append("added") if soundtracks_readded_vbox.visible: visible_sections.append("readded") if soundtracks_changed_title_vbox.visible: visible_sections.append("changed_title") if soundtracks_changed_content_vbox.visible: visible_sections.append("changed_content") if soundtracks_removed_vbox.visible: visible_sections.append("removed") # Show section separators only if there's a visible section after them for i: int in range(visible_sections.size()): var section: String = visible_sections[i] var separator_map: Dictionary = { "added": soundtracks_added_separator, "readded": soundtracks_readded_separator, "changed_title": soundtracks_changed_title_separator, "changed_content": soundtracks_changed_content_separator, "removed": soundtracks_removed_separator } # Show this section's separator only if there's a next section if i < visible_sections.size() - 1: separator_map[section].visible = true else: separator_map[section].visible = false if !changes: no_changes_label.visible = true sync_time.text = "Total time: " + data_received.total_time \ if data_received.has("total_time") else "" Settings.currently_syncing = false sync_timer.stop() GameLog.debug("sync finished") show_sync_result() restart_sync_button.visible = true sync_finished.emit() func list_visible(vbox: VBoxContainer, separator: VSeparator) -> void: vbox.visible = true separator.visible = true func make_header_label(vbox: VBoxContainer, text: String) -> void: var label: Label = Label.new() label.theme_type_variation = &"HighlightLarge" label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER label.text = text vbox.add_child(label) # Items alternate between white and orange text as well as background shade func make_soundtrack_row(text: String, row: int) -> ListRow: var label_style: StringName = &"HighlightMedium" if row % 2 != 0 else &"TextMedium" return ListRow.create(text, row, label_style, HORIZONTAL_ALIGNMENT_CENTER) func reset_sync_result() -> void: sync_progress_bar.value = 0 sync_time.text = "" changes = false no_changes_label.visible = false soundtracks_added_vbox.visible = false soundtracks_added_separator.visible = false soundtracks_readded_vbox.visible = false soundtracks_readded_separator.visible = false soundtracks_changed_title_vbox.visible = false soundtracks_changed_title_separator.visible = false soundtracks_changed_content_vbox.visible = false soundtracks_changed_content_separator.visible = false soundtracks_removed_vbox.visible = false soundtracks_removed_separator.visible = false caught_errors_vbox.visible = false func make_list(list: Array, vbox: VBoxContainer, text: String) -> void: Settings.delete_children(vbox) make_header_label(vbox, text) for row: int in list.size(): vbox.add_child(make_soundtrack_row(list[row], row)) func show_sync_result() -> void: sync_title_label.text = "Sync Result" progress_hbox.visible = false sync_hbox.visible = true restart_sync_button.visible = true func show_sync_progress() -> void: sync_title_label.text = "Sync in Progress" progress_hbox.visible = true sync_progress_bar.wait() no_changes_label.visible = false sync_hbox.visible = false caught_errors_vbox.visible = false restart_sync_button.visible = false