mirror of
https://github.com/penpot/penpot.git
synced 2025-05-29 00:47:21 +02:00
✨ Improve interactions with nested boards
This commit is contained in:
parent
7dcd362abd
commit
0e49625ebf
6 changed files with 81 additions and 35 deletions
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
### :sparkles: New features
|
### :sparkles: New features
|
||||||
|
|
||||||
|
- Improve interactions with nested boards [Taiga #4054](https://tree.taiga.io/project/penpot/us/4054)
|
||||||
- Add team hero in projects dashboard [Taiga #3863](https://tree.taiga.io/project/penpot/us/3863)
|
- Add team hero in projects dashboard [Taiga #3863](https://tree.taiga.io/project/penpot/us/3863)
|
||||||
- Add zoom style to shared link [Taiga #3874](https://tree.taiga.io/project/penpot/us/3874)
|
- Add zoom style to shared link [Taiga #3874](https://tree.taiga.io/project/penpot/us/3874)
|
||||||
- Add dashboard creation button as placeholder [Taiga #3861](https://tree.taiga.io/project/penpot/us/3861)
|
- Add dashboard creation button as placeholder [Taiga #3861](https://tree.taiga.io/project/penpot/us/3861)
|
||||||
|
|
|
@ -512,6 +512,18 @@
|
||||||
(assert (has-offset-effect? interaction))
|
(assert (has-offset-effect? interaction))
|
||||||
(update interaction :animation assoc :offset-effect offset-effect))
|
(update interaction :animation assoc :offset-effect offset-effect))
|
||||||
|
|
||||||
|
(defn dest-to?
|
||||||
|
"Check if the interaction has the given frame as destination."
|
||||||
|
[interaction frame-id]
|
||||||
|
(and (has-destination interaction)
|
||||||
|
(= (:destination interaction) frame-id)))
|
||||||
|
|
||||||
|
(defn navs-to?
|
||||||
|
"Check if the interaction is a navigation to the given frame."
|
||||||
|
[interaction frame-id]
|
||||||
|
(and (= (:action-type interaction) :navigate)
|
||||||
|
(= (:destination interaction) frame-id)))
|
||||||
|
|
||||||
;; -- Helpers for interactions
|
;; -- Helpers for interactions
|
||||||
|
|
||||||
(defn add-interaction
|
(defn add-interaction
|
||||||
|
@ -543,6 +555,12 @@
|
||||||
(d/update-when interaction :destination #(get ids-map % %)))))]
|
(d/update-when interaction :destination #(get ids-map % %)))))]
|
||||||
(into [] xform interactions))))
|
(into [] xform interactions))))
|
||||||
|
|
||||||
|
(defn remove-interactions
|
||||||
|
"Remove all interactions that the fn returns true."
|
||||||
|
[f interactions]
|
||||||
|
(-> (d/removev f interactions)
|
||||||
|
not-empty))
|
||||||
|
|
||||||
(defn actionable?
|
(defn actionable?
|
||||||
"Check if there is any interaction that is clickable by the user"
|
"Check if there is any interaction that is clickable by the user"
|
||||||
[interactions]
|
[interactions]
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.streams :as ms]
|
[app.main.streams :as ms]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[potok.core :as ptk]))
|
[potok.core :as ptk]))
|
||||||
|
@ -149,6 +150,29 @@
|
||||||
(update shape :interactions
|
(update shape :interactions
|
||||||
ctsi/update-interaction index update-fn)))))))
|
ctsi/update-interaction index update-fn)))))))
|
||||||
|
|
||||||
|
(defn remove-all-interactions-nav-to
|
||||||
|
"Remove all interactions that navigate to the given frame."
|
||||||
|
[frame-id]
|
||||||
|
(ptk/reify ::remove-all-interactions-nav-to
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state _]
|
||||||
|
(let [page-id (:current-page-id state)
|
||||||
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
|
|
||||||
|
remove-interactions-shape
|
||||||
|
(fn [shape]
|
||||||
|
(let [interactions (:interactions shape)
|
||||||
|
new-interactions (ctsi/remove-interactions #(ctsi/navs-to? % frame-id)
|
||||||
|
interactions)]
|
||||||
|
(when (not= (count interactions) (count new-interactions))
|
||||||
|
(dch/update-shapes [(:id shape)]
|
||||||
|
(fn [shape]
|
||||||
|
(assoc shape :interactions new-interactions))))))]
|
||||||
|
|
||||||
|
(rx/from (->> (vals objects)
|
||||||
|
(map remove-interactions-shape)
|
||||||
|
(d/vec-without-nils)))))))
|
||||||
|
|
||||||
(declare move-edit-interaction)
|
(declare move-edit-interaction)
|
||||||
(declare finish-edit-interaction)
|
(declare finish-edit-interaction)
|
||||||
|
|
||||||
|
@ -171,8 +195,7 @@
|
||||||
(rx/map #(move-edit-interaction initial-pos %)))
|
(rx/map #(move-edit-interaction initial-pos %)))
|
||||||
(rx/of (finish-edit-interaction index initial-pos))))))))
|
(rx/of (finish-edit-interaction index initial-pos))))))))
|
||||||
|
|
||||||
|
(defn- get-target-frame
|
||||||
(defn get-target-frame
|
|
||||||
[state position]
|
[state position]
|
||||||
|
|
||||||
(let [objects (wsh/lookup-page-objects state)
|
(let [objects (wsh/lookup-page-objects state)
|
||||||
|
@ -185,8 +208,7 @@
|
||||||
target-frame (ctst/frame-by-position objects position)]
|
target-frame (ctst/frame-by-position objects position)]
|
||||||
|
|
||||||
(when (and (not= (:id target-frame) uuid/zero)
|
(when (and (not= (:id target-frame) uuid/zero)
|
||||||
(not= (:id target-frame) from-frame-id)
|
(not= (:id target-frame) from-frame-id))
|
||||||
(not (:hide-in-viewer target-frame)))
|
|
||||||
target-frame)))
|
target-frame)))
|
||||||
|
|
||||||
(defn move-edit-interaction
|
(defn move-edit-interaction
|
||||||
|
@ -225,25 +247,34 @@
|
||||||
:always
|
:always
|
||||||
(ctsi/set-destination (:id target-frame))))]
|
(ctsi/set-destination (:id target-frame))))]
|
||||||
|
|
||||||
|
(rx/of
|
||||||
|
(dwu/start-undo-transaction)
|
||||||
|
|
||||||
|
(when (:hide-in-viewer target-frame)
|
||||||
|
; If the target frame is hidden, we need to unhide it so
|
||||||
|
; users can navigate to it.
|
||||||
|
(dch/update-shapes [(:id target-frame)]
|
||||||
|
#(dissoc % :hide-in-viewer)))
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(or (nil? shape)
|
(or (nil? shape)
|
||||||
|
|
||||||
;; Didn't changed the position for the interaction
|
;; Didn't changed the position for the interaction
|
||||||
(= position initial-pos)
|
(= position initial-pos)
|
||||||
|
|
||||||
;; New interaction but invalid target
|
;; New interaction but invalid target
|
||||||
(and (nil? index) (nil? target-frame)))
|
(and (nil? index) (nil? target-frame)))
|
||||||
nil
|
nil
|
||||||
|
|
||||||
;; Dropped interaction in an invalid target. We remove it
|
;; Dropped interaction in an invalid target. We remove it
|
||||||
(and (some? index) (nil? target-frame))
|
(and (some? index) (nil? target-frame))
|
||||||
(rx/of (remove-interaction shape index))
|
(remove-interaction shape index)
|
||||||
|
|
||||||
(nil? index)
|
(nil? index)
|
||||||
(rx/of (add-new-interaction shape (:id target-frame)))
|
(add-new-interaction shape (:id target-frame))
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(rx/of (update-interaction shape index change-interaction)))))))
|
(update-interaction shape index change-interaction))
|
||||||
|
|
||||||
|
(dwu/commit-undo-transaction))))))
|
||||||
|
|
||||||
;; --- Overlays
|
;; --- Overlays
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
[app.common.pages.helpers :as cph]
|
[app.common.pages.helpers :as cph]
|
||||||
[app.common.spec :as us]
|
[app.common.spec :as us]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[app.common.uuid :as uuid]
|
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
[app.main.data.workspace.collapse :as dwc]
|
[app.main.data.workspace.collapse :as dwc]
|
||||||
[app.main.data.workspace.comments :as-alias dwcm]
|
[app.main.data.workspace.comments :as-alias dwcm]
|
||||||
|
@ -758,23 +757,9 @@
|
||||||
(keep lookup)
|
(keep lookup)
|
||||||
(remove #(= (:frame-id %) frame-id)))
|
(remove #(= (:frame-id %) frame-id)))
|
||||||
|
|
||||||
moving-frames
|
|
||||||
(filter #(cph/frame-shape? (lookup %)) ids)
|
|
||||||
|
|
||||||
changes
|
changes
|
||||||
(-> (pcb/empty-changes it page-id)
|
(-> (pcb/empty-changes it page-id)
|
||||||
(pcb/with-objects objects)
|
(pcb/with-objects objects)
|
||||||
(pcb/update-shapes moving-frames
|
|
||||||
(fn [shape]
|
|
||||||
;; Hide in viwer must be enabled just when a board is moved
|
|
||||||
;; inside another artboard an nested to it, we have to avoid
|
|
||||||
;; situations like: 1. Moving inside the same frame; 2. Moving
|
|
||||||
;; outside the frame
|
|
||||||
(cond-> shape
|
|
||||||
(and (not= frame-id (:id shape))
|
|
||||||
(not= frame-id (:frame-id shape))
|
|
||||||
(not= frame-id uuid/zero))
|
|
||||||
(assoc :hide-in-viewer true))))
|
|
||||||
(pcb/change-parent frame-id moving-shapes))]
|
(pcb/change-parent frame-id moving-shapes))]
|
||||||
|
|
||||||
(when-not (empty? changes)
|
(when-not (empty? changes)
|
||||||
|
|
|
@ -183,7 +183,7 @@
|
||||||
(let [objects (deref refs/workspace-page-objects)
|
(let [objects (deref refs/workspace-page-objects)
|
||||||
destination (get objects (:destination interaction))
|
destination (get objects (:destination interaction))
|
||||||
|
|
||||||
frames (mf/with-memo [objects] (ctt/get-viewer-frames objects {:all-frames? (not= :navigate (:action-type interaction))}))
|
frames (mf/with-memo [objects] (ctt/get-viewer-frames objects {:all-frames? true}))
|
||||||
|
|
||||||
overlay-pos-type (:overlay-pos-type interaction)
|
overlay-pos-type (:overlay-pos-type interaction)
|
||||||
close-click-outside? (:close-click-outside interaction false)
|
close-click-outside? (:close-click-outside interaction false)
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
[app.main.constants :refer [size-presets]]
|
[app.main.constants :refer [size-presets]]
|
||||||
[app.main.data.workspace :as udw]
|
[app.main.data.workspace :as udw]
|
||||||
[app.main.data.workspace.changes :as dch]
|
[app.main.data.workspace.changes :as dch]
|
||||||
|
[app.main.data.workspace.interactions :as dwi]
|
||||||
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.components.dropdown :refer [dropdown]]
|
[app.main.ui.components.dropdown :refer [dropdown]]
|
||||||
|
@ -236,7 +238,16 @@
|
||||||
(mf/deps ids)
|
(mf/deps ids)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [value (-> event dom/get-target dom/checked?)]
|
(let [value (-> event dom/get-target dom/checked?)]
|
||||||
(st/emit! (dch/update-shapes ids (fn [shape] (assoc shape :hide-in-viewer (not value))))))))
|
(do
|
||||||
|
(st/emit! (dwu/start-undo-transaction)
|
||||||
|
(dch/update-shapes ids (fn [shape] (assoc shape :hide-in-viewer (not value)))))
|
||||||
|
|
||||||
|
(when-not value
|
||||||
|
;; when a frame is no longer shown in view mode, cannot have
|
||||||
|
;; interactions that navigate to it.
|
||||||
|
(apply st/emit! (map #(dwi/remove-all-interactions-nav-to %) ids)))
|
||||||
|
|
||||||
|
(st/emit! (dwu/commit-undo-transaction))))))
|
||||||
|
|
||||||
select-all #(-> % (dom/get-target) (.select))]
|
select-all #(-> % (dom/get-target) (.select))]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue