@@ -2123,6 +2123,51 @@ async fn generate_zoom_segments_from_clicks(
21232123 Ok ( zoom_segments)
21242124}
21252125
2126+ #[ tauri:: command]
2127+ #[ specta:: specta]
2128+ #[ instrument( skip( editor_instance) ) ]
2129+ async fn generate_keyboard_segments (
2130+ editor_instance : WindowEditorInstance ,
2131+ grouping_threshold_ms : f64 ,
2132+ linger_duration_ms : f64 ,
2133+ show_modifiers : bool ,
2134+ show_special_keys : bool ,
2135+ ) -> Result < Vec < cap_project:: KeyboardTrackSegment > , String > {
2136+ let meta = editor_instance. meta ( ) ;
2137+
2138+ let RecordingMetaInner :: Studio ( studio_meta) = & meta. inner else {
2139+ return Ok ( vec ! [ ] ) ;
2140+ } ;
2141+
2142+ let segments = match studio_meta. as_ref ( ) {
2143+ StudioRecordingMeta :: MultipleSegments { inner, .. } => & inner. segments ,
2144+ _ => return Ok ( vec ! [ ] ) ,
2145+ } ;
2146+
2147+ let mut all_events = cap_project:: KeyboardEvents { presses : vec ! [ ] } ;
2148+
2149+ for segment in segments {
2150+ let events = segment. keyboard_events ( meta) ;
2151+ all_events. presses . extend ( events. presses ) ;
2152+ }
2153+
2154+ all_events. presses . sort_by ( |a, b| {
2155+ a. time_ms
2156+ . partial_cmp ( & b. time_ms )
2157+ . unwrap_or ( std:: cmp:: Ordering :: Equal )
2158+ } ) ;
2159+
2160+ let grouped = cap_project:: group_key_events (
2161+ & all_events,
2162+ grouping_threshold_ms,
2163+ linger_duration_ms,
2164+ show_modifiers,
2165+ show_special_keys,
2166+ ) ;
2167+
2168+ Ok ( grouped)
2169+ }
2170+
21262171#[ tauri:: command]
21272172#[ specta:: specta]
21282173#[ instrument]
@@ -3105,6 +3150,7 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
31053150 set_project_config,
31063151 update_project_config_in_memory,
31073152 generate_zoom_segments_from_clicks,
3153+ generate_keyboard_segments,
31083154 permissions:: open_permission_settings,
31093155 permissions:: do_permissions_check,
31103156 permissions:: request_permission,
@@ -3673,13 +3719,14 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
36733719 id,
36743720 CapWindowId :: TargetSelectOverlay { .. }
36753721 | CapWindowId :: Main
3676- | CapWindowId :: Camera
36773722 )
36783723 {
36793724 let _ = window. show ( ) ;
36803725 }
36813726 }
36823727
3728+ restore_camera_window ( app) ;
3729+
36833730 #[ cfg( target_os = "windows" ) ]
36843731 if !has_open_editor_window ( app) {
36853732 reopen_main_window ( app) ;
@@ -3694,12 +3741,12 @@ pub async fn run(recording_logging_handle: LoggingHandle, logs_dir: PathBuf) {
36943741 id,
36953742 CapWindowId :: TargetSelectOverlay { .. }
36963743 | CapWindowId :: Main
3697- | CapWindowId :: Camera
36983744 )
36993745 {
37003746 let _ = window. show ( ) ;
37013747 }
37023748 }
3749+ restore_camera_window ( app) ;
37033750 return ;
37043751 }
37053752 CapWindowId :: TargetSelectOverlay { display_id } => {
@@ -3901,9 +3948,25 @@ fn restore_main_windows_if_no_editors(app: &AppHandle) {
39013948 if let Some ( main) = CapWindowId :: Main . get ( app) {
39023949 let _ = main. show ( ) ;
39033950 }
3904- if let Some ( camera) = CapWindowId :: Camera . get ( app) {
3905- let _ = camera. show ( ) ;
3906- }
3951+
3952+ restore_camera_window ( app) ;
3953+ }
3954+ }
3955+
3956+ fn restore_camera_window ( app : & AppHandle ) {
3957+ let should_restore_camera = app
3958+ . state :: < ArcLock < App > > ( )
3959+ . try_read ( )
3960+ . map ( |state| state. selected_camera_id . is_some ( ) )
3961+ . unwrap_or ( false ) ;
3962+
3963+ if should_restore_camera {
3964+ let app = app. clone ( ) ;
3965+ tokio:: spawn ( async move {
3966+ let operation_lock = app. state :: < CameraWindowOperationLock > ( ) ;
3967+ let _operation_guard = operation_lock. lock ( ) . await ;
3968+ let _ = ShowCapWindow :: Camera { centered : false } . show ( & app) . await ;
3969+ } ) ;
39073970 }
39083971}
39093972
0 commit comments