@@ -6,16 +6,35 @@ use crate::scripts::commands::{get_script_commands, reply_editor_request, run_sc
6
6
use crate :: scripts:: loader:: scripts:: ScriptManager ;
7
7
use crate :: settings:: { get_settings, set_preferred_language, set_theme, set_wrap_lines, Settings } ;
8
8
use crate :: window:: Windows ;
9
- use tauri:: async_runtime:: Mutex ;
10
- use tauri:: menu:: { AboutMetadataBuilder , Menu , MenuItemBuilder , SubmenuBuilder } ;
9
+ use tauri:: async_runtime:: { spawn , Mutex } ;
10
+ use tauri:: menu:: { AboutMetadataBuilder , Menu , MenuItemBuilder , Submenu , SubmenuBuilder } ;
11
11
use tauri:: path:: BaseDirectory ;
12
12
use tauri:: Error :: WebviewLabelAlreadyExists ;
13
- use tauri:: { AppHandle , Emitter , Manager , WebviewUrl , WebviewWindowBuilder , WindowEvent } ;
13
+ use tauri:: {
14
+ AppHandle , Emitter , Manager , State , WebviewUrl , WebviewWindowBuilder , WindowEvent , Wry ,
15
+ } ;
14
16
use tauri_plugin_store:: StoreExt ;
15
17
18
+ const MENU_ITEM_ID_SETTINGS : & str = "settings" ;
19
+ const MENU_ITEM_ID_NEW_WINDOW : & str = "window_new" ;
20
+ const MENU_ITEM_ID_SCRIPTS_OPEN_PICKER : & str = "scripts_open_picker" ;
21
+ const MENU_ITEM_ID_SCRIPTS_REEXECUTE_LAST : & str = "scripts_reexecute_last" ;
22
+
23
+ fn get_file_sub_menu ( app : & AppHandle , in_settings : bool ) -> Result < Submenu < Wry > , tauri:: Error > {
24
+ let mut builder = SubmenuBuilder :: new ( app, "File" ) ;
25
+ if !in_settings {
26
+ let new_window_item = MenuItemBuilder :: new ( "New Window" )
27
+ . id ( MENU_ITEM_ID_NEW_WINDOW )
28
+ . accelerator ( "CmdOrCtrl+N" )
29
+ . build ( app) ?;
30
+ builder = builder. item ( & new_window_item) . separator ( ) ;
31
+ }
32
+ builder. close_window ( ) . build ( )
33
+ }
34
+
16
35
fn setup_menu ( app : & AppHandle , in_settings : bool ) -> Result < ( ) , tauri:: Error > {
17
36
let settings = MenuItemBuilder :: new ( "Settings..." )
18
- . id ( "settings" )
37
+ . id ( MENU_ITEM_ID_SETTINGS )
19
38
. accelerator ( "CmdOrCtrl+," )
20
39
. enabled ( !in_settings)
21
40
. build ( app) ?;
@@ -38,8 +57,8 @@ fn setup_menu(app: &AppHandle, in_settings: bool) -> Result<(), tauri::Error> {
38
57
. separator ( )
39
58
. quit ( )
40
59
. build ( ) ?;
41
- let file_sub_menu = SubmenuBuilder :: new ( app, "File" ) . close_window ( ) . build ( ) ?;
42
60
61
+ let file_sub_menu = get_file_sub_menu ( app, in_settings) ?;
43
62
let app_menu = Menu :: new ( app) ?;
44
63
45
64
if !in_settings {
@@ -54,11 +73,11 @@ fn setup_menu(app: &AppHandle, in_settings: bool) -> Result<(), tauri::Error> {
54
73
. build ( ) ?;
55
74
56
75
let open_script_picker_item = MenuItemBuilder :: new ( "Open Picker" )
57
- . id ( "scripts_open_picker" )
76
+ . id ( MENU_ITEM_ID_SCRIPTS_OPEN_PICKER )
58
77
. accelerator ( "CmdOrCtrl+B" )
59
78
. build ( app) ?;
60
79
let reexecute_last_script_item = MenuItemBuilder :: new ( "Re-execute Last Script" )
61
- . id ( "scripts_reexecute_last" )
80
+ . id ( MENU_ITEM_ID_SCRIPTS_REEXECUTE_LAST )
62
81
. accelerator ( "CmdOrCtrl+Shift+B" )
63
82
. enabled ( false )
64
83
. build ( app) ?;
@@ -73,34 +92,6 @@ fn setup_menu(app: &AppHandle, in_settings: bool) -> Result<(), tauri::Error> {
73
92
& edit_sub_menu,
74
93
& scripts_sub_menu,
75
94
] ) ?;
76
-
77
- app. on_menu_event ( move |app, event| {
78
- if event. id ( ) == settings. id ( ) {
79
- let settings_window_result = WebviewWindowBuilder :: new (
80
- app,
81
- "settings" . to_string ( ) ,
82
- WebviewUrl :: App ( "windows/settings.html" . parse ( ) . unwrap ( ) ) ,
83
- )
84
- . min_inner_size ( 200.0 , 400.0 )
85
- . title ( "Snip Settings" )
86
- . build ( ) ;
87
- if let Err ( WebviewLabelAlreadyExists ( _) ) = settings_window_result {
88
- let webview_windows = app. webview_windows ( ) ;
89
- let settings_window = webview_windows. get ( "settings" ) . unwrap ( ) ;
90
- settings_window. unminimize ( ) . unwrap ( ) ; // Must use it if window is minimized
91
- settings_window. set_focus ( ) . unwrap ( ) ;
92
- settings_window. show ( ) . unwrap ( ) ;
93
- }
94
- } else if event. id ( ) == open_script_picker_item. id ( ) {
95
- let focused_window = app. get_focused_window ( ) ;
96
- if let Some ( focused_window) = focused_window {
97
- if focused_window. label ( ) != "settings" {
98
- app. emit_to ( focused_window. label ( ) , "open_picker" , true )
99
- . unwrap ( )
100
- }
101
- }
102
- }
103
- } ) ;
104
95
} else {
105
96
app_menu. append_items ( & [ & app_sub_menu, & file_sub_menu] ) ?;
106
97
}
@@ -113,7 +104,14 @@ fn setup_menu(app: &AppHandle, in_settings: bool) -> Result<(), tauri::Error> {
113
104
pub fn run ( ) {
114
105
tauri:: Builder :: default ( )
115
106
. plugin ( tauri_plugin_os:: init ( ) )
116
- . plugin ( tauri_plugin_single_instance:: init ( |_, _, _| { } ) )
107
+ . plugin ( tauri_plugin_single_instance:: init ( |app, _, _| {
108
+ let app = app. clone ( ) ;
109
+ spawn ( async move {
110
+ let windows: State < ' _ , Mutex < Windows > > = app. state ( ) ;
111
+ let mut windows = windows. lock ( ) . await ;
112
+ windows. create_window ( & app) . unwrap ( ) ;
113
+ } ) ;
114
+ } ) )
117
115
. plugin (
118
116
tauri_plugin_log:: Builder :: new ( )
119
117
. clear_targets ( )
@@ -151,13 +149,54 @@ pub fn run() {
151
149
app. manage ( Mutex :: new ( settings) ) ;
152
150
app. manage ( Mutex :: new ( windows) ) ;
153
151
app. manage ( Mutex :: new ( script_manager) ) ;
152
+
153
+ app. on_menu_event ( move |app, event| {
154
+ match event. id ( ) . 0 . as_str ( ) {
155
+ MENU_ITEM_ID_SETTINGS => {
156
+ let settings_window_result = WebviewWindowBuilder :: new (
157
+ app,
158
+ "settings" . to_string ( ) ,
159
+ WebviewUrl :: App ( "windows/settings.html" . parse ( ) . unwrap ( ) ) ,
160
+ )
161
+ . min_inner_size ( 200.0 , 400.0 )
162
+ . title ( "Snip Settings" )
163
+ . build ( ) ;
164
+ if let Err ( WebviewLabelAlreadyExists ( _) ) = settings_window_result {
165
+ let webview_windows = app. webview_windows ( ) ;
166
+ let settings_window = webview_windows. get ( "settings" ) . unwrap ( ) ;
167
+ settings_window. unminimize ( ) . unwrap ( ) ; // Must use it if window is minimized
168
+ settings_window. set_focus ( ) . unwrap ( ) ;
169
+ settings_window. show ( ) . unwrap ( ) ;
170
+ }
171
+ }
172
+ MENU_ITEM_ID_SCRIPTS_OPEN_PICKER => {
173
+ let focused_window = app. get_focused_window ( ) ;
174
+ if let Some ( focused_window) = focused_window {
175
+ if focused_window. label ( ) != "settings" {
176
+ app. emit_to ( focused_window. label ( ) , "open_picker" , true )
177
+ . unwrap ( )
178
+ }
179
+ }
180
+ }
181
+ MENU_ITEM_ID_NEW_WINDOW => {
182
+ let windows: State < ' _ , Mutex < Windows > > = app. state ( ) ;
183
+ let mut windows = windows. blocking_lock ( ) ;
184
+ windows. create_window ( app) . unwrap ( ) ;
185
+ }
186
+ _ => { }
187
+ }
188
+ } ) ;
189
+
154
190
setup_menu ( app. handle ( ) , false ) ?;
155
191
156
192
Ok ( ( ) )
157
193
} )
158
194
. on_window_event ( |window, event| match event {
159
195
WindowEvent :: Destroyed => {
160
- if window. label ( ) == "main" {
196
+ let windows: State < ' _ , Mutex < Windows > > = window. app_handle ( ) . state ( ) ;
197
+ let windows = & mut windows. blocking_lock ( ) ;
198
+ windows. destroy_window ( window. label ( ) ) ;
199
+ if !windows. has_open ( ) {
161
200
window. app_handle ( ) . exit ( 0 ) ;
162
201
}
163
202
}
0 commit comments