Skip to main content

max / audiofiles

Tighten vault-setup screen layout and copy Pre-fills the name field with "Library" so the default is visible instead of an empty placeholder. Switches the layout from two mutually exclusive action buttons ("Use default location" / "Choose folder...") to a single inline location row with a clear "Continue" primary action — there's now exactly one path that advances the screen. Adopts the shared theme spacing tokens and widgets helpers so the screen no longer drifts from the rest of the app's chrome. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author: Max J. <87768334+MaxJMath@users.noreply.github.com> · 2026-05-21 00:10 UTC
Commit: 88415ea1c033b19b47ac317ee4fea21db8a89e48
Parent: 609ab85
1 file changed, +73 insertions, -65 deletions
@@ -2,88 +2,96 @@
2 2
3 3 use std::path::{Path, PathBuf};
4 4
5 + use audiofiles_browser::ui::{theme, widgets};
5 6 use audiofiles_core::vault::{self, VaultRegistry};
6 7 use eframe::egui;
7 8
8 9 use super::AudioFilesApp;
9 10
11 + const DEFAULT_VAULT_NAME: &str = "Library";
12 +
10 13 impl AudioFilesApp {
11 14 /// Draw the vault setup screen (first-open flow, after activation).
12 15 pub(crate) fn draw_vault_setup_screen(&mut self, ctx: &egui::Context) {
13 16 let default_path = vault::default_vault_path();
14 17 let existing_db = default_path.join("audiofiles.db").exists();
15 18
19 + // Pre-fill the vault-name field on first entry so the fallback is visible.
20 + if self.vault_setup_name.is_empty() {
21 + self.vault_setup_name = DEFAULT_VAULT_NAME.to_string();
22 + }
23 +
16 24 egui::CentralPanel::default().show(ctx, |ui| {
17 25 let available = ui.available_size();
18 - ui.add_space((available.y * 0.25).max(40.0));
26 + ui.add_space((available.y * 0.20).max(40.0));
19 27
20 28 ui.vertical_centered(|ui| {
21 - ui.heading("Choose where to store your sample library");
22 - ui.add_space(8.0);
23 -
24 - if existing_db {
25 - ui.label(
26 - egui::RichText::new(format!(
27 - "Your existing library was found at {}",
28 - default_path.display()
29 - ))
30 - .color(egui::Color32::from_rgb(120, 180, 120)),
31 - );
32 - ui.add_space(8.0);
33 - }
34 -
35 - // Option 1: default location
36 - if ui.button("Use default location").clicked() {
37 - self.vault_setup_path = None;
38 - }
39 - ui.label(
40 - egui::RichText::new(format!("Default: {}", default_path.display()))
41 - .small()
42 - .color(egui::Color32::GRAY),
43 - );
44 -
45 - ui.add_space(8.0);
46 -
47 - // Option 2: custom folder
48 - ui.horizontal(|ui| {
49 - if ui.button("Choose folder...").clicked() {
50 - if let Some(path) = rfd::FileDialog::new().pick_folder() {
51 - self.vault_setup_path = Some(path);
29 + let column_width = 480.0_f32.min(available.x - 40.0);
30 + ui.allocate_ui(egui::vec2(column_width, 0.0), |ui| {
31 + ui.vertical(|ui| {
32 + ui.heading("Where should we store your library?");
33 + ui.add_space(theme::space::MD);
34 +
35 + if existing_db && self.vault_setup_path.is_none() {
36 + ui.label(
37 + egui::RichText::new(format!(
38 + "Your existing library at {} will be opened.",
39 + default_path.display()
40 + ))
41 + .color(theme::text_secondary()),
42 + );
43 + ui.add_space(theme::space::SECTION);
44 + } else {
45 + ui.add_space(theme::space::SM);
52 46 }
53 - }
54 - if self.vault_setup_path.is_some()
55 - && ui.small_button("Reset to default").clicked()
56 - {
57 - self.vault_setup_path = None;
58 - }
59 - });
60 -
61 - if let Some(ref custom) = self.vault_setup_path {
62 - ui.label(
63 - egui::RichText::new(format!("Selected: {}", custom.display()))
64 - .small()
65 - .color(egui::Color32::from_rgb(150, 200, 255)),
66 - );
67 - }
68 47
69 - ui.add_space(12.0);
70 -
71 - // Vault name input
72 - ui.horizontal(|ui| {
73 - ui.label("Vault name:");
74 - ui.text_edit_singleline(&mut self.vault_setup_name);
48 + // Vault name
49 + ui.horizontal(|ui| {
50 + ui.label("Name:");
51 + ui.text_edit_singleline(&mut self.vault_setup_name);
52 + });
53 +
54 + ui.add_space(theme::space::MD);
55 +
56 + // Location: shown inline with the picker action. No
57 + // separate "Use default location" button — the default
58 + // is already the value displayed, and "Continue"
59 + // commits whatever is shown here.
60 + let chosen_path = self
61 + .vault_setup_path
62 + .clone()
63 + .unwrap_or_else(|| default_path.clone());
64 + let is_custom = self.vault_setup_path.is_some();
65 + ui.label("Location:");
66 + ui.horizontal_wrapped(|ui| {
67 + let path_text = if is_custom {
68 + widgets::accent_strong(chosen_path.display().to_string())
69 + } else {
70 + egui::RichText::new(chosen_path.display().to_string())
71 + .color(theme::text_secondary())
72 + };
73 + ui.label(path_text);
74 + });
75 + ui.add_space(theme::space::SM);
76 + ui.horizontal(|ui| {
77 + if ui.button("Choose different location...").clicked() {
78 + if let Some(path) = rfd::FileDialog::new().pick_folder() {
79 + self.vault_setup_path = Some(path);
80 + }
81 + }
82 + if is_custom && ui.button("Use default").clicked() {
83 + self.vault_setup_path = None;
84 + }
85 + });
86 +
87 + ui.add_space(theme::space::XL);
88 +
89 + // Single primary action — the only path that advances.
90 + if widgets::primary_button(ui, "Continue").clicked() {
91 + self.finalize_vault_setup(chosen_path);
92 + }
93 + });
75 94 });
76 -
77 - ui.add_space(16.0);
78 -
79 - // Continue button
80 - let chosen = self
81 - .vault_setup_path
82 - .clone()
83 - .unwrap_or_else(|| default_path.clone());
84 - if ui.button("Continue").clicked() {
85 - self.finalize_vault_setup(chosen);
86 - }
87 95 });
88 96 });
89 97 }
@@ -91,7 +99,7 @@ impl AudioFilesApp {
91 99 /// Finalise vault setup: create registry, set data_dir, open browser.
92 100 fn finalize_vault_setup(&mut self, vault_path: PathBuf) {
93 101 let name = if self.vault_setup_name.trim().is_empty() {
94 - "Library".to_string()
102 + DEFAULT_VAULT_NAME.to_string()
95 103 } else {
96 104 self.vault_setup_name.trim().to_string()
97 105 };