Repository navigation
Settings: Mac layout for General, Notifications, Advanced and About #816
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+2,286
−833
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
4292429
Add quota notification setting, adaptive refresh default and build date
Finesssee 798f215
Add Mac settings pane strings for all locales
Finesssee 5ee879e
Add grouped settings controls: switch, menu select, SettingsGroup
Finesssee b5dde12
Move General, Notifications, Advanced and About to the Mac layout
Finesssee a101fdc
Left-align About groups and style threshold override inputs
Finesssee 0e04fd8
Read the build date with option_env so a reused build script cannot b…
Finesssee 327f83a
Keep Tab focus inside the switcher shortcuts dialog
Finesssee 5b34472
Say the Claude keychain-prompt option is not enforced on Windows yet
Finesssee 5f2b59e
Merge remote-tracking branch 'origin/main' into feat/mac-settings-app…
Finesssee 44aed4d
Merge remote-tracking branch 'origin/main' into feat/mac-settings-app…
Finesssee 1152cab
Show global shortcut register and clear errors instead of saving
Finesssee a8a07e7
Assert the rendered About build date
Finesssee 247cd09
Refresh the About build date when shell or core sources change
Finesssee fd17786
Say the Providers Claude keychain-prompt option is not enforced on Wi…
Finesssee ec7bd73
Merge branch 'main' into feat/mac-settings-app-panes
Finesssee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,44 @@ | ||
| use std::time::{SystemTime, UNIX_EPOCH}; | ||
|
|
||
| fn main() { | ||
| emit_build_date(); | ||
| tauri_build::build() | ||
| } | ||
|
|
||
| /// Expose the UTC build date as `CODEXBAR_BUILD_DATE` (YYYY-MM-DD) for the | ||
| /// About pane. `SOURCE_DATE_EPOCH` pins it for reproducible builds. | ||
| /// | ||
| /// `tauri_build` registers its own rerun triggers, so Cargo would otherwise | ||
| /// keep this script's first date across later incremental builds. Rerunning | ||
| /// when the shell or `codexbar` sources change keeps the date current; those | ||
| /// changes recompile this crate anyway. | ||
| fn emit_build_date() { | ||
| println!("cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH"); | ||
| println!("cargo:rerun-if-changed=src"); | ||
| println!("cargo:rerun-if-changed=../../../rust/src"); | ||
| let seconds = std::env::var("SOURCE_DATE_EPOCH") | ||
| .ok() | ||
| .and_then(|value| value.trim().parse::<u64>().ok()) | ||
| .unwrap_or_else(|| { | ||
| SystemTime::now() | ||
| .duration_since(UNIX_EPOCH) | ||
| .map(|elapsed| elapsed.as_secs()) | ||
| .unwrap_or(0) | ||
| }); | ||
| let (year, month, day) = civil_from_days(seconds / 86_400); | ||
| println!("cargo:rustc-env=CODEXBAR_BUILD_DATE={year:04}-{month:02}-{day:02}"); | ||
| } | ||
|
|
||
| /// Days since 1970-01-01 to a proleptic Gregorian date (Howard Hinnant's algorithm). | ||
| fn civil_from_days(days: u64) -> (u64, u64, u64) { | ||
| let z = days + 719_468; | ||
| let era = z / 146_097; | ||
| let doe = z - era * 146_097; | ||
| let yoe = (doe - doe / 1_460 + doe / 36_524 - doe / 146_096) / 365; | ||
| let doy = doe - (365 * yoe + yoe / 4 - yoe / 100); | ||
| let mp = (5 * doy + 2) / 153; | ||
| let day = doy - (153 * mp + 2) / 5 + 1; | ||
| let month = if mp < 10 { mp + 3 } else { mp - 9 }; | ||
| let year = yoe + era * 400 + u64::from(month <= 2); | ||
| (year, month, day) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
93 changes: 93 additions & 0 deletions
93
apps/desktop-tauri/src/surfaces/settings/SwitcherShortcutsDialog.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,93 @@ | ||
| import { fireEvent, render, screen } from "@testing-library/react"; | ||
| import { describe, expect, it, vi } from "vitest"; | ||
|
|
||
| vi.mock("../../hooks/useLocale", () => ({ | ||
| useLocale: () => ({ t: (key: string) => key, language: "english" }), | ||
| })); | ||
|
|
||
| import SwitcherShortcutsDialog from "./SwitcherShortcutsDialog"; | ||
| import type { SettingsSnapshot } from "../../types/bridge"; | ||
|
|
||
| function renderDialog(onClose = vi.fn(), set = vi.fn()) { | ||
| const opener = document.createElement("button"); | ||
| document.body.appendChild(opener); | ||
| opener.focus(); | ||
| const view = render( | ||
| <SwitcherShortcutsDialog | ||
| settings={{ switcherShortcuts: { next: "ctrl+alt+2" } } as unknown as SettingsSnapshot} | ||
| set={set as never} | ||
| saving={false} | ||
| onClose={onClose} | ||
| />, | ||
| ); | ||
| return { ...view, opener, onClose, set }; | ||
| } | ||
|
|
||
| describe("SwitcherShortcutsDialog", () => { | ||
| it("is a labelled modal dialog that takes focus and returns it on close", () => { | ||
| const { opener, unmount } = renderDialog(); | ||
| const dialog = screen.getByRole("dialog", { name: "SwitcherShortcutsTitle" }); | ||
| expect(dialog).toHaveAttribute("aria-modal", "true"); | ||
| expect(dialog).toHaveFocus(); | ||
|
|
||
| unmount(); | ||
| expect(opener).toHaveFocus(); | ||
| opener.remove(); | ||
| }); | ||
|
|
||
| it("keeps Tab and Shift+Tab inside the sheet", () => { | ||
| const { onClose, opener } = renderDialog(); | ||
| const dialog = screen.getByRole("dialog"); | ||
| const done = screen.getByRole("button", { name: "DialogDone" }); | ||
| const firstRecord = screen.getByRole("button", { | ||
| name: "SwitcherShortcutPrevious: ShortcutRecordButton", | ||
| }); | ||
|
|
||
| // Tab from the last control wraps to the first one. | ||
| done.focus(); | ||
| fireEvent.keyDown(done, { key: "Tab" }); | ||
| expect(firstRecord).toHaveFocus(); | ||
|
|
||
| // Shift+Tab from the first control wraps to Done. | ||
| fireEvent.keyDown(firstRecord, { key: "Tab", shiftKey: true }); | ||
| expect(done).toHaveFocus(); | ||
|
|
||
| // From the sheet itself (focus on open), Shift+Tab lands on Done and Tab on the first control. | ||
| dialog.focus(); | ||
| fireEvent.keyDown(dialog, { key: "Tab", shiftKey: true }); | ||
| expect(done).toHaveFocus(); | ||
| dialog.focus(); | ||
| fireEvent.keyDown(dialog, { key: "Tab" }); | ||
| expect(firstRecord).toHaveFocus(); | ||
|
|
||
| // A Tab between two inner controls is left to the browser. | ||
| const event = new KeyboardEvent("keydown", { key: "Tab", bubbles: true, cancelable: true }); | ||
| firstRecord.dispatchEvent(event); | ||
| expect(event.defaultPrevented).toBe(false); | ||
| expect(onClose).not.toHaveBeenCalled(); | ||
| opener.remove(); | ||
| }); | ||
|
|
||
| it("closes on Escape, on Done and on a backdrop click", () => { | ||
| const { onClose, container, opener } = renderDialog(); | ||
| fireEvent.keyDown(screen.getByRole("dialog"), { key: "Escape" }); | ||
| fireEvent.click(screen.getByRole("button", { name: "DialogDone" })); | ||
| fireEvent.mouseDown(container.querySelector(".settings-dialog-backdrop") as Element); | ||
| expect(onClose).toHaveBeenCalledTimes(3); | ||
| opener.remove(); | ||
| }); | ||
|
|
||
| it("does not close when the press starts inside the sheet", () => { | ||
| const { onClose, opener } = renderDialog(); | ||
| fireEvent.mouseDown(screen.getByRole("dialog")); | ||
| expect(onClose).not.toHaveBeenCalled(); | ||
| opener.remove(); | ||
| }); | ||
|
|
||
| it("restores defaults through the section's Restore Defaults button", () => { | ||
| const { set, opener } = renderDialog(); | ||
| fireEvent.click(screen.getByRole("button", { name: "SwitcherShortcutReset" })); | ||
| expect(set).toHaveBeenCalledWith({ switcherShortcuts: {} }); | ||
| opener.remove(); | ||
| }); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.