Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions site/src/content/docs/account-and-privacy.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ description: Optional sign-in that carries your settings between computers, auto

## Running in the background

Switchify PC lives in the system tray on Windows or the menu bar on a Mac, with live connection status. From there you can show the window, open Settings and the Switch Forwarding profiles, disconnect devices, release the switch keys, or quit. **Start with system** launches it quietly when you sign in.
Switchify PC lives in the system tray on Windows or the menu bar on a Mac, with live connection status. From there you can show the window, open Settings and the Switch Forwarding profiles, disconnect devices, pause listening for switch keys, or quit. **Start with system** launches it quietly when you sign in.

**Release switch keys** hands your switch keys back to other apps until you choose **Resume switch keys**. See [Use the switch key as a normal key](/get-started/add-a-switch/#use-the-switch-key-as-a-normal-key).
**Pause listening** hands your switch keys back to other apps until you choose **Resume listening**. See [Use the switch key as a normal key](/get-started/add-a-switch/#use-the-switch-key-as-a-normal-key).

## Account

Expand Down
4 changes: 2 additions & 2 deletions site/src/content/docs/get-started/add-a-switch.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ Press **Escape**, or hold any switch for at least 4 seconds (longer if that swit

## Use the switch key as a normal key

While a Select switch is saved, Switchify PC takes its key everywhere, so a switch set to Space cannot type a space in other apps. To hand the keys back for a while, choose **Release switch keys** in the system tray on Windows or the menu bar on a Mac, or on the Home page under Saved switches. Your switches then do nothing in Switchify PC and the keys work as they normally would.
While a Select switch is saved, Switchify PC takes its key everywhere, so a switch set to Space cannot type a space in other apps. To hand the keys back for a while, choose **Pause listening** in the system tray on Windows or the menu bar on a Mac, or on the Home page under Saved switches. Your switches then do nothing in Switchify PC and the keys work as they normally would.

Choose **Resume switch keys** in the same places to take them back. Home shows **Keys released** under Saved switches while they are, and testing local switches waits until you resume. The release lasts until you resume or restart Switchify PC, so the switches are always ready after a restart. Switchify on Android is not affected: a remote scanning session carries on, and the release takes effect on the computer's own keys once it ends.
Choose **Resume listening** in the same places to take them back. Home shows **Listening paused** under Saved switches while listening is paused, and testing local switches waits until you resume. The pause lasts until you resume or restart Switchify PC, so the switches are always ready after a restart. Switchify on Android is not affected: a remote scanning session carries on, and the pause takes effect on the computer's own keys once it ends.

## On Windows

Expand Down
4 changes: 2 additions & 2 deletions site/src/content/docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ Holding any switch for about 4 seconds is the emergency stop; so is Escape. Pres

When the computer goes to sleep, Switchify PC releases the switch keys and shows **Switches paused while the computer sleeps**. After it wakes, scanning starts again on its own within a few seconds; press Select to begin. If the switches stay quiet after wake, release them, wait a moment and press Select once more, or restart Switchify PC. Sleep also ends a session forwarded from your phone; start forwarding again once the computer is awake.

If Home shows **Keys released** under Saved switches, someone chose **Release switch keys** in the tray or menu bar. Choose **Resume switch keys** there or on Home, or restart Switchify PC.
If Home shows **Listening paused** under Saved switches, someone chose **Pause listening** in the tray or menu bar. Choose **Resume listening** there or on Home, or restart Switchify PC.

## My switch key no longer types in other apps

That is expected while a Select switch is saved: Switchify PC takes the key everywhere. Choose **Release switch keys** in the tray or menu bar to use it as a normal key for a while, then **Resume switch keys** when you are done. See [Use the switch key as a normal key](/get-started/add-a-switch/#use-the-switch-key-as-a-normal-key).
That is expected while a Select switch is saved: Switchify PC takes the key everywhere. Choose **Pause listening** in the tray or menu bar to use it as a normal key for a while, then **Resume listening** when you are done. See [Use the switch key as a normal key](/get-started/add-a-switch/#use-the-switch-key-as-a-normal-key).

## Input access on a Mac

Expand Down
28 changes: 14 additions & 14 deletions src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,8 @@ struct TraySnapshot {
release_label: String,
}

const RELEASE_SWITCH_KEYS_LABEL: &str = "Release switch keys";
const RESUME_SWITCH_KEYS_LABEL: &str = "Resume switch keys";
const RELEASE_SWITCH_KEYS_LABEL: &str = "Pause listening";
const RESUME_SWITCH_KEYS_LABEL: &str = "Resume listening";

impl TraySnapshot {
fn from_state(state: &AppState) -> Self {
Expand Down Expand Up @@ -307,9 +307,9 @@ fn set_switch_keys_released_inner(app: &AppHandle, model: &AppModel, released: b
&model.shared,
ActivityKind::Info,
if released {
"Switch keys released. They work as normal keys until you resume."
"Listening paused. Your switch keys work as normal keys until you resume."
} else {
"Switch keys resumed."
"Listening resumed."
},
);
state::emit_state(app, &model.shared);
Expand Down Expand Up @@ -2237,7 +2237,7 @@ mod tests {
TraySnapshot {
status: "Status: Starting Bluetooth".into(),
can_disconnect: false,
release_label: "Release switch keys".into(),
release_label: "Pause listening".into(),
}
);

Expand All @@ -2250,7 +2250,7 @@ mod tests {
TraySnapshot {
status: "Status: Ready to connect".into(),
can_disconnect: false,
release_label: "Release switch keys".into(),
release_label: "Pause listening".into(),
}
);

Expand All @@ -2264,7 +2264,7 @@ mod tests {
TraySnapshot {
status: "Status: Connected to Pixel".into(),
can_disconnect: true,
release_label: "Release switch keys".into(),
release_label: "Pause listening".into(),
}
);

Expand All @@ -2277,7 +2277,7 @@ mod tests {
TraySnapshot {
status: "Status: Connected to Pixel".into(),
can_disconnect: true,
release_label: "Resume switch keys".into(),
release_label: "Resume listening".into(),
}
);
let _ = std::fs::remove_dir_all(root);
Expand All @@ -2288,7 +2288,7 @@ mod tests {
let snapshot = |status: &str, can_disconnect| TraySnapshot {
status: status.into(),
can_disconnect,
release_label: "Release switch keys".into(),
release_label: "Pause listening".into(),
};
let cache = TrayCache::default();
// Records the setter calls made for one sync; `fail` makes them error.
Expand All @@ -2315,7 +2315,7 @@ mod tests {
[
"text Status: Ready to connect",
"enabled false",
"release Release switch keys"
"release Pause listening"
]
);
assert!(sync(snapshot("Status: Ready to connect", false), false).is_empty());
Expand All @@ -2330,12 +2330,12 @@ mod tests {
assert_eq!(
sync(
TraySnapshot {
release_label: "Resume switch keys".into(),
release_label: "Resume listening".into(),
..snapshot("Status: Connected to Pixel", true)
},
false
),
["release Resume switch keys"]
["release Resume listening"]
);
}

Expand All @@ -2344,7 +2344,7 @@ mod tests {
let snapshot = TraySnapshot {
status: "Status: Bluetooth is off".into(),
can_disconnect: true,
release_label: "Release switch keys".into(),
release_label: "Pause listening".into(),
};
let cache = TrayCache::default();
let attempts = std::cell::Cell::new(0);
Expand All @@ -2362,7 +2362,7 @@ mod tests {
TrayShown {
status: None,
can_disconnect: Some(true),
release_label: Some("Release switch keys".into()),
release_label: Some("Pause listening".into()),
}
);
cache.apply(
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/scanning_runtime.rs
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ struct ScanService {
struct SwitchKeysRelease(AtomicBool);
/// Shown on Home while the keys are released; it names where to resume.
pub const SWITCH_KEYS_RELEASED_MESSAGE: &str =
"Switch keys released. Resume them from the tray or menu bar, or on Home.";
"Listening paused. Resume listening from the tray or menu bar, or on Home.";
pub fn switch_keys_released(app: &AppHandle) -> bool {
app.try_state::<SwitchKeysRelease>()
.is_some_and(|flag| flag.0.load(Ordering::SeqCst))
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/src/switch_practice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ pub fn begin(app: &AppHandle, remote: bool) -> Result<View, String> {
// Practice enables the key broker itself, so honour the release here
// as `wanted` does for scanning.
if crate::scanning_runtime::switch_keys_released(app) {
return Err("Resume the switch keys before testing switches.".into());
return Err("Resume listening before testing switches.".into());
}
(switches.settings(), 0)
};
Expand Down
10 changes: 5 additions & 5 deletions src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ describe("Switchify PC shell", () => {
const release = vi.spyOn(api, "setSwitchKeysReleased");
render(<App />);
await screen.findByRole("heading", { name: "Ready" });
fireEvent.click(screen.getByRole("button", { name: "Release switch keys" }));
fireEvent.click(screen.getByRole("button", { name: "Pause listening" }));
expect(release).toHaveBeenCalledWith(true);
await screen.findByRole("heading", { name: "Switch keys released" });
expect(screen.getByText("1 saved · Keys released")).toBeInTheDocument();
await screen.findByRole("heading", { name: "Listening paused" });
expect(screen.getByText("1 saved · Listening paused")).toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Edit switches" })).not.toBeInTheDocument();
expect(screen.getAllByRole("button", { name: "Resume switch keys" })).toHaveLength(2);
fireEvent.click(screen.getAllByRole("button", { name: "Resume switch keys" })[0]);
expect(screen.getAllByRole("button", { name: "Resume listening" })).toHaveLength(2);
fireEvent.click(screen.getAllByRole("button", { name: "Resume listening" })[0]);
expect(release).toHaveBeenLastCalledWith(false);
await screen.findByRole("heading", { name: "Ready" });
expect(screen.getByRole("button", { name: "Edit switches" })).toBeInTheDocument();
Expand Down
4 changes: 2 additions & 2 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -108,12 +108,12 @@ function HomeView({ state, switches, scanning, navigate, onDisconnect, onAccessi
<StatusIcon ok={ready ? true : tone === "attention" ? false : undefined}><Keyboard size={26} /></StatusIcon>
<div><h2 id="home-status-title">{title}</h2><p role="status">{message}</p></div>
{released
? <Button className="primary" onClick={() => onReleaseSwitchKeys(false)}>Resume switch keys</Button>
? <Button className="primary" onClick={() => onReleaseSwitchKeys(false)}>Resume listening</Button>
: <Button className={ready ? "secondary" : "primary"} onClick={() => navigate("switches")}>{hasSelect ? "Edit switches" : "Set up switches"}</Button>}
</section>
<section className="status-list" aria-label="Switch control status">
<article><StatusIcon ok={state.accessibility === "granted"}><Accessibility size={19} /></StatusIcon><div><h3>Input access</h3><AccessibilityCopy state={state} /></div>{state.accessibility === "required" && <Button className="text-button" onClick={onAccessibility}>Open Accessibility Settings</Button>}</article>
<article><StatusIcon ok={released ? undefined : hasSelect}><Keyboard size={19} /></StatusIcon><div><h3>Saved switches</h3><p>{saved.length} saved · {released ? "Keys released" : hasSelect ? "Select assigned" : "Select action needed"}</p></div>{saved.length > 0 && <Button className="text-button" onClick={() => onReleaseSwitchKeys(!released)}>{released ? "Resume switch keys" : "Release switch keys"}</Button>}</article>
<article><StatusIcon ok={released ? undefined : hasSelect}><Keyboard size={19} /></StatusIcon><div><h3>Saved switches</h3><p>{saved.length} saved · {released ? "Listening paused" : hasSelect ? "Select assigned" : "Select action needed"}</p></div>{saved.length > 0 && <Button className="text-button" onClick={() => onReleaseSwitchKeys(!released)}>{released ? "Resume listening" : "Pause listening"}</Button>}</article>
<article><StatusIcon><SlidersHorizontal size={19} /></StatusIcon><div><h3>Scanning</h3><p>{selectOpensHome(scanning.config) ? "Select opens Home" : `Select starts ${lastModeName(scanning.config)}`} · {areaOptions(scanning.config, scanning.config.controlMode).automatic ? "Automatic" : "Manual"}</p></div><Button className="text-button" onClick={() => navigate("scanning")}>Change scanning</Button></article>
<article><StatusIcon ok={mobileConnected || undefined}><Smartphone size={19} /></StatusIcon><div><h3>Mobile connection (optional)</h3><p>{mobileConnected ? state.connectedDeviceName ?? bluetoothLabels.connected : bluetoothLabels[state.bluetooth]}</p></div>{mobileConnected ? <Button className="secondary" onClick={onDisconnect}>Disconnect</Button> : <Button className="text-button" onClick={() => navigate("mobile")}>Connect mobile</Button>}</article>
</section>
Expand Down
2 changes: 1 addition & 1 deletion src/homeStatus.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ describe("homeStatus", () => {
["Remote in control when otherwise ready", { scanning: { ...scanning, remote: true } }, "Remote in control", "neutral"],
["Remote in control without a local Select", { scanning: { ...scanning, remote: true }, bluetooth: "connected", hasSelect: false }, "Remote in control", "neutral"],
["a mobile connection without a local Select", { bluetooth: "connected", hasSelect: false }, "Paused for mobile", "neutral"],
["released switch keys", { switchKeysReleased: true, scanning: { ...scanning, enabled: false } }, "Switch keys released", "neutral"],
["released switch keys", { switchKeysReleased: true, scanning: { ...scanning, enabled: false } }, "Listening paused", "neutral"],
["Remote in control while the keys are released", { switchKeysReleased: true, scanning: { ...scanning, remote: true } }, "Remote in control", "neutral"],
["no Select switch", { hasSelect: false }, "Finish setting up", "attention"],
["paused", { scanning: { ...scanning, paused: true } }, "Paused", "neutral"],
Expand Down
2 changes: 1 addition & 1 deletion src/homeStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function homeStatus({ accessibility, bluetooth, switchesLoaded, hasSelect
if (!scanning.supported) return { title: "Switch control unavailable", tone: "neutral", message: scanning.message };
if (scanning.remote) return { title: "Remote in control", tone: "neutral", message: "Remote controls scanning. Use the switches in Remote; PC Escape stops the session." };
if (bluetooth === "connected") return { title: "Paused for mobile", tone: "neutral", message: "Local scanning is paused while a mobile device is connected." };
if (switchKeysReleased) return { title: "Switch keys released", tone: "neutral", message: "Your switch keys work as normal keys in other apps. Resume them to scan again." };
if (switchKeysReleased) return { title: "Listening paused", tone: "neutral", message: "Your switch keys work as normal keys in other apps. Choose Resume listening to scan again." };
if (!switchesLoaded) return { title: "Switch control", tone: "neutral", message: "Loading switch control..." };
if (!hasSelect) return { title: "Finish setting up", tone: "attention", message: "Add a switch with the Select action to begin scanning." };
if (scanning.paused) return { title: "Paused", tone: "neutral", message: "Scanning is paused. Use your Pause / resume switch to continue." };
Expand Down
Loading