mirror of
https://github.com/penpot/penpot.git
synced 2025-05-20 02:46:09 +02:00
Merge pull request #4171 from penpot/niwinz-staging-perfix-2
🐛 Bugfixes and ⚡ Performance enhancements
This commit is contained in:
commit
5883a50520
8 changed files with 203 additions and 156 deletions
|
@ -593,20 +593,21 @@
|
||||||
(defn rename-file
|
(defn rename-file
|
||||||
[id name]
|
[id name]
|
||||||
{:pre [(uuid? id) (string? name)]}
|
{:pre [(uuid? id) (string? name)]}
|
||||||
(ptk/reify ::rename-file
|
(let [name (str/prune name 200)]
|
||||||
IDeref
|
(ptk/reify ::rename-file
|
||||||
(-deref [_]
|
IDeref
|
||||||
{::ev/origin "workspace" :id id :name name})
|
(-deref [_]
|
||||||
|
{::ev/origin "workspace" :id id :name name})
|
||||||
|
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(assoc-in state [:workspace-file :name] name))
|
(assoc-in state [:workspace-file :name] name))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ _ _]
|
(watch [_ _ _]
|
||||||
(let [params {:id id :name name}]
|
(let [params {:id id :name name}]
|
||||||
(->> (rp/cmd! :rename-file params)
|
(->> (rp/cmd! :rename-file params)
|
||||||
(rx/ignore))))))
|
(rx/ignore)))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; Workspace State Manipulation
|
;; Workspace State Manipulation
|
||||||
|
|
|
@ -27,6 +27,11 @@
|
||||||
|
|
||||||
(defn add-flow
|
(defn add-flow
|
||||||
[starting-frame]
|
[starting-frame]
|
||||||
|
|
||||||
|
(dm/assert!
|
||||||
|
"expect uuid"
|
||||||
|
(uuid? starting-frame))
|
||||||
|
|
||||||
(ptk/reify ::add-flow
|
(ptk/reify ::add-flow
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
|
|
|
@ -144,7 +144,8 @@
|
||||||
(remove nil?))
|
(remove nil?))
|
||||||
used (into #{} xfm presence)
|
used (into #{} xfm presence)
|
||||||
avail (set/difference presence-palette used)]
|
avail (set/difference presence-palette used)]
|
||||||
(or (first avail) "var(--app-black)")))
|
;; If all colores are used we select the default one
|
||||||
|
(or (first avail) "#dee563")))
|
||||||
|
|
||||||
(update-color [color presence]
|
(update-color [color presence]
|
||||||
(if (some? color)
|
(if (some? color)
|
||||||
|
@ -158,7 +159,7 @@
|
||||||
(assoc :updated-at (dt/now))
|
(assoc :updated-at (dt/now))
|
||||||
(assoc :version version)
|
(assoc :version version)
|
||||||
(update :color update-color presence)
|
(update :color update-color presence)
|
||||||
(assoc :text-color "#000")))
|
(assoc :text-color "#000000")))
|
||||||
|
|
||||||
(update-presence [presence]
|
(update-presence [presence]
|
||||||
(-> presence
|
(-> presence
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.colors :as cc]
|
[app.common.colors :as cc]
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
[app.config :as cfg]
|
[app.config :as cfg]
|
||||||
[app.main.data.modal :as modal]
|
[app.main.data.modal :as modal]
|
||||||
[app.main.data.workspace.colors :as dc]
|
[app.main.data.workspace.colors :as dc]
|
||||||
|
@ -50,6 +51,7 @@
|
||||||
;; --- Color Picker Modal
|
;; --- Color Picker Modal
|
||||||
|
|
||||||
(mf/defc colorpicker
|
(mf/defc colorpicker
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [data disable-gradient disable-opacity disable-image on-change on-accept]}]
|
[{:keys [data disable-gradient disable-opacity disable-image on-change on-accept]}]
|
||||||
(let [state (mf/deref refs/colorpicker)
|
(let [state (mf/deref refs/colorpicker)
|
||||||
node-ref (mf/use-ref)
|
node-ref (mf/use-ref)
|
||||||
|
@ -90,7 +92,7 @@
|
||||||
(not @drag?)))))
|
(not @drag?)))))
|
||||||
|
|
||||||
on-fill-image-click
|
on-fill-image-click
|
||||||
(mf/use-callback #(dom/click (mf/ref-val fill-image-ref)))
|
(mf/use-fn #(dom/click (mf/ref-val fill-image-ref)))
|
||||||
|
|
||||||
on-fill-image-selected
|
on-fill-image-selected
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
@ -107,7 +109,7 @@
|
||||||
(assoc :keep-aspect-ratio keep-aspect-ratio?))}
|
(assoc :keep-aspect-ratio keep-aspect-ratio?))}
|
||||||
true)))))
|
true)))))
|
||||||
|
|
||||||
set-tab!
|
on-change-tab
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [tab (-> (dom/get-current-target event)
|
(let [tab (-> (dom/get-current-target event)
|
||||||
|
@ -226,7 +228,7 @@
|
||||||
(dom/set-css-property! node "--saturation-grad-from" (format-hsl hsl-from))
|
(dom/set-css-property! node "--saturation-grad-from" (format-hsl hsl-from))
|
||||||
(dom/set-css-property! node "--saturation-grad-to" (format-hsl hsl-to))))
|
(dom/set-css-property! node "--saturation-grad-to" (format-hsl hsl-to))))
|
||||||
|
|
||||||
;; Updates color when used el pixel picker
|
;; Updates color when pixel picker is used
|
||||||
(mf/with-effect [picking-color? picked-color picked-color-select]
|
(mf/with-effect [picking-color? picked-color picked-color-select]
|
||||||
(when (and picking-color? picked-color picked-color-select)
|
(when (and picking-color? picked-color picked-color-select)
|
||||||
(let [[r g b alpha] picked-color
|
(let [[r g b alpha] picked-color
|
||||||
|
@ -294,7 +296,7 @@
|
||||||
[:*
|
[:*
|
||||||
[:div {:class (stl/css :colorpicker-tabs)}
|
[:div {:class (stl/css :colorpicker-tabs)}
|
||||||
[:& tab-container
|
[:& tab-container
|
||||||
{:on-change-tab set-tab!
|
{:on-change-tab on-change-tab
|
||||||
:selected @active-color-tab
|
:selected @active-color-tab
|
||||||
:collapsable false}
|
:collapsable false}
|
||||||
|
|
||||||
|
@ -349,7 +351,7 @@
|
||||||
:on-select-color on-select-library-color
|
:on-select-color on-select-library-color
|
||||||
:on-add-library-color on-add-library-color}]])
|
:on-add-library-color on-add-library-color}]])
|
||||||
|
|
||||||
(when on-accept
|
(when (fn? on-accept)
|
||||||
[:div {:class (stl/css :actions)}
|
[:div {:class (stl/css :actions)}
|
||||||
[:button {:class (stl/css-case
|
[:button {:class (stl/css-case
|
||||||
:accept-color true
|
:accept-color true
|
||||||
|
@ -372,59 +374,69 @@
|
||||||
x-pos 400]
|
x-pos 400]
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(or (nil? x) (nil? y)) #js {:left "auto" :right "16rem" :top "4rem"}
|
(or (nil? x) (nil? y))
|
||||||
|
#js {:left "auto" :right "16rem" :top "4rem"}
|
||||||
|
|
||||||
(= position :left)
|
(= position :left)
|
||||||
(if (> y max-y)
|
(if (> y max-y)
|
||||||
#js {:left (str (- x x-pos) "px")
|
#js {:left (dm/str (- x x-pos) "px")
|
||||||
:bottom "1rem"}
|
:bottom "1rem"}
|
||||||
#js {:left (str (- x x-pos) "px")
|
#js {:left (dm/str (- x x-pos) "px")
|
||||||
:top (str (- y 70) "px")})
|
:top (dm/str (- y 70) "px")})
|
||||||
|
|
||||||
(= position :right)
|
(= position :right)
|
||||||
(if (> y max-y)
|
(if (> y max-y)
|
||||||
#js {:left (str (+ x 80) "px")
|
#js {:left (dm/str (+ x 80) "px")
|
||||||
:bottom "1rem"}
|
:bottom "1rem"}
|
||||||
#js {:left (str (+ x 80) "px")
|
#js {:left (dm/str (+ x 80) "px")
|
||||||
:top (str (- y 70) "px")})
|
:top (dm/str (- y 70) "px")})
|
||||||
:else (if (> y max-y)
|
|
||||||
#js {:left (str (+ x left-offset) "px")
|
:else
|
||||||
:bottom "1rem"}
|
(if (> y max-y)
|
||||||
#js {:left (str (+ x left-offset) "px")
|
#js {:left (dm/str (+ x left-offset) "px")
|
||||||
:top (str (- y 70) "px")}))))
|
:bottom "1rem"}
|
||||||
|
#js {:left (dm/str (+ x left-offset) "px")
|
||||||
|
:top (dm/str (- y 70) "px")}))))
|
||||||
|
|
||||||
(mf/defc colorpicker-modal
|
(mf/defc colorpicker-modal
|
||||||
{::mf/register modal/components
|
{::mf/register modal/components
|
||||||
::mf/register-as :colorpicker}
|
::mf/register-as :colorpicker
|
||||||
|
::mf/props :obj}
|
||||||
[{:keys [x y data position
|
[{:keys [x y data position
|
||||||
disable-gradient
|
disable-gradient
|
||||||
disable-opacity
|
disable-opacity
|
||||||
disable-image
|
disable-image
|
||||||
on-change
|
on-change
|
||||||
on-close
|
on-close
|
||||||
on-accept] :as props}]
|
on-accept]}]
|
||||||
(let [vport (mf/deref viewport)
|
(let [vport (mf/deref viewport)
|
||||||
dirty? (mf/use-var false)
|
dirty? (mf/use-var false)
|
||||||
last-change (mf/use-var nil)
|
last-change (mf/use-var nil)
|
||||||
position (or position :left)
|
position (d/nilv position :left)
|
||||||
style (calculate-position vport position x y)
|
style (calculate-position vport position x y)
|
||||||
|
|
||||||
handle-change
|
on-change'
|
||||||
(fn [new-data]
|
(mf/use-fn
|
||||||
(reset! dirty? (not= data new-data))
|
(mf/deps on-change)
|
||||||
(reset! last-change new-data)
|
(fn [new-data]
|
||||||
(when on-change
|
(reset! dirty? (not= data new-data))
|
||||||
(on-change new-data)))]
|
(reset! last-change new-data)
|
||||||
|
|
||||||
(mf/use-effect
|
(if (fn? on-change)
|
||||||
(fn []
|
(on-change new-data)
|
||||||
#(when (and @dirty? @last-change on-close)
|
(st/emit! (dc/update-colorpicker new-data)))))]
|
||||||
(on-close @last-change))))
|
|
||||||
|
(mf/with-effect []
|
||||||
|
#(when (and @dirty? @last-change on-close)
|
||||||
|
(on-close @last-change)))
|
||||||
|
|
||||||
[:div {:class (stl/css :colorpicker-tooltip)
|
[:div {:class (stl/css :colorpicker-tooltip)
|
||||||
:style style}
|
:style style}
|
||||||
|
|
||||||
[:& colorpicker {:data data
|
[:& colorpicker {:data data
|
||||||
:disable-gradient disable-gradient
|
:disable-gradient disable-gradient
|
||||||
:disable-opacity disable-opacity
|
:disable-opacity disable-opacity
|
||||||
:disable-image disable-image
|
:disable-image disable-image
|
||||||
:on-change handle-change
|
:on-change on-change'
|
||||||
:on-accept on-accept}]]))
|
:on-accept on-accept}]]))
|
||||||
|
|
||||||
|
|
|
@ -15,61 +15,64 @@
|
||||||
[app.util.timers :as tm]
|
[app.util.timers :as tm]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
;; --- SESSION WIDGET
|
|
||||||
|
|
||||||
(mf/defc session-widget
|
(mf/defc session-widget
|
||||||
[{:keys [session profile index] :as props}]
|
{::mf/props :obj
|
||||||
(let [profile (assoc profile :color (:color session))]
|
::mf/memo true}
|
||||||
|
[{:keys [color profile index]}]
|
||||||
|
(let [profile (assoc profile :color color)
|
||||||
|
full-name (:fullname profile)]
|
||||||
[:li {:class (stl/css :session-icon)
|
[:li {:class (stl/css :session-icon)
|
||||||
:style {:z-index (str (or (+ 1 (* -1 index)) 0))
|
:style {:z-index (dm/str (+ 1 (* -1 index)))
|
||||||
:background-color (:color session)}
|
:background-color color}
|
||||||
:title (:fullname profile)}
|
:title full-name}
|
||||||
[:img {:alt (:fullname profile)
|
[:img {:alt full-name
|
||||||
:style {:background-color (:color session)}
|
:style {:background-color color}
|
||||||
:src (cfg/resolve-profile-photo-url profile)}]]))
|
:src (cfg/resolve-profile-photo-url profile)}]]))
|
||||||
|
|
||||||
(mf/defc active-sessions
|
(mf/defc active-sessions
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/memo true}
|
||||||
[]
|
[]
|
||||||
(let [users (mf/deref refs/users)
|
(let [users (mf/deref refs/users)
|
||||||
presence (mf/deref refs/workspace-presence)
|
presence (mf/deref refs/workspace-presence)
|
||||||
user-ids (vals presence)
|
|
||||||
num-users (count user-ids)
|
sessions (vals presence)
|
||||||
first-users (take 2 user-ids)
|
num-sessions (count sessions)
|
||||||
|
|
||||||
open* (mf/use-state false)
|
open* (mf/use-state false)
|
||||||
open? (deref open*)
|
open? (and ^boolean (deref open*) (> num-sessions 2))
|
||||||
open-users-widget
|
on-open
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(reset! open* true)
|
(reset! open* true)
|
||||||
(tm/schedule-on-idle
|
(tm/schedule-on-idle
|
||||||
#(dom/focus! (dom/get-element "users-close")))))
|
#(dom/focus! (dom/get-element "users-close")))))
|
||||||
close-users-widget (mf/use-fn #(reset! open* false))]
|
|
||||||
|
on-close
|
||||||
|
(mf/use-fn #(reset! open* false))]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
(when (and (> num-users 2) open?)
|
(when ^boolean open?
|
||||||
[:button {:id "users-close"
|
[:button {:id "users-close"
|
||||||
:class (stl/css :active-users-opened)
|
:class (stl/css :active-users-opened)
|
||||||
:on-click close-users-widget
|
:on-click on-close
|
||||||
:on-blur close-users-widget}
|
:on-blur on-close}
|
||||||
[:ul {:class (stl/css :active-users-list)}
|
[:ul {:class (stl/css :active-users-list)}
|
||||||
(for [session user-ids]
|
(for [session sessions]
|
||||||
[:& session-widget
|
[:& session-widget
|
||||||
{:session session
|
{:color (:color session)
|
||||||
:index 0
|
:index 0
|
||||||
:profile (get users (:profile-id session))
|
:profile (get users (:profile-id session))
|
||||||
:key (:id session)}])]])
|
:key (dm/str (:id session))}])]])
|
||||||
|
|
||||||
[:button {:class (stl/css-case :active-users true)
|
[:button {:class (stl/css-case :active-users true)
|
||||||
:on-click open-users-widget}
|
:on-click on-open}
|
||||||
|
|
||||||
[:ul {:class (stl/css :active-users-list)}
|
[:ul {:class (stl/css :active-users-list)}
|
||||||
(when (> num-users 2) [:span {:class (stl/css :users-num)} (dm/str "+" (- num-users 2))])
|
(when (> num-sessions 2)
|
||||||
(for [[index session] (d/enumerate first-users)]
|
[:span {:class (stl/css :users-num)} (dm/str "+" (- num-sessions 2))])
|
||||||
|
|
||||||
|
(for [[index session] (d/enumerate (take 2 sessions))]
|
||||||
[:& session-widget
|
[:& session-widget
|
||||||
{:session session
|
{:color (:color session)
|
||||||
:index index
|
:index index
|
||||||
:profile (get users (:profile-id session))
|
:profile (get users (:profile-id session))
|
||||||
:key (:id session)}])]]]))
|
:key (dm/str (:id session))}])]]]))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -377,6 +377,7 @@
|
||||||
(grp/group-assets colors reverse-sort?))
|
(grp/group-assets colors reverse-sort?))
|
||||||
|
|
||||||
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
read-only? (mf/use-ctx ctx/workspace-read-only?)
|
||||||
|
|
||||||
add-color
|
add-color
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(fn [value _]
|
(fn [value _]
|
||||||
|
@ -386,23 +387,22 @@
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
(mf/deps file-id)
|
(mf/deps file-id)
|
||||||
(fn [event]
|
(fn [event]
|
||||||
(let [bounding-rect (-> event
|
(let [bounds (-> event
|
||||||
(dom/get-current-target)
|
(dom/get-current-target)
|
||||||
(dom/get-bounding-rect))
|
(dom/get-bounding-rect))
|
||||||
x-position (:right bounding-rect)
|
x-position (:right bounds)
|
||||||
y-position (:top bounding-rect)]
|
y-position (:top bounds)]
|
||||||
|
|
||||||
(st/emit! (dw/set-assets-section-open file-id :colors true)
|
(st/emit! (dw/set-assets-section-open file-id :colors true)
|
||||||
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
(ptk/event ::ev/event {::ev/name "add-asset-to-library"
|
||||||
:asset-type "color"}))
|
:asset-type "color"})
|
||||||
;; FIXME: replace interop with dom helpers
|
(modal/show :colorpicker
|
||||||
(modal/show! :colorpicker
|
{:x x-position
|
||||||
{:x x-position
|
:y y-position
|
||||||
:y y-position
|
:on-accept add-color
|
||||||
:on-accept add-color
|
:data {:color "#406280"
|
||||||
:data {:color "#406280"
|
:opacity 1}
|
||||||
:opacity 1}
|
:position :right})))))
|
||||||
:position :right}))))
|
|
||||||
|
|
||||||
create-group
|
create-group
|
||||||
(mf/use-fn
|
(mf/use-fn
|
||||||
|
|
|
@ -61,7 +61,7 @@
|
||||||
:layout-grid-rows])
|
:layout-grid-rows])
|
||||||
|
|
||||||
(defn get-layout-flex-icon
|
(defn get-layout-flex-icon
|
||||||
[type val is-col?]
|
[type val ^boolean is-col?]
|
||||||
(case type
|
(case type
|
||||||
:align-items
|
:align-items
|
||||||
(if is-col?
|
(if is-col?
|
||||||
|
@ -115,7 +115,6 @@
|
||||||
:space-between i/align-content-row-between-refactor
|
:space-between i/align-content-row-between-refactor
|
||||||
:stretch nil))
|
:stretch nil))
|
||||||
|
|
||||||
|
|
||||||
:align-self
|
:align-self
|
||||||
(if is-col?
|
(if is-col?
|
||||||
(case val
|
(case val
|
||||||
|
@ -134,7 +133,7 @@
|
||||||
:baseline i/align-self-column-baseline))))
|
:baseline i/align-self-column-baseline))))
|
||||||
|
|
||||||
(defn get-layout-grid-icon-refactor
|
(defn get-layout-grid-icon-refactor
|
||||||
[type val is-col?]
|
[type val ^boolean is-col?]
|
||||||
(case type
|
(case type
|
||||||
:align-items
|
:align-items
|
||||||
(if is-col?
|
(if is-col?
|
||||||
|
@ -171,7 +170,8 @@
|
||||||
:stretch i/align-content-row-stretch-refactor))))
|
:stretch i/align-content-row-stretch-refactor))))
|
||||||
|
|
||||||
(mf/defc direction-row-flex
|
(mf/defc direction-row-flex
|
||||||
[{:keys [saved-dir on-change] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [saved-dir on-change]}]
|
||||||
[:& radio-buttons {:selected (d/name saved-dir)
|
[:& radio-buttons {:selected (d/name saved-dir)
|
||||||
:on-change on-change
|
:on-change on-change
|
||||||
:name "flex-direction"}
|
:name "flex-direction"}
|
||||||
|
@ -193,7 +193,8 @@
|
||||||
:icon (dir-icons-refactor :column-reverse)}]])
|
:icon (dir-icons-refactor :column-reverse)}]])
|
||||||
|
|
||||||
(mf/defc wrap-row
|
(mf/defc wrap-row
|
||||||
[{:keys [wrap-type on-click] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [wrap-type on-click]}]
|
||||||
[:button {:class (stl/css-case :wrap-button true
|
[:button {:class (stl/css-case :wrap-button true
|
||||||
:selected (= wrap-type :wrap))
|
:selected (= wrap-type :wrap))
|
||||||
:title (if (= :wrap wrap-type)
|
:title (if (= :wrap wrap-type)
|
||||||
|
@ -203,7 +204,8 @@
|
||||||
i/wrap-refactor])
|
i/wrap-refactor])
|
||||||
|
|
||||||
(mf/defc align-row
|
(mf/defc align-row
|
||||||
[{:keys [is-col? align-items on-change] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [is-col? align-items on-change]}]
|
||||||
[:& radio-buttons {:selected (d/name align-items)
|
[:& radio-buttons {:selected (d/name align-items)
|
||||||
:on-change on-change
|
:on-change on-change
|
||||||
:name "flex-align-items"}
|
:name "flex-align-items"}
|
||||||
|
@ -221,7 +223,8 @@
|
||||||
:id "align-items-end"}]])
|
:id "align-items-end"}]])
|
||||||
|
|
||||||
(mf/defc align-content-row
|
(mf/defc align-content-row
|
||||||
[{:keys [is-col? align-content on-change] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [is-col? align-content on-change]}]
|
||||||
[:& radio-buttons {:selected (d/name align-content)
|
[:& radio-buttons {:selected (d/name align-content)
|
||||||
:on-change on-change
|
:on-change on-change
|
||||||
:name "flex-align-content"}
|
:name "flex-align-content"}
|
||||||
|
@ -251,7 +254,8 @@
|
||||||
:id "align-content-space-evenly"}]])
|
:id "align-content-space-evenly"}]])
|
||||||
|
|
||||||
(mf/defc justify-content-row
|
(mf/defc justify-content-row
|
||||||
[{:keys [is-col? justify-content on-change] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [is-col? justify-content on-change]}]
|
||||||
[:& radio-buttons {:selected (d/name justify-content)
|
[:& radio-buttons {:selected (d/name justify-content)
|
||||||
:on-change on-change
|
:on-change on-change
|
||||||
:name "flex-justify"}
|
:name "flex-justify"}
|
||||||
|
@ -281,8 +285,8 @@
|
||||||
:id "justify-content-space-evenly"}]])
|
:id "justify-content-space-evenly"}]])
|
||||||
|
|
||||||
(mf/defc padding-section
|
(mf/defc padding-section
|
||||||
[{:keys [values on-change-style on-change] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [values on-change-style on-change]}]
|
||||||
(let [padding-type (:layout-padding-type values)
|
(let [padding-type (:layout-padding-type values)
|
||||||
|
|
||||||
toggle-padding-mode
|
toggle-padding-mode
|
||||||
|
@ -418,6 +422,7 @@
|
||||||
i/padding-extended-refactor]]))
|
i/padding-extended-refactor]]))
|
||||||
|
|
||||||
(mf/defc gap-section
|
(mf/defc gap-section
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [is-col? wrap-type gap-selected? on-change gap-value]}]
|
[{:keys [is-col? wrap-type gap-selected? on-change gap-value]}]
|
||||||
(let [select-gap
|
(let [select-gap
|
||||||
(fn [gap]
|
(fn [gap]
|
||||||
|
@ -474,7 +479,7 @@
|
||||||
;; GRID COMPONENTS
|
;; GRID COMPONENTS
|
||||||
|
|
||||||
(defn get-layout-grid-icon
|
(defn get-layout-grid-icon
|
||||||
[type val is-col?]
|
[type val ^boolean is-col?]
|
||||||
(case type
|
(case type
|
||||||
:justify-items
|
:justify-items
|
||||||
(if is-col?
|
(if is-col?
|
||||||
|
@ -497,6 +502,7 @@
|
||||||
:space-evenly i/grid-justify-content-row-between))))
|
:space-evenly i/grid-justify-content-row-between))))
|
||||||
|
|
||||||
(mf/defc direction-row-grid
|
(mf/defc direction-row-grid
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [saved-dir on-change] :as props}]
|
[{:keys [saved-dir on-change] :as props}]
|
||||||
[:& radio-buttons {:selected (d/name saved-dir)
|
[:& radio-buttons {:selected (d/name saved-dir)
|
||||||
:on-change on-change
|
:on-change on-change
|
||||||
|
@ -511,7 +517,8 @@
|
||||||
:icon (dir-icons-refactor :column)}]])
|
:icon (dir-icons-refactor :column)}]])
|
||||||
|
|
||||||
(mf/defc grid-edit-mode
|
(mf/defc grid-edit-mode
|
||||||
[{:keys [id] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [id]}]
|
||||||
(let [edition (mf/deref refs/selected-edition)
|
(let [edition (mf/deref refs/selected-edition)
|
||||||
active? (= id edition)
|
active? (= id edition)
|
||||||
|
|
||||||
|
@ -529,7 +536,8 @@
|
||||||
(tr "workspace.layout_grid.editor.options.edit-grid")]))
|
(tr "workspace.layout_grid.editor.options.edit-grid")]))
|
||||||
|
|
||||||
(mf/defc align-grid-row
|
(mf/defc align-grid-row
|
||||||
[{:keys [is-col? align-items set-align] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [is-col? align-items set-align]}]
|
||||||
(let [type (if is-col? :column :row)]
|
(let [type (if is-col? :column :row)]
|
||||||
[:& radio-buttons {:selected (d/name align-items)
|
[:& radio-buttons {:selected (d/name align-items)
|
||||||
:on-change #(set-align % type)
|
:on-change #(set-align % type)
|
||||||
|
@ -548,7 +556,8 @@
|
||||||
:id (dm/str "align-items-end-" (d/name type))}]]))
|
:id (dm/str "align-items-end-" (d/name type))}]]))
|
||||||
|
|
||||||
(mf/defc justify-grid-row
|
(mf/defc justify-grid-row
|
||||||
[{:keys [is-col? justify-items set-justify] :as props}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [is-col? justify-items set-justify]}]
|
||||||
(let [type (if is-col? :column :row)]
|
(let [type (if is-col? :column :row)]
|
||||||
|
|
||||||
[:& radio-buttons {:selected (d/name justify-items)
|
[:& radio-buttons {:selected (d/name justify-items)
|
||||||
|
@ -561,7 +570,8 @@
|
||||||
:title (dm/str "Justify items " (d/name justify))
|
:title (dm/str "Justify items " (d/name justify))
|
||||||
:id (dm/str "justify-items-" (d/name justify) "-" (d/name type))}])]))
|
:id (dm/str "justify-items-" (d/name justify) "-" (d/name type))}])]))
|
||||||
|
|
||||||
(defn manage-values [{:keys [value type]}]
|
(defn- manage-values
|
||||||
|
[{:keys [type value]}]
|
||||||
(case type
|
(case type
|
||||||
:auto "auto"
|
:auto "auto"
|
||||||
:percent (fmt/format-percent value)
|
:percent (fmt/format-percent value)
|
||||||
|
@ -570,6 +580,7 @@
|
||||||
value))
|
value))
|
||||||
|
|
||||||
(mf/defc grid-track-info
|
(mf/defc grid-track-info
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [is-col?
|
[{:keys [is-col?
|
||||||
type
|
type
|
||||||
index
|
index
|
||||||
|
@ -650,12 +661,13 @@
|
||||||
i/remove-refactor]]))
|
i/remove-refactor]]))
|
||||||
|
|
||||||
(mf/defc grid-columns-row
|
(mf/defc grid-columns-row
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type
|
[{:keys [is-col? expanded? column-values toggle add-new-element set-column-value set-column-type
|
||||||
remove-element reorder-track hover-track on-select-track] :as props}]
|
remove-element reorder-track hover-track on-select-track]}]
|
||||||
(let [column-num (count column-values)
|
(let [column-num (count column-values)
|
||||||
direction (if (> column-num 1)
|
direction (if (> column-num 1)
|
||||||
(if is-col? "Columns " "Rows ")
|
(if ^boolean is-col? "Columns " "Rows ")
|
||||||
(if is-col? "Column " "Row "))
|
(if ^boolean is-col? "Column " "Row "))
|
||||||
|
|
||||||
track-name (dm/str direction (if (= column-num 0) " - empty" column-num))
|
track-name (dm/str direction (if (= column-num 0) " - empty" column-num))
|
||||||
track-detail (str/join ", " (map manage-values column-values))
|
track-detail (str/join ", " (map manage-values column-values))
|
||||||
|
@ -694,8 +706,9 @@
|
||||||
;; LAYOUT COMPONENT
|
;; LAYOUT COMPONENT
|
||||||
|
|
||||||
(mf/defc layout-container-menu
|
(mf/defc layout-container-menu
|
||||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values" "multiple"]))]}
|
{::mf/memo #{:ids :values :multiple}
|
||||||
[{:keys [ids values multiple] :as props}]
|
::mf/props :obj}
|
||||||
|
[{:keys [ids values multiple]}]
|
||||||
(let [;; Display
|
(let [;; Display
|
||||||
layout-type (:layout values)
|
layout-type (:layout values)
|
||||||
has-layout? (some? layout-type)
|
has-layout? (some? layout-type)
|
||||||
|
@ -711,7 +724,7 @@
|
||||||
toggle-content (mf/use-fn #(swap! state* not))
|
toggle-content (mf/use-fn #(swap! state* not))
|
||||||
|
|
||||||
on-add-layout
|
on-add-layout
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn [type]
|
(fn [type]
|
||||||
(st/emit! (dwsl/create-layout type))
|
(st/emit! (dwsl/create-layout type))
|
||||||
(reset! state* true)))
|
(reset! state* true)))
|
||||||
|
@ -730,13 +743,13 @@
|
||||||
(reset! state* false))
|
(reset! state* false))
|
||||||
|
|
||||||
set-flex
|
set-flex
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-add-layout)
|
(mf/deps on-add-layout)
|
||||||
(fn []
|
(fn []
|
||||||
(on-add-layout :flex)))
|
(on-add-layout :flex)))
|
||||||
|
|
||||||
set-grid
|
set-grid
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-add-layout)
|
(mf/deps on-add-layout)
|
||||||
(fn []
|
(fn []
|
||||||
(on-add-layout :grid)))
|
(on-add-layout :grid)))
|
||||||
|
@ -875,22 +888,22 @@
|
||||||
(st/emit! (dwsl/update-layout ids {:layout-align-content value}))))))
|
(st/emit! (dwsl/update-layout ids {:layout-align-content value}))))))
|
||||||
|
|
||||||
handle-show-layout-dropdown
|
handle-show-layout-dropdown
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(swap! show-layout-dropdown* not)))
|
(swap! show-layout-dropdown* not)))
|
||||||
|
|
||||||
handle-close-layout-options
|
handle-close-layout-options
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(reset! show-layout-dropdown* false)))
|
(reset! show-layout-dropdown* false)))
|
||||||
|
|
||||||
handle-open-flex-help
|
handle-open-flex-help
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dom/open-new-window cf/flex-help-uri))))
|
(st/emit! (dom/open-new-window cf/flex-help-uri))))
|
||||||
|
|
||||||
handle-open-grid-help
|
handle-open-grid-help
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dom/open-new-window cf/grid-help-uri))))]
|
(st/emit! (dom/open-new-window cf/grid-help-uri))))]
|
||||||
|
|
||||||
|
@ -1011,8 +1024,9 @@
|
||||||
nil)))]))
|
nil)))]))
|
||||||
|
|
||||||
(mf/defc grid-layout-edition
|
(mf/defc grid-layout-edition
|
||||||
{::mf/wrap [#(mf/memo' % (mf/check-props ["ids" "values"]))]}
|
{::mf/memo #{:ids :values}
|
||||||
[{:keys [ids values] :as props}]
|
::mf/props :obj}
|
||||||
|
[{:keys [ids values]}]
|
||||||
(let [;; Gap
|
(let [;; Gap
|
||||||
gap-selected? (mf/use-state :none)
|
gap-selected? (mf/use-state :none)
|
||||||
saved-grid-dir (:layout-grid-dir values)
|
saved-grid-dir (:layout-grid-dir values)
|
||||||
|
@ -1135,12 +1149,12 @@
|
||||||
(st/emit! (dwsl/change-layout-track ids type index {:value value
|
(st/emit! (dwsl/change-layout-track ids type index {:value value
|
||||||
:type track-type})))))
|
:type track-type})))))
|
||||||
handle-open-grid-help
|
handle-open-grid-help
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dom/open-new-window cf/grid-help-uri))))
|
(st/emit! (dom/open-new-window cf/grid-help-uri))))
|
||||||
|
|
||||||
handle-locate-grid
|
handle-locate-grid
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
(fn []
|
||||||
(st/emit! (dwge/locate-board (first ids)))))]
|
(st/emit! (dwge/locate-board (first ids)))))]
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.main.ui.workspace.viewport.presence
|
(ns app.main.ui.workspace.viewport.presence
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.util.time :as dt]
|
[app.util.time :as dt]
|
||||||
[app.util.timers :as ts]
|
[app.util.timers :as ts]
|
||||||
|
@ -13,56 +14,66 @@
|
||||||
[cuerdas.core :as str]
|
[cuerdas.core :as str]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def pointer-icon-path
|
(def pointer-path
|
||||||
(str "M11.58,-0.47L11.47,-0.35L0.34,10.77L0.30,10.96L-0.46,"
|
(dm/str "M11.58,-0.47L11.47,-0.35L0.34,10.77L0.30,10.96L-0.46,"
|
||||||
"15.52L4.29,14.72L15.53,3.47L11.58,-0.47ZL11.58,"
|
"15.52L4.29,14.72L15.53,3.47L11.58,-0.47ZL11.58,"
|
||||||
"-0.47ZL11.58,-0.47ZM11.58,1.3C12.31,2.05,13.02,"
|
"-0.47ZL11.58,-0.47ZM11.58,1.3C12.31,2.05,13.02,"
|
||||||
"2.742,13.76,3.47L4.0053,13.23C3.27,12.50,2.55,"
|
"2.742,13.76,3.47L4.0053,13.23C3.27,12.50,2.55,"
|
||||||
"11.78,1.82,11.05L11.58,1.30ZL11.58,1.30ZM1.37,12.15L2.90,"
|
"11.78,1.82,11.05L11.58,1.30ZL11.58,1.30ZM1.37,12.15L2.90,"
|
||||||
"13.68L1.67,13.89L1.165,13.39L1.37,12.15ZL1.37,12.15Z"))
|
"13.68L1.67,13.89L1.165,13.39L1.37,12.15ZL1.37,12.15Z"))
|
||||||
|
|
||||||
(mf/defc session-cursor
|
(mf/defc session-cursor
|
||||||
[{:keys [session profile] :as props}]
|
{::mf/props :obj
|
||||||
(let [zoom (mf/deref refs/selected-zoom)
|
::mf/memo true}
|
||||||
point (:point session)
|
[{:keys [session profile zoom]}]
|
||||||
background-color (:color session "var(--app-black)")
|
(let [point (:point session)
|
||||||
text-color (:text-color session "var(--app-white)")
|
bg-color (:color session)
|
||||||
transform (str/fmt "translate(%s, %s) scale(%s)" (:x point) (:y point) (/ 1 zoom))
|
fg-color "var(--app-white)"
|
||||||
shown-name (if (> (count (:fullname profile)) 16)
|
transform (str/ffmt "translate(%, %) scale(%)"
|
||||||
(str (str/slice (:fullname profile) 0 12) "...")
|
(dm/get-prop point :x)
|
||||||
(:fullname profile))]
|
(dm/get-prop point :y)
|
||||||
|
(/ 1 zoom))
|
||||||
|
|
||||||
|
|
||||||
|
fullname (:fullname profile)
|
||||||
|
fullname (if (> (count fullname) 16)
|
||||||
|
(dm/str (str/slice fullname 0 12) "...")
|
||||||
|
fullname)]
|
||||||
|
|
||||||
[:g.multiuser-cursor {:transform transform}
|
[:g.multiuser-cursor {:transform transform}
|
||||||
[:path {:fill background-color
|
[:path {:fill bg-color :d pointer-path}]
|
||||||
:d pointer-icon-path}]
|
|
||||||
[:g {:transform "translate(17 -10)"}
|
[:g {:transform "translate(17 -10)"}
|
||||||
[:foreignObject {:x -0.3
|
[:foreignObject {:x -0.3
|
||||||
:y -12.5
|
:y -12.5
|
||||||
:width 300
|
:width 300
|
||||||
:height 120}
|
:height 120}
|
||||||
[:div.profile-name {:style {:background-color background-color
|
[:div.profile-name {:style {:background-color bg-color
|
||||||
:color text-color}}
|
:color fg-color}}
|
||||||
shown-name]]]]))
|
fullname]]]]))
|
||||||
|
|
||||||
(mf/defc active-cursors
|
(mf/defc active-cursors
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/props :obj}
|
||||||
[{:keys [page-id] :as props}]
|
[{:keys [page-id]}]
|
||||||
(let [counter (mf/use-state 0)
|
(let [counter (mf/use-state 0)
|
||||||
users (mf/deref refs/users)
|
users (mf/deref refs/users)
|
||||||
sessions (mf/deref refs/workspace-presence)
|
sessions (mf/deref refs/workspace-presence)
|
||||||
|
zoom (mf/deref refs/selected-zoom)
|
||||||
|
|
||||||
sessions (->> (vals sessions)
|
sessions (->> (vals sessions)
|
||||||
|
(filter :point)
|
||||||
(filter #(= page-id (:page-id %)))
|
(filter #(= page-id (:page-id %)))
|
||||||
(filter #(>= 5000 (- (inst-ms (dt/now)) (inst-ms (:updated-at %))))))]
|
(filter #(>= 5000 (- (inst-ms (dt/now))
|
||||||
(mf/use-effect
|
(inst-ms (:updated-at %))))))]
|
||||||
nil
|
(mf/with-effect nil
|
||||||
(fn []
|
(let [sem (ts/schedule 1000 #(swap! counter inc))]
|
||||||
(let [sem (ts/schedule 1000 #(swap! counter inc))]
|
(fn [] (rx/dispose! sem))))
|
||||||
(fn [] (rx/dispose! sem)))))
|
|
||||||
|
|
||||||
(for [session sessions]
|
(for [session sessions]
|
||||||
(when (:point session)
|
[:& session-cursor
|
||||||
[:& session-cursor {:session session
|
{:session session
|
||||||
:profile (get users (:profile-id session))
|
:zoom zoom
|
||||||
:key (:id session)}]))))
|
:profile (get users (:profile-id session))
|
||||||
|
:key (dm/str (:id session))}])))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue