mirror of
https://github.com/penpot/penpot.git
synced 2026-07-22 05:57:56 +00:00
✨ Improve workspace debug sidebar workflow (#10678)
This commit is contained in:
parent
c11d3aaaa7
commit
95cfbf5f7c
@ -1568,6 +1568,7 @@
|
||||
(dm/export dwcp/paste-shapes)
|
||||
(dm/export dwcp/paste-data-valid?)
|
||||
(dm/export dwcp/copy-link-to-clipboard)
|
||||
(dm/export dwcp/copy-id-to-clipboard)
|
||||
(dm/export dwcp/copy-as-image)
|
||||
|
||||
;; Drawing
|
||||
|
||||
@ -1138,6 +1138,15 @@
|
||||
(watch [_ _ _]
|
||||
(clipboard/to-clipboard (rt/get-current-href)))))
|
||||
|
||||
(defn copy-id-to-clipboard
|
||||
[id]
|
||||
(ptk/reify ::copy-id-to-clipboard
|
||||
ptk/WatchEvent
|
||||
(watch [_ _ _]
|
||||
(->> (rx/from (clipboard/to-clipboard id))
|
||||
(rx/map (fn [_]
|
||||
(ntf/info "The id has been copied to the clipboard")))))))
|
||||
|
||||
(defn copy-as-image
|
||||
[]
|
||||
(ptk/reify ::copy-as-image
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
:add #{:tokens}}})
|
||||
|
||||
(def valid-options-mode
|
||||
#{:design :prototype :inspect})
|
||||
#{:design :prototype :inspect :debug})
|
||||
|
||||
(def default-layout
|
||||
#{:sitemap
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
[app.main.ui.ds.foundations.assets.icon :refer [icon*] :as i]
|
||||
[app.main.ui.workspace.sidebar.assets.common :as cmm]
|
||||
[app.util.clipboard :as clipboard]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr] :as i18n]
|
||||
[app.util.shape-icon :as usi]
|
||||
@ -152,6 +153,7 @@
|
||||
|
||||
do-copy #(st/emit! (dw/copy-selected))
|
||||
do-copy-link #(st/emit! (dw/copy-link-to-clipboard))
|
||||
do-copy-id #(st/emit! (dw/copy-id-to-clipboard (-> shapes first :id str)))
|
||||
|
||||
do-cut #(st/emit! (dw/copy-selected)
|
||||
(dw/delete-selected))
|
||||
@ -200,6 +202,10 @@
|
||||
(reset! enabled-paste-props* false))))))]
|
||||
|
||||
[:*
|
||||
(when (and (not multiple?)
|
||||
(dbg/enabled? :show-ids))
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.copy-id")
|
||||
:on-click do-copy-id}])
|
||||
[:> menu-entry* {:title (tr "workspace.shape.menu.copy")
|
||||
:shortcut (sc/get-tooltip :copy)
|
||||
:on-click do-copy}]
|
||||
|
||||
@ -33,7 +33,6 @@
|
||||
[app.main.ui.workspace.right-header :refer [right-header*]]
|
||||
[app.main.ui.workspace.sidebar.assets :refer [assets-toolbox*]]
|
||||
[app.main.ui.workspace.sidebar.debug :refer [debug-panel*]]
|
||||
[app.main.ui.workspace.sidebar.debug-shape-info :refer [debug-shape-info*]]
|
||||
[app.main.ui.workspace.sidebar.history :refer [history-toolbox*]]
|
||||
[app.main.ui.workspace.sidebar.layers :refer [layers-toolbox*]]
|
||||
[app.main.ui.workspace.sidebar.options :refer [options-toolbox*]]
|
||||
@ -41,7 +40,6 @@
|
||||
[app.main.ui.workspace.sidebar.sitemap :refer [sitemap*]]
|
||||
[app.main.ui.workspace.sidebar.versions :refer [versions-toolbox*]]
|
||||
[app.main.ui.workspace.tokens.sidebar :refer [tokens-sidebar-tab*]]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
@ -285,18 +283,16 @@
|
||||
(let [is-comments? (= drawing-tool :comments)
|
||||
is-history? (contains? layout :document-history)
|
||||
is-inspect? (= section :inspect)
|
||||
|
||||
dbg-shape-panel? (dbg/enabled? :shape-panel)
|
||||
is-debug? (= section :debug)
|
||||
|
||||
current-section* (mf/use-state :info)
|
||||
current-section (deref current-section*)
|
||||
|
||||
can-be-expanded?
|
||||
(or dbg-shape-panel?
|
||||
(and (not is-comments?)
|
||||
(not is-history?)
|
||||
is-inspect?
|
||||
(= current-section :code)))
|
||||
(and (not is-comments?)
|
||||
(not is-history?)
|
||||
is-inspect?
|
||||
(= current-section :code))
|
||||
|
||||
{on-pointer-down :on-pointer-down
|
||||
on-lost-pointer-capture :on-lost-pointer-capture
|
||||
@ -325,15 +321,16 @@
|
||||
[:aside
|
||||
{:class (stl/css-case :right-settings-bar true
|
||||
:not-expand (not can-be-expanded?)
|
||||
:expanded (> width right-sidebar-default-width))
|
||||
:expanded (or is-debug? (> width right-sidebar-default-width)))
|
||||
|
||||
:id "right-sidebar-aside"
|
||||
:data-testid "right-sidebar"
|
||||
:data-size (str width)
|
||||
:on-context-menu dom/prevent-default-context-menu
|
||||
:style {:--right-sidebar-width (if can-be-expanded?
|
||||
(dm/str width "px")
|
||||
(dm/str right-sidebar-default-width "px"))}}
|
||||
:style {:--right-sidebar-width (cond
|
||||
is-debug? (dm/str right-sidebar-default-max-width "px")
|
||||
can-be-expanded? (dm/str width "px")
|
||||
:else (dm/str right-sidebar-default-width "px"))}}
|
||||
|
||||
(when can-be-expanded?
|
||||
[:div {:class (stl/css :resize-area)
|
||||
@ -348,9 +345,6 @@
|
||||
|
||||
[:div {:class (stl/css :settings-bar-inside)}
|
||||
(cond
|
||||
dbg-shape-panel?
|
||||
[:> debug-shape-info*]
|
||||
|
||||
is-comments?
|
||||
[:> comments-sidebar* {}]
|
||||
|
||||
|
||||
@ -18,15 +18,28 @@
|
||||
[app.util.i18n :refer [tr]]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
(def ^:private no-reload-options
|
||||
"Debug options that don't require a page reload to take effect.
|
||||
These options are handled reactively via okulary subscriptions."
|
||||
#{:shape-panel
|
||||
:show-ids
|
||||
:show-touched})
|
||||
|
||||
(mf/defc debug-panel*
|
||||
[{:keys [class]}]
|
||||
(let [on-toggle-enabled
|
||||
(let [;; dbg/state is an okulary atom; deref'ing it makes this component
|
||||
;; re-render whenever any debug option is toggled, so checkboxes
|
||||
;; reflect the current state without a page reload.
|
||||
_dbg (mf/deref dbg/state)
|
||||
|
||||
on-toggle-enabled
|
||||
(mf/use-fn
|
||||
(fn [event option]
|
||||
(dom/prevent-default event)
|
||||
(dom/stop-propagation event)
|
||||
(dbg/toggle! option)
|
||||
(js* "app.main.reinit(true)")))
|
||||
(when-not (contains? no-reload-options option)
|
||||
(js* "app.main.reinit(true)"))))
|
||||
|
||||
handle-close
|
||||
(mf/use-fn
|
||||
|
||||
@ -13,7 +13,6 @@
|
||||
[app.main.data.workspace :as dw]
|
||||
[app.main.refs :as refs]
|
||||
[app.main.store :as st]
|
||||
[app.main.ui.ds.product.panel-title :refer [panel-title*]]
|
||||
[debug :as dbg]
|
||||
[rumext.v2 :as mf]))
|
||||
|
||||
@ -125,10 +124,6 @@
|
||||
(map (d/getf objects)))]
|
||||
|
||||
[:div {:class (stl/css :shape-info)}
|
||||
[:> panel-title* {:class (stl/css :shape-info-title)
|
||||
:text "Debug"
|
||||
:on-close #(dbg/disable! :shape-panel)}]
|
||||
|
||||
(if (empty? selected)
|
||||
[:div {:class (stl/css :attrs-container)} "No shapes selected"]
|
||||
(for [[idx current] (d/enumerate selected)]
|
||||
|
||||
@ -26,7 +26,11 @@
|
||||
type-comp type-frame component-id is-hidden is-blocked
|
||||
variant-id variant-name variant-properties variant-error
|
||||
on-tab-press ref]}]
|
||||
(let [edition* (mf/use-state false)
|
||||
(let [;; Subscribe to dbg/state so the component re-renders when
|
||||
;; :show-ids or :show-touched are toggled without a page reload.
|
||||
_dbg (mf/deref dbg/state)
|
||||
|
||||
edition* (mf/use-state false)
|
||||
edition? (deref edition*)
|
||||
|
||||
local-ref (mf/use-ref)
|
||||
|
||||
@ -21,6 +21,7 @@
|
||||
[app.main.ui.context :as ctx]
|
||||
[app.main.ui.ds.layout.tab-switcher :refer [tab-switcher*]]
|
||||
[app.main.ui.inspect.right-sidebar :as hrs]
|
||||
[app.main.ui.workspace.sidebar.debug-shape-info :refer [debug-shape-info*]]
|
||||
[app.main.ui.workspace.sidebar.options.drawing :as drawing]
|
||||
[app.main.ui.workspace.sidebar.options.menus.align :refer [align-options*]]
|
||||
[app.main.ui.workspace.sidebar.options.menus.bool :refer [bool-options*]]
|
||||
@ -38,6 +39,7 @@
|
||||
[app.main.ui.workspace.sidebar.options.shapes.rect :as rect]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.svg-raw :as svg-raw]
|
||||
[app.main.ui.workspace.sidebar.options.shapes.text :as text]
|
||||
[app.util.debug :as dbg]
|
||||
[app.util.i18n :as i18n :refer [tr]]
|
||||
[okulary.core :as l]
|
||||
[rumext.v2 :as mf]))
|
||||
@ -199,13 +201,17 @@
|
||||
|
||||
[:> hrs/right-sidebar* props]))
|
||||
|
||||
(def ^:private options-tabs
|
||||
[{:label (tr "workspace.options.design")
|
||||
:id "design"}
|
||||
{:label (tr "workspace.options.prototype")
|
||||
:id "prototype"}
|
||||
{:label (tr "workspace.options.inspect")
|
||||
:id "inspect"}])
|
||||
(defn- generate-options-tabs
|
||||
[]
|
||||
(cond-> [{:label (tr "workspace.options.design")
|
||||
:id "design"}
|
||||
{:label (tr "workspace.options.prototype")
|
||||
:id "prototype"}
|
||||
{:label (tr "workspace.options.inspect")
|
||||
:id "inspect"}]
|
||||
(dbg/enabled? :shape-panel)
|
||||
(conj {:label "Debug"
|
||||
:id "debug"})))
|
||||
|
||||
(defn- on-option-tab-change
|
||||
[mode]
|
||||
@ -225,9 +231,28 @@
|
||||
options-mode
|
||||
(mf/deref refs/options-mode-global)
|
||||
|
||||
;; dbg/state is an okulary atom; deref'ing it makes this component
|
||||
;; re-render when debug options change (e.g. :shape-panel toggle)
|
||||
;; so the tabs list is regenerated reactively without a page reload.
|
||||
dbg-state
|
||||
(mf/deref dbg/state)
|
||||
|
||||
shapes
|
||||
(mf/with-memo [selected objects]
|
||||
(sequence (keep (d/getf objects)) selected))]
|
||||
(sequence (keep (d/getf objects)) selected))
|
||||
|
||||
options-tabs
|
||||
(generate-options-tabs)]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps dbg-state)
|
||||
(fn []
|
||||
(if (contains? dbg-state :shape-panel)
|
||||
;; shape-panel was just enabled: select the debug tab
|
||||
(on-option-tab-change "debug")
|
||||
;; shape-panel was just disabled: if debug tab is active, go back to design
|
||||
(when (= options-mode :debug)
|
||||
(on-option-tab-change "design")))))
|
||||
|
||||
[:div {:class (stl/css :tool-window)}
|
||||
(if (and (:can-edit permissions) (not render-context-lost?))
|
||||
@ -255,7 +280,10 @@
|
||||
:objects objects
|
||||
:page-id page-id
|
||||
:file-id file-id
|
||||
:shapes shapes}])]
|
||||
:shapes shapes}]
|
||||
|
||||
:debug
|
||||
[:> debug-shape-info*])]
|
||||
|
||||
[:div {:class (stl/css :element-options :inspect-options :read-only)}
|
||||
[:> inspect-tab* {:page-id page-id
|
||||
|
||||
@ -6,9 +6,11 @@
|
||||
|
||||
(ns app.util.debug
|
||||
(:require
|
||||
[app.main.store :as st]))
|
||||
[app.main.store :as st]
|
||||
[app.util.storage :as storage]
|
||||
[okulary.core :as l]))
|
||||
|
||||
(defonce state (atom #{#_:events}))
|
||||
(def ^:private storage-key :app.util.debug/enabled-options)
|
||||
|
||||
(def options
|
||||
#{;; Displays the bounding box for the shapes
|
||||
@ -105,6 +107,17 @@
|
||||
;; Event times
|
||||
:events-times})
|
||||
|
||||
(defn- load-state
|
||||
[]
|
||||
(let [stored (get storage/user storage-key #{})]
|
||||
(into #{} (filter options) stored)))
|
||||
|
||||
(defonce state (l/atom (load-state)))
|
||||
|
||||
(defn- persist-state!
|
||||
[state]
|
||||
(swap! storage/user assoc storage-key state))
|
||||
|
||||
(defn handle-change
|
||||
[]
|
||||
(set! st/*debug-events* (contains? @state :events))
|
||||
@ -112,7 +125,9 @@
|
||||
|
||||
(when *assert*
|
||||
(handle-change)
|
||||
(add-watch state :watcher handle-change))
|
||||
(add-watch state :watcher handle-change)
|
||||
(add-watch state :persistence (fn [_ _ _ new-state]
|
||||
(persist-state! new-state))))
|
||||
|
||||
(defn enable!
|
||||
[option]
|
||||
|
||||
@ -8779,6 +8779,9 @@ msgstr "Copy as CSS (nested layers)"
|
||||
msgid "workspace.shape.menu.copy-link"
|
||||
msgstr "Copy link"
|
||||
|
||||
msgid "workspace.shape.menu.copy-id"
|
||||
msgstr "Copy id"
|
||||
|
||||
#: src/app/main/ui/workspace/context_menu.cljs:219
|
||||
msgid "workspace.shape.menu.copy-paste-as"
|
||||
msgstr "Copy/Paste as ..."
|
||||
|
||||
@ -4629,7 +4629,7 @@ msgid "onboarding.choice.team-up.invite-members"
|
||||
msgstr "Invitar integrantes"
|
||||
|
||||
msgid "onboarding.choice.team-up.invite-members-desc"
|
||||
msgstr ""
|
||||
msgstr ""
|
||||
"Personas de desarrollo, diseño, gestión... todo el mundo es bienvenido. "
|
||||
"Podrás invitar a más gente posteriormente."
|
||||
|
||||
@ -8551,6 +8551,9 @@ msgstr "Copiar como CSS (capas anidadas)"
|
||||
msgid "workspace.shape.menu.copy-link"
|
||||
msgstr "Copiar enlace"
|
||||
|
||||
msgid "workspace.shape.menu.copy-id"
|
||||
msgstr "Copiar id"
|
||||
|
||||
#: src/app/main/ui/workspace/context_menu.cljs:219
|
||||
msgid "workspace.shape.menu.copy-paste-as"
|
||||
msgstr "Copiar/Pegar como ..."
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user