Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 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
11 changes: 11 additions & 0 deletions apps/desktop/src-tauri/src/general_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ pub enum MainWindowRecordingStartBehaviour {
Minimise,
}

#[derive(Default, Serialize, Deserialize, Type, Debug, Clone, Copy)]
#[serde(rename_all = "camelCase")]
pub enum PostDeletionBehaviour {
#[default]
Exit,
ReopenRecordingWindow,
}

impl MainWindowRecordingStartBehaviour {
pub fn perform(&self, window: &tauri::WebviewWindow) -> tauri::Result<()> {
match self {
Expand Down Expand Up @@ -79,6 +87,8 @@ pub struct GeneralSettingsStore {
pub enable_native_camera_preview: bool,
#[serde(default)]
pub auto_zoom_on_clicks: bool,
#[serde(default)]
pub post_deletion_behaviour: PostDeletionBehaviour,
}

fn default_server_url() -> String {
Expand Down Expand Up @@ -119,6 +129,7 @@ impl Default for GeneralSettingsStore {
_open_editor_after_recording: false,
enable_native_camera_preview: false,
auto_zoom_on_clicks: false,
post_deletion_behaviour: PostDeletionBehaviour::Exit,
}
}
}
Expand Down
24 changes: 23 additions & 1 deletion apps/desktop/src-tauri/src/recording.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
audio::AppSounds,
auth::AuthStore,
create_screenshot,
general_settings::{GeneralSettingsStore, PostStudioRecordingBehaviour},
general_settings::{GeneralSettingsStore, PostDeletionBehaviour, PostStudioRecordingBehaviour},
open_external_link,
presets::PresetsStore,
upload::{
Expand Down Expand Up @@ -485,6 +485,7 @@ pub async fn start_recording(
// this clears the current recording for us
handle_recording_end(app, None, &mut state).await.ok();
}
// Actor hasn't errored, it's just finished
_ => {}
}
}
Expand Down Expand Up @@ -589,6 +590,27 @@ pub async fn delete_recording(app: AppHandle, state: MutableState<'_, App>) -> R
)
.await;
}

// Check user's post-deletion behavior setting
let settings = GeneralSettingsStore::get(&app)
.ok()
.flatten()
.unwrap_or_default();

if let Some(window) = CapWindowId::InProgressRecording.get(&app) {
let _ = window.close();
}

match settings.post_deletion_behaviour {
PostDeletionBehaviour::Exit => {
if let Some(window) = CapWindowId::Main.get(&app) {
let _ = window.close();
}
}
PostDeletionBehaviour::ReopenRecordingWindow => {
let _ = ShowCapWindow::Main.show(&app).await;
}
}
Comment thread
Brendonovich marked this conversation as resolved.
}

Ok(())
Expand Down
40 changes: 39 additions & 1 deletion apps/desktop/src/routes/(window-chrome)/settings/general.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
type GeneralSettingsStore,
type MainWindowRecordingStartBehaviour,
type PostStudioRecordingBehaviour,
type PostDeletionBehaviour,
} from "~/utils/tauri";
Comment thread
Brendonovich marked this conversation as resolved.
import { CheckMenuItem, Menu } from "@tauri-apps/api/menu";
import { confirm } from "@tauri-apps/plugin-dialog";
Expand Down Expand Up @@ -148,9 +149,13 @@
value:
| MainWindowRecordingStartBehaviour
| PostStudioRecordingBehaviour
| PostDeletionBehaviour
| number;
onChange: (
value: MainWindowRecordingStartBehaviour | PostStudioRecordingBehaviour
value:
| MainWindowRecordingStartBehaviour
| PostStudioRecordingBehaviour
| PostDeletionBehaviour
) => void | Promise<void>;
};

Expand Down Expand Up @@ -249,7 +254,7 @@
get value() {
return settings.recordingCountdown ?? 0;
},
onChange: (

Check failure on line 257 in apps/desktop/src/routes/(window-chrome)/settings/general.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Type '(value: MainWindowRecordingStartBehaviour | PostStudioRecordingBehaviour | number) => Promise<void>' is not assignable to type '((value: boolean) => void | Promise<void>) | ((value: PostStudioRecordingBehaviour | MainWindowRecordingStartBehaviour | PostDeletionBehaviour) => void | Promise<...>)'.
value:
| MainWindowRecordingStartBehaviour
| PostStudioRecordingBehaviour
Expand All @@ -263,7 +268,7 @@
get value() {
return settings.mainWindowRecordingStartBehaviour ?? "close";
},
onChange: (

Check failure on line 271 in apps/desktop/src/routes/(window-chrome)/settings/general.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Type '(value: MainWindowRecordingStartBehaviour | PostStudioRecordingBehaviour) => Promise<void>' is not assignable to type '((value: boolean) => void | Promise<void>) | ((value: PostStudioRecordingBehaviour | MainWindowRecordingStartBehaviour | PostDeletionBehaviour) => void | Promise<...>)'.
value:
| MainWindowRecordingStartBehaviour
| PostStudioRecordingBehaviour
Expand All @@ -280,7 +285,7 @@
get value() {
return settings.postStudioRecordingBehaviour ?? "openEditor";
},
onChange: (

Check failure on line 288 in apps/desktop/src/routes/(window-chrome)/settings/general.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Type '(value: MainWindowRecordingStartBehaviour | PostStudioRecordingBehaviour) => Promise<void>' is not assignable to type '((value: boolean) => void | Promise<void>) | ((value: PostStudioRecordingBehaviour | MainWindowRecordingStartBehaviour | PostDeletionBehaviour) => void | Promise<...>)'.
value:
| MainWindowRecordingStartBehaviour
| PostStudioRecordingBehaviour
Expand All @@ -290,6 +295,24 @@
value as PostStudioRecordingBehaviour
),
},
{
label: "After deleting recording",
description: "What happens to the window after deleting a recording",
type: "select",
get value() {

Check failure on line 302 in apps/desktop/src/routes/(window-chrome)/settings/general.tsx

View workflow job for this annotation

GitHub Actions / Typecheck

Type 'PostDeletionBehaviour | "closeWindow"' is not assignable to type 'number | boolean | PostStudioRecordingBehaviour | MainWindowRecordingStartBehaviour | PostDeletionBehaviour'.
return settings.postDeletionBehaviour ?? "closeWindow";
},
onChange: (
value:
| MainWindowRecordingStartBehaviour
| PostStudioRecordingBehaviour
| PostDeletionBehaviour
) =>
handleChange(
"postDeletionBehaviour",
value as PostDeletionBehaviour
),
},
Comment thread
Brendonovich marked this conversation as resolved.
],
},
];
Expand All @@ -301,6 +324,7 @@
getValue: () =>
| MainWindowRecordingStartBehaviour
| PostStudioRecordingBehaviour
| PostDeletionBehaviour
| number,
onChange: (value: any) => void,
options: { text: string; value: any }[]
Expand Down Expand Up @@ -421,6 +445,20 @@
{ text: "10 seconds", value: 10 },
]
);
} else if (item.label === "After deleting recording") {
return renderRecordingSelect(
item.label,
item.description,
() => item.value,
item.onChange,
[
{ text: "Hide Cap", value: "exit" },
{
text: "Open Cap",
value: "reopenRecordingWindow",
},
]
);
}
}
return null;
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop/src/utils/tauri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ openEditorAfterRecording?: boolean;
/**
* @deprecated can be removed when native camera preview is ready
*/
enableNativeCameraPreview?: boolean; autoZoomOnClicks?: boolean }
enableNativeCameraPreview?: boolean; autoZoomOnClicks?: boolean; postDeletionBehaviour?: PostDeletionBehaviour }
export type GifExportSettings = { fps: number; resolution_base: XY<number> }
export type HapticPattern = "Alignment" | "LevelChange" | "Generic"
export type HapticPerformanceTime = "Default" | "Now" | "DrawCompleted"
Expand All @@ -383,6 +383,7 @@ export type OSPermissionStatus = "notNeeded" | "empty" | "granted" | "denied"
export type OSPermissionsCheck = { screenRecording: OSPermissionStatus; microphone: OSPermissionStatus; camera: OSPermissionStatus; accessibility: OSPermissionStatus }
export type Plan = { upgraded: boolean; manual: boolean; last_checked: number }
export type Platform = "MacOS" | "Windows"
export type PostDeletionBehaviour = "exit" | "reopenRecordingWindow"
export type PostStudioRecordingBehaviour = "openEditor" | "showOverlay"
export type Preset = { name: string; config: ProjectConfiguration }
export type PresetsStore = { presets: Preset[]; default: number | null }
Expand Down
10 changes: 9 additions & 1 deletion crates/recording/src/studio_recording.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,15 @@ async fn run_actor_iteration(
// Cancel from any state
(Msg::Cancel(tx), state) => {
let result = match state {
State::Recording { mut pipeline, .. } => pipeline.inner.shutdown().await,
State::Recording { mut pipeline, .. } => {
if let Some(cursor) = &mut pipeline.cursor
&& let Some(actor) = cursor.actor.take()
{
actor.stop().await;
}

pipeline.inner.shutdown().await
}
State::Paused { .. } => Ok(()),
};

Expand Down
39 changes: 0 additions & 39 deletions packages/ui-solid/src/auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,36 +6,25 @@
// biome-ignore lint: disable
export {}
declare global {
const IconCapArrows: typeof import('~icons/cap/arrows.jsx')['default']
const IconCapAudioOn: typeof import('~icons/cap/audio-on.jsx')['default']
const IconCapAuto: typeof import("~icons/cap/auto.jsx")["default"]
const IconCapBgBlur: typeof import('~icons/cap/bg-blur.jsx')['default']
const IconCapBlur: typeof import("~icons/cap/blur.jsx")["default"]
const IconCapCamera: typeof import('~icons/cap/camera.jsx')['default']
const IconCapCaptions: typeof import('~icons/cap/captions.jsx')['default']
const IconCapCheck: typeof import("~icons/cap/check.jsx")["default"]
const IconCapChevronDown: typeof import('~icons/cap/chevron-down.jsx')['default']
const IconCapCircle: typeof import('~icons/cap/circle.jsx')['default']
const IconCapCircleCheck: typeof import('~icons/cap/circle-check.jsx')['default']
const IconCapCirclePlus: typeof import('~icons/cap/circle-plus.jsx')['default']
const IconCapCircleX: typeof import('~icons/cap/circle-x.jsx')['default']
const IconCapClock: typeof import("~icons/cap/clock.jsx")["default"]
const IconCapCopy: typeof import('~icons/cap/copy.jsx')['default']
const IconCapCorners: typeof import('~icons/cap/corners.jsx')['default']
const IconCapCrop: typeof import('~icons/cap/crop.jsx')['default']
const IconCapCursor: typeof import('~icons/cap/cursor.jsx')['default']
const IconCapDownload: typeof import("~icons/cap/download.jsx")["default"]
const IconCapEditor: typeof import('~icons/cap/editor.jsx')['default']
const IconCapEnlarge: typeof import('~icons/cap/enlarge.jsx')['default']
const IconCapFile: typeof import('~icons/cap/file.jsx')['default']
const IconCapFilmCut: typeof import('~icons/cap/film-cut.jsx')['default']
const IconCapFrameFirst: typeof import("~icons/cap/frame-first.jsx")["default"]
const IconCapFrameLast: typeof import("~icons/cap/frame-last.jsx")["default"]
const IconCapGauge: typeof import('~icons/cap/gauge.jsx')['default']
const IconCapHotkeys: typeof import('~icons/cap/hotkeys.jsx')['default']
const IconCapImage: typeof import('~icons/cap/image.jsx')['default']
const IconCapInfo: typeof import('~icons/cap/info.jsx')['default']
const IconCapInset: typeof import("~icons/cap/inset.jsx")["default"]
const IconCapInstant: typeof import('~icons/cap/instant.jsx')['default']
const IconCapLayout: typeof import('~icons/cap/layout.jsx')['default']
const IconCapLink: typeof import('~icons/cap/link.jsx')['default']
Expand All @@ -45,8 +34,6 @@ declare global {
const IconCapMessageBubble: typeof import('~icons/cap/message-bubble.jsx')['default']
const IconCapMicrophone: typeof import('~icons/cap/microphone.jsx')['default']
const IconCapMoreVertical: typeof import('~icons/cap/more-vertical.jsx')['default']
const IconCapMoveLeft: typeof import("~icons/cap/move-left.jsx")["default"]
const IconCapMoveRight: typeof import("~icons/cap/move-right.jsx")["default"]
const IconCapNext: typeof import('~icons/cap/next.jsx')['default']
const IconCapPadding: typeof import('~icons/cap/padding.jsx')['default']
const IconCapPause: typeof import('~icons/cap/pause.jsx')['default']
Expand All @@ -56,58 +43,32 @@ declare global {
const IconCapPresets: typeof import('~icons/cap/presets.jsx')['default']
const IconCapPrev: typeof import('~icons/cap/prev.jsx')['default']
const IconCapRedo: typeof import('~icons/cap/redo.jsx')['default']
const IconCapRefresh: typeof import("~icons/cap/refresh.jsx")["default"]
const IconCapRestart: typeof import('~icons/cap/restart.jsx')['default']
const IconCapScissors: typeof import('~icons/cap/scissors.jsx')['default']
const IconCapSettings: typeof import('~icons/cap/settings.jsx')['default']
const IconCapShadow: typeof import('~icons/cap/shadow.jsx')['default']
const IconCapSize: typeof import("~icons/cap/size.jsx")["default"]
const IconCapSquare: typeof import('~icons/cap/square.jsx')['default']
const IconCapStop: typeof import("~icons/cap/stop.jsx")["default"]
const IconCapStopCircle: typeof import('~icons/cap/stop-circle.jsx')['default']
const IconCapTrash: typeof import('~icons/cap/trash.jsx')['default']
const IconCapUndo: typeof import('~icons/cap/undo.jsx')['default']
const IconCapUpload: typeof import("~icons/cap/upload.jsx")["default"]
const IconCapWindow: typeof import("~icons/cap/window.jsx")["default"]
const IconCapX: typeof import("~icons/cap/x.jsx")["default"]
const IconCapZoomIn: typeof import('~icons/cap/zoom-in.jsx')['default']
const IconCapZoomOut: typeof import('~icons/cap/zoom-out.jsx')['default']
const IconHugeiconsEaseCurveControlPoints: typeof import('~icons/hugeicons/ease-curve-control-points.jsx')['default']
const IconIcBaselineMonitor: typeof import("~icons/ic/baseline-monitor.jsx")["default"]
const IconIcRoundSearch: typeof import("~icons/ic/round-search.jsx")["default"]
const IconLucideAppWindowMac: typeof import('~icons/lucide/app-window-mac.jsx')['default']
const IconLucideBell: typeof import('~icons/lucide/bell.jsx')['default']
const IconLucideBug: typeof import('~icons/lucide/bug.jsx')['default']
const IconLucideCamera: typeof import("~icons/lucide/camera.jsx")["default"]
const IconLucideCheck: typeof import('~icons/lucide/check.jsx')['default']
const IconLucideChevronDown: typeof import("~icons/lucide/chevron-down.jsx")["default"]
const IconLucideClock: typeof import('~icons/lucide/clock.jsx')['default']
const IconLucideDatabase: typeof import('~icons/lucide/database.jsx')['default']
const IconLucideEdit: typeof import('~icons/lucide/edit.jsx')['default']
const IconLucideEye: typeof import('~icons/lucide/eye.jsx')['default']
const IconLucideFolder: typeof import('~icons/lucide/folder.jsx')['default']
const IconLucideGift: typeof import('~icons/lucide/gift.jsx')['default']
const IconLucideHardDrive: typeof import('~icons/lucide/hard-drive.jsx')['default']
const IconLucideLayoutGrid: typeof import("~icons/lucide/layout-grid.jsx")["default"]
const IconLucideLoaderCircle: typeof import('~icons/lucide/loader-circle.jsx')['default']
const IconLucideMessageCircle: typeof import("~icons/lucide/message-circle.jsx")["default"]
const IconLucideMessageSquare: typeof import("~icons/lucide/message-square.jsx")["default"]
const IconLucideMessageSquarePlus: typeof import('~icons/lucide/message-square-plus.jsx')['default']
const IconLucideMicOff: typeof import('~icons/lucide/mic-off.jsx')['default']
const IconLucideMonitor: typeof import('~icons/lucide/monitor.jsx')['default']
const IconLucideRabbit: typeof import("~icons/lucide/rabbit.jsx")["default"]
const IconLucideRectangle: typeof import("~icons/lucide/rectangle.jsx")["default"]
const IconLucideRectangleHorizontal: typeof import('~icons/lucide/rectangle-horizontal.jsx')['default']
const IconLucideRectangleSquare: typeof import("~icons/lucide/rectangle-square.jsx")["default"]
const IconLucideRotateCcw: typeof import('~icons/lucide/rotate-ccw.jsx')['default']
const IconLucideSearch: typeof import('~icons/lucide/search.jsx')['default']
const IconLucideSquarePlay: typeof import('~icons/lucide/square-play.jsx')['default']
const IconLucideUnplug: typeof import('~icons/lucide/unplug.jsx')['default']
const IconLucideVideo: typeof import("~icons/lucide/video.jsx")["default"]
const IconLucideVolume2: typeof import('~icons/lucide/volume2.jsx')['default']
const IconLucideVolumeX: typeof import('~icons/lucide/volume-x.jsx')['default']
const IconLucideX: typeof import("~icons/lucide/x.jsx")["default"]
const IconMaterialSymbolsScreenshotFrame2Rounded: typeof import('~icons/material-symbols/screenshot-frame2-rounded.jsx')['default']
const IconMdiMonitor: typeof import('~icons/mdi/monitor.jsx')['default']
const IconPhMonitorBold: typeof import('~icons/ph/monitor-bold.jsx')['default']
}
Loading