1
+ use crate :: PLUGIN_NAME ;
1
2
use tauri:: {
2
3
image:: Image ,
3
- menu:: { Menu , MenuId , MenuItem , PredefinedMenuItem } ,
4
+ menu:: { CheckMenuItem , Menu , MenuId , MenuItem , PredefinedMenuItem } ,
4
5
tray:: TrayIconBuilder ,
5
- AppHandle , Manager , Result ,
6
+ AppHandle , Result ,
6
7
} ;
7
8
8
9
pub enum TrayItem {
9
- Open ,
10
+ Info ,
11
+ Github ,
12
+ Twitter ,
13
+ Discord ,
10
14
Quit ,
15
+ AlwaysOnTop ,
11
16
}
12
17
13
18
impl From < TrayItem > for MenuId {
14
19
fn from ( value : TrayItem ) -> Self {
15
20
match value {
16
- TrayItem :: Open => "open_hypr" ,
21
+ TrayItem :: Info => "info_hypr" ,
22
+ TrayItem :: Github => "github_hypr" ,
23
+ TrayItem :: Twitter => "twitter_hypr" ,
24
+ TrayItem :: Discord => "discord_hypr" ,
17
25
TrayItem :: Quit => "quit_hypr" ,
26
+ TrayItem :: AlwaysOnTop => "always_on_top_hypr" ,
18
27
}
19
28
. into ( )
20
29
}
@@ -24,8 +33,12 @@ impl From<MenuId> for TrayItem {
24
33
fn from ( id : MenuId ) -> Self {
25
34
let id = id. 0 . as_str ( ) ;
26
35
match id {
27
- "open_hypr" => TrayItem :: Open ,
36
+ "info_hypr" => TrayItem :: Info ,
37
+ "github_hypr" => TrayItem :: Github ,
38
+ "twitter_hypr" => TrayItem :: Twitter ,
39
+ "discord_hypr" => TrayItem :: Discord ,
28
40
"quit_hypr" => TrayItem :: Quit ,
41
+ "always_on_top_hypr" => TrayItem :: AlwaysOnTop ,
29
42
_ => unreachable ! ( ) ,
30
43
}
31
44
}
@@ -35,16 +48,35 @@ pub trait TrayPluginExt<R: tauri::Runtime> {
35
48
fn create_tray ( & self ) -> Result < ( ) > ;
36
49
}
37
50
51
+ #[ derive( Debug , PartialEq , Eq , Hash , strum:: Display ) ]
52
+ enum StoreKey {
53
+ MainWindowAlwaysOnTop ,
54
+ }
55
+
56
+ impl tauri_plugin_store2:: ScopedStoreKey for StoreKey { }
57
+
38
58
impl < T : tauri:: Manager < tauri:: Wry > > TrayPluginExt < tauri:: Wry > for T {
39
59
fn create_tray ( & self ) -> Result < ( ) > {
40
60
let app = self . app_handle ( ) ;
41
61
62
+ let store = {
63
+ use tauri_plugin_store2:: StorePluginExt ;
64
+ app. scoped_store :: < StoreKey > ( PLUGIN_NAME ) . unwrap ( )
65
+ } ;
66
+
67
+ let always_on_top = always_on_top_menu ( app, always_on_top_state ( & store) ) ?;
68
+
42
69
let menu = Menu :: with_items (
43
70
app,
44
71
& [
45
- & MenuItem :: with_id ( app, TrayItem :: Open , "Open" , true , None :: < & str > ) ?,
72
+ & info_menu ( app) ?,
73
+ & github_menu ( app) ?,
74
+ & twitter_menu ( app) ?,
75
+ & discord_menu ( app) ?,
76
+ & PredefinedMenuItem :: separator ( app) ?,
77
+ & always_on_top,
46
78
& PredefinedMenuItem :: separator ( app) ?,
47
- & MenuItem :: with_id ( app, TrayItem :: Quit , "Quit" , true , None :: < & str > ) ?,
79
+ & quit_menu ( app) ?,
48
80
] ,
49
81
) ?;
50
82
@@ -57,10 +89,34 @@ impl<T: tauri::Manager<tauri::Wry>> TrayPluginExt<tauri::Wry> for T {
57
89
. show_menu_on_left_click ( true )
58
90
. on_menu_event ( {
59
91
move |app : & AppHandle , event| match TrayItem :: from ( event. id . clone ( ) ) {
60
- TrayItem :: Open => {
61
- if let Some ( window) = app. get_webview_window ( "main" ) {
62
- window. show ( ) . unwrap ( ) ;
63
- window. set_focus ( ) . unwrap ( ) ;
92
+ TrayItem :: Info => { }
93
+ TrayItem :: Github => {
94
+ let _ = webbrowser:: open ( "https://github.com/fastrepl/hyprnote" ) ;
95
+ }
96
+ TrayItem :: Twitter => {
97
+ let _ = webbrowser:: open ( "https://hyprnote.com/x" ) ;
98
+ }
99
+ TrayItem :: Discord => {
100
+ let _ = webbrowser:: open ( "https://hyprnote.com/discord" ) ;
101
+ }
102
+ TrayItem :: AlwaysOnTop => {
103
+ let next_always_on_top = !always_on_top_state ( & store) ;
104
+
105
+ let toggled = {
106
+ use tauri_plugin_windows:: HyprWindowId ;
107
+ if let Some ( window) = HyprWindowId :: Main . get ( app) {
108
+ window. set_always_on_top ( next_always_on_top) . is_ok ( )
109
+ } else {
110
+ false
111
+ }
112
+ } ;
113
+
114
+ if toggled {
115
+ store
116
+ . set ( StoreKey :: MainWindowAlwaysOnTop , next_always_on_top)
117
+ . unwrap ( ) ;
118
+
119
+ always_on_top. set_checked ( next_always_on_top) . unwrap ( ) ;
64
120
}
65
121
}
66
122
TrayItem :: Quit => {
@@ -77,3 +133,55 @@ impl<T: tauri::Manager<tauri::Wry>> TrayPluginExt<tauri::Wry> for T {
77
133
Ok ( ( ) )
78
134
}
79
135
}
136
+
137
+ fn info_menu < R : tauri:: Runtime > ( app : & AppHandle < R > ) -> Result < MenuItem < R > > {
138
+ let info = app. package_info ( ) ;
139
+
140
+ let display_name = match info. name . as_str ( ) {
141
+ "Hyprnote" => format ! ( "Hyprnote v{}" , & info. version) ,
142
+ "Hyprnote Dev" => format ! ( "Hyprnote v{} (dev)" , & info. version) ,
143
+ "Hyprnote Nightly" => format ! ( "Hyprnote v{} (nightly)" , & info. version) ,
144
+ _ => unreachable ! ( ) ,
145
+ } ;
146
+
147
+ MenuItem :: with_id ( app, TrayItem :: Info , & display_name, false , None :: < & str > )
148
+ }
149
+
150
+ fn github_menu < R : tauri:: Runtime > ( app : & AppHandle < R > ) -> Result < MenuItem < R > > {
151
+ MenuItem :: with_id ( app, TrayItem :: Github , "GitHub" , true , None :: < & str > )
152
+ }
153
+
154
+ fn twitter_menu < R : tauri:: Runtime > ( app : & AppHandle < R > ) -> Result < MenuItem < R > > {
155
+ MenuItem :: with_id ( app, TrayItem :: Twitter , "Twitter" , true , None :: < & str > )
156
+ }
157
+
158
+ fn discord_menu < R : tauri:: Runtime > ( app : & AppHandle < R > ) -> Result < MenuItem < R > > {
159
+ MenuItem :: with_id ( app, TrayItem :: Discord , "Discord" , true , None :: < & str > )
160
+ }
161
+
162
+ fn quit_menu < R : tauri:: Runtime > ( app : & AppHandle < R > ) -> Result < MenuItem < R > > {
163
+ MenuItem :: with_id ( app, TrayItem :: Quit , "Quit Completely" , true , Some ( "cmd+q" ) )
164
+ }
165
+
166
+ fn always_on_top_menu < R : tauri:: Runtime > (
167
+ app : & AppHandle < R > ,
168
+ initial_state : bool ,
169
+ ) -> Result < CheckMenuItem < R > > {
170
+ CheckMenuItem :: with_id (
171
+ app,
172
+ TrayItem :: AlwaysOnTop ,
173
+ "Always on top" ,
174
+ true ,
175
+ initial_state,
176
+ Some ( "cmd+shift+t" ) ,
177
+ )
178
+ }
179
+
180
+ fn always_on_top_state < R : tauri:: Runtime > (
181
+ store : & tauri_plugin_store2:: ScopedStore < R , StoreKey > ,
182
+ ) -> bool {
183
+ store
184
+ . get :: < bool > ( StoreKey :: MainWindowAlwaysOnTop )
185
+ . unwrap_or ( Some ( false ) )
186
+ . unwrap_or ( false )
187
+ }
0 commit comments