use crate::adapters::filesystem::FilePickerAdapter; use crate::domain::value_objects::{FilePath, SyncOffset, TrackLanguage}; use crate::ui::components::{language_field::LanguageField, sync_offset_field::SyncOffsetField}; use eframe::egui; /// Evento emitido ao confirmar adição de faixa de áudio. pub struct AddAudioTrackRequest { pub path: FilePath, pub offset: SyncOffset, pub language: TrackLanguage, pub is_default: bool, pub title: String, /// Fator de escala temporal (correção de drift). 1.0 = sem correção. pub drift_scale: f64, } /// Formulário para adicionar uma faixa de áudio externa. pub struct AddAudioTrackForm { selected_path: Option, offset_field: SyncOffsetField, language_field: LanguageField, is_default: bool, title_input: String, } impl AddAudioTrackForm { pub fn new() -> Self { AddAudioTrackForm { selected_path: None, offset_field: SyncOffsetField::new(SyncOffset::default()), language_field: LanguageField::new(None), is_default: false, title_input: String::new(), } } /// Renderiza o formulário. Retorna `Some(request)` ao confirmar. pub fn ui(&mut self, ui: &mut egui::Ui, mkvmerge_available: bool) -> Option { let mut result = None; ui.group(|ui| { ui.heading("Adicionar faixa de áudio"); ui.horizontal(|ui| { let label = self .selected_path .as_ref() .map(|p| p.to_string_lossy().to_string()) .unwrap_or_else(|| "Nenhum arquivo".to_string()); ui.label(&label); if ui.button("Selecionar áudio…").clicked() { self.selected_path = FilePickerAdapter::pick_audio(); } }); self.offset_field.ui_with_drift(ui, "Atraso:", mkvmerge_available); self.language_field.ui(ui); ui.horizontal(|ui| { ui.label("Nome da faixa:"); ui.text_edit_singleline(&mut self.title_input) .on_hover_text( "Nome exibido no player (ex: \"Português\", \"Comentários\").\n\ Deixe vazio para remover o nome original do arquivo fonte.\n\ Recomendado para evitar nomes como \"ISO Media file produced by Google Inc.\"", ); }); ui.checkbox(&mut self.is_default, "Definir como faixa padrão") .on_hover_text( "Marca esta faixa como padrão no container MKV.\n\ Recomendado para que players como Jellyfin selecionem este áudio automaticamente.", ); ui.add_space(4.0); let can_add = self.selected_path.is_some(); if ui .add_enabled(can_add, egui::Button::new("Adicionar")) .clicked() { if let (Some(path), Some(offset), Some(language)) = ( self.selected_path.clone(), self.offset_field.parse(), self.language_field.parse(), ) { let drift_scale = self.offset_field.parse_drift(); result = Some(AddAudioTrackRequest { path, offset, language, is_default: self.is_default, title: self.title_input.trim().to_string(), drift_scale, }); // Reset form self.selected_path = None; self.offset_field = SyncOffsetField::new(SyncOffset::default()); self.language_field = LanguageField::new(None); self.is_default = false; self.title_input = String::new(); } } }); result } }