mirror of
https://github.com/penpot/penpot.git
synced 2026-08-18 10:48:35 +00:00
1165 lines
50 KiB
Clojure
1165 lines
50 KiB
Clojure
;; This Source Code Form is subject to the terms of the Mozilla Public
|
|
;; License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
;;
|
|
;; Copyright (c) KALEIDOS INC Sucursal en España SL
|
|
|
|
(ns app.main.ui.workspace.main-menu
|
|
(:require-macros [app.main.style :as stl])
|
|
(:require
|
|
[app.common.data :as d]
|
|
[app.common.data.macros :as dm]
|
|
[app.common.files.helpers :as cfh]
|
|
[app.common.uuid :as uuid]
|
|
[app.config :as cf]
|
|
[app.main.data.common :as dcm]
|
|
[app.main.data.event :as ev]
|
|
[app.main.data.exports.assets :as de]
|
|
[app.main.data.exports.files :as fexp]
|
|
[app.main.data.modal :as modal]
|
|
[app.main.data.notifications :as ntf]
|
|
[app.main.data.plugins :as dp]
|
|
[app.main.data.profile :as du]
|
|
[app.main.data.shortcuts :as scd]
|
|
[app.main.data.workspace :as dw]
|
|
[app.main.data.workspace.comments :as dwcm]
|
|
[app.main.data.workspace.libraries :as dwl]
|
|
[app.main.data.workspace.mcp :as mcp]
|
|
[app.main.data.workspace.shortcuts :as sc]
|
|
[app.main.data.workspace.undo :as dwu]
|
|
[app.main.data.workspace.versions :as dwv]
|
|
[app.main.features :as features]
|
|
[app.main.refs :as refs]
|
|
[app.main.repo :as rp]
|
|
[app.main.store :as st]
|
|
[app.main.ui.components.dropdown-menu :refer [dropdown-menu*
|
|
dropdown-menu-item*]]
|
|
[app.main.ui.context :as ctx]
|
|
[app.main.ui.dashboard.subscription :refer [get-subscription-type
|
|
main-menu-power-up*]]
|
|
[app.main.ui.ds.buttons.icon-button :refer [icon-button*]]
|
|
[app.main.ui.ds.foundations.assets.icon :as i :refer [icon*]]
|
|
[app.main.ui.hooks.resize :as r]
|
|
[app.plugins.register :as preg]
|
|
[app.util.dom :as dom]
|
|
[app.util.i18n :as i18n :refer [tr]]
|
|
[app.util.keyboard :as kbd]
|
|
[beicon.v2.core :as rx]
|
|
[potok.v2.core :as ptk]
|
|
[rumext.v2 :as mf]))
|
|
|
|
(mf/defc shortcuts*
|
|
{::mf/private true}
|
|
[{:keys [id]}]
|
|
(let [custom-shortcuts (mf/deref refs/custom-shortcuts)
|
|
customized? (let [c (get-in custom-shortcuts [:workspace id])]
|
|
(and c (not= c "")))]
|
|
[:span {:class (stl/css :shortcut)}
|
|
(for [sc (scd/split-sc (sc/get-effective-tooltip id custom-shortcuts))]
|
|
[:span {:class (stl/css-case :shortcut-key true
|
|
:customized-key customized?)
|
|
:key sc}
|
|
sc])]))
|
|
|
|
(mf/defc help-info-menu*
|
|
{::mf/private true
|
|
::mf/wrap [mf/memo]}
|
|
[{:keys [layout on-close]}]
|
|
(let [nav-to-helpc-center
|
|
(mf/use-fn
|
|
(fn []
|
|
(st/emit! (ev/event {::ev/name "explore-help-center-click"
|
|
::ev/origin "workspace:menu"}))
|
|
(dom/open-new-window "https://help.penpot.app")))
|
|
|
|
nav-to-community
|
|
(mf/use-fn
|
|
(fn []
|
|
(st/emit! (ev/event {::ev/name "explore-community-click"
|
|
::ev/origin "workspace:menu"}))
|
|
(dom/open-new-window "https://community.penpot.app")))
|
|
|
|
nav-to-youtube
|
|
(mf/use-fn
|
|
(fn []
|
|
(st/emit! (ev/event {::ev/name "explore-tutorials-click"
|
|
::ev/origin "workspace:menu"}))
|
|
(dom/open-new-window "https://www.youtube.com/c/Penpot")))
|
|
|
|
nav-to-templates
|
|
(mf/use-fn
|
|
(fn []
|
|
(st/emit! (ev/event {::ev/name "explore-libraries-click"
|
|
::ev/origin "workspace"}))
|
|
(dom/open-new-window "https://penpot.app/libraries-templates")))
|
|
|
|
nav-to-github
|
|
(mf/use-fn
|
|
(fn []
|
|
(st/emit! (ev/event {::ev/name "explore-github-repository-click"
|
|
::ev/origin "workspace:menu"}))
|
|
(dom/open-new-window "https://github.com/penpot/penpot")))
|
|
|
|
nav-to-terms
|
|
(mf/use-fn
|
|
(fn []
|
|
(st/emit! (ev/event {::ev/name "explore-terms-service-click"
|
|
::ev/origin "workspace:menu"}))
|
|
(dom/open-new-window "https://penpot.app/terms")))
|
|
|
|
nav-to-feedback
|
|
(mf/use-fn #(st/emit! (dcm/go-to-feedback)))
|
|
|
|
plugins?
|
|
(features/active-feature? @st/state "plugins/runtime")
|
|
|
|
mcp-enabled?
|
|
(contains? cf/flags :mcp)
|
|
|
|
show-shortcuts
|
|
(mf/use-fn
|
|
(mf/deps layout)
|
|
(fn []
|
|
(when (contains? layout :collapse-left-sidebar)
|
|
(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
|
|
|
(st/emit!
|
|
(-> (dw/toggle-layout-flag :shortcuts)
|
|
(vary-meta assoc ::ev/origin "workspace:menu")))))
|
|
|
|
show-release-notes
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(let [version (:main cf/version)]
|
|
(st/emit! (ev/event {::ev/name "show-release-notes"
|
|
:version version}))
|
|
(println version)
|
|
(if (and (kbd/alt? event) (kbd/mod? event))
|
|
(st/emit! (modal/show {:type :onboarding}))
|
|
(st/emit! (modal/show {:type :release-notes
|
|
:version version}))))))]
|
|
|
|
[:> dropdown-menu* {:show true
|
|
:on-close on-close
|
|
:class (stl/css-case :base-menu true
|
|
:sub-menu true
|
|
:pos-final-5 (not (or plugins? mcp-enabled?))
|
|
:pos-final-6 (not= plugins? mcp-enabled?)
|
|
:pos-final-7 (and plugins? mcp-enabled?))}
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click nav-to-helpc-center
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(nav-to-helpc-center event)))
|
|
:id "file-menu-help-center"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "labels.help-center")]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click nav-to-community
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(nav-to-community event)))
|
|
:id "file-menu-community"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "labels.community")]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click nav-to-youtube
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(nav-to-youtube event)))
|
|
:id "file-menu-youtube"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "labels.tutorials")]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click show-release-notes
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(show-release-notes event)))
|
|
:id "file-menu-release-notes"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "labels.release-notes")]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click nav-to-templates
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(nav-to-templates event)))
|
|
:id "file-menu-templates"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "labels.libraries-and-templates")]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click nav-to-github
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(nav-to-github event)))
|
|
:id "file-menu-github"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "labels.github-repo")]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click nav-to-terms
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(nav-to-terms event)))
|
|
:id "file-menu-terms"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "auth.terms-of-service")]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click show-shortcuts
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(show-shortcuts event)))
|
|
:id "file-menu-shortcuts"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "label.shortcuts")]
|
|
[:> shortcuts* {:id :show-shortcuts}]]
|
|
|
|
(when (contains? cf/flags :user-feedback)
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click nav-to-feedback
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(nav-to-feedback event)))
|
|
:id "file-menu-feedback"}
|
|
[:span {:class (stl/css :feedback :item-name)}
|
|
(tr "labels.give-feedback")]])]))
|
|
|
|
(mf/defc preferences-menu*
|
|
{::mf/private true
|
|
::mf/wrap [mf/memo]}
|
|
[{:keys [layout profile toggle-flag on-close toggle-theme toggle-render]}]
|
|
(let [renderer (or (-> profile :props :renderer) :svg)
|
|
|
|
show-nudge-options
|
|
(mf/use-fn
|
|
#(modal/show! {:type :nudge-option}))]
|
|
|
|
[:> dropdown-menu* {:show true
|
|
:class (stl/css :base-menu :sub-menu :pos-4)
|
|
:on-close on-close}
|
|
[:> dropdown-menu-item* {:on-click toggle-flag
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "scale-text"
|
|
:id "file-menu-scale-text"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :scale-text)
|
|
(tr "workspace.header.menu.disable-scale-content")
|
|
(tr "workspace.header.menu.enable-scale-content"))]
|
|
[:> shortcuts* {:id :scale}]]
|
|
|
|
[:> dropdown-menu-item* {:on-click toggle-flag
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "snap-ruler-guides"
|
|
:id "file-menu-snap-ruler-guides"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :snap-ruler-guides)
|
|
(tr "workspace.header.menu.disable-snap-ruler-guides")
|
|
(tr "workspace.header.menu.enable-snap-ruler-guides"))]
|
|
[:> shortcuts* {:id :toggle-snap-ruler-guide}]]
|
|
|
|
[:> dropdown-menu-item* {:on-click toggle-flag
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "snap-guides"
|
|
:id "file-menu-snap-guides"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :snap-guides)
|
|
(tr "workspace.header.menu.disable-snap-guides")
|
|
(tr "workspace.header.menu.enable-snap-guides"))]
|
|
[:> shortcuts* {:id :toggle-snap-guides}]]
|
|
|
|
[:> dropdown-menu-item* {:on-click toggle-flag
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "dynamic-alignment"
|
|
:id "file-menu-dynamic-alignment"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :dynamic-alignment)
|
|
(tr "workspace.header.menu.disable-dynamic-alignment")
|
|
(tr "workspace.header.menu.enable-dynamic-alignment"))]
|
|
[:> shortcuts* {:id :toggle-alignment}]]
|
|
|
|
[:> dropdown-menu-item* {:on-click toggle-flag
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "snap-pixel-grid"
|
|
:id "file-menu-pixel-grid"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :snap-pixel-grid)
|
|
(tr "workspace.header.menu.disable-snap-pixel-grid")
|
|
(tr "workspace.header.menu.enable-snap-pixel-grid"))]
|
|
[:> shortcuts* {:id :snap-pixel-grid}]]
|
|
|
|
[:> dropdown-menu-item* {:on-click show-nudge-options
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(show-nudge-options event)))
|
|
:data-testid "snap-pixel-grid"
|
|
:id "file-menu-nudge"}
|
|
[:span {:class (stl/css :item-name)} (tr "modals.nudge-title")]]
|
|
|
|
[:> dropdown-menu-item* {:on-click toggle-theme
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-theme event)))
|
|
:data-testid "toggle-theme"
|
|
:id "file-menu-toggle-theme"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(case (:theme profile) ;; dark -> light -> system -> dark and so on
|
|
"dark" (tr "workspace.header.menu.toggle-light-theme")
|
|
"light" (tr "workspace.header.menu.toggle-system-theme")
|
|
"system" (tr "workspace.header.menu.toggle-dark-theme")
|
|
(tr "workspace.header.menu.toggle-light-theme"))]
|
|
[:> shortcuts* {:id :toggle-theme}]]
|
|
(when (contains? cf/flags :render-switch)
|
|
[:> dropdown-menu-item* {:on-click toggle-render
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-render event)))}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (= renderer :wasm)
|
|
(tr "workspace.header.menu.disable-webgl")
|
|
(tr "workspace.header.menu.enable-webgl"))]])]))
|
|
|
|
(mf/defc view-menu*
|
|
{::mf/private true
|
|
::mf/wrap [mf/memo]}
|
|
[{:keys [layout toggle-flag on-close]}]
|
|
(let [read-only? (mf/use-ctx ctx/workspace-read-only?)
|
|
|
|
toggle-color-palette
|
|
(mf/use-fn
|
|
(fn []
|
|
(r/set-resize-type! :bottom)
|
|
(st/emit! (dw/remove-layout-flag :textpalette)
|
|
(-> (dw/toggle-layout-flag :colorpalette)
|
|
(vary-meta assoc ::ev/origin "workspace:menu")))))
|
|
|
|
toggle-text-palette
|
|
(mf/use-fn
|
|
(fn []
|
|
(r/set-resize-type! :bottom)
|
|
(st/emit! (dw/remove-layout-flag :colorpalette)
|
|
(-> (dw/toggle-layout-flag :textpalette)
|
|
(vary-meta assoc ::ev/origin "workspace:menu")))))
|
|
|
|
toggle-comments-visibility
|
|
(mf/use-fn
|
|
(mf/deps on-close)
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(st/emit! (dwcm/toggle-comments-visibility {:origin "workspace:menu"}))
|
|
(on-close)))]
|
|
|
|
[:> dropdown-menu* {:show true
|
|
:class (stl/css :base-menu :sub-menu :pos-3)
|
|
:on-close on-close}
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-flag
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "rulers"
|
|
:id "file-menu-rulers"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :rulers)
|
|
(tr "workspace.header.menu.hide-rules")
|
|
(tr "workspace.header.menu.show-rules"))]
|
|
[:> shortcuts* {:id :toggle-rulers}]]
|
|
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-flag
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "display-guides"
|
|
:id "file-menu-guides"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :display-guides)
|
|
(tr "workspace.header.menu.hide-guides")
|
|
(tr "workspace.header.menu.show-guides"))]
|
|
[:> shortcuts* {:id :toggle-guides}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-flag
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "lock-guides"
|
|
:id "file-menu-lock-guides"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :lock-guides)
|
|
(tr "workspace.header.menu.unlock-guides")
|
|
(tr "workspace.header.menu.lock-guides"))]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-comments-visibility
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-comments-visibility event)))
|
|
:data-testid "display-comments"
|
|
:id "file-menu-comments"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :display-comments)
|
|
(tr "workspace.header.menu.hide-comments")
|
|
(tr "workspace.header.menu.show-comments"))]
|
|
[:> shortcuts* {:id :toggle-comments-visibility}]]
|
|
|
|
(when-not ^boolean read-only?
|
|
[:*
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-color-palette
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-color-palette event)))
|
|
:id "file-menu-color-palette"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :colorpalette)
|
|
(tr "workspace.header.menu.hide-palette")
|
|
(tr "workspace.header.menu.show-palette"))]
|
|
[:> shortcuts* {:id :toggle-colorpalette}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-text-palette
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-text-palette event)))
|
|
:id "file-menu-text-palette"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :textpalette)
|
|
(tr "workspace.header.menu.hide-textpalette")
|
|
(tr "workspace.header.menu.show-textpalette"))]
|
|
[:> shortcuts* {:id :toggle-textpalette}]]])
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-flag
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "display-artboard-names"
|
|
:id "file-menu-artboards"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :display-artboard-names)
|
|
(tr "workspace.header.menu.hide-artboard-names")
|
|
(tr "workspace.header.menu.show-artboard-names"))]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-flag
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "show-pixel-grid"
|
|
:id "file-menu-pixel-grid"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if (contains? layout :show-pixel-grid)
|
|
(tr "workspace.header.menu.hide-pixel-grid")
|
|
(tr "workspace.header.menu.show-pixel-grid"))]
|
|
[:> shortcuts* {:id :show-pixel-grid}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click toggle-flag
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(toggle-flag event)))
|
|
:data-testid "hide-ui"
|
|
:id "file-menu-hide-ui"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.shape.menu.hide-ui")]
|
|
[:> shortcuts* {:id :hide-ui}]]]))
|
|
|
|
(mf/defc edit-menu*
|
|
{::mf/private true
|
|
::mf/wrap [mf/memo]}
|
|
[{:keys [on-close]}]
|
|
(let [perms (mf/use-ctx ctx/permissions)
|
|
can-edit (:can-edit perms)
|
|
|
|
select-all
|
|
(mf/use-fn
|
|
#(st/emit! (dw/select-all)))
|
|
|
|
find
|
|
(mf/use-fn (fn [] (on-close) (st/emit! (dw/open-layers-search :find {:force? true}))))
|
|
|
|
find-and-replace
|
|
(mf/use-fn (fn [] (on-close) (st/emit! (dw/open-layers-search :find-and-replace {:force? true}))))
|
|
|
|
undo
|
|
(mf/use-fn
|
|
#(st/emit! dwu/undo))
|
|
|
|
redo
|
|
(mf/use-fn
|
|
#(st/emit! dwu/redo))]
|
|
|
|
[:> dropdown-menu* {:show true
|
|
:class (stl/css :base-menu :sub-menu :pos-2)
|
|
:on-close on-close}
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click select-all
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(select-all event)))
|
|
:id "file-menu-select-all"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.select-all")]
|
|
[:> shortcuts* {:id :select-all}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click find
|
|
:on-key-down (fn [event] (when (kbd/enter? event) (find event)))
|
|
:id "file-menu-find"}
|
|
[:span {:class (stl/css :item-name)} (tr "workspace.header.menu.find")]
|
|
[:> shortcuts* {:id :find}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click find-and-replace
|
|
:on-key-down (fn [event] (when (kbd/enter? event) (find-and-replace event)))
|
|
:id "file-menu-find-and-replace"}
|
|
[:span {:class (stl/css :item-name)} (tr "workspace.header.menu.find-and-replace")]
|
|
[:> shortcuts* {:id :find-and-replace}]]
|
|
|
|
(when can-edit
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click undo
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(undo event)))
|
|
:id "file-menu-undo"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.undo")]
|
|
[:> shortcuts* {:id :undo}]])
|
|
|
|
(when can-edit
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click redo
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(redo event)))
|
|
:id "file-menu-redo"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.redo")]
|
|
[:> shortcuts* {:id :redo}]])]))
|
|
|
|
(mf/defc file-menu*
|
|
{::mf/private true}
|
|
[{:keys [on-close file]}]
|
|
(let [file-id (:id file)
|
|
shared? (:is-shared file)
|
|
|
|
objects (mf/deref refs/workspace-page-objects)
|
|
selected (mf/deref refs/selected-shapes)
|
|
all-frames (->> (cfh/get-immediate-children objects uuid/zero)
|
|
(filterv cfh/frame-shape?))
|
|
|
|
;; If there are selected frames, use only those. Otherwise, use all frames
|
|
selected-frames (filterv #(contains? selected (:id %)) all-frames)
|
|
frames (if (seq selected-frames) selected-frames all-frames)
|
|
|
|
perms (mf/use-ctx ctx/permissions)
|
|
can-edit (:can-edit perms)
|
|
|
|
on-remove-shared
|
|
(mf/use-fn
|
|
(mf/deps file-id)
|
|
(fn [event]
|
|
(dom/prevent-default event)
|
|
(dom/stop-propagation event)
|
|
(modal/show! {:type :delete-shared-libraries
|
|
:origin :unpublish
|
|
:ids #{file-id}
|
|
:on-accept #(st/emit! (dwl/set-file-shared file-id false))
|
|
:count-libraries 1})))
|
|
|
|
on-remove-shared-key-down
|
|
(mf/use-fn
|
|
(mf/deps on-remove-shared)
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-remove-shared event))))
|
|
|
|
on-add-shared
|
|
(mf/use-fn
|
|
(mf/deps file-id)
|
|
(fn [_event]
|
|
(let [on-accept #(st/emit! (dwl/set-file-shared file-id true))]
|
|
(st/emit! (dcm/show-shared-dialog file-id on-accept)))))
|
|
|
|
on-add-shared-key-down
|
|
(mf/use-fn
|
|
(mf/deps on-add-shared)
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-add-shared event))))
|
|
|
|
on-show-version-history
|
|
(mf/use-fn
|
|
(mf/deps file-id)
|
|
(fn [_]
|
|
(st/emit! (dw/toggle-layout-flag :document-history))))
|
|
|
|
on-show-version-history-key-down
|
|
(mf/use-fn
|
|
(mf/deps on-show-version-history)
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-show-version-history event))))
|
|
|
|
on-pin-version
|
|
(mf/use-fn
|
|
(fn [_]
|
|
(st/emit! (dwv/create-version))))
|
|
|
|
on-pin-version-key-down
|
|
(mf/use-fn
|
|
(mf/deps on-pin-version)
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-pin-version event))))
|
|
|
|
on-export-shapes
|
|
(mf/use-fn
|
|
#(st/emit! (de/show-workspace-export-dialog {:origin "workspace:menu"})))
|
|
|
|
on-export-shapes-key-down
|
|
(mf/use-fn
|
|
(mf/deps on-export-shapes)
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-export-shapes event))))
|
|
|
|
on-export-file
|
|
(mf/use-fn
|
|
(mf/deps file)
|
|
(fn [_]
|
|
(st/emit! (-> (fexp/open-export-dialog [file])
|
|
(with-meta {::ev/origin "workspace:menu"})))))
|
|
|
|
on-export-file-key-down
|
|
(mf/use-fn
|
|
(mf/deps on-export-file)
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-export-file event))))
|
|
|
|
on-export-frames
|
|
(mf/use-fn
|
|
(mf/deps frames)
|
|
(fn [_]
|
|
(st/emit! (de/show-workspace-export-frames-dialog frames))))
|
|
|
|
on-export-frames-key-down
|
|
(mf/use-fn
|
|
(mf/deps on-export-frames)
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-export-frames event))))]
|
|
|
|
[:> dropdown-menu* {:show true
|
|
:class (stl/css :base-menu :sub-menu :pos-1)
|
|
:on-close on-close}
|
|
|
|
(if ^boolean shared?
|
|
(when can-edit
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-remove-shared
|
|
:on-key-down on-remove-shared-key-down
|
|
:id "file-menu-remove-shared"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "dashboard.unpublish-shared")]])
|
|
|
|
(when can-edit
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-add-shared
|
|
:on-key-down on-add-shared-key-down
|
|
:id "file-menu-add-shared"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "dashboard.add-shared")]]))
|
|
|
|
(when can-edit
|
|
[:*
|
|
[:div {:class (stl/css :separator)}]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-pin-version
|
|
:on-key-down on-pin-version-key-down
|
|
:id "file-menu-create-version"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "dashboard.create-version-menu")]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-show-version-history
|
|
:on-key-down on-show-version-history-key-down
|
|
:id "file-menu-show-version-history"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "dashboard.show-version-history")]
|
|
[:> shortcuts* {:id :toggle-history}]]
|
|
|
|
[:div {:class (stl/css :separator)}]])
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-export-shapes
|
|
:on-key-down on-export-shapes-key-down
|
|
:id "file-menu-export-shapes"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "dashboard.export-shapes")]
|
|
[:> shortcuts* {:id :export-shapes}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-export-file
|
|
:on-key-down on-export-file-key-down
|
|
:data-format "binfile-v3"
|
|
:id "file-menu-binary-file"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "dashboard.download-binary-file")]]
|
|
|
|
(when (seq frames)
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-export-frames
|
|
:on-key-down on-export-frames-key-down
|
|
:id "file-menu-export-frames"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "dashboard.export-frames")]])]))
|
|
|
|
(mf/defc plugins-menu*
|
|
{::mf/private true
|
|
::mf/wrap [mf/memo]}
|
|
[{:keys [open-plugins on-close]}]
|
|
(when (features/active-feature? @st/state "plugins/runtime")
|
|
(let [plugins (preg/plugins-list)
|
|
user-can-edit? (:can-edit (deref refs/permissions))
|
|
permissions-peek (deref refs/plugins-permissions-peek)]
|
|
[:> dropdown-menu* {:show true
|
|
:class (stl/css :base-menu :sub-menu :pos-5 :plugins)
|
|
:on-close on-close}
|
|
[:> dropdown-menu-item* {:on-click open-plugins
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(open-plugins event)))
|
|
:data-testid "open-plugins"
|
|
:id "file-menu-open-plugins"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.plugins.menu.plugins-manager")]
|
|
[:> shortcuts* {:id :plugins}]]
|
|
|
|
|
|
(when (d/not-empty? plugins)
|
|
[:div {:class (stl/css :separator)}])
|
|
|
|
(for [[idx {:keys [plugin-id name host permissions] :as manifest}] (d/enumerate plugins)]
|
|
(let [permissions (or (get permissions-peek plugin-id) permissions)
|
|
is-edition-plugin? (or (contains? permissions "content:write")
|
|
(contains? permissions "library:write"))
|
|
can-open? (or user-can-edit?
|
|
(not is-edition-plugin?))
|
|
on-click
|
|
(mf/use-fn
|
|
(mf/deps can-open? name host manifest user-can-edit?)
|
|
(fn [event]
|
|
(if can-open?
|
|
(do
|
|
(st/emit! (ev/event {::ev/name "start-plugin"
|
|
::ev/origin "workspace:menu"
|
|
:name name
|
|
:host host}))
|
|
(dp/open-plugin! manifest user-can-edit?))
|
|
(dom/stop-propagation event))))
|
|
on-key-down
|
|
(mf/use-fn
|
|
(mf/deps can-open? name host manifest user-can-edit?)
|
|
(fn [event]
|
|
(when can-open?
|
|
(when (kbd/enter? event)
|
|
(st/emit! (ev/event {::ev/name "start-plugin"
|
|
::ev/origin "workspace:menu"
|
|
:name name
|
|
:host host}))
|
|
(dp/open-plugin! manifest user-can-edit?)))))]
|
|
|
|
[:> dropdown-menu-item* {:key (dm/str "plugins-menu-" idx)
|
|
:on-click on-click
|
|
:class (stl/css-case :base-menu-item true
|
|
:submenu-item true
|
|
:disabled (not can-open?))
|
|
:on-key-down on-key-down}
|
|
[:span {:class (stl/css :item-name)} name]
|
|
(when-not can-open?
|
|
[:span {:title (tr "workspace.plugins.error.need-editor")}
|
|
[:> icon* {:icon-id i/help
|
|
:class (stl/css :item-icon)}]])]))])))
|
|
|
|
(mf/defc mcp-menu*
|
|
{::mf/private true}
|
|
[{:keys [on-close mcp]}]
|
|
(let [plugins-enabled? (features/use-feature "plugins/runtime")
|
|
has-valid-token? (get mcp :token-valid)
|
|
enabled? (get mcp :enabled)
|
|
|
|
conn-status (get mcp :connection-status)
|
|
connected? (= conn-status "connected")
|
|
|
|
show-enabled? (and enabled? has-valid-token?)
|
|
|
|
on-nav-to-integrations
|
|
(mf/use-fn
|
|
(fn []
|
|
(st/emit! (ev/event {::ev/name "manage-mpc-option"
|
|
::ev/origin "workspace:menu"}))
|
|
(dom/open-new-window "/#/settings/integrations")))
|
|
|
|
on-nav-to-integrations-key-down
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-nav-to-integrations))))
|
|
|
|
on-toggle-mcp-plugin
|
|
(mf/use-fn
|
|
(mf/deps connected?)
|
|
(fn []
|
|
(if connected?
|
|
(st/emit! (mcp/user-disconnect-mcp)
|
|
(ev/event {::ev/name "disconnect-mcp-plugin"
|
|
::ev/origin "workspace:menu"}))
|
|
(st/emit! (mcp/connect-mcp)
|
|
(ev/event {::ev/name "connect-mcp-plugin"
|
|
::ev/origin "workspace:menu"})))))
|
|
|
|
on-toggle-mcp-plugin-key-down
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-toggle-mcp-plugin))))]
|
|
|
|
[:> dropdown-menu* {:show true
|
|
:class (stl/css-case :base-menu true
|
|
:sub-menu true
|
|
:pos-5 (not plugins-enabled?)
|
|
:pos-6 plugins-enabled?)
|
|
:on-close on-close}
|
|
|
|
|
|
(when (and show-enabled? has-valid-token?)
|
|
[:> dropdown-menu-item* {:id "mcp-menu-toggle-mcp-plugin"
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-toggle-mcp-plugin
|
|
:on-key-down on-toggle-mcp-plugin-key-down}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if connected?
|
|
(tr "workspace.header.menu.mcp.plugin.status.disconnect")
|
|
(tr "workspace.header.menu.mcp.plugin.status.connect"))]])
|
|
|
|
[:> dropdown-menu-item* {:id "mcp-menu-nav-to-integrations"
|
|
:class (stl/css :base-menu-item :submenu-item)
|
|
:on-click on-nav-to-integrations
|
|
:on-key-down on-nav-to-integrations-key-down}
|
|
[:span {:class (stl/css :item-name)}
|
|
(if show-enabled?
|
|
(tr "workspace.header.menu.mcp.server.status.enabled")
|
|
(tr "workspace.header.menu.mcp.server.status.disabled"))]]]))
|
|
|
|
(mf/defc menu*
|
|
[{:keys [layout file]}]
|
|
(let [profile (mf/deref refs/profile)
|
|
|
|
show-menu* (mf/use-state false)
|
|
show-menu? (deref show-menu*)
|
|
selected-sub-menu* (mf/use-state nil)
|
|
selected-sub-menu (deref selected-sub-menu*)
|
|
mcp (mf/deref refs/mcp)
|
|
|
|
toggle-menu
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(swap! show-menu* not)
|
|
(when (not show-menu?)
|
|
(reset! selected-sub-menu* nil))))
|
|
|
|
close-menu
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(reset! show-menu* false)))
|
|
|
|
close-sub-menu
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(reset! selected-sub-menu* nil)))
|
|
|
|
close-all-menus
|
|
(mf/use-fn
|
|
(fn []
|
|
(reset! show-menu* false)
|
|
(reset! selected-sub-menu* nil)))
|
|
|
|
on-menu-click
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(let [menu (-> (dom/get-current-target event)
|
|
(dom/get-data "testid")
|
|
(keyword))]
|
|
(reset! selected-sub-menu* menu))))
|
|
|
|
toggle-flag
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(let [flag (-> (dom/get-current-target event)
|
|
(dom/get-data "testid")
|
|
(keyword))]
|
|
(st/emit!
|
|
(-> (dw/toggle-layout-flag flag)
|
|
(vary-meta assoc ::ev/origin "workspace:menu")))
|
|
(reset! show-menu* false)
|
|
(reset! selected-sub-menu* nil))))
|
|
|
|
toggle-theme
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(st/emit! (du/toggle-theme))))
|
|
|
|
toggle-render
|
|
(mf/use-fn
|
|
(mf/deps profile)
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(let [renderer (or (-> profile :props :renderer) :svg)
|
|
next-renderer (if (= renderer :wasm) :svg :wasm)
|
|
ev-name (if (= next-renderer :wasm)
|
|
"enable-webgl-rendering"
|
|
"disable-webgl-rendering")]
|
|
(->> (rx/zip
|
|
(rp/cmd! :update-profile-props {:props {:renderer next-renderer}})
|
|
(rx/filter (ptk/type? ::ev/chunk-persisted) st/stream))
|
|
(rx/timeout 2000 (rx/of :timeout))
|
|
(rx/subs! (fn [_]
|
|
(dom/reload-current-window true))
|
|
(fn [_]
|
|
(st/emit! (ntf/error (tr "errors.generic"))))))
|
|
(st/emit! (ev/event {::ev/name ev-name
|
|
::ev/origin "workspace:menu"})
|
|
(ptk/data-event ::ev/force-persist {})))))
|
|
|
|
open-plugins-manager
|
|
(mf/use-fn
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(reset! show-menu* false)
|
|
(reset! selected-sub-menu* nil)
|
|
(st/emit!
|
|
(ev/event {::ev/name "open-plugins-manager"
|
|
::ev/origin "workspace:menu"})
|
|
(modal/show :plugin-management {}))))
|
|
|
|
show-shortcuts
|
|
(mf/use-fn
|
|
(mf/deps layout)
|
|
(fn [event]
|
|
(dom/stop-propagation event)
|
|
(reset! show-menu* false)
|
|
(reset! selected-sub-menu* nil)
|
|
(when (contains? layout :collapse-left-sidebar)
|
|
(st/emit! (dw/toggle-layout-flag :collapse-left-sidebar)))
|
|
(st/emit!
|
|
(-> (dw/toggle-layout-flag :shortcuts)
|
|
(vary-meta assoc ::ev/origin "workspace-menu")))))
|
|
|
|
subscription (:subscription (:props profile))
|
|
subscription-type (get-subscription-type subscription)]
|
|
|
|
(mf/with-effect []
|
|
(let [disposable (->> st/stream
|
|
(rx/filter #(= :interrupt %))
|
|
(rx/subs! close-all-menus))]
|
|
(partial rx/dispose! disposable)))
|
|
|
|
|
|
[:*
|
|
[:> icon-button* {:variant "ghost"
|
|
:aria-pressed show-menu?
|
|
:aria-label (tr "shortcut-subsection.main-menu")
|
|
:on-click toggle-menu
|
|
:icon i/menu}]
|
|
|
|
[:> dropdown-menu* {:show show-menu?
|
|
:id "workspace:menu"
|
|
:on-close close-menu
|
|
:class (stl/css :base-menu :menu)}
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :menu-item)
|
|
:on-click on-menu-click
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-menu-click event)))
|
|
:on-pointer-enter on-menu-click
|
|
:data-testid "file"
|
|
:id "file-menu-file"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.option.file")]
|
|
[:> icon* {:icon-id i/arrow-right
|
|
:class (stl/css :item-arrow)}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :menu-item)
|
|
:on-click on-menu-click
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-menu-click event)))
|
|
:on-pointer-enter on-menu-click
|
|
:data-testid "edit"
|
|
:id "file-menu-edit"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.option.edit")]
|
|
[:> icon* {:icon-id i/arrow-right
|
|
:class (stl/css :item-arrow)}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :menu-item)
|
|
:on-click on-menu-click
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-menu-click event)))
|
|
:on-pointer-enter on-menu-click
|
|
:data-testid "view"
|
|
:id "file-menu-view"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.option.view")]
|
|
[:> icon* {:icon-id i/arrow-right
|
|
:class (stl/css :item-arrow)}]]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :menu-item)
|
|
:on-click on-menu-click
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-menu-click event)))
|
|
:on-pointer-enter on-menu-click
|
|
:data-testid "preferences"
|
|
:id "file-menu-preferences"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.option.preferences")]
|
|
[:> icon* {:icon-id i/arrow-right
|
|
:class (stl/css :item-arrow)}]]
|
|
|
|
(when (features/active-feature? @st/state "plugins/runtime")
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :menu-item)
|
|
:on-click on-menu-click
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-menu-click event)))
|
|
:on-pointer-enter on-menu-click
|
|
:data-testid "plugins"
|
|
:id "file-menu-plugins"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.plugins.menu.title")]
|
|
[:> icon* {:icon-id i/arrow-right
|
|
:class (stl/css :item-arrow)}]])
|
|
|
|
(when (contains? cf/flags :mcp)
|
|
(let [enabled? (get mcp :enabled)
|
|
conn-status (get mcp :connection-status)
|
|
has-valid-token? (get mcp :token-valid)
|
|
|
|
connected? (= conn-status "connected")
|
|
error? (= conn-status "error")
|
|
|
|
|
|
active? (and enabled? connected?)
|
|
failed? (or (and enabled? error?)
|
|
(not has-valid-token?))]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :menu-item)
|
|
:on-click on-menu-click
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-menu-click event)))
|
|
:on-pointer-enter on-menu-click
|
|
:data-testid "mcp"
|
|
:id "file-menu-mcp"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.option.mcp")]
|
|
[:span {:class (stl/css-case :item-indicator true
|
|
:active active?
|
|
:failed failed?)}]
|
|
[:> icon* {:icon-id i/arrow-right
|
|
:class (stl/css :item-arrow)}]]))
|
|
|
|
[:div {:class (stl/css :separator)}]
|
|
|
|
[:> dropdown-menu-item* {:class (stl/css :base-menu-item :menu-item)
|
|
:on-click on-menu-click
|
|
:on-key-down (fn [event]
|
|
(when (kbd/enter? event)
|
|
(on-menu-click event)))
|
|
:on-pointer-enter on-menu-click
|
|
:data-testid "help-info"
|
|
:id "file-menu-help-info"}
|
|
[:span {:class (stl/css :item-name)}
|
|
(tr "workspace.header.menu.option.help-info")]
|
|
[:> icon* {:icon-id i/arrow-right
|
|
:class (stl/css :item-arrow)}]]
|
|
|
|
(when (or (and (contains? cf/flags :subscriptions)
|
|
(not= "enterprise" subscription-type))
|
|
(contains? cf/flags :admin-console))
|
|
[:> main-menu-power-up* {:close-sub-menu close-sub-menu}])]
|
|
|
|
(case selected-sub-menu
|
|
:file
|
|
[:> file-menu* {:file file
|
|
:on-close close-sub-menu}]
|
|
|
|
:edit
|
|
[:> edit-menu* {:on-close close-sub-menu}]
|
|
|
|
:view
|
|
[:> view-menu* {:layout layout
|
|
:toggle-flag toggle-flag
|
|
:on-close close-sub-menu}]
|
|
|
|
:preferences
|
|
[:> preferences-menu* {:layout layout
|
|
:profile profile
|
|
:toggle-flag toggle-flag
|
|
:toggle-theme toggle-theme
|
|
:toggle-render toggle-render
|
|
:show-shortcuts show-shortcuts
|
|
:on-close close-sub-menu}]
|
|
|
|
:plugins
|
|
[:> plugins-menu* {:open-plugins open-plugins-manager
|
|
:on-close close-sub-menu}]
|
|
|
|
:mcp
|
|
[:> mcp-menu* {:on-close close-sub-menu :mcp mcp}]
|
|
|
|
:help-info
|
|
[:> help-info-menu* {:layout layout
|
|
:on-close close-sub-menu}]
|
|
|
|
nil)]))
|