diff --git a/src/main.rs b/src/main.rs index daccf5f3f..fdab63353 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,14 +18,7 @@ fn main() { fn main() { // https://docs.rs/flexi_logger/latest/flexi_logger/error_info/index.html#write let mut _async_logger_holder: Option = None; - let mut args = Vec::new(); - let mut i = 0; - for arg in std::env::args() { - if i > 0 { - args.push(arg); - } - i += 1; - } + let mut args: Vec = std::env::args().skip(1).collect(); if args.len() > 0 && args[0] == "--version" { println!("{}", crate::VERSION); return; diff --git a/src/ui.rs b/src/ui.rs index 0afb761f5..268b8bc59 100644 --- a/src/ui.rs +++ b/src/ui.rs @@ -71,7 +71,7 @@ pub fn start(args: &mut [String]) { allow_err!(sciter::set_options(sciter::RuntimeOptions::UxTheming(true))); frame.set_title(APP_NAME); #[cfg(target_os = "macos")] - macos::make_menubar(); + macos::make_menubar(frame.get_host()); let page; if args.len() > 1 && args[0] == "--play" { args[0] = "--connect".to_owned(); diff --git a/src/ui/index.tis b/src/ui/index.tis index 90c99d693..3e15bd904 100644 --- a/src/ui/index.tis +++ b/src/ui/index.tis @@ -170,7 +170,7 @@ class MyIdMenu: Reactor.Component {
  • {translate('Socks5 Proxy')}
  • {is_win ?
  • Install virtual display
  • : ""}
    -
  • {svg_checkmark}{translate("Enable Service")}
  • +
  • {svg_checkmark}{translate("Enable Service")}
  • {translate('About')} {" "} {handler.get_app_name()}
  • @@ -179,11 +179,15 @@ class MyIdMenu: Reactor.Component { } event click $(svg#menu) (_, me) { + this.showSettingMenu(); + } + + function showSettingMenu() { audioInputMenu.update({ show: true }); this.toggleMenuState(); if (direct_server) direct_server.update(); var menu = $(menu#config-options); - me.popup(menu); + this.popup(menu); } function toggleMenuState() { @@ -192,10 +196,29 @@ class MyIdMenu: Reactor.Component { var enabled = handler.get_option(el.id) != "N"; el.attributes.toggleClass("selected", enabled); el.attributes.toggleClass("line-through", !enabled); + } else if (el.id && el.id === "stop-service") { + el.attributes.toggleClass("selected", !service_stopped); + el.attributes.toggleClass("line-through", service_stopped); } } } + function showAbout() { + var name = handler.get_app_name(); + msgbox("custom-nocancel-nook-hasclose", "About " + name, "
    \ +
    Version: " + handler.get_version() + " \ +
    Privacy Statement
    \ +
    Website
    \ +
    Copyright © 2022 Purslane Ltd.\ +

    Made with heart in this chaotic world!

    \ +
    \ +
    ", function(el) { + if (el && el.attributes) { + handler.open_url(el.attributes['url']); + }; + }, 400); + } + event click $(menu#config-options>li) (_, me) { if (me.id && me.id.indexOf("enable-") == 0) { handler.set_option(me.id, handler.get_option(me.id) == "N" ? "" : "N"); @@ -274,19 +297,7 @@ class MyIdMenu: Reactor.Component { } else if (me.id == "stop-service") { handler.set_option("stop-service", service_stopped ? "" : "Y"); } else if (me.id == "about") { - var name = handler.get_app_name(); - msgbox("custom-nocancel-nook-hasclose", "About " + name, "
    \ -
    Version: " + handler.get_version() + " \ -
    Privacy Statement
    \ -
    Website
    \ -
    Copyright © 2022 Purslane Ltd.\ -

    Made with heart in this chaotic world!

    \ -
    \ -
    ", function(el) { - if (el && el.attributes) { - handler.open_url(el.attributes['url']); - }; - }, 400); + this.showAbout() } } } @@ -344,7 +355,7 @@ class App: Reactor.Component
    {translate('Your Desktop')}
    {translate('desk_tip')}
    - + {key_confirmed ? : translate("Generating ...")}
    @@ -728,7 +739,7 @@ event keydown (evt) { } } -$(body).content(); +$(body).content(); function self.closing() { // return false; // can prevent window close @@ -748,6 +759,14 @@ function self.ready() { } } +function showAbout() { + $(body).$(#app).$(#id-menu).showAbout(); +} + +function showSettings() { + $(body).$(#app).$(#id-menu).showSettingMenu(); +} + function checkConnectStatus() { self.timer(1s, function() { var tmp = !!handler.get_option("stop-service"); diff --git a/src/ui/macos.rs b/src/ui/macos.rs index b722f3875..44b246aa2 100644 --- a/src/ui/macos.rs +++ b/src/ui/macos.rs @@ -11,13 +11,20 @@ use objc::{ runtime::{Object, Sel, BOOL}, sel, sel_impl, }; +use sciter::{make_args, Host}; use std::{ ffi::c_void, + rc::Rc, sync::{Arc, Mutex}, }; static APP_HANDLER_IVAR: &str = "GoDeskAppHandler"; +const TERMINATE_TAG: u32 = 0; +const SHOW_ABOUT_TAG: u32 = 1; +const SHOW_SETTINGS_TAG: u32 = 2; +const RUN_ME_TAG: u32 = 3; + lazy_static::lazy_static! { pub static ref SHOULD_OPEN_UNTITLED_FILE_CALLBACK: Arc>>> = Default::default(); } @@ -32,7 +39,7 @@ struct DelegateState { impl DelegateState { fn command(&mut self, command: u32) { - if command == 0 { + if command == TERMINATE_TAG { unsafe { let () = msg_send!(NSApp(), terminate: nil); } @@ -42,6 +49,16 @@ impl DelegateState { } } +impl AppHandler for Rc { + fn command(&mut self, cmd: u32) { + if cmd == SHOW_ABOUT_TAG { + let _ = self.call_function("showAbout", &make_args![]); + } else if cmd == SHOW_SETTINGS_TAG { + let _ = self.call_function("showSettings", &make_args![]); + } + } +} + // https://github.com/xi-editor/druid/blob/master/druid-shell/src/platform/mac/application.rs unsafe fn set_delegate(handler: Option>) { let mut decl = @@ -92,32 +109,57 @@ extern "C" fn application_should_handle_open_untitled_file( extern "C" fn handle_menu_item(this: &mut Object, _: Sel, item: id) { unsafe { let tag: isize = msg_send![item, tag]; - if tag == 0 { + let tag = tag as u32; + if tag == RUN_ME_TAG { + crate::run_me(Vec::::new()).ok(); + } else { let inner: *mut c_void = *this.get_ivar(APP_HANDLER_IVAR); let inner = &mut *(inner as *mut DelegateState); (*inner).command(tag as u32); - } else if tag == 1 { - crate::run_me(Vec::::new()).ok(); } } } -pub fn make_menubar() { +unsafe fn make_menu_item(title: &str, key: &str, tag: u32) -> *mut Object { + let title = NSString::alloc(nil).init_str(title); + let action = sel!(handleMenuItem:); + let key = NSString::alloc(nil).init_str(key); + let object = NSMenuItem::alloc(nil) + .initWithTitle_action_keyEquivalent_(title, action, key) + .autorelease(); + let () = msg_send![object, setTag: tag]; + object +} + +pub fn make_menubar(host: Rc) { unsafe { let _pool = NSAutoreleasePool::new(nil); - set_delegate(None); + set_delegate(Some(Box::new(host))); let menubar = NSMenu::new(nil).autorelease(); let app_menu_item = NSMenuItem::new(nil).autorelease(); menubar.addItem_(app_menu_item); let app_menu = NSMenu::new(nil).autorelease(); - let quit_title = - NSString::alloc(nil).init_str(&format!("Quit {}", hbb_common::config::APP_NAME)); - let quit_action = sel!(handleMenuItem:); - let quit_key = NSString::alloc(nil).init_str("q"); - let quit_item = NSMenuItem::alloc(nil) - .initWithTitle_action_keyEquivalent_(quit_title, quit_action, quit_key) - .autorelease(); - let () = msg_send![quit_item, setTag: 0]; + + let about_item = make_menu_item("About", "a", SHOW_ABOUT_TAG); + app_menu.addItem_(about_item); + let separator = NSMenuItem::separatorItem(nil).autorelease(); + app_menu.addItem_(separator); + let settings_item = make_menu_item("Settings", "s", SHOW_SETTINGS_TAG); + app_menu.addItem_(settings_item); + + if std::env::args().len() > 1 { + let new_item = make_menu_item("New Window", "n", RUN_ME_TAG); + app_menu.addItem_(new_item); + } + + let separator = NSMenuItem::separatorItem(nil).autorelease(); + app_menu.addItem_(separator); + let quit_item = make_menu_item( + &format!("Quit {}", hbb_common::config::APP_NAME), + "q", + TERMINATE_TAG, + ); + app_menu_item.setSubmenu_(app_menu); /* if !enabled { let () = msg_send![quit_item, setEnabled: NO]; @@ -129,17 +171,6 @@ pub fn make_menubar() { let () = msg_send![item, setTag: id as isize]; */ app_menu.addItem_(quit_item); - if std::env::args().len() > 1 { - let new_title = NSString::alloc(nil).init_str("New Window"); - let new_action = sel!(handleMenuItem:); - let new_key = NSString::alloc(nil).init_str("n"); - let new_item = NSMenuItem::alloc(nil) - .initWithTitle_action_keyEquivalent_(new_title, new_action, new_key) - .autorelease(); - let () = msg_send![new_item, setTag: 1]; - app_menu.addItem_(new_item); - } - app_menu_item.setSubmenu_(app_menu); NSApp().setMainMenu_(menubar); } }