mirror of
https://github.com/penpot/penpot.git
synced 2025-08-06 05:18:21 +02:00
commit
aed94c8e91
23 changed files with 175 additions and 85 deletions
14
CHANGES.md
14
CHANGES.md
|
@ -17,7 +17,19 @@
|
||||||
|
|
||||||
- Fix broken profile and profile options form.
|
- Fix broken profile and profile options form.
|
||||||
- Fix problem with mask and flip [#715](https://github.com/penpot/penpot/issues/715)
|
- Fix problem with mask and flip [#715](https://github.com/penpot/penpot/issues/715)
|
||||||
|
- Fix problem with rotated blur [Taiga #1370](https://tree.taiga.io/project/penpot/issue/1370)
|
||||||
|
- Disables buttons in view mode for users without permissions [Taiga #1328](https://tree.taiga.io/project/penpot/issue/1328)
|
||||||
|
- Fix issue when undo after changing the artboard of a shape [Taiga #1304](https://tree.taiga.io/project/penpot/issue/1304)
|
||||||
|
- Fix problem with system shortcuts and application [#737](https://github.com/penpot/penpot/issues/737)
|
||||||
|
- Fix issue with typographies panel cannot be collapsed [#707](https://github.com/penpot/penpot/issues/707)
|
||||||
|
- Fix problem with middle mouse button press moving the canvas when not moving mouse [#717](https://github.com/penpot/penpot/issues/717)
|
||||||
|
- Fix problem with masks interactions outside bounds [#718](https://github.com/penpot/penpot/issues/718)
|
||||||
|
- Fix issues with Alt key in distance measurement [#672](https://github.com/penpot/penpot/issues/672)
|
||||||
|
- Fix problem with rotation degree input [#741](https://github.com/penpot/penpot/issues/741)
|
||||||
|
- Fix problem with resolved comments [Taiga #1406](https://tree.taiga.io/project/penpot/issue/1406)
|
||||||
|
- Fix problem with comments styles on dashboard [Taiga #1405](https://tree.taiga.io/project/penpot/issue/1405)
|
||||||
|
- Fix problem with default square grid [Taiga #1344](https://tree.taiga.io/project/penpot/issue/1344)
|
||||||
|
- Fix error with the "Navigate to" button on prototypes [Taiga #1268](https://tree.taiga.io/project/penpot/issue/1268)
|
||||||
|
|
||||||
### :heart: Community contributions by (Thank you!)
|
### :heart: Community contributions by (Thank you!)
|
||||||
|
|
||||||
|
|
|
@ -146,14 +146,14 @@
|
||||||
(db/with-atomic [conn pool]
|
(db/with-atomic [conn pool]
|
||||||
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
(let [thread (db/get-by-id conn :comment-thread id {:for-update true})]
|
||||||
(when-not thread
|
(when-not thread
|
||||||
(ex/raise :type :not-found)
|
(ex/raise :type :not-found))
|
||||||
|
|
||||||
(files/check-read-permissions! conn profile-id (:file-id thread))
|
(files/check-read-permissions! conn profile-id (:file-id thread))
|
||||||
|
|
||||||
(db/update! conn :comment-thread
|
(db/update! conn :comment-thread
|
||||||
{:is-resolved is-resolved}
|
{:is-resolved is-resolved}
|
||||||
{:id id})
|
{:id id})
|
||||||
nil))))
|
nil)))
|
||||||
|
|
||||||
|
|
||||||
;; --- Mutation: Add Comment
|
;; --- Mutation: Add Comment
|
||||||
|
|
|
@ -62,6 +62,7 @@
|
||||||
(d/export helpers/touched-group?)
|
(d/export helpers/touched-group?)
|
||||||
(d/export helpers/get-base-shape)
|
(d/export helpers/get-base-shape)
|
||||||
(d/export helpers/is-parent?)
|
(d/export helpers/is-parent?)
|
||||||
|
(d/export helpers/get-index-in-parent)
|
||||||
|
|
||||||
;; Process changes
|
;; Process changes
|
||||||
(d/export changes/process-changes)
|
(d/export changes/process-changes)
|
||||||
|
|
|
@ -401,3 +401,12 @@
|
||||||
(recur (get objects (first pending))
|
(recur (get objects (first pending))
|
||||||
(conj done (:id current))
|
(conj done (:id current))
|
||||||
(concat (rest pending) (:shapes current))))))
|
(concat (rest pending) (:shapes current))))))
|
||||||
|
|
||||||
|
(defn get-index-in-parent
|
||||||
|
"Retrieves the index in the parent"
|
||||||
|
[objects shape-id]
|
||||||
|
(let [shape (get objects shape-id)
|
||||||
|
parent (get objects (:parent-id shape))
|
||||||
|
[parent-idx _] (d/seek (fn [[idx child-id]] (= child-id shape-id))
|
||||||
|
(d/enumerate (:shapes parent)))]
|
||||||
|
parent-idx))
|
||||||
|
|
|
@ -246,6 +246,7 @@
|
||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
|
|
||||||
.thread-groups {
|
.thread-groups {
|
||||||
|
|
||||||
hr {
|
hr {
|
||||||
border: 0;
|
border: 0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
|
@ -424,16 +425,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.thread-group {
|
.thread-groups {
|
||||||
.section-title {
|
max-height: calc(30rem - 40px);
|
||||||
color: $color-black;
|
overflow: auto;
|
||||||
}
|
|
||||||
|
|
||||||
.threads {
|
hr {
|
||||||
max-height: 25rem;
|
background-color: $color-gray-10;
|
||||||
overflow: auto;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.thread-group .section-title {
|
||||||
|
color: $color-black;
|
||||||
|
}
|
||||||
|
|
||||||
.comment {
|
.comment {
|
||||||
.author .name .fullname {
|
.author .name .fullname {
|
||||||
|
|
|
@ -82,7 +82,8 @@
|
||||||
(st/emit! (rt/initialize-router ui/routes)
|
(st/emit! (rt/initialize-router ui/routes)
|
||||||
(rt/initialize-history on-navigate))
|
(rt/initialize-history on-navigate))
|
||||||
|
|
||||||
(st/emit! (udu/fetch-profile))
|
(st/emit! (udu/fetch-profile)
|
||||||
|
(udu/fetch-user-teams))
|
||||||
(mf/mount (mf/element ui/app) (dom/get-element "app"))
|
(mf/mount (mf/element ui/app) (dom/get-element "app"))
|
||||||
(mf/mount (mf/element modal) (dom/get-element "modal")))
|
(mf/mount (mf/element modal) (dom/get-element "modal")))
|
||||||
|
|
||||||
|
|
|
@ -327,9 +327,7 @@
|
||||||
(let [{:keys [show mode open]} cstate]
|
(let [{:keys [show mode open]} cstate]
|
||||||
(cond->> threads
|
(cond->> threads
|
||||||
(= :pending show)
|
(= :pending show)
|
||||||
(filter (fn [item]
|
(filter (comp not :is-resolved))
|
||||||
(or (not (:is-resolved item))
|
|
||||||
(= (:id item) open))))
|
|
||||||
|
|
||||||
(= :yours mode)
|
(= :yours mode)
|
||||||
(filter #(contains? (:participants %) (:id profile))))))
|
(filter #(contains? (:participants %) (:id profile))))))
|
||||||
|
|
|
@ -39,13 +39,23 @@
|
||||||
(str "command+" shortcut)
|
(str "command+" shortcut)
|
||||||
(str "ctrl+" shortcut)))
|
(str "ctrl+" shortcut)))
|
||||||
|
|
||||||
|
(defn a-mod
|
||||||
|
"Adds the alt/option modifier to a shortcuts depending on the
|
||||||
|
operating system for the user"
|
||||||
|
[shortcut]
|
||||||
|
(str "alt+" shortcut))
|
||||||
|
|
||||||
|
(defn ca-mod
|
||||||
|
[shortcut]
|
||||||
|
(c-mod (a-mod shortcut)))
|
||||||
|
|
||||||
(defn bind-shortcuts [shortcuts bind-fn cb-fn]
|
(defn bind-shortcuts [shortcuts bind-fn cb-fn]
|
||||||
(doseq [[key {:keys [command disabled fn]}] shortcuts]
|
(doseq [[key {:keys [command disabled fn type]}] shortcuts]
|
||||||
(when-not disabled
|
(when-not disabled
|
||||||
(if (vector? command)
|
(if (vector? command)
|
||||||
(doseq [cmd (seq command)]
|
(doseq [cmd (seq command)]
|
||||||
(bind-fn cmd (cb-fn key fn)))
|
(bind-fn cmd (cb-fn key fn) type))
|
||||||
(bind-fn command (cb-fn key fn))))))
|
(bind-fn command (cb-fn key fn) type)))))
|
||||||
|
|
||||||
(defn meta [key]
|
(defn meta [key]
|
||||||
(str
|
(str
|
||||||
|
@ -61,9 +71,19 @@
|
||||||
"Shift+")
|
"Shift+")
|
||||||
key))
|
key))
|
||||||
|
|
||||||
|
(defn alt [key]
|
||||||
|
(str
|
||||||
|
(if (cfg/check-platform? :macos)
|
||||||
|
mac-option
|
||||||
|
"Alt+")
|
||||||
|
key))
|
||||||
|
|
||||||
(defn meta-shift [key]
|
(defn meta-shift [key]
|
||||||
(-> key meta shift))
|
(-> key meta shift))
|
||||||
|
|
||||||
|
(defn meta-alt [key]
|
||||||
|
(-> key meta alt))
|
||||||
|
|
||||||
(defn supr []
|
(defn supr []
|
||||||
(if (cfg/check-platform? :macos)
|
(if (cfg/check-platform? :macos)
|
||||||
mac-delete
|
mac-delete
|
||||||
|
|
|
@ -55,7 +55,10 @@
|
||||||
(ptk/reify ::profile-fetched
|
(ptk/reify ::profile-fetched
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc state :profile data))
|
(-> state
|
||||||
|
(assoc :profile data)
|
||||||
|
;; Safeguard if the profile is loaded after teams
|
||||||
|
(assoc-in [:profile :teams] (get-in state [:profile :teams]))))
|
||||||
|
|
||||||
ptk/EffectEvent
|
ptk/EffectEvent
|
||||||
(effect [_ state stream]
|
(effect [_ state stream]
|
||||||
|
@ -203,4 +206,23 @@
|
||||||
(->> (rp/query :team-users {:team-id team-id})
|
(->> (rp/query :team-users {:team-id team-id})
|
||||||
(rx/map #(partial fetched %)))))))
|
(rx/map #(partial fetched %)))))))
|
||||||
|
|
||||||
|
(defn user-teams-fetched [data]
|
||||||
|
(ptk/reify ::user-teams-fetched
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(let [teams (->> data
|
||||||
|
(group-by :id)
|
||||||
|
(d/mapm #(first %2)))]
|
||||||
|
(assoc-in state [:profile :teams] teams)))))
|
||||||
|
|
||||||
|
(defn fetch-user-teams []
|
||||||
|
(ptk/reify ::fetch-user-teams
|
||||||
|
ptk/WatchEvent
|
||||||
|
(watch [_ state s]
|
||||||
|
(->> (rp/query! :teams)
|
||||||
|
(rx/map user-teams-fetched)
|
||||||
|
(rx/catch (fn [error]
|
||||||
|
(if (= (:type error) :not-found)
|
||||||
|
(rx/of (rt/nav :auth-login))
|
||||||
|
(rx/empty))))))))
|
||||||
|
|
||||||
|
|
|
@ -1726,6 +1726,13 @@
|
||||||
:data [image]}]
|
:data [image]}]
|
||||||
(rx/of (dwp/upload-media-workspace params @ms/mouse-position))))))
|
(rx/of (dwp/upload-media-workspace params @ms/mouse-position))))))
|
||||||
|
|
||||||
|
(defn toggle-distances-display [value]
|
||||||
|
(ptk/reify ::toggle-distances-display
|
||||||
|
|
||||||
|
ptk/UpdateEvent
|
||||||
|
(update [_ state]
|
||||||
|
(assoc-in state [:workspace-local :show-distances?] value))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Interactions
|
;; Interactions
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
data (get-in state [:workspace-data page-id])
|
data (get-in state [:workspace-data :pages-index page-id])
|
||||||
params (or (get-in data [:options :saved-grids :square])
|
params (or (get-in data [:options :saved-grids :square])
|
||||||
(:square default-grid-params))
|
(:square default-grid-params))
|
||||||
grid {:type :square
|
grid {:type :square
|
||||||
|
|
|
@ -44,20 +44,20 @@
|
||||||
(rx/empty))))))
|
(rx/empty))))))
|
||||||
|
|
||||||
(def shortcuts
|
(def shortcuts
|
||||||
{:toggle-layers {:tooltip (ds/meta "L")
|
{:toggle-layers {:tooltip (ds/alt "L")
|
||||||
:command (ds/c-mod "l")
|
:command (ds/a-mod "l")
|
||||||
:fn #(st/emit! (dw/go-to-layout :layers))}
|
:fn #(st/emit! (dw/go-to-layout :layers))}
|
||||||
|
|
||||||
:toggle-assets {:tooltip (ds/meta "I")
|
:toggle-assets {:tooltip (ds/alt "I")
|
||||||
:command (ds/c-mod "i")
|
:command (ds/a-mod "i")
|
||||||
:fn #(st/emit! (dw/go-to-layout :assets))}
|
:fn #(st/emit! (dw/go-to-layout :assets))}
|
||||||
|
|
||||||
:toggle-history {:tooltip (ds/meta "H")
|
:toggle-history {:tooltip (ds/alt "H")
|
||||||
:command (ds/c-mod "h")
|
:command (ds/a-mod "h")
|
||||||
:fn #(st/emit! (dw/go-to-layout :document-history))}
|
:fn #(st/emit! (dw/go-to-layout :document-history))}
|
||||||
|
|
||||||
:toggle-palette {:tooltip (ds/meta "P")
|
:toggle-palette {:tooltip (ds/alt "P")
|
||||||
:command (ds/c-mod "p")
|
:command (ds/a-mod "p")
|
||||||
:fn #(st/emit! (dw/toggle-layout-flags :colorpalette))}
|
:fn #(st/emit! (dw/toggle-layout-flags :colorpalette))}
|
||||||
|
|
||||||
:toggle-rules {:tooltip (ds/meta-shift "R")
|
:toggle-rules {:tooltip (ds/meta-shift "R")
|
||||||
|
@ -260,6 +260,16 @@
|
||||||
:start-editing {:tooltip (ds/enter)
|
:start-editing {:tooltip (ds/enter)
|
||||||
:command "enter"
|
:command "enter"
|
||||||
:fn #(st/emit! (dw/start-editing-selected))}
|
:fn #(st/emit! (dw/start-editing-selected))}
|
||||||
|
|
||||||
|
:start-measure {:tooltip (ds/alt "")
|
||||||
|
:command ["alt" "."]
|
||||||
|
:type "keydown"
|
||||||
|
:fn #(st/emit! (dw/toggle-distances-display true))}
|
||||||
|
|
||||||
|
:stop-measure {:tooltip (ds/alt "")
|
||||||
|
:command ["alt" "."]
|
||||||
|
:type "keyup"
|
||||||
|
:fn #(st/emit! (dw/toggle-distances-display false))}
|
||||||
})
|
})
|
||||||
|
|
||||||
(defn get-tooltip [shortcut]
|
(defn get-tooltip [shortcut]
|
||||||
|
|
|
@ -249,14 +249,15 @@
|
||||||
:parent-id frame-id
|
:parent-id frame-id
|
||||||
:shapes (mapv :id moving-shapes)}]
|
:shapes (mapv :id moving-shapes)}]
|
||||||
|
|
||||||
moving-shapes-by-frame-id (group-by :frame-id moving-shapes)
|
|
||||||
|
|
||||||
uch (->> moving-shapes-by-frame-id
|
uch (->> moving-shapes
|
||||||
(mapv (fn [[frame-id shapes]]
|
(reverse)
|
||||||
|
(mapv (fn [shape]
|
||||||
{:type :mov-objects
|
{:type :mov-objects
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:parent-id frame-id
|
:parent-id (:parent-id shape)
|
||||||
:shapes (mapv :id shapes)})))]
|
:index (cp/get-index-in-parent objects (:id shape))
|
||||||
|
:shapes [(:id shape)]})))]
|
||||||
|
|
||||||
(when-not (empty? rch)
|
(when-not (empty? rch)
|
||||||
(rx/of dwc/pop-undo-into-transaction
|
(rx/of dwc/pop-undo-into-transaction
|
||||||
|
|
|
@ -69,7 +69,8 @@
|
||||||
:transform
|
:transform
|
||||||
:hover
|
:hover
|
||||||
:modifiers
|
:modifiers
|
||||||
:selrect])
|
:selrect
|
||||||
|
:show-distances?])
|
||||||
workspace-local =))
|
workspace-local =))
|
||||||
|
|
||||||
(def selected-zoom
|
(def selected-zoom
|
||||||
|
|
|
@ -143,28 +143,3 @@
|
||||||
(rx/dedupe))]
|
(rx/dedupe))]
|
||||||
(rx/subscribe-with ob sub)
|
(rx/subscribe-with ob sub)
|
||||||
sub))
|
sub))
|
||||||
|
|
||||||
(defn mouse-position-deltas
|
|
||||||
[current]
|
|
||||||
(->> (rx/concat (rx/of current)
|
|
||||||
(rx/sample 10 mouse-position))
|
|
||||||
(rx/buffer 2 1)
|
|
||||||
(rx/map (fn [[old new]]
|
|
||||||
(gpt/subtract new old)))))
|
|
||||||
|
|
||||||
|
|
||||||
(defonce mouse-position-delta
|
|
||||||
(let [sub (rx/behavior-subject nil)
|
|
||||||
ob (->> st/stream
|
|
||||||
(rx/filter pointer-event?)
|
|
||||||
(rx/filter #(= :delta (:source %)))
|
|
||||||
(rx/map :pt))]
|
|
||||||
(rx/subscribe-with ob sub)
|
|
||||||
sub))
|
|
||||||
|
|
||||||
(defonce viewport-scroll
|
|
||||||
(let [sub (rx/behavior-subject nil)
|
|
||||||
sob (->> (rx/filter scroll-event? st/stream)
|
|
||||||
(rx/map :point))]
|
|
||||||
(rx/subscribe-with sob sub)
|
|
||||||
sub))
|
|
||||||
|
|
|
@ -78,10 +78,10 @@
|
||||||
(dom/set-value! (dom/get-target event) new-value))
|
(dom/set-value! (dom/get-target event) new-value))
|
||||||
|
|
||||||
(and wrap-value? (num? max-val) (num? min-val) (= value max-val) up?)
|
(and wrap-value? (num? max-val) (num? min-val) (= value max-val) up?)
|
||||||
(dom/set-value! (dom/get-target event) min-val)
|
(dom/set-value! (dom/get-target event) (dec min-val))
|
||||||
|
|
||||||
(and wrap-value? (num? min-val) (num? max-val) (= value min-val) down?)
|
(and wrap-value? (num? min-val) (num? max-val) (= value min-val) down?)
|
||||||
(dom/set-value! (dom/get-target event) max-val))))))
|
(dom/set-value! (dom/get-target event) (inc max-val)))))))
|
||||||
|
|
||||||
handle-key-down
|
handle-key-down
|
||||||
(mf/use-callback
|
(mf/use-callback
|
||||||
|
|
|
@ -9,12 +9,13 @@
|
||||||
|
|
||||||
(ns app.main.ui.shapes.filters
|
(ns app.main.ui.shapes.filters
|
||||||
(:require
|
(:require
|
||||||
[rumext.alpha :as mf]
|
|
||||||
[cuerdas.core :as str]
|
|
||||||
[app.util.color :as color]
|
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
[app.common.uuid :as uuid]))
|
[app.common.uuid :as uuid]
|
||||||
|
[app.util.color :as color]
|
||||||
|
[cuerdas.core :as str]
|
||||||
|
[rumext.alpha :as mf]))
|
||||||
|
|
||||||
(defn get-filter-id []
|
(defn get-filter-id []
|
||||||
(str "filter_" (uuid/next)))
|
(str "filter_" (uuid/next)))
|
||||||
|
@ -137,7 +138,7 @@
|
||||||
(filter #(= :drop-shadow (:type %)))
|
(filter #(= :drop-shadow (:type %)))
|
||||||
(map (partial filter-bounds shape) ))
|
(map (partial filter-bounds shape) ))
|
||||||
;; We add the selrect so the minimum size will be the selrect
|
;; We add the selrect so the minimum size will be the selrect
|
||||||
filter-bounds (conj filter-bounds (:selrect shape))
|
filter-bounds (conj filter-bounds (-> shape :points gsh/points->selrect))
|
||||||
x1 (apply min (map :x1 filter-bounds))
|
x1 (apply min (map :x1 filter-bounds))
|
||||||
y1 (apply min (map :y1 filter-bounds))
|
y1 (apply min (map :y1 filter-bounds))
|
||||||
x2 (apply max (map :x2 filter-bounds))
|
x2 (apply max (map :x2 filter-bounds))
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[app.main.ui.shapes.attrs :as attrs]
|
[app.main.ui.shapes.attrs :as attrs]
|
||||||
[app.main.ui.shapes.mask :refer [mask-str mask-factory]]))
|
[app.main.ui.shapes.mask :refer [mask-str clip-str mask-factory]]))
|
||||||
|
|
||||||
(defn group-shape
|
(defn group-shape
|
||||||
[shape-wrapper]
|
[shape-wrapper]
|
||||||
|
@ -35,6 +35,7 @@
|
||||||
props (-> (attrs/extract-style-attrs shape)
|
props (-> (attrs/extract-style-attrs shape)
|
||||||
(obj/merge!
|
(obj/merge!
|
||||||
#js {:pointerEvents pointer-events
|
#js {:pointerEvents pointer-events
|
||||||
|
:clipPath (when (and mask (not expand-mask)) (clip-str mask))
|
||||||
:mask (when (and mask (not expand-mask)) (mask-str mask))}))]
|
:mask (when (and mask (not expand-mask)) (mask-str mask))}))]
|
||||||
|
|
||||||
[:> :g props
|
[:> :g props
|
||||||
|
|
|
@ -10,18 +10,25 @@
|
||||||
(ns app.main.ui.shapes.mask
|
(ns app.main.ui.shapes.mask
|
||||||
(:require
|
(:require
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[cuerdas.core :as str]))
|
[cuerdas.core :as str]
|
||||||
|
[app.common.geom.shapes :as gsh]))
|
||||||
|
|
||||||
(defn mask-str [mask]
|
(defn mask-str [mask]
|
||||||
(str/fmt "url(#%s)" (str (:id mask) "-mask")))
|
(str/fmt "url(#%s)" (str (:id mask) "-mask")))
|
||||||
|
|
||||||
|
(defn clip-str [mask]
|
||||||
|
(str/fmt "url(#%s)" (str (:id mask) "-clip")))
|
||||||
|
|
||||||
(defn mask-factory
|
(defn mask-factory
|
||||||
[shape-wrapper]
|
[shape-wrapper]
|
||||||
(mf/fnc mask-shape
|
(mf/fnc mask-shape
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [frame (unchecked-get props "frame")
|
(let [frame (unchecked-get props "frame")
|
||||||
mask (unchecked-get props "mask")]
|
mask (unchecked-get props "mask")
|
||||||
|
mask' (-> mask
|
||||||
|
(gsh/transform-shape)
|
||||||
|
(gsh/translate-to-frame frame))]
|
||||||
[:defs
|
[:defs
|
||||||
[:filter {:id (str (:id mask) "-filter")}
|
[:filter {:id (str (:id mask) "-filter")}
|
||||||
[:feFlood {:flood-color "white"
|
[:feFlood {:flood-color "white"
|
||||||
|
@ -30,8 +37,16 @@
|
||||||
:in2 "SourceGraphic"
|
:in2 "SourceGraphic"
|
||||||
:operator "in"
|
:operator "in"
|
||||||
:result "comp"}]]
|
:result "comp"}]]
|
||||||
|
;; Clip path is necesary so the elements inside the mask won't affect
|
||||||
|
;; the events outside. Clip hides the elements but mask doesn't (like display vs visibility)
|
||||||
|
;; we cannot use clips instead of mask because clips can only be simple shapes
|
||||||
|
[:clipPath {:id (str (:id mask) "-clip")}
|
||||||
|
[:polyline {:points (->> (:points mask')
|
||||||
|
(map #(str (:x %) "," (:y %)))
|
||||||
|
(str/join " "))}]]
|
||||||
[:mask {:id (str (:id mask) "-mask")}
|
[:mask {:id (str (:id mask) "-mask")}
|
||||||
[:g {:filter (str/fmt "url(#%s)" (str (:id mask) "-filter"))}
|
[:g {:filter (str/fmt "url(#%s)" (str (:id mask) "-filter"))}
|
||||||
[:& shape-wrapper {:frame frame :shape (-> mask
|
[:& shape-wrapper {:frame frame
|
||||||
(dissoc :shadow :blur))}]]]])))
|
:shape (-> mask
|
||||||
|
(dissoc :shadow :blur))}]]]])))
|
||||||
|
|
||||||
|
|
|
@ -191,6 +191,11 @@
|
||||||
profile (mf/deref refs/profile)
|
profile (mf/deref refs/profile)
|
||||||
anonymous? (= uuid/zero (:id profile))
|
anonymous? (= uuid/zero (:id profile))
|
||||||
|
|
||||||
|
team-id (get-in data [:project :team-id])
|
||||||
|
|
||||||
|
has-permission? (and (not anonymous?)
|
||||||
|
(contains? (:teams profile) team-id))
|
||||||
|
|
||||||
project-id (get-in data [:project :id])
|
project-id (get-in data [:project :id])
|
||||||
file-id (get-in data [:file :id])
|
file-id (get-in data [:file :id])
|
||||||
page-id (get-in data [:page :id])
|
page-id (get-in data [:page :id])
|
||||||
|
@ -219,7 +224,9 @@
|
||||||
|
|
||||||
[:header.viewer-header
|
[:header.viewer-header
|
||||||
[:div.main-icon
|
[:div.main-icon
|
||||||
[:a {:on-click on-goback} i/logo-icon]]
|
[:a {:on-click on-goback
|
||||||
|
;; If the user doesn't have permission we disable the link
|
||||||
|
:style {:pointer-events (when-not has-permission? "none")}} i/logo-icon]]
|
||||||
|
|
||||||
[:div.sitemap-zone {:alt (t locale "viewer.header.sitemap")
|
[:div.sitemap-zone {:alt (t locale "viewer.header.sitemap")
|
||||||
:on-click on-click}
|
:on-click on-click}
|
||||||
|
@ -238,7 +245,7 @@
|
||||||
:alt "View mode"}
|
:alt "View mode"}
|
||||||
i/play]
|
i/play]
|
||||||
|
|
||||||
(when-not anonymous?
|
(when has-permission?
|
||||||
[:button.mode-zone-button.tooltip.tooltip-bottom
|
[:button.mode-zone-button.tooltip.tooltip-bottom
|
||||||
{:on-click #(navigate :comments)
|
{:on-click #(navigate :comments)
|
||||||
:class (dom/classnames :active (= section :comments))
|
:class (dom/classnames :active (= section :comments))
|
||||||
|
@ -257,11 +264,11 @@
|
||||||
:comments [:& comments-menu {:locale locale}]
|
:comments [:& comments-menu {:locale locale}]
|
||||||
nil)
|
nil)
|
||||||
|
|
||||||
(when-not anonymous?
|
(when has-permission?
|
||||||
[:& share-link {:token (:token data)
|
[:& share-link {:token (:token data)
|
||||||
:page (:page data)}])
|
:page (:page data)}])
|
||||||
|
|
||||||
(when-not anonymous?
|
(when has-permission?
|
||||||
[:a.btn-text-basic.btn-small {:on-click on-edit}
|
[:a.btn-text-basic.btn-small {:on-click on-edit}
|
||||||
(t locale "viewer.header.edit-page")])
|
(t locale "viewer.header.edit-page")])
|
||||||
|
|
||||||
|
|
|
@ -491,7 +491,7 @@
|
||||||
|
|
||||||
[:div.asset-group
|
[:div.asset-group
|
||||||
[:div.group-title {:class (when (not open?) "closed")}
|
[:div.group-title {:class (when (not open?) "closed")}
|
||||||
[:span {:on-click (st/emitf (dwl/set-assets-box-open file-id :typography (not open?)))}
|
[:span {:on-click (st/emitf (dwl/set-assets-box-open file-id :typographies (not open?)))}
|
||||||
i/arrow-slide (t locale "workspace.assets.typography")]
|
i/arrow-slide (t locale "workspace.assets.typography")]
|
||||||
[:span.num-assets (str "\u00A0(") (count typographies) ")"] ;; Unicode 00A0 is non-breaking space
|
[:span.num-assets (str "\u00A0(") (count typographies) ")"] ;; Unicode 00A0 is non-breaking space
|
||||||
(when local?
|
(when local?
|
||||||
|
|
|
@ -37,7 +37,8 @@
|
||||||
show-frames-dropdown? (mf/use-state false)
|
show-frames-dropdown? (mf/use-state false)
|
||||||
|
|
||||||
on-set-blur #(reset! show-frames-dropdown? false)
|
on-set-blur #(reset! show-frames-dropdown? false)
|
||||||
on-navigate #(st/emit! (dw/select-shapes (d/ordered-set (:id destination))))
|
on-navigate #(when destination
|
||||||
|
(st/emit! (dw/select-shapes (d/ordered-set (:id destination)))))
|
||||||
|
|
||||||
on-select-destination
|
on-select-destination
|
||||||
(fn [dest]
|
(fn [dest]
|
||||||
|
@ -77,4 +78,5 @@
|
||||||
[:li {:key (:id frame)
|
[:li {:key (:id frame)
|
||||||
:on-click #(on-select-destination (:id frame))}
|
:on-click #(on-select-destination (:id frame))}
|
||||||
(:name frame)]))]]]
|
(:name frame)]))]]]
|
||||||
[:span.navigate-icon {on-click on-navigate} i/navigate]]]])))
|
[:span.navigate-icon {:style {:visibility (when (not destination) "hidden")}
|
||||||
|
:on-click on-navigate} i/navigate]]]])))
|
||||||
|
|
|
@ -131,18 +131,21 @@
|
||||||
(defn- handle-viewport-positioning
|
(defn- handle-viewport-positioning
|
||||||
[viewport-ref]
|
[viewport-ref]
|
||||||
(let [node (mf/ref-val viewport-ref)
|
(let [node (mf/ref-val viewport-ref)
|
||||||
stoper (rx/filter #(= ::finish-positioning %) st/stream)
|
stoper (rx/filter #(= ::finish-positioning %) st/stream)]
|
||||||
|
|
||||||
stream (->> ms/mouse-position-delta
|
|
||||||
(rx/take-until stoper))]
|
|
||||||
(st/emit! dw/start-pan)
|
(st/emit! dw/start-pan)
|
||||||
(rx/subscribe stream
|
|
||||||
(fn [delta]
|
(->> st/stream
|
||||||
|
(rx/filter ms/pointer-event?)
|
||||||
|
(rx/filter #(= :delta (:source %)))
|
||||||
|
(rx/map :pt)
|
||||||
|
(rx/take-until stoper)
|
||||||
|
(rx/subs (fn [delta]
|
||||||
(let [zoom (gpt/point @refs/selected-zoom)
|
(let [zoom (gpt/point @refs/selected-zoom)
|
||||||
delta (gpt/divide delta zoom)]
|
delta (gpt/divide delta zoom)]
|
||||||
(st/emit! (dw/update-viewport-position
|
(st/emit! (dw/update-viewport-position
|
||||||
{:x #(- % (:x delta))
|
{:x #(- % (:x delta))
|
||||||
:y #(- % (:y delta))})))))))
|
:y #(- % (:y delta))}))))))))
|
||||||
|
|
||||||
;; --- Viewport
|
;; --- Viewport
|
||||||
|
|
||||||
|
@ -347,7 +350,8 @@
|
||||||
transform
|
transform
|
||||||
hover
|
hover
|
||||||
modifiers
|
modifiers
|
||||||
selrect]} local
|
selrect
|
||||||
|
show-distances?]} local
|
||||||
|
|
||||||
page-id (mf/use-ctx ctx/current-page-id)
|
page-id (mf/use-ctx ctx/current-page-id)
|
||||||
|
|
||||||
|
@ -794,7 +798,7 @@
|
||||||
[:& selection-handlers {:selected selected
|
[:& selection-handlers {:selected selected
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:edition edition
|
:edition edition
|
||||||
:show-distances (and (not transform) @alt?)
|
:show-distances (and (not transform) show-distances?)
|
||||||
:disable-handlers (or drawing-tool edition)}])
|
:disable-handlers (or drawing-tool edition)}])
|
||||||
|
|
||||||
(when (= (count selected) 1)
|
(when (= (count selected) 1)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue