@@ -3,7 +3,7 @@ use cap_recording::{
33} ;
44use serde:: { Deserialize , Serialize } ;
55use std:: path:: { Path , PathBuf } ;
6- use tauri:: { AppHandle , Manager , Url } ;
6+ use tauri:: { AppHandle , Emitter , Manager , Url } ;
77use tracing:: trace;
88
99use crate :: { App , ArcLock , recording:: StartRecordingInputs , windows:: ShowCapWindow } ;
@@ -25,6 +25,12 @@ pub enum DeepLinkAction {
2525 capture_system_audio : bool ,
2626 mode : RecordingMode ,
2727 } ,
28+ TogglePauseRecording ,
29+ TakeScreenshot ,
30+ SetCamera { id : String } ,
31+ SetMicrophone { label : String } ,
32+ ListCameras ,
33+ ListMicrophones ,
2834 StopRecording ,
2935 OpenEditor {
3036 project_path : PathBuf ,
@@ -34,42 +40,6 @@ pub enum DeepLinkAction {
3440 } ,
3541}
3642
37- pub fn handle ( app_handle : & AppHandle , urls : Vec < Url > ) {
38- trace ! ( "Handling deep actions for: {:?}" , & urls) ;
39-
40- let actions: Vec < _ > = urls
41- . into_iter ( )
42- . filter ( |url| !url. as_str ( ) . is_empty ( ) )
43- . filter_map ( |url| {
44- DeepLinkAction :: try_from ( & url)
45- . map_err ( |e| match e {
46- ActionParseFromUrlError :: ParseFailed ( msg) => {
47- eprintln ! ( "Failed to parse deep link \" {}\" : {}" , & url, msg)
48- }
49- ActionParseFromUrlError :: Invalid => {
50- eprintln ! ( "Invalid deep link format \" {}\" " , & url)
51- }
52- // Likely login action, not handled here.
53- ActionParseFromUrlError :: NotAction => { }
54- } )
55- . ok ( )
56- } )
57- . collect ( ) ;
58-
59- if actions. is_empty ( ) {
60- return ;
61- }
62-
63- let app_handle = app_handle. clone ( ) ;
64- tauri:: async_runtime:: spawn ( async move {
65- for action in actions {
66- if let Err ( e) = action. execute ( & app_handle) . await {
67- eprintln ! ( "Failed to handle deep link action: {e}" ) ;
68- }
69- }
70- } ) ;
71- }
72-
7343pub enum ActionParseFromUrlError {
7444 ParseFailed ( String ) ,
7545 Invalid ,
@@ -80,78 +50,108 @@ impl TryFrom<&Url> for DeepLinkAction {
8050 type Error = ActionParseFromUrlError ;
8151
8252 fn try_from ( url : & Url ) -> Result < Self , Self :: Error > {
83- #[ cfg( target_os = "macos" ) ]
84- if url. scheme ( ) == "file" {
85- return url
86- . to_file_path ( )
87- . map ( |project_path| Self :: OpenEditor { project_path } )
88- . map_err ( |_| ActionParseFromUrlError :: Invalid ) ;
53+ if url. scheme ( ) != "cap-desktop" {
54+ return Err ( ActionParseFromUrlError :: NotAction ) ;
8955 }
9056
9157 match url. domain ( ) {
92- Some ( v) if v != "action" => Err ( ActionParseFromUrlError :: NotAction ) ,
93- _ => Err ( ActionParseFromUrlError :: Invalid ) ,
94- } ?;
95-
96- let params = url
97- . query_pairs ( )
98- . collect :: < std:: collections:: HashMap < _ , _ > > ( ) ;
99- let json_value = params
100- . get ( "value" )
101- . ok_or ( ActionParseFromUrlError :: Invalid ) ?;
102- let action: Self = serde_json:: from_str ( json_value)
103- . map_err ( |e| ActionParseFromUrlError :: ParseFailed ( e. to_string ( ) ) ) ?;
104- Ok ( action)
58+ Some ( "toggle-pause" ) => Ok ( Self :: TogglePauseRecording ) ,
59+ Some ( "stop" ) => Ok ( Self :: StopRecording ) ,
60+ Some ( "screenshot" ) => Ok ( Self :: TakeScreenshot ) ,
61+ _ => {
62+ // Original JSON path
63+ if url. domain ( ) == Some ( "action" ) {
64+ let params = url. query_pairs ( ) . collect :: < std:: collections:: HashMap < _ , _ > > ( ) ;
65+ let json_value = params. get ( "value" ) . ok_or ( ActionParseFromUrlError :: Invalid ) ?;
66+ let action: Self = serde_json:: from_str ( json_value)
67+ . map_err ( |e| ActionParseFromUrlError :: ParseFailed ( e. to_string ( ) ) ) ?;
68+ Ok ( action)
69+ } else {
70+ Err ( ActionParseFromUrlError :: Invalid )
71+ }
72+ }
73+ }
10574 }
10675}
10776
10877impl DeepLinkAction {
109- pub async fn execute ( self , app : & AppHandle ) -> Result < ( ) , String > {
78+ pub async fn execute ( & self , app : & AppHandle ) -> anyhow :: Result < ( ) > {
11079 match self {
111- DeepLinkAction :: StartRecording {
80+ Self :: TogglePauseRecording => {
81+ app. emit ( "recording-action" , "toggle-pause" )
82+ . map_err ( |e| anyhow:: anyhow!( e. to_string( ) ) ) ?;
83+ Ok ( ( ) )
84+ }
85+ Self :: StopRecording => {
86+ app. emit ( "recording-action" , "stop" )
87+ . map_err ( |e| anyhow:: anyhow!( e. to_string( ) ) ) ?;
88+ Ok ( ( ) )
89+ }
90+ Self :: TakeScreenshot => {
91+ app. emit ( "recording-action" , "screenshot" )
92+ . map_err ( |e| anyhow:: anyhow!( e. to_string( ) ) ) ?;
93+ Ok ( ( ) )
94+ }
95+ Self :: StartRecording {
11296 capture_mode,
11397 camera,
11498 mic_label,
11599 capture_system_audio,
116100 mode,
117101 } => {
118- let state = app. state :: < ArcLock < App > > ( ) ;
102+ let state = app. state :: < crate :: ArcLock < crate :: App > > ( ) ;
119103
120- crate :: set_camera_input ( app. clone ( ) , state. clone ( ) , camera, None ) . await ?;
121- crate :: set_mic_input ( state. clone ( ) , mic_label) . await ?;
122-
123- let capture_target: ScreenCaptureTarget = match capture_mode {
124- CaptureMode :: Screen ( name) => cap_recording:: screen_capture:: list_displays ( )
104+ let capture_target: cap_recording:: sources:: screen_capture:: ScreenCaptureTarget = match capture_mode {
105+ CaptureMode :: Screen ( name) => cap_recording:: sources:: screen_capture:: list_displays ( )
125106 . into_iter ( )
126- . find ( |( s, _) | s. name == name)
127- . map ( |( s, _) | ScreenCaptureTarget :: Display { id : s. id } )
128- . ok_or ( format ! ( "No screen with name \" {}\" " , & name) ) ?,
129- CaptureMode :: Window ( name) => cap_recording:: screen_capture:: list_windows ( )
107+ . find ( |( s, _) | s. name == * name)
108+ . map ( |( s, _) | cap_recording :: sources :: screen_capture :: ScreenCaptureTarget :: Display { id : s. id } )
109+ . ok_or ( anyhow :: anyhow !( "No screen with name \" {}\" " , & name) ) ?,
110+ CaptureMode :: Window ( name) => cap_recording:: sources :: screen_capture:: list_windows ( )
130111 . into_iter ( )
131- . find ( |( w, _) | w. name == name)
132- . map ( |( w, _) | ScreenCaptureTarget :: Window { id : w. id } )
133- . ok_or ( format ! ( "No window with name \" {}\" " , & name) ) ?,
112+ . find ( |( w, _) | w. name == * name)
113+ . map ( |( w, _) | cap_recording :: sources :: screen_capture :: ScreenCaptureTarget :: Window { id : w. id } )
114+ . ok_or ( anyhow :: anyhow !( "No window with name \" {}\" " , & name) ) ?,
134115 } ;
135116
136- let inputs = StartRecordingInputs {
137- mode,
117+ let inputs = crate :: recording:: StartRecordingInputs {
138118 capture_target,
139- capture_system_audio,
119+ capture_system_audio : * capture_system_audio,
120+ mode : * mode,
140121 organization_id : None ,
141122 } ;
142123
143- crate :: recording:: start_recording ( app. clone ( ) , state, inputs)
124+ if let Some ( camera_id) = camera {
125+ crate :: set_camera_input ( app. clone ( ) , state. clone ( ) , Some ( camera_id. clone ( ) ) , None )
126+ . await
127+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
128+ }
129+
130+ if let Some ( mic) = mic_label {
131+ crate :: set_mic_input ( state. clone ( ) , Some ( mic. clone ( ) ) )
132+ . await
133+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
134+ }
135+
136+ crate :: recording:: start_recording ( app. clone ( ) , state. clone ( ) , inputs)
144137 . await
145- . map ( |_| ( ) )
138+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
139+ Ok ( ( ) )
146140 }
147- DeepLinkAction :: StopRecording => {
148- crate :: recording:: stop_recording ( app. clone ( ) , app. state ( ) ) . await
141+ Self :: OpenEditor { project_path } => {
142+ crate :: open_project_from_path ( Path :: new ( project_path) , app. clone ( ) )
143+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
144+ Ok ( ( ) )
149145 }
150- DeepLinkAction :: OpenEditor { project_path } => {
151- crate :: open_project_from_path ( Path :: new ( & project_path) , app. clone ( ) )
146+ Self :: OpenSettings { page } => {
147+ crate :: show_window ( app. clone ( ) , crate :: ShowCapWindow :: Settings { page : page. clone ( ) } )
148+ . await
149+ . map_err ( |e| anyhow:: anyhow!( e) ) ?;
150+ Ok ( ( ) )
152151 }
153- DeepLinkAction :: OpenSettings { page } => {
154- crate :: show_window ( app. clone ( ) , ShowCapWindow :: Settings { page } ) . await
152+ _ => {
153+ tracing:: warn!( "Deep link action not implemented: {:?}" , self ) ;
154+ Ok ( ( ) )
155155 }
156156 }
157157 }
0 commit comments