Add a menu bar option to the desktop config (#2107)
* add an option to set a custom menu in the desktop config * Fix rename issue --------- Co-authored-by: Jonathan Kelley <jkelleyrtp@gmail.com>
This commit is contained in:
1 parent
10d361a44e
commit
d442dac168
11 files changed
+152
-95
No files matched your search
+1
-1
@@ -63,7 +63,7 @@ dioxus-html-internal-macro = { path = "packages/html-internal-macro", version =
|
|||||||
dioxus-hooks = { path = "packages/hooks", version = "0.5.0-alpha.2" }
|
dioxus-hooks = { path = "packages/hooks", version = "0.5.0-alpha.2" }
|
||||||
dioxus-web = { path = "packages/web", version = "0.5.0-alpha.2" }
|
dioxus-web = { path = "packages/web", version = "0.5.0-alpha.2" }
|
||||||
dioxus-ssr = { path = "packages/ssr", version = "0.5.0-alpha.2", default-features = false }
|
dioxus-ssr = { path = "packages/ssr", version = "0.5.0-alpha.2", default-features = false }
|
||||||
dioxus-desktop = { path = "packages/desktop", version = "0.5.0-alpha.2" }
|
dioxus-desktop = { path = "packages/desktop", version = "0.5.0-alpha.2", default-features = false }
|
||||||
dioxus-mobile = { path = "packages/mobile", version = "0.5.0-alpha.2" }
|
dioxus-mobile = { path = "packages/mobile", version = "0.5.0-alpha.2" }
|
||||||
dioxus-interpreter-js = { path = "packages/interpreter", version = "0.5.0-alpha.2" }
|
dioxus-interpreter-js = { path = "packages/interpreter", version = "0.5.0-alpha.2" }
|
||||||
dioxus-liveview = { path = "packages/liveview", version = "0.5.0-alpha.2" }
|
dioxus-liveview = { path = "packages/liveview", version = "0.5.0-alpha.2" }
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
//! This example shows how to use a custom menu bar with Dioxus desktop.
|
||||||
|
//! This example is not supported on the mobile or web renderers.
|
||||||
|
|
||||||
|
use dioxus::desktop::muda::*;
|
||||||
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// Create a menu bar that only contains the edit menu
|
||||||
|
let menu = Menu::new();
|
||||||
|
let edit_menu = Submenu::new("Edit", true);
|
||||||
|
|
||||||
|
edit_menu
|
||||||
|
.append_items(&[
|
||||||
|
&PredefinedMenuItem::undo(None),
|
||||||
|
&PredefinedMenuItem::redo(None),
|
||||||
|
&PredefinedMenuItem::separator(),
|
||||||
|
&PredefinedMenuItem::cut(None),
|
||||||
|
&PredefinedMenuItem::copy(None),
|
||||||
|
&PredefinedMenuItem::paste(None),
|
||||||
|
&PredefinedMenuItem::select_all(None),
|
||||||
|
])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
menu.append(&edit_menu).unwrap();
|
||||||
|
|
||||||
|
// Create a desktop config that overrides the default menu with the custom menu
|
||||||
|
let config = dioxus::desktop::Config::new().with_menu(menu);
|
||||||
|
|
||||||
|
// Launch the app with the custom menu
|
||||||
|
LaunchBuilder::new().with_cfg(config).launch(app)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn app() -> Element {
|
||||||
|
rsx! {"Hello World!"}
|
||||||
|
}
|
||||||
@@ -8,12 +8,12 @@
|
|||||||
use dioxus::desktop::tao::event::Event as WryEvent;
|
use dioxus::desktop::tao::event::Event as WryEvent;
|
||||||
use dioxus::desktop::tao::event::WindowEvent;
|
use dioxus::desktop::tao::event::WindowEvent;
|
||||||
use dioxus::desktop::use_wry_event_handler;
|
use dioxus::desktop::use_wry_event_handler;
|
||||||
use dioxus::desktop::{Config, WindowCloseBehaviour};
|
use dioxus::desktop::{Config, WindowCloseBehavior};
|
||||||
use dioxus::prelude::*;
|
use dioxus::prelude::*;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
LaunchBuilder::desktop()
|
LaunchBuilder::desktop()
|
||||||
.with_cfg(Config::new().with_close_behaviour(WindowCloseBehaviour::CloseWindow))
|
.with_cfg(Config::new().with_close_behaviour(WindowCloseBehavior::CloseWindow))
|
||||||
.launch(app)
|
.launch(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
config::{Config, WindowCloseBehaviour},
|
config::{Config, WindowCloseBehavior},
|
||||||
element::DesktopElement,
|
element::DesktopElement,
|
||||||
event_handlers::WindowEventHandlers,
|
event_handlers::WindowEventHandlers,
|
||||||
file_upload::{DesktopFileDragEvent, DesktopFileUploadForm, FileDialogRequest},
|
file_upload::{DesktopFileDragEvent, DesktopFileUploadForm, FileDialogRequest},
|
||||||
@@ -33,7 +33,7 @@ pub(crate) struct App {
|
|||||||
// Stuff we need mutable access to
|
// Stuff we need mutable access to
|
||||||
pub(crate) control_flow: ControlFlow,
|
pub(crate) control_flow: ControlFlow,
|
||||||
pub(crate) is_visible_before_start: bool,
|
pub(crate) is_visible_before_start: bool,
|
||||||
pub(crate) window_behavior: WindowCloseBehaviour,
|
pub(crate) window_behavior: WindowCloseBehavior,
|
||||||
pub(crate) webviews: HashMap<WindowId, WebviewInstance>,
|
pub(crate) webviews: HashMap<WindowId, WebviewInstance>,
|
||||||
|
|
||||||
/// This single blob of state is shared between all the windows so they have access to the runtime state
|
/// This single blob of state is shared between all the windows so they have access to the runtime state
|
||||||
@@ -43,8 +43,6 @@ pub(crate) struct App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A bundle of state shared between all the windows, providing a way for us to communicate with running webview.
|
/// A bundle of state shared between all the windows, providing a way for us to communicate with running webview.
|
||||||
///
|
|
||||||
/// Todo: everything in this struct is wrapped in Rc<>, but we really only need the one top-level refcell
|
|
||||||
pub(crate) struct SharedContext {
|
pub(crate) struct SharedContext {
|
||||||
pub(crate) event_handlers: WindowEventHandlers,
|
pub(crate) event_handlers: WindowEventHandlers,
|
||||||
pub(crate) pending_webviews: RefCell<Vec<WebviewInstance>>,
|
pub(crate) pending_webviews: RefCell<Vec<WebviewInstance>>,
|
||||||
@@ -58,7 +56,7 @@ impl App {
|
|||||||
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
let event_loop = EventLoopBuilder::<UserWindowEvent>::with_user_event().build();
|
||||||
|
|
||||||
let app = Self {
|
let app = Self {
|
||||||
window_behavior: cfg.last_window_close_behaviour,
|
window_behavior: cfg.last_window_close_behavior,
|
||||||
is_visible_before_start: true,
|
is_visible_before_start: true,
|
||||||
webviews: HashMap::new(),
|
webviews: HashMap::new(),
|
||||||
control_flow: ControlFlow::Wait,
|
control_flow: ControlFlow::Wait,
|
||||||
@@ -128,7 +126,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_close_requested(&mut self, id: WindowId) {
|
pub fn handle_close_requested(&mut self, id: WindowId) {
|
||||||
use WindowCloseBehaviour::*;
|
use WindowCloseBehavior::*;
|
||||||
|
|
||||||
match self.window_behavior {
|
match self.window_behavior {
|
||||||
LastWindowExitsApp => {
|
LastWindowExitsApp => {
|
||||||
@@ -156,7 +154,7 @@ impl App {
|
|||||||
|
|
||||||
if matches!(
|
if matches!(
|
||||||
self.window_behavior,
|
self.window_behavior,
|
||||||
WindowCloseBehaviour::LastWindowExitsApp
|
WindowCloseBehavior::LastWindowExitsApp
|
||||||
) && self.webviews.is_empty()
|
) && self.webviews.is_empty()
|
||||||
{
|
{
|
||||||
self.control_flow = ControlFlow::Exit
|
self.control_flow = ControlFlow::Exit
|
||||||
|
|||||||
@@ -3,9 +3,11 @@ use std::path::PathBuf;
|
|||||||
use tao::window::{Icon, WindowBuilder};
|
use tao::window::{Icon, WindowBuilder};
|
||||||
use wry::http::{Request as HttpRequest, Response as HttpResponse};
|
use wry::http::{Request as HttpRequest, Response as HttpResponse};
|
||||||
|
|
||||||
|
use crate::menubar::{default_menu_bar, DioxusMenu};
|
||||||
|
|
||||||
/// The behaviour of the application when the last window is closed.
|
/// The behaviour of the application when the last window is closed.
|
||||||
#[derive(Copy, Clone, Eq, PartialEq)]
|
#[derive(Copy, Clone, Eq, PartialEq)]
|
||||||
pub enum WindowCloseBehaviour {
|
pub enum WindowCloseBehavior {
|
||||||
/// Default behaviour, closing the last window exits the app
|
/// Default behaviour, closing the last window exits the app
|
||||||
LastWindowExitsApp,
|
LastWindowExitsApp,
|
||||||
/// Closing the last window will not actually close it, just hide it
|
/// Closing the last window will not actually close it, just hide it
|
||||||
@@ -17,6 +19,7 @@ pub enum WindowCloseBehaviour {
|
|||||||
/// The configuration for the desktop application.
|
/// The configuration for the desktop application.
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub(crate) window: WindowBuilder,
|
pub(crate) window: WindowBuilder,
|
||||||
|
pub(crate) menu: Option<DioxusMenu>,
|
||||||
pub(crate) protocols: Vec<WryProtocol>,
|
pub(crate) protocols: Vec<WryProtocol>,
|
||||||
pub(crate) pre_rendered: Option<String>,
|
pub(crate) pre_rendered: Option<String>,
|
||||||
pub(crate) disable_context_menu: bool,
|
pub(crate) disable_context_menu: bool,
|
||||||
@@ -26,8 +29,7 @@ pub struct Config {
|
|||||||
pub(crate) custom_index: Option<String>,
|
pub(crate) custom_index: Option<String>,
|
||||||
pub(crate) root_name: String,
|
pub(crate) root_name: String,
|
||||||
pub(crate) background_color: Option<(u8, u8, u8, u8)>,
|
pub(crate) background_color: Option<(u8, u8, u8, u8)>,
|
||||||
pub(crate) last_window_close_behaviour: WindowCloseBehaviour,
|
pub(crate) last_window_close_behavior: WindowCloseBehavior,
|
||||||
pub(crate) enable_default_menu_bar: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type WryProtocol = (
|
pub(crate) type WryProtocol = (
|
||||||
@@ -48,6 +50,7 @@ impl Config {
|
|||||||
|
|
||||||
Self {
|
Self {
|
||||||
window,
|
window,
|
||||||
|
menu: Some(default_menu_bar()),
|
||||||
protocols: Vec::new(),
|
protocols: Vec::new(),
|
||||||
pre_rendered: None,
|
pre_rendered: None,
|
||||||
disable_context_menu: !cfg!(debug_assertions),
|
disable_context_menu: !cfg!(debug_assertions),
|
||||||
@@ -57,19 +60,10 @@ impl Config {
|
|||||||
custom_index: None,
|
custom_index: None,
|
||||||
root_name: "main".to_string(),
|
root_name: "main".to_string(),
|
||||||
background_color: None,
|
background_color: None,
|
||||||
last_window_close_behaviour: WindowCloseBehaviour::LastWindowExitsApp,
|
last_window_close_behavior: WindowCloseBehavior::LastWindowExitsApp,
|
||||||
enable_default_menu_bar: true,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set whether the default menu bar should be enabled.
|
|
||||||
///
|
|
||||||
/// > Note: `enable` is `true` by default. To disable the default menu bar pass `false`.
|
|
||||||
pub fn with_default_menu_bar(mut self, enable: bool) -> Self {
|
|
||||||
self.enable_default_menu_bar = enable;
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
/// set the directory from which assets will be searched in release mode
|
/// set the directory from which assets will be searched in release mode
|
||||||
pub fn with_resource_directory(mut self, path: impl Into<PathBuf>) -> Self {
|
pub fn with_resource_directory(mut self, path: impl Into<PathBuf>) -> Self {
|
||||||
self.resource_dir = Some(path.into());
|
self.resource_dir = Some(path.into());
|
||||||
@@ -105,8 +99,8 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the behaviour of the application when the last window is closed.
|
/// Sets the behaviour of the application when the last window is closed.
|
||||||
pub fn with_close_behaviour(mut self, behaviour: WindowCloseBehaviour) -> Self {
|
pub fn with_close_behaviour(mut self, behaviour: WindowCloseBehavior) -> Self {
|
||||||
self.last_window_close_behaviour = behaviour;
|
self.last_window_close_behavior = behaviour;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,7 +140,7 @@ impl Config {
|
|||||||
|
|
||||||
/// Set the name of the element that Dioxus will use as the root.
|
/// Set the name of the element that Dioxus will use as the root.
|
||||||
///
|
///
|
||||||
/// This is akint to calling React.render() on the element with the specified name.
|
/// This is akin to calling React.render() on the element with the specified name.
|
||||||
pub fn with_root_name(mut self, name: impl Into<String>) -> Self {
|
pub fn with_root_name(mut self, name: impl Into<String>) -> Self {
|
||||||
self.root_name = name.into();
|
self.root_name = name.into();
|
||||||
self
|
self
|
||||||
@@ -159,6 +153,18 @@ impl Config {
|
|||||||
self.background_color = Some(color);
|
self.background_color = Some(color);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets the menu the window will use. This will override the default menu bar.
|
||||||
|
///
|
||||||
|
/// > Note: A default menu bar will be enabled unless the menu is overridden or set to `None`.
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn with_menu(mut self, menu: impl Into<Option<DioxusMenu>>) -> Self {
|
||||||
|
#[cfg(not(any(target_os = "ios", target_os = "android")))]
|
||||||
|
{
|
||||||
|
self.menu = menu.into();
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
|
|||||||
@@ -35,10 +35,13 @@ pub use tao::dpi::{LogicalPosition, LogicalSize};
|
|||||||
pub use tao::event::WindowEvent;
|
pub use tao::event::WindowEvent;
|
||||||
pub use tao::window::WindowBuilder;
|
pub use tao::window::WindowBuilder;
|
||||||
pub use wry;
|
pub use wry;
|
||||||
|
// Reexport muda only if we are on desktop platforms that support menus
|
||||||
|
#[cfg(not(any(target_os = "ios", target_os = "android")))]
|
||||||
|
pub use muda;
|
||||||
|
|
||||||
// Public exports
|
// Public exports
|
||||||
pub use assets::AssetRequest;
|
pub use assets::AssetRequest;
|
||||||
pub use config::{Config, WindowCloseBehaviour};
|
pub use config::{Config, WindowCloseBehavior};
|
||||||
pub use desktop_context::{window, DesktopContext, DesktopService};
|
pub use desktop_context::{window, DesktopContext, DesktopService};
|
||||||
pub use event_handlers::WryEventHandler;
|
pub use event_handlers::WryEventHandler;
|
||||||
pub use hooks::{use_asset_handler, use_global_shortcut, use_window, use_wry_event_handler};
|
pub use hooks::{use_asset_handler, use_global_shortcut, use_window, use_wry_event_handler};
|
||||||
|
|||||||
@@ -1,31 +1,39 @@
|
|||||||
use std::any::Any;
|
|
||||||
|
|
||||||
use tao::window::Window;
|
use tao::window::Window;
|
||||||
|
|
||||||
|
#[cfg(not(any(target_os = "ios", target_os = "android")))]
|
||||||
|
pub type DioxusMenu = muda::Menu;
|
||||||
|
#[cfg(any(target_os = "ios", target_os = "android"))]
|
||||||
|
pub type DioxusMenu = ();
|
||||||
|
|
||||||
|
/// Initializes the menu bar for the window.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn build_menu(window: &Window, default_menu_bar: bool) -> Option<Box<dyn Any>> {
|
pub fn init_menu_bar(menu: &DioxusMenu, window: &Window) {
|
||||||
#[cfg(not(any(target_os = "ios", target_os = "android")))]
|
#[cfg(not(any(target_os = "ios", target_os = "android")))]
|
||||||
{
|
{
|
||||||
return Some(Box::new(impl_::build_menu_bar(default_menu_bar, window)) as Box<dyn Any>);
|
desktop_platforms::init_menu_bar(menu, window);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
None
|
/// Creates a standard menu bar depending on the users platform. It may be used as a starting point
|
||||||
|
/// to further customize the menu bar and pass it to a [`WindowBuilder`](tao::window::WindowBuilder).
|
||||||
|
/// > Note: The default menu bar enables macOS shortcuts like cut/copy/paste.
|
||||||
|
/// > The menu bar differs per platform because of constraints introduced
|
||||||
|
/// > by [`MenuItem`](tao::menu::MenuItem).
|
||||||
|
#[allow(unused)]
|
||||||
|
pub fn default_menu_bar() -> DioxusMenu {
|
||||||
|
#[cfg(not(any(target_os = "ios", target_os = "android")))]
|
||||||
|
{
|
||||||
|
desktop_platforms::default_menu_bar()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(any(target_os = "ios", target_os = "android")))]
|
#[cfg(not(any(target_os = "ios", target_os = "android")))]
|
||||||
mod impl_ {
|
mod desktop_platforms {
|
||||||
use super::*;
|
use super::*;
|
||||||
use muda::{Menu, MenuItem, PredefinedMenuItem, Submenu};
|
use muda::{Menu, MenuItem, PredefinedMenuItem, Submenu};
|
||||||
|
|
||||||
/// Builds a standard menu bar depending on the users platform. It may be used as a starting point
|
|
||||||
/// to further customize the menu bar and pass it to a [`WindowBuilder`](tao::window::WindowBuilder).
|
|
||||||
/// > Note: The default menu bar enables macOS shortcuts like cut/copy/paste.
|
|
||||||
/// > The menu bar differs per platform because of constraints introduced
|
|
||||||
/// > by [`MenuItem`](tao::menu::MenuItem).
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub fn build_menu_bar(default: bool, window: &Window) -> Menu {
|
pub fn init_menu_bar(menu: &Menu, window: &Window) {
|
||||||
let menu = Menu::new();
|
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
{
|
{
|
||||||
use tao::platform::windows::WindowExtWindows;
|
use tao::platform::windows::WindowExtWindows;
|
||||||
@@ -44,53 +52,54 @@ mod impl_ {
|
|||||||
use tao::platform::macos::WindowExtMacOS;
|
use tao::platform::macos::WindowExtMacOS;
|
||||||
menu.init_for_nsapp();
|
menu.init_for_nsapp();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if default {
|
pub fn default_menu_bar() -> Menu {
|
||||||
// since it is uncommon on windows to have an "application menu"
|
let menu = Menu::new();
|
||||||
// we add a "window" menu to be more consistent across platforms with the standard menu
|
// since it is uncommon on windows to have an "application menu"
|
||||||
let window_menu = Submenu::new("Window", true);
|
// we add a "window" menu to be more consistent across platforms with the standard menu
|
||||||
window_menu
|
let window_menu = Submenu::new("Window", true);
|
||||||
.append_items(&[
|
window_menu
|
||||||
&PredefinedMenuItem::fullscreen(None),
|
.append_items(&[
|
||||||
&PredefinedMenuItem::separator(),
|
&PredefinedMenuItem::fullscreen(None),
|
||||||
&PredefinedMenuItem::hide(None),
|
&PredefinedMenuItem::separator(),
|
||||||
&PredefinedMenuItem::hide_others(None),
|
&PredefinedMenuItem::hide(None),
|
||||||
&PredefinedMenuItem::show_all(None),
|
&PredefinedMenuItem::hide_others(None),
|
||||||
&PredefinedMenuItem::maximize(None),
|
&PredefinedMenuItem::show_all(None),
|
||||||
&PredefinedMenuItem::minimize(None),
|
&PredefinedMenuItem::maximize(None),
|
||||||
&PredefinedMenuItem::close_window(None),
|
&PredefinedMenuItem::minimize(None),
|
||||||
&PredefinedMenuItem::separator(),
|
&PredefinedMenuItem::close_window(None),
|
||||||
&PredefinedMenuItem::quit(None),
|
&PredefinedMenuItem::separator(),
|
||||||
])
|
&PredefinedMenuItem::quit(None),
|
||||||
.unwrap();
|
])
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let edit_menu = Submenu::new("Edit", true);
|
let edit_menu = Submenu::new("Edit", true);
|
||||||
edit_menu
|
edit_menu
|
||||||
.append_items(&[
|
.append_items(&[
|
||||||
&PredefinedMenuItem::undo(None),
|
&PredefinedMenuItem::undo(None),
|
||||||
&PredefinedMenuItem::redo(None),
|
&PredefinedMenuItem::redo(None),
|
||||||
&PredefinedMenuItem::separator(),
|
&PredefinedMenuItem::separator(),
|
||||||
&PredefinedMenuItem::cut(None),
|
&PredefinedMenuItem::cut(None),
|
||||||
&PredefinedMenuItem::copy(None),
|
&PredefinedMenuItem::copy(None),
|
||||||
&PredefinedMenuItem::paste(None),
|
&PredefinedMenuItem::paste(None),
|
||||||
&PredefinedMenuItem::separator(),
|
&PredefinedMenuItem::separator(),
|
||||||
&PredefinedMenuItem::select_all(None),
|
&PredefinedMenuItem::select_all(None),
|
||||||
])
|
])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let help_menu = Submenu::new("Help", true);
|
let help_menu = Submenu::new("Help", true);
|
||||||
help_menu
|
help_menu
|
||||||
.append_items(&[&MenuItem::new("Toggle Developer Tools", true, None)])
|
.append_items(&[&MenuItem::new("Toggle Developer Tools", true, None)])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
menu.append_items(&[&window_menu, &edit_menu, &help_menu])
|
menu.append_items(&[&window_menu, &edit_menu, &help_menu])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
{
|
{
|
||||||
window_menu.set_as_windows_menu_for_nsapp();
|
window_menu.set_as_windows_menu_for_nsapp();
|
||||||
help_menu.set_as_help_menu_for_nsapp();
|
help_menu.set_as_help_menu_for_nsapp();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
menu
|
menu
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
use crate::menubar::DioxusMenu;
|
||||||
use crate::{
|
use crate::{
|
||||||
app::SharedContext, assets::AssetHandlerRegistry, edits::EditQueue, eval::DesktopEvalProvider,
|
app::SharedContext, assets::AssetHandlerRegistry, edits::EditQueue, eval::DesktopEvalProvider,
|
||||||
file_upload::NativeFileHover, ipc::UserWindowEvent, protocol, waker::tao_waker, Config,
|
file_upload::NativeFileHover, ipc::UserWindowEvent, protocol, waker::tao_waker, Config,
|
||||||
@@ -6,7 +7,7 @@ use crate::{
|
|||||||
use dioxus_core::{ScopeId, VirtualDom};
|
use dioxus_core::{ScopeId, VirtualDom};
|
||||||
use dioxus_html::prelude::EvalProvider;
|
use dioxus_html::prelude::EvalProvider;
|
||||||
use futures_util::{pin_mut, FutureExt};
|
use futures_util::{pin_mut, FutureExt};
|
||||||
use std::{any::Any, rc::Rc, task::Waker};
|
use std::{rc::Rc, task::Waker};
|
||||||
use wry::{RequestAsyncResponder, WebContext, WebViewBuilder};
|
use wry::{RequestAsyncResponder, WebContext, WebViewBuilder};
|
||||||
|
|
||||||
pub(crate) struct WebviewInstance {
|
pub(crate) struct WebviewInstance {
|
||||||
@@ -19,11 +20,11 @@ pub(crate) struct WebviewInstance {
|
|||||||
_web_context: WebContext,
|
_web_context: WebContext,
|
||||||
|
|
||||||
// Same with the menu.
|
// Same with the menu.
|
||||||
// Currently it's a box<dyn any> because 1) we don't touch it and 2) we support a number of platforms
|
// Currently it's a DioxusMenu because 1) we don't touch it and 2) we support a number of platforms
|
||||||
// like ios where muda does not give us a menu type. It sucks but alas.
|
// like ios where muda does not give us a menu type. It sucks but alas.
|
||||||
//
|
//
|
||||||
// This would be a good thing for someone looking to contribute to fix.
|
// This would be a good thing for someone looking to contribute to fix.
|
||||||
_menu: Option<Box<dyn Any>>,
|
_menu: Option<DioxusMenu>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebviewInstance {
|
impl WebviewInstance {
|
||||||
@@ -165,9 +166,11 @@ impl WebviewInstance {
|
|||||||
|
|
||||||
let webview = webview.build().unwrap();
|
let webview = webview.build().unwrap();
|
||||||
|
|
||||||
// TODO: allow users to specify their own menubars, again :/
|
|
||||||
let menu = if cfg!(not(any(target_os = "android", target_os = "ios"))) {
|
let menu = if cfg!(not(any(target_os = "android", target_os = "ios"))) {
|
||||||
crate::menubar::build_menu(&window, cfg.enable_default_menu_bar)
|
if let Some(menu) = &cfg.menu {
|
||||||
|
crate::menubar::init_menu_bar(menu, &window);
|
||||||
|
}
|
||||||
|
cfg.menu
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
@@ -221,7 +224,7 @@ impl WebviewInstance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unused)]
|
#[cfg(all(feature = "hot-reload", debug_assertions))]
|
||||||
pub fn kick_stylsheets(&self) {
|
pub fn kick_stylsheets(&self) {
|
||||||
// run eval in the webview to kick the stylesheets by appending a query string
|
// run eval in the webview to kick the stylesheets by appending a query string
|
||||||
// we should do something less clunky than this
|
// we should do something less clunky than this
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ dioxus-signals = { workspace = true, optional = true }
|
|||||||
dioxus-router = { workspace = true, optional = true }
|
dioxus-router = { workspace = true, optional = true }
|
||||||
dioxus-web = { workspace = true, optional = true }
|
dioxus-web = { workspace = true, optional = true }
|
||||||
dioxus-mobile = { workspace = true, optional = true }
|
dioxus-mobile = { workspace = true, optional = true }
|
||||||
dioxus-desktop = { workspace = true, optional = true }
|
dioxus-desktop = { workspace = true, default-features = true, optional = true }
|
||||||
dioxus-fullstack = { workspace = true, optional = true }
|
dioxus-fullstack = { workspace = true, optional = true }
|
||||||
dioxus-liveview = { workspace = true, optional = true }
|
dioxus-liveview = { workspace = true, optional = true }
|
||||||
dioxus-ssr ={ workspace = true, optional = true }
|
dioxus-ssr ={ workspace = true, optional = true }
|
||||||
|
|
||||||
serde = { version = "1.0.136", optional = true }
|
serde = { version = "1.0.136", optional = true }
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(any(target_arch = "wasm32", target_os = "ios", target_os = "android")))'.dependencies]
|
||||||
dioxus-hot-reload = { workspace = true, optional = true }
|
dioxus-hot-reload = { workspace = true, optional = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
@@ -44,7 +44,7 @@ router = ["dioxus-router"]
|
|||||||
# Platforms
|
# Platforms
|
||||||
fullstack = ["dioxus-fullstack", "dioxus-config-macro/fullstack", "serde", "dioxus-router?/fullstack"]
|
fullstack = ["dioxus-fullstack", "dioxus-config-macro/fullstack", "serde", "dioxus-router?/fullstack"]
|
||||||
desktop = ["dioxus-desktop", "dioxus-fullstack?/desktop", "dioxus-config-macro/desktop"]
|
desktop = ["dioxus-desktop", "dioxus-fullstack?/desktop", "dioxus-config-macro/desktop"]
|
||||||
mobile = ["dioxus-mobile", "dioxus-desktop", "dioxus-fullstack?/mobile", "dioxus-config-macro/mobile"]
|
mobile = ["dioxus-mobile", "dioxus-fullstack?/mobile", "dioxus-config-macro/mobile"]
|
||||||
web = ["dioxus-web", "dioxus-fullstack?/web", "dioxus-config-macro/web", "dioxus-router?/web"]
|
web = ["dioxus-web", "dioxus-fullstack?/web", "dioxus-config-macro/web", "dioxus-router?/web"]
|
||||||
ssr = ["dioxus-ssr", "dioxus-router?/ssr", "dioxus-config-macro/ssr"]
|
ssr = ["dioxus-ssr", "dioxus-router?/ssr", "dioxus-config-macro/ssr"]
|
||||||
liveview = ["dioxus-liveview", "dioxus-config-macro/liveview", "dioxus-router?/liveview"]
|
liveview = ["dioxus-liveview", "dioxus-config-macro/liveview", "dioxus-router?/liveview"]
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ mod current_platform {
|
|||||||
pub use dioxus_desktop::launch::*;
|
pub use dioxus_desktop::launch::*;
|
||||||
|
|
||||||
#[cfg(all(feature = "mobile", not(feature = "fullstack")))]
|
#[cfg(all(feature = "mobile", not(feature = "fullstack")))]
|
||||||
pub use dioxus_desktop::launch::*;
|
pub use dioxus_mobile::launch::*;
|
||||||
|
|
||||||
#[cfg(feature = "fullstack")]
|
#[cfg(feature = "fullstack")]
|
||||||
pub use dioxus_fullstack::launch::*;
|
pub use dioxus_fullstack::launch::*;
|
||||||
|
|||||||
@@ -63,7 +63,10 @@ pub mod prelude {
|
|||||||
#[cfg_attr(docsrs, doc(cfg(feature = "html")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "html")))]
|
||||||
pub use dioxus_elements::{prelude::*, GlobalAttributes, SvgAttributes};
|
pub use dioxus_elements::{prelude::*, GlobalAttributes, SvgAttributes};
|
||||||
|
|
||||||
#[cfg(all(not(target_arch = "wasm32"), feature = "hot-reload"))]
|
#[cfg(all(
|
||||||
|
not(any(target_arch = "wasm32", target_os = "ios", target_os = "android")),
|
||||||
|
feature = "hot-reload"
|
||||||
|
))]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "hot-reload")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "hot-reload")))]
|
||||||
pub use dioxus_hot_reload::{self, hot_reload_init};
|
pub use dioxus_hot_reload::{self, hot_reload_init};
|
||||||
|
|
||||||
@@ -100,7 +103,7 @@ pub use dioxus_desktop as desktop;
|
|||||||
|
|
||||||
#[cfg(feature = "mobile")]
|
#[cfg(feature = "mobile")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "mobile")))]
|
||||||
pub use dioxus_desktop as mobile;
|
pub use dioxus_mobile as mobile;
|
||||||
|
|
||||||
#[cfg(feature = "liveview")]
|
#[cfg(feature = "liveview")]
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "liveview")))]
|
#[cfg_attr(docsrs, doc(cfg(feature = "liveview")))]
|
||||||
|
|||||||
Reference in new issue
Block a user