@@ -21,6 +21,10 @@ pub struct Settings {
2121 pub compact_recording_status : bool ,
2222 pub check_updates_automatically : bool ,
2323 pub selected_microphone : Option < String > ,
24+ // Push-to-talk support
25+ pub recording_mode : String , // "toggle" or "push_to_talk"
26+ pub use_different_ptt_key : bool ,
27+ pub ptt_hotkey : Option < String > ,
2428}
2529
2630impl Default for Settings {
@@ -38,6 +42,9 @@ impl Default for Settings {
3842 compact_recording_status : true , // Default to compact mode
3943 check_updates_automatically : true , // Default to automatic updates enabled
4044 selected_microphone : None , // Default to system default microphone
45+ recording_mode : "toggle" . to_string ( ) , // Default to toggle mode for backward compatibility
46+ use_different_ptt_key : false , // Default to using same key
47+ ptt_hotkey : Some ( "Alt+Space" . to_string ( ) ) , // Default PTT key
4148 }
4249 }
4350}
@@ -102,6 +109,17 @@ pub async fn get_settings(app: AppHandle) -> Result<Settings, String> {
102109 selected_microphone : store
103110 . get ( "selected_microphone" )
104111 . and_then ( |v| v. as_str ( ) . map ( |s| s. to_string ( ) ) ) ,
112+ recording_mode : store
113+ . get ( "recording_mode" )
114+ . and_then ( |v| v. as_str ( ) . map ( |s| s. to_string ( ) ) )
115+ . unwrap_or_else ( || Settings :: default ( ) . recording_mode ) ,
116+ use_different_ptt_key : store
117+ . get ( "use_different_ptt_key" )
118+ . and_then ( |v| v. as_bool ( ) )
119+ . unwrap_or_else ( || Settings :: default ( ) . use_different_ptt_key ) ,
120+ ptt_hotkey : store
121+ . get ( "ptt_hotkey" )
122+ . and_then ( |v| v. as_str ( ) . map ( |s| s. to_string ( ) ) ) ,
105123 } ;
106124
107125 // Pill position is already loaded from store, no need for duplicate state
@@ -144,13 +162,71 @@ pub async fn save_settings(app: AppHandle, settings: Settings) -> Result<(), Str
144162 ) ;
145163 store. set ( "selected_microphone" , json ! ( settings. selected_microphone) ) ;
146164
165+ // Save push-to-talk settings
166+ store. set ( "recording_mode" , json ! ( settings. recording_mode. clone( ) ) ) ;
167+ store. set ( "use_different_ptt_key" , json ! ( settings. use_different_ptt_key) ) ;
168+ if let Some ( ref ptt_hotkey) = settings. ptt_hotkey {
169+ store. set ( "ptt_hotkey" , json ! ( ptt_hotkey) ) ;
170+ }
171+
147172 // Save pill position if provided
148173 if let Some ( ( x, y) ) = settings. pill_position {
149174 store. set ( "pill_position" , json ! ( [ x, y] ) ) ;
150175 }
151176
152177 store. save ( ) . map_err ( |e| e. to_string ( ) ) ?;
153178
179+ // Update recording mode in AppState
180+ let app_state = app. state :: < crate :: AppState > ( ) ;
181+ let recording_mode = match settings. recording_mode . as_str ( ) {
182+ "push_to_talk" => crate :: RecordingMode :: PushToTalk ,
183+ _ => crate :: RecordingMode :: Toggle ,
184+ } ;
185+
186+ if let Ok ( mut mode_guard) = app_state. recording_mode . lock ( ) {
187+ * mode_guard = recording_mode;
188+ log:: info!( "Recording mode updated to: {:?}" , recording_mode) ;
189+ }
190+
191+ // Handle PTT shortcut registration if needed
192+ if recording_mode == crate :: RecordingMode :: PushToTalk && settings. use_different_ptt_key {
193+ if let Some ( ptt_hotkey) = settings. ptt_hotkey . clone ( ) {
194+ let normalized_ptt = crate :: commands:: key_normalizer:: normalize_shortcut_keys ( & ptt_hotkey) ;
195+
196+ if let Ok ( ptt_shortcut) = normalized_ptt. parse :: < tauri_plugin_global_shortcut:: Shortcut > ( ) {
197+ let shortcuts = app. global_shortcut ( ) ;
198+
199+ // Unregister old PTT shortcut if exists
200+ if let Ok ( ptt_guard) = app_state. ptt_shortcut . lock ( ) {
201+ if let Some ( old_ptt) = ptt_guard. clone ( ) {
202+ let _ = shortcuts. unregister ( old_ptt) ;
203+ }
204+ }
205+
206+ // Register new PTT shortcut
207+ match shortcuts. register ( ptt_shortcut. clone ( ) ) {
208+ Ok ( _) => {
209+ if let Ok ( mut ptt_guard) = app_state. ptt_shortcut . lock ( ) {
210+ * ptt_guard = Some ( ptt_shortcut) ;
211+ }
212+ log:: info!( "PTT shortcut updated to: {}" , ptt_hotkey) ;
213+ }
214+ Err ( e) => {
215+ log:: error!( "Failed to register PTT shortcut: {}" , e) ;
216+ }
217+ }
218+ }
219+ }
220+ } else {
221+ // Clear PTT shortcut if not using different key
222+ if let Ok ( mut ptt_guard) = app_state. ptt_shortcut . lock ( ) {
223+ if let Some ( old_ptt) = ptt_guard. clone ( ) {
224+ let _ = app. global_shortcut ( ) . unregister ( old_ptt) ;
225+ }
226+ * ptt_guard = None ;
227+ }
228+ }
229+
154230 // Preload new model and update tray menu if model changed
155231 if !settings. current_model . is_empty ( ) && old_model != settings. current_model {
156232 use crate :: commands:: model:: preload_model;
0 commit comments