0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-22 14:39:45 -05:00

🐛 Fix incorrect event handling on file-menu

Don't wait team to be present for open the menu,
because with slow connection speed it can cause
unexpected ux glitche showing menu when the component
inner request is resoved
This commit is contained in:
Andrey Antukh 2024-12-09 10:15:13 +01:00
parent aeb1ac41da
commit 2f79d71262
2 changed files with 116 additions and 128 deletions

View file

@ -13,7 +13,6 @@
[app.main.data.exports.files :as fexp] [app.main.data.exports.files :as fexp]
[app.main.data.modal :as modal] [app.main.data.modal :as modal]
[app.main.data.notifications :as ntf] [app.main.data.notifications :as ntf]
[app.main.refs :as refs]
[app.main.repo :as rp] [app.main.repo :as rp]
[app.main.store :as st] [app.main.store :as st]
[app.main.ui.components.context-menu-a11y :refer [context-menu*]] [app.main.ui.components.context-menu-a11y :refer [context-menu*]]
@ -57,9 +56,8 @@
(mf/defc file-menu* (mf/defc file-menu*
{::mf/props :obj} {::mf/props :obj}
[{:keys [files show on-edit on-menu-close top left navigate origin parent-id can-edit]}] [{:keys [files on-edit on-menu-close top left navigate origin parent-id can-edit]}]
(assert (seq files) "missing `files` prop") (assert (seq files) "missing `files` prop")
(assert (boolean? show) "missing `show` prop")
(assert (fn? on-edit) "missing `on-edit` prop") (assert (fn? on-edit) "missing `on-edit` prop")
(assert (fn? on-menu-close) "missing `on-menu-close` prop") (assert (fn? on-menu-close) "missing `on-menu-close` prop")
(assert (boolean? navigate) "missing `navigate` prop") (assert (boolean? navigate) "missing `navigate` prop")
@ -74,12 +72,11 @@
multi? (> file-count 1) multi? (> file-count 1)
current-team-id (mf/use-ctx ctx/current-team-id) current-team-id (mf/use-ctx ctx/current-team-id)
teams (mf/use-state nil) teams* (mf/use-state nil)
default-team (-> (mf/deref refs/teams) teams (deref teams*)
(get current-team-id))
current-team (or (get @teams current-team-id) default-team) current-team (get teams current-team-id)
other-teams (remove #(= (:id %) current-team-id) (vals @teams)) other-teams (remove #(= (:id %) current-team-id) (vals teams))
current-projects (remove #(= (:id %) (:project-id file)) current-projects (remove #(= (:id %) (:project-id file))
(:projects current-team)) (:projects current-team))
@ -207,142 +204,134 @@
on-export-standard-files on-export-standard-files
(mf/use-fn (mf/use-fn
(mf/deps on-export-files) (mf/deps on-export-files)
(partial on-export-files :legacy-zip)) (partial on-export-files :legacy-zip))]
;; NOTE: this is used for detect if component is still mounted (mf/with-effect []
mounted-ref (mf/use-ref true)] (->> (rp/cmd! :get-all-projects)
(rx/map group-by-team)
(rx/subs! #(reset! teams* %))))
(mf/use-effect (let [sub-options
(mf/deps show) (concat
(fn [] (for [project current-projects]
(when show {:name (get-project-name project)
(->> (rp/cmd! :get-all-projects) :id (get-project-id project)
(rx/map group-by-team) :handler (on-move (:id current-team)
(rx/subs! #(when (mf/ref-val mounted-ref) (:id project))})
(reset! teams %))))))) (when (seq other-teams)
[{:name (tr "dashboard.move-to-other-team")
:id "move-to-other-team"
:options
(for [team other-teams]
{:name (get-team-name team)
:id (get-project-id team)
:options
(for [sub-project (:projects team)]
{:name (get-project-name sub-project)
:id (get-project-id sub-project)
:handler (on-move (:id team)
(:id sub-project))})})}]))
(when current-team options
(let [sub-options (if multi?
(concat [(when can-edit
(for [project current-projects] {:name (tr "dashboard.duplicate-multi" file-count)
{:name (get-project-name project) :id "duplicate-multi"
:id (get-project-id project) :handler on-duplicate})
:handler (on-move (:id current-team)
(:id project))})
(when (seq other-teams)
[{:name (tr "dashboard.move-to-other-team")
:id "move-to-other-team"
:options
(for [team other-teams]
{:name (get-team-name team)
:id (get-project-id team)
:options
(for [sub-project (:projects team)]
{:name (get-project-name sub-project)
:id (get-project-id sub-project)
:handler (on-move (:id team)
(:id sub-project))})})}]))
options (when (and (or (seq current-projects) (seq other-teams)) can-edit)
(if multi? {:name (tr "dashboard.move-to-multi" file-count)
[(when can-edit :id "file-move-multi"
{:name (tr "dashboard.duplicate-multi" file-count) :options sub-options})
:id "duplicate-multi"
:handler on-duplicate})
(when (and (or (seq current-projects) (seq other-teams)) can-edit) (when-not (contains? cf/flags :export-file-v3)
{:name (tr "dashboard.move-to-multi" file-count) {:name (tr "dashboard.export-binary-multi" file-count)
:id "file-move-multi" :id "file-binary-export-multi"
:options sub-options}) :handler on-export-binary-files})
(when-not (contains? cf/flags :export-file-v3) (when (contains? cf/flags :export-file-v3)
{:name (tr "dashboard.export-binary-multi" file-count) {:name (tr "dashboard.export-binary-multi" file-count)
:id "file-binary-export-multi" :id "file-binary-export-multi"
:handler on-export-binary-files}) :handler on-export-binary-files-v3})
(when (contains? cf/flags :export-file-v3) (when-not (contains? cf/flags :export-file-v3)
{:name (tr "dashboard.export-binary-multi" file-count) {:name (tr "dashboard.export-standard-multi" file-count)
:id "file-binary-export-multi" :id "file-standard-export-multi"
:handler on-export-binary-files-v3}) :handler on-export-standard-files})
(when-not (contains? cf/flags :export-file-v3) (when (and (:is-shared file) can-edit)
{:name (tr "dashboard.export-standard-multi" file-count) {:name (tr "labels.unpublish-multi-files" file-count)
:id "file-standard-export-multi" :id "file-unpublish-multi"
:handler on-export-standard-files}) :handler on-del-shared})
(when (and (:is-shared file) can-edit) (when (and (not is-lib-page?) can-edit)
{:name (tr "labels.unpublish-multi-files" file-count) {:name :separator}
:id "file-unpublish-multi" {:name (tr "labels.delete-multi-files" file-count)
:handler on-del-shared}) :id "file-delete-multi"
:handler on-delete})]
(when (and (not is-lib-page?) can-edit) [{:name (tr "dashboard.open-in-new-tab")
{:name :separator} :id "file-open-new-tab"
{:name (tr "labels.delete-multi-files" file-count) :handler on-new-tab}
:id "file-delete-multi" (when (and (not is-search-page?) can-edit)
:handler on-delete})] {:name (tr "labels.rename")
:id "file-rename"
:handler on-edit})
[{:name (tr "dashboard.open-in-new-tab") (when (and (not is-search-page?) can-edit)
:id "file-open-new-tab" {:name (tr "dashboard.duplicate")
:handler on-new-tab} :id "file-duplicate"
(when (and (not is-search-page?) can-edit) :handler on-duplicate})
{:name (tr "labels.rename")
:id "file-rename"
:handler on-edit})
(when (and (not is-search-page?) can-edit) (when (and (not is-lib-page?)
{:name (tr "dashboard.duplicate") (not is-search-page?)
:id "file-duplicate" (or (seq current-projects) (seq other-teams))
:handler on-duplicate}) can-edit)
{:name (tr "dashboard.move-to")
:id "file-move-to"
:options sub-options})
(when (and (not is-lib-page?) (when (and (not is-search-page?)
(not is-search-page?) can-edit)
(or (seq current-projects) (seq other-teams)) (if (:is-shared file)
can-edit) {:name (tr "dashboard.unpublish-shared")
{:name (tr "dashboard.move-to") :id "file-del-shared"
:id "file-move-to" :handler on-del-shared}
:options sub-options}) {:name (tr "dashboard.add-shared")
:id "file-add-shared"
:handler on-add-shared}))
(when (and (not is-search-page?) {:name :separator}
can-edit)
(if (:is-shared file)
{:name (tr "dashboard.unpublish-shared")
:id "file-del-shared"
:handler on-del-shared}
{:name (tr "dashboard.add-shared")
:id "file-add-shared"
:handler on-add-shared}))
{:name :separator} (when-not (contains? cf/flags :export-file-v3)
{:name (tr "dashboard.download-binary-file")
:id "download-binary-file"
:handler on-export-binary-files})
(when-not (contains? cf/flags :export-file-v3) (when (contains? cf/flags :export-file-v3)
{:name (tr "dashboard.download-binary-file") {:name (tr "dashboard.download-binary-file")
:id "download-binary-file" :id "download-binary-file"
:handler on-export-binary-files}) :handler on-export-binary-files-v3})
(when (contains? cf/flags :export-file-v3) (when-not (contains? cf/flags :export-file-v3)
{:name (tr "dashboard.download-binary-file") {:name (tr "dashboard.download-standard-file")
:id "download-binary-file" :id "download-standard-file"
:handler on-export-binary-files-v3}) :handler on-export-standard-files})
(when-not (contains? cf/flags :export-file-v3) (when (and (not is-lib-page?) (not is-search-page?) can-edit)
{:name (tr "dashboard.download-standard-file") {:name :separator})
:id "download-standard-file"
:handler on-export-standard-files})
(when (and (not is-lib-page?) (not is-search-page?) can-edit) (when (and (not is-lib-page?) (not is-search-page?) can-edit)
{:name :separator}) {:name (tr "labels.delete")
:id "file-delete"
:handler on-delete})])]
(when (and (not is-lib-page?) (not is-search-page?) can-edit) [:> context-menu*
{:name (tr "labels.delete") {:on-close on-menu-close
:id "file-delete" :fixed (or (not= top 0) (not= left 0))
:handler on-delete})])] :show true
:min-width true
[:> context-menu* :top top
{:on-close on-menu-close :left left
:show show :options options
:fixed (or (not= top 0) (not= left 0)) :origin parent-id}])))
:min-width true
:top top
:left left
:options options
:origin parent-id}]))))

View file

@ -406,7 +406,6 @@
;; so the menu can be handled ;; so the menu can be handled
[:div {:style {:pointer-events "all"}} [:div {:style {:pointer-events "all"}}
[:> file-menu* {:files (vals selected-files) [:> file-menu* {:files (vals selected-files)
:show (:menu-open dashboard-local)
:left (+ 24 (:x (:menu-pos dashboard-local))) :left (+ 24 (:x (:menu-pos dashboard-local)))
:top (:y (:menu-pos dashboard-local)) :top (:y (:menu-pos dashboard-local))
:can-edit can-edit :can-edit can-edit