diff --git a/app/src-tauri/src/lib.rs b/app/src-tauri/src/lib.rs index 3298e8f1..fb92b2ca 100644 --- a/app/src-tauri/src/lib.rs +++ b/app/src-tauri/src/lib.rs @@ -15,7 +15,7 @@ pub fn run() { note::catch_panics(); let app = tauri::Builder::default() .plugin(tauri_plugin_single_instance::init(|app, _argv, _cwd| { - panel::show(app); + welcome::reopened(app); })) .plugin(tauri_plugin_opener::init()) .plugin(tauri_plugin_shell::init()) @@ -79,7 +79,10 @@ pub fn run() { } => api.prevent_exit(), tauri::RunEvent::Exit => panel::quit(app), #[cfg(target_os = "macos")] - tauri::RunEvent::Reopen { .. } => panel::show(app), + tauri::RunEvent::Reopen { + has_visible_windows: false, + .. + } => welcome::reopened(app), _ => {} }); } diff --git a/app/src-tauri/src/welcome.rs b/app/src-tauri/src/welcome.rs index 5bedcd1f..bc10acf7 100644 --- a/app/src-tauri/src/welcome.rs +++ b/app/src-tauri/src/welcome.rs @@ -11,6 +11,7 @@ pub const LABEL: &str = "welcome"; pub enum Greeting { Tour { former: bool }, News { versions: Vec }, + Keys, Nothing, } @@ -137,7 +138,7 @@ pub fn open(app: &AppHandle) { Ok(window) => { let handle = app.clone(); window.on_window_event(move |event| { - if matches!(event, tauri::WindowEvent::Destroyed) { + if matches!(event, tauri::WindowEvent::Destroyed) && !only_keys(&handle) { mark(&handle); } }); @@ -147,6 +148,31 @@ pub fn open(app: &AppHandle) { } } +pub fn remembers(greeting: Option<&Greeting>) -> bool { + !matches!(greeting, Some(Greeting::Keys)) +} + +fn only_keys(app: &AppHandle) -> bool { + app.try_state::() + .and_then(|state| state.0.lock().ok().map(|held| !remembers(held.as_ref()))) + .unwrap_or(false) +} + +fn hold(app: &AppHandle, greeting: Greeting) { + if let Some(state) = app.try_state::() + && let Ok(mut held) = state.0.lock() + { + *held = Some(greeting); + } +} + +pub fn reopened(app: &AppHandle) { + if app.get_webview_window(LABEL).is_none() { + hold(app, Greeting::Keys); + } + open(app); +} + #[tauri::command] pub fn greeting(state: tauri::State<'_, Now>) -> Greeting { state @@ -160,11 +186,7 @@ pub fn greeting(state: tauri::State<'_, Now>) -> Greeting { #[tauri::command] pub async fn tour(app: AppHandle) { let wanted = Greeting::Tour { former: false }; - if let Some(state) = app.try_state::() - && let Ok(mut held) = state.0.lock() - { - *held = Some(wanted.clone()); - } + hold(&app, wanted.clone()); if app.get_webview_window(LABEL).is_some() { let _ = app.emit_to(LABEL, "greeting", wanted); } diff --git a/app/src-tauri/src/welcome_test.rs b/app/src-tauri/src/welcome_test.rs index 08227209..27309442 100644 --- a/app/src-tauri/src/welcome_test.rs +++ b/app/src-tauri/src/welcome_test.rs @@ -1,4 +1,4 @@ -use super::{Greeting, behind, decide, told}; +use super::{Greeting, behind, decide, remembers, told}; fn said(all: &[&str]) -> Vec { all.iter().map(|one| (*one).to_owned()).collect() @@ -138,3 +138,21 @@ fn a_build_made_by_hand_never_marks_a_published_version_as_seen() { "the real release still tells what it brings after a build made by hand" ); } + +#[test] +fn opening_it_again_asks_the_window_for_the_shortcut_alone() { + assert_eq!( + serde_json::to_value(Greeting::Keys).expect("it serializes"), + serde_json::json!({ "kind": "keys" }) + ); +} + +#[test] +fn closing_the_shortcut_alone_leaves_the_welcome_as_it_was() { + assert!(!remembers(Some(&Greeting::Keys))); + assert!(remembers(Some(&Greeting::Tour { former: false }))); + assert!(remembers(Some(&Greeting::News { + versions: vec!["3.0.0".to_owned()] + }))); + assert!(remembers(None)); +} diff --git a/app/src/locales.ts b/app/src/locales.ts index 122df475..a76f020b 100644 --- a/app/src/locales.ts +++ b/app/src/locales.ts @@ -202,6 +202,7 @@ const ES = { welcomeTryAgain: "Probar de nuevo", welcomeStep: "Paso {one}", welcomeKeysOver: "1 · El atajo", + welcomeKeysAloneOver: "El atajo", welcomeKeysTitle: "Pruébalo ahora", welcomeKeysWhy: "Desde cualquier app, esta combinación abre tu historial.", welcomeKeysWaiting: "Esperando que lo pruebes…", @@ -479,6 +480,7 @@ const EN: Record = { welcomeTryAgain: "Try again", welcomeStep: "Step {one}", welcomeKeysOver: "1 · The shortcut", + welcomeKeysAloneOver: "The shortcut", welcomeKeysTitle: "Try it now", welcomeKeysWhy: "From any app, this combination opens your history.", welcomeKeysWaiting: "Waiting for you to try it…", diff --git a/app/src/tests/tour.test.tsx b/app/src/tests/tour.test.tsx index b21965a2..40661e90 100644 --- a/app/src/tests/tour.test.tsx +++ b/app/src/tests/tour.test.tsx @@ -230,3 +230,20 @@ describe("las novedades tras una actualización", () => { expect(theWindow.close).toHaveBeenCalled(); }); }); + +describe("abrir la app cuando ya está corriendo", () => { + beforeEach(() => { + vi.clearAllMocks(); + }); + + it("enseña solo el atajo, sin el recorrido, y se cierra con un botón", async () => { + asked.greeting = { kind: "keys" }; + asked.locale = "en"; + render(); + + expect(await screen.findByText("The shortcut")).toBeInTheDocument(); + expect(screen.queryByText("1 · The shortcut")).toBeNull(); + await press("Close"); + expect(theWindow.close).toHaveBeenCalled(); + }); +}); diff --git a/app/src/ui/Welcome.tsx b/app/src/ui/Welcome.tsx index 023ff281..62c7b9ff 100644 --- a/app/src/ui/Welcome.tsx +++ b/app/src/ui/Welcome.tsx @@ -13,6 +13,7 @@ const RELEASES = "https://github.com/rgdevment/CopyPaste/releases"; export type Greeting = | { kind: "tour"; former: boolean } | { kind: "news"; versions: string[] } + | { kind: "keys" } | { kind: "nothing" }; type Step = "former" | "hello" | "trust" | "keys" | "where" | "use"; @@ -92,6 +93,9 @@ export default function Welcome() { )} {kept && greeting?.kind === "news" && } + {kept && greeting?.kind === "keys" && ( + + )} ); } @@ -244,14 +248,18 @@ function TryIt({ mac, dots, next, + alone = false, }: { kept: Kept; change: (what: Partial) => Promise; mac: boolean; dots: ReactNode; next: () => void; + alone?: boolean; }) { const { keys, spare, recheck } = useKeys(kept.shortcut); + const over = alone ? t("welcomeKeysAloneOver") : t("welcomeKeysOver"); + const skip = alone ? t("chromeClose") : t("welcomeSkipStep"); const [tried, setTried] = useState(false); useEffect(() => { @@ -266,9 +274,9 @@ function TryIt({ if (taken) { return ( - } right={null}> + } right={null}> 0 ? "welcomeKeysTakenWhy" : "welcomeKeysTakenAlone", shown)} /> @@ -297,16 +305,14 @@ function TryIt({ tried ? ( setTried(false)} /> ) : ( - + ) } - right={tried ? : null} + right={ + tried ? : null + } > - +
{caps(kept.shortcut, mac).map((one, index) => (