3
3
// SPDX-License-Identifier: MIT
4
4
5
5
use std:: {
6
- io:: { BufWriter , Error , ErrorKind , Read , Write } ,
6
+ io:: { BufWriter , ErrorKind , Read , Write } ,
7
7
os:: unix:: net:: { UnixListener , UnixStream } ,
8
8
path:: PathBuf ,
9
9
} ;
@@ -16,17 +16,25 @@ use tauri::{
16
16
AppHandle , Config , Manager , RunEvent , Runtime ,
17
17
} ;
18
18
19
+ #[ cfg( debug_assertions) ]
20
+ static IS_PRIMARY_APP : std:: sync:: OnceLock < bool > = std:: sync:: OnceLock :: new ( ) ;
21
+
19
22
pub fn init < R : Runtime > ( cb : Box < SingleInstanceCallback < R > > ) -> TauriPlugin < R > {
20
23
plugin:: Builder :: new ( "single-instance" )
21
24
. setup ( |app, _api| {
22
25
let socket = socket_path ( app. config ( ) , app. package_info ( ) ) ;
23
26
24
27
// Notify the singleton which may or may not exist.
25
- match notify_singleton ( & socket) {
28
+ match notify_singleton ( & socket, & std :: env :: args ( ) . collect :: < Vec < _ > > ( ) ) {
26
29
Ok ( _) => {
30
+ #[ cfg( debug_assertions) ]
31
+ IS_PRIMARY_APP . set ( false ) . unwrap ( ) ;
32
+ #[ cfg( not( debug_assertions) ) ]
27
33
std:: process:: exit ( 0 ) ;
28
34
}
29
35
Err ( e) => {
36
+ #[ cfg( debug_assertions) ]
37
+ IS_PRIMARY_APP . set ( true ) . unwrap ( ) ;
30
38
match e. kind ( ) {
31
39
ErrorKind :: NotFound | ErrorKind :: ConnectionRefused => {
32
40
// This process claims itself as singleton as likely none exists
@@ -44,10 +52,32 @@ pub fn init<R: Runtime>(cb: Box<SingleInstanceCallback<R>>) -> TauriPlugin<R> {
44
52
}
45
53
Ok ( ( ) )
46
54
} )
47
- . on_event ( |app, event| {
48
- if let RunEvent :: Exit = event {
55
+ . on_event ( |app, event| match event {
56
+ RunEvent :: Exit => {
49
57
destroy ( app) ;
50
58
}
59
+ #[ cfg( debug_assertions) ]
60
+ RunEvent :: Opened { urls } => {
61
+ if let Some ( true ) = IS_PRIMARY_APP . get ( ) {
62
+ return ;
63
+ }
64
+ let socket = socket_path ( app. config ( ) , app. package_info ( ) ) ;
65
+ match notify_singleton (
66
+ & socket,
67
+ & std:: env:: args ( )
68
+ . take ( 1 )
69
+ . chain ( urls. iter ( ) . map ( |url| url. to_string ( ) ) )
70
+ . collect :: < Vec < String > > ( ) ,
71
+ ) {
72
+ Ok ( _) => {
73
+ std:: process:: exit ( 0 ) ;
74
+ }
75
+ Err ( e) => {
76
+ tracing:: error!( ?e) ;
77
+ }
78
+ }
79
+ }
80
+ _ => { }
51
81
} )
52
82
. build ( )
53
83
}
@@ -74,10 +104,10 @@ fn socket_cleanup(socket: &PathBuf) {
74
104
let _ = std:: fs:: remove_file ( socket) ;
75
105
}
76
106
77
- fn notify_singleton ( socket : & PathBuf ) -> Result < ( ) , Error > {
107
+ fn notify_singleton ( socket : & PathBuf , args : & [ String ] ) -> Result < ( ) , std :: io :: Error > {
78
108
let stream = UnixStream :: connect ( socket) ?;
79
109
let mut bf = BufWriter :: new ( & stream) ;
80
- let args_joined = std :: env :: args ( ) . collect :: < Vec < String > > ( ) . join ( "\0 " ) ;
110
+ let args_joined = args. join ( "\0 " ) ;
81
111
bf. write_all ( args_joined. as_bytes ( ) ) ?;
82
112
bf. flush ( ) ?;
83
113
drop ( bf) ;
0 commit comments