Skip to content

Commit 3002070

Browse files
Merge pull request #1709 from CapSoftware/sentry-bugs
Misc sentry bugs, performance stuff etc
2 parents c8d2e6b + b1be016 commit 3002070

File tree

30 files changed

+1251
-327
lines changed

30 files changed

+1251
-327
lines changed

Cargo.lock

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

apps/desktop/src-tauri/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,6 @@ winreg = "0.55"
150150

151151
[target.'cfg(unix)'.dependencies]
152152
nix = { version = "0.29.0", features = ["fs"] }
153+
154+
[dev-dependencies]
155+
tauri = { workspace = true, features = ["test"] }

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

Lines changed: 60 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,20 @@ fn clamp_size(size: f32) -> f32 {
6767
size.clamp(MIN_CAMERA_SIZE, MAX_CAMERA_SIZE)
6868
}
6969

70+
fn preferred_alpha_mode(alpha_modes: &[CompositeAlphaMode]) -> CompositeAlphaMode {
71+
[
72+
CompositeAlphaMode::PreMultiplied,
73+
CompositeAlphaMode::PostMultiplied,
74+
CompositeAlphaMode::Opaque,
75+
CompositeAlphaMode::Auto,
76+
CompositeAlphaMode::Inherit,
77+
]
78+
.into_iter()
79+
.find(|mode| alpha_modes.contains(mode))
80+
.or_else(|| alpha_modes.first().copied())
81+
.unwrap_or(CompositeAlphaMode::Opaque)
82+
}
83+
7084
pub struct CameraPreviewManager {
7185
store: Result<Arc<tauri_plugin_store::Store<tauri::Wry>>, String>,
7286
preview: Option<InitializedCameraPreview>,
@@ -483,19 +497,7 @@ impl InitializedCameraPreview {
483497
});
484498

485499
let surface_capabilities = surface.get_capabilities(&adapter);
486-
let alpha_mode = if surface_capabilities
487-
.alpha_modes
488-
.contains(&CompositeAlphaMode::PreMultiplied)
489-
{
490-
CompositeAlphaMode::PreMultiplied
491-
} else if surface_capabilities
492-
.alpha_modes
493-
.contains(&CompositeAlphaMode::PostMultiplied)
494-
{
495-
CompositeAlphaMode::PostMultiplied
496-
} else {
497-
CompositeAlphaMode::Inherit
498-
};
500+
let alpha_mode = preferred_alpha_mode(&surface_capabilities.alpha_modes);
499501

500502
let surface_config = wgpu::SurfaceConfiguration {
501503
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
@@ -1021,6 +1023,51 @@ async fn resize_window(
10211023
.map_err(anyhow::Error::new)
10221024
}
10231025

1026+
#[cfg(test)]
1027+
mod tests {
1028+
use super::preferred_alpha_mode;
1029+
use wgpu::CompositeAlphaMode;
1030+
1031+
#[test]
1032+
fn preferred_alpha_mode_avoids_unsupported_inherit_fallback() {
1033+
assert_eq!(
1034+
preferred_alpha_mode(&[CompositeAlphaMode::Opaque]),
1035+
CompositeAlphaMode::Opaque
1036+
);
1037+
}
1038+
1039+
#[test]
1040+
fn preferred_alpha_mode_keeps_transparent_modes_when_supported() {
1041+
assert_eq!(
1042+
preferred_alpha_mode(&[
1043+
CompositeAlphaMode::Opaque,
1044+
CompositeAlphaMode::PreMultiplied,
1045+
]),
1046+
CompositeAlphaMode::PreMultiplied
1047+
);
1048+
assert_eq!(
1049+
preferred_alpha_mode(&[
1050+
CompositeAlphaMode::Opaque,
1051+
CompositeAlphaMode::PostMultiplied,
1052+
]),
1053+
CompositeAlphaMode::PostMultiplied
1054+
);
1055+
}
1056+
1057+
#[test]
1058+
fn preferred_alpha_mode_uses_other_supported_fallbacks() {
1059+
assert_eq!(
1060+
preferred_alpha_mode(&[CompositeAlphaMode::Auto]),
1061+
CompositeAlphaMode::Auto
1062+
);
1063+
assert_eq!(
1064+
preferred_alpha_mode(&[CompositeAlphaMode::Inherit]),
1065+
CompositeAlphaMode::Inherit
1066+
);
1067+
assert_eq!(preferred_alpha_mode(&[]), CompositeAlphaMode::Opaque);
1068+
}
1069+
}
1070+
10241071
fn render_solid_frame(color: [u8; 4], width: u32, height: u32) -> (Vec<u8>, u32) {
10251072
let pixel_count = (height * width) as usize;
10261073
let buffer: Vec<u8> = color

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::editor_window::{OptionalWindowEditorInstance, WindowEditorInstance};
2-
use crate::recording::should_force_ffmpeg_for_recovered_project;
32
use crate::{FramesRendered, get_video_metadata};
43
use cap_export::{ExporterBase, make_cursor_only_project};
54
use cap_project::{RecordingMeta, XY};
@@ -145,7 +144,8 @@ fn is_frame_decode_error(error: &str) -> bool {
145144
}
146145

147146
fn should_force_ffmpeg_export(project_path: &Path, settings: &ExportSettings) -> bool {
148-
settings.force_ffmpeg_decoder() || should_force_ffmpeg_for_recovered_project(project_path)
147+
let _ = project_path;
148+
settings.force_ffmpeg_decoder()
149149
}
150150

151151
#[tauri::command]
@@ -541,7 +541,7 @@ mod tests {
541541
}
542542

543543
#[test]
544-
fn recovered_projects_force_ffmpeg_for_gif_exports() {
544+
fn recovered_projects_do_not_force_ffmpeg_without_explicit_setting() {
545545
let dir = tempdir().unwrap();
546546
std::fs::write(
547547
dir.path()
@@ -556,7 +556,7 @@ mod tests {
556556
quality: None,
557557
});
558558

559-
assert!(should_force_ffmpeg_export(dir.path(), &gif_settings));
559+
assert!(!should_force_ffmpeg_export(dir.path(), &gif_settings));
560560
}
561561
}
562562

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,12 @@ impl GeneralSettingsStore {
268268
let mut settings = Self::get(app)?.unwrap_or_default();
269269
update(&mut settings);
270270
store.set("general_settings", json!(settings));
271-
store.save().map_err(|e| e.to_string())
271+
store.save().map_err(|e| e.to_string())?;
272+
273+
#[cfg(target_os = "macos")]
274+
crate::permissions::sync_macos_dock_visibility(app);
275+
276+
Ok(())
272277
}
273278

274279
fn save(&self, app: &AppHandle) -> Result<(), String> {
@@ -297,6 +302,9 @@ pub fn init(app: &AppHandle) {
297302
error!("Failed to save general settings: {}", e);
298303
}
299304

305+
#[cfg(target_os = "macos")]
306+
crate::permissions::sync_macos_dock_visibility(app);
307+
300308
println!("GeneralSettingsState managed");
301309
}
302310

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

Lines changed: 43 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ mod thumbnails;
3333
mod tray;
3434
mod update_project_names;
3535
mod upload;
36-
mod web_api;
36+
pub mod web_api;
3737
mod window_exclusion;
3838
mod windows;
3939

@@ -89,6 +89,7 @@ use std::{
8989
},
9090
time::{Duration, SystemTime, UNIX_EPOCH},
9191
};
92+
use tauri::Listener;
9293
use tauri::{AppHandle, Manager, State, Window, WindowEvent, ipc::Channel};
9394
use tauri_plugin_deep_link::DeepLinkExt;
9495
use tauri_plugin_dialog::DialogExt;
@@ -158,6 +159,24 @@ impl AppExitState {
158159
}
159160
}
160161

162+
pub struct MainWindowReadyState(AtomicBool);
163+
164+
impl Default for MainWindowReadyState {
165+
fn default() -> Self {
166+
Self(AtomicBool::new(false))
167+
}
168+
}
169+
170+
impl MainWindowReadyState {
171+
pub fn is_ready(&self) -> bool {
172+
self.0.load(Ordering::Acquire)
173+
}
174+
175+
pub fn set_ready(&self, value: bool) {
176+
self.0.store(value, Ordering::Release);
177+
}
178+
}
179+
161180
const APP_EXIT_STEP_TIMEOUT: Duration = Duration::from_millis(750);
162181
const APP_EXIT_CAMERA_SHUTDOWN_TIMEOUT: Duration = Duration::from_millis(1200);
163182
const APP_EXIT_TOTAL_TIMEOUT: Duration = Duration::from_secs(3);
@@ -1113,14 +1132,6 @@ async fn cleanup_app_resources_for_exit(app: &AppHandle) {
11131132
})
11141133
.await;
11151134

1116-
#[cfg(target_os = "macos")]
1117-
{
1118-
app.state::<CameraWindowCloseGate>().set_allow_close(true);
1119-
if let Some(camera_window) = CapWindowId::Camera.get(app) {
1120-
let _ = camera_window.close();
1121-
}
1122-
}
1123-
11241135
if let Some(rx) = camera_shutdown {
11251136
let _ = await_exit_step(
11261137
"camera_preview_shutdown",
@@ -3501,16 +3512,6 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
35013512
});
35023513
}
35033514

3504-
tokio::spawn({
3505-
let app = app.clone();
3506-
async move {
3507-
resume_uploads(app)
3508-
.await
3509-
.map_err(|err| warn!("Error resuming uploads: {err}"))
3510-
.ok();
3511-
}
3512-
});
3513-
35143515
{
35153516
let (server_url, should_update) = if cfg!(debug_assertions)
35163517
&& let Ok(url) = std::env::var("VITE_SERVER_URL")
@@ -3570,12 +3571,30 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
35703571
app.manage(CameraWindowPositionGuard::default());
35713572
app.manage(CameraWindowOperationLock::default());
35723573
app.manage(AppExitState::default());
3574+
app.manage(MainWindowReadyState::default());
35733575

35743576
app.manage(Arc::new(RwLock::new(
35753577
ClipboardContext::new().expect("Failed to create clipboard context"),
35763578
)));
35773579
}
35783580

3581+
app.listen_any("main-window-ready", {
3582+
let app = app.clone();
3583+
move |_| {
3584+
app.state::<MainWindowReadyState>().set_ready(true);
3585+
}
3586+
});
3587+
3588+
tokio::spawn({
3589+
let app = app.clone();
3590+
async move {
3591+
resume_uploads(app)
3592+
.await
3593+
.map_err(|err| warn!("Error resuming uploads: {err}"))
3594+
.ok();
3595+
}
3596+
});
3597+
35793598
spawn_mic_error_handler(app.clone(), mic_error_rx);
35803599
spawn_device_watchers(app.clone());
35813600
spawn_devices_snapshot_emitter(app.clone());
@@ -3825,6 +3844,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
38253844
reopen_main_window(app);
38263845
}
38273846

3847+
#[cfg(target_os = "macos")]
38283848
return;
38293849
}
38303850
CapWindowId::Upgrade | CapWindowId::ModeSelect => {
@@ -3840,6 +3860,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
38403860
}
38413861
}
38423862
restore_camera_window(app);
3863+
#[cfg(target_os = "macos")]
38433864
return;
38443865
}
38453866
CapWindowId::TargetSelectOverlay { display_id } => {
@@ -3875,18 +3896,8 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
38753896
};
38763897
}
38773898

3878-
if let Some(settings) = GeneralSettingsStore::get(app).unwrap_or(None)
3879-
&& settings.hide_dock_icon
3880-
&& app.webview_windows().keys().all(|label| {
3881-
CapWindowId::from_str(label)
3882-
.map(|id| !id.activates_dock())
3883-
.unwrap_or(false)
3884-
})
3885-
{
3886-
#[cfg(target_os = "macos")]
3887-
app.set_activation_policy(tauri::ActivationPolicy::Accessory)
3888-
.ok();
3889-
}
3899+
#[cfg(target_os = "macos")]
3900+
crate::permissions::sync_macos_dock_visibility(app);
38903901
}
38913902
#[cfg(target_os = "macos")]
38923903
WindowEvent::Focused(focused) => {
@@ -3906,8 +3917,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
39063917
&& let Ok(window_id) = window_id
39073918
&& window_id.activates_dock()
39083919
{
3909-
app.set_activation_policy(tauri::ActivationPolicy::Regular)
3910-
.ok();
3920+
crate::permissions::sync_macos_dock_visibility(app);
39113921
}
39123922
}
39133923
WindowEvent::DragDrop(tauri::DragDropEvent::Drop { paths, .. }) => {

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

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ fn macos_focus_permission_window(app: &tauri::AppHandle) {
100100

101101
#[cfg(target_os = "macos")]
102102
fn macos_activate_permission_request(app: &tauri::AppHandle) {
103+
if let Err(err) = app.set_dock_visibility(true) {
104+
tracing::warn!("Failed to show dock icon for permission request: {err}");
105+
}
106+
103107
if let Err(err) = app.set_activation_policy(tauri::ActivationPolicy::Regular) {
104108
tracing::warn!("Failed to set activation policy to Regular: {err}");
105109
}
@@ -117,21 +121,21 @@ fn macos_activate_permission_request(app: &tauri::AppHandle) {
117121
}
118122

119123
#[cfg(target_os = "macos")]
120-
fn macos_restore_activation_policy(app: &tauri::AppHandle) {
124+
pub(crate) fn sync_macos_dock_visibility(app: &tauri::AppHandle) {
121125
let should_hide_dock = GeneralSettingsStore::get(app)
122126
.ok()
123127
.flatten()
124128
.is_some_and(|settings| settings.hide_dock_icon);
125129

126-
if should_hide_dock
127-
&& app.webview_windows().keys().all(|label| {
130+
let should_show_dock = !should_hide_dock
131+
|| app.webview_windows().keys().any(|label| {
128132
CapWindowId::from_str(label)
129-
.map(|window_id| !window_id.activates_dock())
133+
.map(|window_id| window_id.activates_dock())
130134
.unwrap_or(false)
131-
})
132-
&& let Err(err) = app.set_activation_policy(tauri::ActivationPolicy::Accessory)
133-
{
134-
tracing::warn!("Failed to restore activation policy to Accessory: {err}");
135+
});
136+
137+
if let Err(err) = app.set_dock_visibility(should_show_dock) {
138+
tracing::warn!("Failed to update dock visibility: {err}");
135139
}
136140
}
137141

@@ -262,12 +266,12 @@ fn macos_open_permission_settings(app: &tauri::AppHandle, permission: &OSPermiss
262266
_ => {}
263267
}
264268
crate::tray::refresh_tray_menu_for_app(&app);
265-
macos_restore_activation_policy(&app);
269+
sync_macos_dock_visibility(&app);
266270
});
267271
}
268272
Err(err) => {
269273
tracing::error!("Failed to open permission settings: {err}");
270-
macos_restore_activation_policy(app);
274+
sync_macos_dock_visibility(app);
271275
}
272276
}
273277
}
@@ -312,7 +316,7 @@ pub async fn request_permission(_app: tauri::AppHandle, _permission: OSPermissio
312316
if macos_permission_needs_settings_fallback(&_permission) && !granted {
313317
macos_open_permission_settings(&_app, &_permission);
314318
} else {
315-
macos_restore_activation_policy(&_app);
319+
sync_macos_dock_visibility(&_app);
316320
}
317321
}
318322

0 commit comments

Comments
 (0)