Skip to content

Commit

Permalink
Single instance, fix titlebars, better Windows support (#169)
Browse files Browse the repository at this point in the history
* adjust editor titlebar height, and radius incosistency in prev-recordings items

* Open in Explorer, skip taskbar for prev-recordings

* Add single-instance plugin, try to not open terminal when rendering in release mode

* Don't show startup permissions screen on Windows

* Adjust traffic lights position on Editor

* Actually stop the terminal opening when rendering on Windows

* Hide macOS specific setting on Windows

* Add installer banners

* Fix nsis and wix banners

* Cleanup for PR

* Adjust nsis banners and add installer icon.
  • Loading branch information
ItsEeleeya authored Nov 17, 2024
1 parent 8649b7b commit e488c9a
Show file tree
Hide file tree
Showing 15 changed files with 200 additions and 157 deletions.
16 changes: 16 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions apps/desktop/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ tauri-plugin-updater = "2.0.0"
tauri-plugin-notification = "2.0.0-rc"
tauri-plugin-oauth = { git = "https://github.com/FabianLars/tauri-plugin-oauth", branch = "v2" }
tauri-plugin-global-shortcut = "2.0.0"
tauri-plugin-single-instance = "2.0.1"
tauri-specta = { version = "=2.0.0-rc.20", features = ["derive", "typescript"] }

serde = { version = "1", features = ["derive"] }
Expand Down
Binary file added apps/desktop/src-tauri/assets/nsis-header.bmp
Binary file not shown.
Binary file added apps/desktop/src-tauri/assets/nsis-sidebar.bmp
Binary file not shown.
Binary file added apps/desktop/src-tauri/assets/wix-banner.bmp
Binary file not shown.
16 changes: 4 additions & 12 deletions apps/desktop/src-tauri/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,7 +949,7 @@ async fn copy_screenshot_to_clipboard(app: AppHandle, path: PathBuf) -> Result<(

#[tauri::command]
#[specta::specta]
async fn open_file_path(app: AppHandle, path: PathBuf) -> Result<(), String> {
async fn open_file_path(_app: AppHandle, path: PathBuf) -> Result<(), String> {
let path_str = path.to_str().ok_or("Invalid path")?;

#[cfg(target_os = "windows")]
Expand Down Expand Up @@ -1693,16 +1693,6 @@ async fn set_project_config(app: AppHandle, video_id: String, config: ProjectCon
editor_instance.project_config.0.send(config).ok();
}

#[tauri::command(async)]
#[specta::specta]
fn open_in_finder(path: PathBuf) {
Command::new("open")
.arg("-R")
.arg(path)
.spawn()
.expect("Failed to open in Finder");
}

#[tauri::command]
#[specta::specta]
async fn list_audio_devices() -> Result<Vec<String>, ()> {
Expand Down Expand Up @@ -2441,7 +2431,6 @@ pub async fn run() {
start_playback,
stop_playback,
set_playhead_position,
open_in_finder,
set_project_config,
open_editor,
open_main_window,
Expand Down Expand Up @@ -2519,6 +2508,9 @@ pub async fn run() {
}

builder
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
let _ = CapWindow::Main.show(&app);
}))
.plugin(tauri_plugin_shell::init())
.plugin(tauri_plugin_dialog::init())
.plugin(tauri_plugin_store::Builder::new().build())
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop/src-tauri/src/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl CapWindowId {
pub fn traffic_lights_position(&self) -> Option<Option<LogicalPosition<f64>>> {
match self {
Self::Camera | Self::WindowCaptureOccluder | Self::PrevRecordings => None,
Self::Editor { .. } => Some(Some(LogicalPosition::new(20.0, 48.0))),
Self::Editor { .. } => Some(Some(LogicalPosition::new(20.0, 40.5))),
Self::InProgressRecording => Some(Some(LogicalPosition::new(-100.0, -100.0))),
_ => Some(None),
}
Expand Down Expand Up @@ -263,6 +263,7 @@ impl CapWindow {
)
.visible(false)
.theme(Some(tauri::Theme::Dark))
.skip_taskbar(true)
.build()?
}
Self::PrevRecordings => {
Expand Down
10 changes: 10 additions & 0 deletions apps/desktop/src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@
"y": 140
}
}
},
"windows": {
"nsis": {
"headerImage": "assets/nsis-header.bmp",
"sidebarImage": "assets/nsis-sidebar.bmp",
"installerIcon": "icons/icon.ico"
},
"wix": {
"bannerPath": "assets/wix-banner.bmp"
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { cx } from "cva";
export default function (props: ComponentProps<"div">) {
const [local, otherProps] = splitProps(props, ["class"]);
const window = getCurrentWindow();

return (
<div
class={`h-full align-baseline select-none *:outline-none *:transition-all *:duration-200 ${local.class}`}
Expand All @@ -21,7 +21,7 @@ export default function (props: ComponentProps<"div">) {
? "text-black/90 dark:text-white"
: "text-gray-50 dark:text-white",
titlebarState.minimizable
? "hover:bg-[#0000000D] active:bg-[#00000008] dark:hover:bg-[#FFFFFF1A] dark:active:bg-[#FFFFFF0D]"
? "hover:bg-[#0000000D] active:bg-[#00000008]"
: "[&>*]:opacity-30"
)}
>
Expand All @@ -42,7 +42,7 @@ export default function (props: ComponentProps<"div">) {
? "text-black/90 dark:text-white"
: "text-gray-50 dark:text-white",
titlebarState.maximizable
? "hover:bg-[#0000000D] active:bg-[#00000008] dark:hover:bg-[#FFFFFF1A] dark:active:bg-[#FFFFFF0D]"
? "hover:bg-[#0000000D] active:bg-[#00000008]"
: "[&>*]:opacity-30"
)}
>
Expand Down
165 changes: 85 additions & 80 deletions apps/desktop/src/routes/(window-chrome)/settings/general.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,54 @@ import {
isPermissionGranted,
requestPermission,
} from "@tauri-apps/plugin-notification";
import { OsType, Platform, type } from "@tauri-apps/plugin-os";

const settingsList = [
{
key: "uploadIndividualFiles",
label: "Upload individual recording files when creating shareable link",
description:
'Warning: this will cause shareable link uploads to become significantly slower, since all individual recording files will be uploaded. Shows "Download Assets" button in Share page.',
},
{
key: "openEditorAfterRecording",
label: "Open editor automatically after recording stops",
description:
"The editor will be shown immediately after you finish recording.",
},
{
key: "hideDockIcon",
label: "Hide dock icon",
description:
"The dock icon will be hidden when there are no windows available to close.",
},
{
key: "autoCreateShareableLink",
label: "Cap Pro: Automatically create shareable link after recording",
description:
"When enabled, a shareable link will be created automatically after stopping the recording. You'll be redirected to the URL while the upload continues in the background.",
},
{
key: "disableAutoOpenLinks",
label: "Cap Pro: Disable automatic link opening",
description:
"When enabled, Cap will not automatically open links in your browser (e.g. after creating a shareable link).",
},
{
key: "enableNotifications",
label: "Enable System Notifications",
description:
"Show system notifications for events like copying to clipboard, saving files, and more. You may need to manually allow Cap access via your system's notification settings.",
requiresPermission: true,
},
] satisfies Array<{
const settingsList: Array<{
key: keyof GeneralSettingsStore;
label: string;
description: string;
platforms?: OsType[],
requiresPermission?: boolean;
}>;
}> = [
{
key: "uploadIndividualFiles",
label: "Upload individual recording files when creating shareable link",
description:
'Warning: this will cause shareable link uploads to become significantly slower, since all individual recording files will be uploaded. Shows "Download Assets" button in Share page.',
},
{
key: "openEditorAfterRecording",
label: "Open editor automatically after recording stops",
description:
"The editor will be shown immediately after you finish recording.",
},
{
key: "hideDockIcon",
label: "Hide dock icon",
platforms: ["macos"],
description:
"The dock icon will be hidden when there are no windows available to close.",
},
{
key: "autoCreateShareableLink",
label: "Cap Pro: Automatically create shareable link after recording",
description:
"When enabled, a shareable link will be created automatically after stopping the recording. You'll be redirected to the URL while the upload continues in the background.",
},
{
key: "disableAutoOpenLinks",
label: "Cap Pro: Disable automatic link opening",
description:
"When enabled, Cap will not automatically open links in your browser (e.g. after creating a shareable link).",
},
{
key: "enableNotifications",
label: "Enable System Notifications",
description:
"Show system notifications for events like copying to clipboard, saving files, and more. You may need to manually allow Cap access via your system's notification settings.",
requiresPermission: true,
},
];

export default function GeneralSettings() {
const [store] = createResource(() => generalSettingsStore.get());
Expand Down Expand Up @@ -101,61 +104,63 @@ function Inner(props: { initialStore: GeneralSettingsStore | null }) {
generalSettingsStore.set({ [key]: value });
};

const ostype: OsType = type();

return (
<div class="flex flex-col w-full h-full">
<div class="flex-1 overflow-y-auto">
<div class="p-4 space-y-2 divide-y divide-gray-200">
<For each={settingsList}>
{(setting) => (
<div class="space-y-2 py-3">
<div class="flex items-center justify-between">
<p>{setting.label}</p>
<button
type="button"
role="switch"
aria-checked={
settings[setting.key as keyof GeneralSettingsStore]
}
data-state={
settings[setting.key as keyof GeneralSettingsStore]
? "checked"
: "unchecked"
}
value={
settings[setting.key as keyof GeneralSettingsStore]
? "on"
: "off"
}
class={`peer inline-flex h-4 w-8 shrink-0 cursor-pointer items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 ${
settings[setting.key as keyof GeneralSettingsStore]
? "bg-blue-400 border-blue-400"
: "bg-gray-300 border-gray-300"
}`}
onClick={() =>
handleChange(
setting.key,
!settings[setting.key as keyof GeneralSettingsStore]
)
}
>
<span
<Show when={!setting.platforms || setting.platforms.includes(ostype)}>
<div class="space-y-2 py-3">
<div class="flex items-center justify-between">
<p>{setting.label}</p>
<button
type="button"
role="switch"
aria-checked={
settings[setting.key as keyof GeneralSettingsStore]
}
data-state={
settings[setting.key as keyof GeneralSettingsStore]
? "checked"
: "unchecked"
}
class={`pointer-events-none block h-4 w-4 rounded-full bg-gray-50 shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0 border-2 ${
value={
settings[setting.key as keyof GeneralSettingsStore]
? "on"
: "off"
}
class={`peer inline-flex h-4 w-8 shrink-0 cursor-pointer items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 ${settings[setting.key as keyof GeneralSettingsStore]
? "bg-blue-400 border-blue-400"
: "bg-gray-300 border-gray-300"
}`}
onClick={() =>
handleChange(
setting.key,
!settings[setting.key as keyof GeneralSettingsStore]
)
}
>
<span
data-state={
settings[setting.key as keyof GeneralSettingsStore]
? "checked"
: "unchecked"
}
class={`pointer-events-none block h-4 w-4 rounded-full bg-gray-50 shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0 border-2 ${settings[setting.key as keyof GeneralSettingsStore]
? "border-blue-400"
: "border-gray-300"
}`}
/>
</button>
}`}
/>
</button>
</div>
{setting.description && (
<p class="text-xs text-gray-400">{setting.description}</p>
)}
</div>
{setting.description && (
<p class="text-xs text-gray-400">{setting.description}</p>
)}
</div>
</Show>
)}
</For>
</div>
Expand Down
Loading

1 comment on commit e488c9a

@vercel
Copy link

@vercel vercel bot commented on e488c9a Nov 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.