diff --git a/src/ui/application.rs b/src/ui/application.rs index ce471f1..9c820dc 100644 --- a/src/ui/application.rs +++ b/src/ui/application.rs @@ -36,6 +36,7 @@ pub struct RuxApplication { sound_font_file: Option, // sound font file beat_sender: Arc>, // beat notifier beat_receiver: Arc>>, // beat receiver + file_picker_folder: Option, // last folder used in file picker, } #[derive(Debug)] @@ -114,10 +115,10 @@ impl Display for TrackSelection { #[derive(Debug, Clone)] pub enum Message { - OpenFileDialog, // open file dialog - OpenFile(PathBuf), // open file path - FileOpened(Result<(Vec, String), FilePickerError>), // file content & file name - TrackSelected(TrackSelection), // track selection + OpenFileDialog, // open file dialog + OpenFile(PathBuf), // open file path + FileOpened(Result<(Vec, Option, String), FilePickerError>), // file content, parent folder & file name + TrackSelected(TrackSelection), // track selection FocusMeasure(usize), // used when clicking on measure in tablature FocusTick(usize), // focus on a specific tick in the tablature PlayPause, // toggle play/pause @@ -145,6 +146,7 @@ impl RuxApplication { sound_font_file, beat_receiver: Arc::new(Mutex::new(beat_receiver)), beat_sender: Arc::new(beat_sender), + file_picker_folder: None, // TODO store last folder used in $user/home/.ruxguitar } } @@ -192,7 +194,10 @@ impl RuxApplication { Task::none() } else { self.tab_file_is_loading = true; - Task::perform(open_file_dialog(), Message::FileOpened) + Task::perform( + open_file_dialog(self.file_picker_folder.clone()), + Message::FileOpened, + ) } } Message::OpenFile(path) => { @@ -206,7 +211,8 @@ impl RuxApplication { audio_player.stop(); } match result { - Ok((contents, file_name)) => { + Ok((contents, parent_folder, file_name)) => { + self.file_picker_folder = parent_folder; if let Ok(song) = parse_gp_data(&contents) { // build all tracks selection let track_selections: Vec<_> = song diff --git a/src/ui/picker.rs b/src/ui/picker.rs index 80132e9..65e11ad 100644 --- a/src/ui/picker.rs +++ b/src/ui/picker.rs @@ -9,11 +9,18 @@ pub enum FilePickerError { } /// Opens a file dialog and returns the content of the picked file. -pub async fn open_file_dialog() -> Result<(Vec, String), FilePickerError> { - let picked_file = rfd::AsyncFileDialog::new() +pub async fn open_file_dialog( + picker_folder: Option, +) -> Result<(Vec, Option, String), FilePickerError> { + let mut picker = rfd::AsyncFileDialog::new() .add_filter("Guitar Pro files", &["gp5", "gp4"]) - .set_title("Pick a GP file") - //.set_directory() TODO remember last directory and set it here + .set_title("Select a Guitar Pro file"); + + if let Some(folder) = picker_folder { + picker = picker.set_directory(folder); + } + + let picked_file = picker .pick_file() .await .ok_or(FilePickerError::DialogClosed)?; @@ -23,7 +30,9 @@ pub async fn open_file_dialog() -> Result<(Vec, String), FilePickerError> { /// Loads the content of a file at the given path. /// /// Return the content of the file and its name. -pub async fn load_file(path: impl Into) -> Result<(Vec, String), FilePickerError> { +pub async fn load_file( + path: impl Into, +) -> Result<(Vec, Option, String), FilePickerError> { let path = path.into(); let file_extension = path .extension() @@ -41,9 +50,10 @@ pub async fn load_file(path: impl Into) -> Result<(Vec, String), Fi .and_then(|f| f.to_str()) .map(|f| f.to_string()) .unwrap_or_default(); + let parent_folder = path.parent().map(|p| p.into()); log::info!("Loading file: {:?}", file_name); tokio::fs::read(&path) .await .map_err(|error| FilePickerError::IoError(error.to_string())) - .map(|content| (content, file_name)) + .map(|content| (content, parent_folder, file_name)) }