1+ use crate :: PLUGIN_NAME ;
12use tauri:: {
23 image:: Image ,
3- menu:: { Menu , MenuId , MenuItem , PredefinedMenuItem } ,
4+ menu:: { CheckMenuItem , Menu , MenuId , MenuItem , PredefinedMenuItem } ,
45 tray:: TrayIconBuilder ,
5- AppHandle , Manager , Result ,
6+ AppHandle , Result ,
67} ;
78
89pub enum TrayItem {
9- Open ,
10+ Info ,
11+ Github ,
12+ Twitter ,
13+ Discord ,
1014 Quit ,
15+ AlwaysOnTop ,
1116}
1217
1318impl From < TrayItem > for MenuId {
1419 fn from ( value : TrayItem ) -> Self {
1520 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" ,
1725 TrayItem :: Quit => "quit_hypr" ,
26+ TrayItem :: AlwaysOnTop => "always_on_top_hypr" ,
1827 }
1928 . into ( )
2029 }
@@ -24,8 +33,12 @@ impl From<MenuId> for TrayItem {
2433 fn from ( id : MenuId ) -> Self {
2534 let id = id. 0 . as_str ( ) ;
2635 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 ,
2840 "quit_hypr" => TrayItem :: Quit ,
41+ "always_on_top_hypr" => TrayItem :: AlwaysOnTop ,
2942 _ => unreachable ! ( ) ,
3043 }
3144 }
@@ -35,16 +48,35 @@ pub trait TrayPluginExt<R: tauri::Runtime> {
3548 fn create_tray ( & self ) -> Result < ( ) > ;
3649}
3750
51+ #[ derive( Debug , PartialEq , Eq , Hash , strum:: Display ) ]
52+ enum StoreKey {
53+ MainWindowAlwaysOnTop ,
54+ }
55+
56+ impl tauri_plugin_store2:: ScopedStoreKey for StoreKey { }
57+
3858impl < T : tauri:: Manager < tauri:: Wry > > TrayPluginExt < tauri:: Wry > for T {
3959 fn create_tray ( & self ) -> Result < ( ) > {
4060 let app = self . app_handle ( ) ;
4161
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+
4269 let menu = Menu :: with_items (
4370 app,
4471 & [
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,
4678 & PredefinedMenuItem :: separator ( app) ?,
47- & MenuItem :: with_id ( app, TrayItem :: Quit , "Quit" , true , None :: < & str > ) ?,
79+ & quit_menu ( app) ?,
4880 ] ,
4981 ) ?;
5082
@@ -57,10 +89,34 @@ impl<T: tauri::Manager<tauri::Wry>> TrayPluginExt<tauri::Wry> for T {
5789 . show_menu_on_left_click ( true )
5890 . on_menu_event ( {
5991 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 ( ) ;
64120 }
65121 }
66122 TrayItem :: Quit => {
@@ -77,3 +133,55 @@ impl<T: tauri::Manager<tauri::Wry>> TrayPluginExt<tauri::Wry> for T {
77133 Ok ( ( ) )
78134 }
79135}
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