Skip to content

Commit 8b02f88

Browse files
committed
Merge branch 'main' into rendering-speed
2 parents 953d0b0 + bb554f8 commit 8b02f88

231 files changed

Lines changed: 5971 additions & 2548 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
2-
"permissions": {
3-
"allow": [
4-
"Bash(pnpm typecheck:*)",
5-
"Bash(pnpm lint:*)",
6-
"Bash(pnpm build:*)",
7-
"Bash(cargo check:*)"
8-
],
9-
"deny": [],
10-
"ask": []
11-
}
12-
}
2+
"permissions": {
3+
"allow": [
4+
"Bash(pnpm typecheck:*)",
5+
"Bash(pnpm lint:*)",
6+
"Bash(pnpm build:*)",
7+
"Bash(cargo check:*)"
8+
],
9+
"deny": [],
10+
"ask": []
11+
}
12+
}

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@
5454
"@ts-rest/core": "^3.52.1",
5555
"@types/react-tooltip": "^4.2.4",
5656
"cva": "npm:class-variance-authority@^0.7.0",
57-
"effect": "^3.17.14",
57+
"effect": "^3.18.4",
5858
"mp4box": "^0.5.2",
5959
"posthog-js": "^1.215.3",
6060
"solid-js": "^1.9.3",

apps/desktop/src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cap-desktop"
3-
version = "0.3.72"
3+
version = "0.3.73"
44
description = "Beautiful screen recordings, owned by you."
55
authors = ["you"]
66
edition = "2024"

apps/desktop/src-tauri/src/api.rs

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ use serde::{Deserialize, Serialize};
55
use serde_json::json;
66
use tauri::AppHandle;
77

8-
use crate::web_api::ManagerExt;
8+
use crate::web_api::{AuthedApiError, ManagerExt};
99

10-
pub async fn upload_multipart_initiate(app: &AppHandle, video_id: &str) -> Result<String, String> {
10+
pub async fn upload_multipart_initiate(
11+
app: &AppHandle,
12+
video_id: &str,
13+
) -> Result<String, AuthedApiError> {
1114
#[derive(Deserialize)]
1215
#[serde(rename_all = "camelCase")]
1316
pub struct Response {
@@ -32,14 +35,12 @@ pub async fn upload_multipart_initiate(app: &AppHandle, video_id: &str) -> Resul
3235
.text()
3336
.await
3437
.unwrap_or_else(|_| "<no response body>".to_string());
35-
return Err(format!(
36-
"api/upload_multipart_initiate/{status}: {error_body}"
37-
));
38+
return Err(format!("api/upload_multipart_initiate/{status}: {error_body}").into());
3839
}
3940

4041
resp.json::<Response>()
4142
.await
42-
.map_err(|err| format!("api/upload_multipart_initiate/response: {err}"))
43+
.map_err(|err| format!("api/upload_multipart_initiate/response: {err}").into())
4344
.map(|data| data.upload_id)
4445
}
4546

@@ -49,7 +50,7 @@ pub async fn upload_multipart_presign_part(
4950
upload_id: &str,
5051
part_number: u32,
5152
md5_sum: &str,
52-
) -> Result<String, String> {
53+
) -> Result<String, AuthedApiError> {
5354
#[derive(Deserialize)]
5455
#[serde(rename_all = "camelCase")]
5556
pub struct Response {
@@ -76,14 +77,12 @@ pub async fn upload_multipart_presign_part(
7677
.text()
7778
.await
7879
.unwrap_or_else(|_| "<no response body>".to_string());
79-
return Err(format!(
80-
"api/upload_multipart_presign_part/{status}: {error_body}"
81-
));
80+
return Err(format!("api/upload_multipart_presign_part/{status}: {error_body}").into());
8281
}
8382

8483
resp.json::<Response>()
8584
.await
86-
.map_err(|err| format!("api/upload_multipart_presign_part/response: {err}"))
85+
.map_err(|err| format!("api/upload_multipart_presign_part/response: {err}").into())
8786
.map(|data| data.presigned_url)
8887
}
8988

@@ -114,7 +113,7 @@ pub async fn upload_multipart_complete(
114113
upload_id: &str,
115114
parts: &[UploadedPart],
116115
meta: Option<S3VideoMeta>,
117-
) -> Result<Option<String>, String> {
116+
) -> Result<Option<String>, AuthedApiError> {
118117
#[derive(Serialize)]
119118
#[serde(rename_all = "camelCase")]
120119
pub struct MultipartCompleteRequest<'a> {
@@ -150,14 +149,12 @@ pub async fn upload_multipart_complete(
150149
.text()
151150
.await
152151
.unwrap_or_else(|_| "<no response body>".to_string());
153-
return Err(format!(
154-
"api/upload_multipart_complete/{status}: {error_body}"
155-
));
152+
return Err(format!("api/upload_multipart_complete/{status}: {error_body}").into());
156153
}
157154

158155
resp.json::<Response>()
159156
.await
160-
.map_err(|err| format!("api/upload_multipart_complete/response: {err}"))
157+
.map_err(|err| format!("api/upload_multipart_complete/response: {err}").into())
161158
.map(|data| data.location)
162159
}
163160

@@ -179,7 +176,10 @@ pub struct PresignedS3PutRequest {
179176
pub meta: Option<S3VideoMeta>,
180177
}
181178

182-
pub async fn upload_signed(app: &AppHandle, body: PresignedS3PutRequest) -> Result<String, String> {
179+
pub async fn upload_signed(
180+
app: &AppHandle,
181+
body: PresignedS3PutRequest,
182+
) -> Result<String, AuthedApiError> {
183183
#[derive(Deserialize)]
184184
struct Data {
185185
url: String,
@@ -204,12 +204,12 @@ pub async fn upload_signed(app: &AppHandle, body: PresignedS3PutRequest) -> Resu
204204
.text()
205205
.await
206206
.unwrap_or_else(|_| "<no response body>".to_string());
207-
return Err(format!("api/upload_signed/{status}: {error_body}"));
207+
return Err(format!("api/upload_signed/{status}: {error_body}").into());
208208
}
209209

210210
resp.json::<Response>()
211211
.await
212-
.map_err(|err| format!("api/upload_signed/response: {err}"))
212+
.map_err(|err| format!("api/upload_signed/response: {err}").into())
213213
.map(|data| data.presigned_put_data.url)
214214
}
215215

@@ -218,7 +218,7 @@ pub async fn desktop_video_progress(
218218
video_id: &str,
219219
uploaded: u64,
220220
total: u64,
221-
) -> Result<(), String> {
221+
) -> Result<(), AuthedApiError> {
222222
let resp = app
223223
.authed_api_request("/api/desktop/video/progress", |client, url| {
224224
client.post(url).json(&json!({
@@ -237,7 +237,7 @@ pub async fn desktop_video_progress(
237237
.text()
238238
.await
239239
.unwrap_or_else(|_| "<no response body>".to_string());
240-
return Err(format!("api/desktop_video_progress/{status}: {error_body}"));
240+
return Err(format!("api/desktop_video_progress/{status}: {error_body}").into());
241241
}
242242

243243
Ok(())

apps/desktop/src-tauri/src/auth.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,3 @@ impl AuthStore {
118118
store.save().map_err(|e| e.to_string())
119119
}
120120
}
121-
122-
#[derive(specta::Type, serde::Serialize, tauri_specta::Event, Debug, Clone, serde::Deserialize)]
123-
pub struct AuthenticationInvalid;

apps/desktop/src-tauri/src/deeplink_actions.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ impl DeepLinkAction {
138138
mode,
139139
};
140140

141-
crate::recording::start_recording(app.clone(), state, inputs).await
141+
crate::recording::start_recording(app.clone(), state, inputs)
142+
.await
143+
.map(|_| ())
142144
}
143145
DeepLinkAction::StopRecording => {
144146
crate::recording::stop_recording(app.clone(), app.state()).await

apps/desktop/src-tauri/src/general_settings.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::window_exclusion::WindowExclusion;
12
use serde::{Deserialize, Serialize};
23
use serde_json::json;
34
use specta::Type;
@@ -39,6 +40,24 @@ impl MainWindowRecordingStartBehaviour {
3940
}
4041
}
4142

43+
const DEFAULT_EXCLUDED_WINDOW_TITLES: &[&str] = &[
44+
"Cap",
45+
"Cap Settings",
46+
"Cap Recording Controls",
47+
"Cap Camera",
48+
];
49+
50+
pub fn default_excluded_windows() -> Vec<WindowExclusion> {
51+
DEFAULT_EXCLUDED_WINDOW_TITLES
52+
.iter()
53+
.map(|title| WindowExclusion {
54+
bundle_identifier: None,
55+
owner_name: None,
56+
window_title: Some((*title).to_string()),
57+
})
58+
.collect()
59+
}
60+
4261
// When adding fields here, #[serde(default)] defines the value to use for existing configurations,
4362
// and `Default::default` defines the value to use for new configurations.
4463
// Things that affect the user experience should only be enabled by default for new configurations.
@@ -99,6 +118,8 @@ pub struct GeneralSettingsStore {
99118
pub post_deletion_behaviour: PostDeletionBehaviour,
100119
#[serde(default = "default_enable_new_uploader", skip_serializing_if = "no")]
101120
pub enable_new_uploader: bool,
121+
#[serde(default = "default_excluded_windows")]
122+
pub excluded_windows: Vec<WindowExclusion>,
102123
}
103124

104125
fn default_enable_native_camera_preview() -> bool {
@@ -111,7 +132,7 @@ fn default_enable_new_recording_flow() -> bool {
111132
}
112133

113134
fn default_enable_new_uploader() -> bool {
114-
cfg!(debug_assertions)
135+
true
115136
}
116137

117138
fn no(_: &bool) -> bool {
@@ -162,6 +183,7 @@ impl Default for GeneralSettingsStore {
162183
enable_new_recording_flow: default_enable_new_recording_flow(),
163184
post_deletion_behaviour: PostDeletionBehaviour::DoNothing,
164185
enable_new_uploader: default_enable_new_uploader(),
186+
excluded_windows: default_excluded_windows(),
165187
}
166188
}
167189
}
@@ -231,3 +253,9 @@ pub fn init(app: &AppHandle) {
231253

232254
println!("GeneralSettingsState managed");
233255
}
256+
257+
#[tauri::command]
258+
#[specta::specta]
259+
pub fn get_default_excluded_windows() -> Vec<WindowExclusion> {
260+
default_excluded_windows()
261+
}

apps/desktop/src-tauri/src/hotkeys.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ async fn handle_hotkey(app: AppHandle, action: HotkeyAction) -> Result<(), Strin
146146
Ok(())
147147
}
148148
HotkeyAction::StopRecording => recording::stop_recording(app.clone(), app.state()).await,
149-
HotkeyAction::RestartRecording => {
150-
recording::restart_recording(app.clone(), app.state()).await
151-
}
149+
HotkeyAction::RestartRecording => recording::restart_recording(app.clone(), app.state())
150+
.await
151+
.map(|_| ()),
152152
HotkeyAction::OpenRecordingPicker => {
153153
let _ = RequestOpenRecordingPicker { target_mode: None }.emit(&app);
154154
Ok(())

0 commit comments

Comments
 (0)