mirror of
https://github.com/penpot/penpot.git
synced 2025-06-12 10:01:40 +02:00
♻️ Refactor page options data structure
This commit is contained in:
parent
2dea0b52ed
commit
4ad4057878
41 changed files with 659 additions and 525 deletions
|
@ -741,46 +741,36 @@
|
||||||
|
|
||||||
(defn add-guide
|
(defn add-guide
|
||||||
[file guide]
|
[file guide]
|
||||||
|
|
||||||
(let [guide (cond-> guide
|
(let [guide (cond-> guide
|
||||||
(nil? (:id guide))
|
(nil? (:id guide))
|
||||||
(assoc :id (uuid/next)))
|
(assoc :id (uuid/next)))
|
||||||
page-id (:current-page-id file)
|
page-id (:current-page-id file)]
|
||||||
old-guides (or (dm/get-in file [:data :pages-index page-id :options :guides]) {})
|
|
||||||
new-guides (assoc old-guides (:id guide) guide)]
|
|
||||||
(-> file
|
(-> file
|
||||||
(commit-change
|
(commit-change
|
||||||
{:type :set-option
|
{:type :set-guide
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:option :guides
|
:id (:id guide)
|
||||||
:value new-guides})
|
:params guide})
|
||||||
(assoc :last-id (:id guide)))))
|
(assoc :last-id (:id guide)))))
|
||||||
|
|
||||||
(defn delete-guide
|
(defn delete-guide
|
||||||
[file id]
|
[file id]
|
||||||
|
|
||||||
(let [page-id (:current-page-id file)
|
(let [page-id (:current-page-id file)]
|
||||||
old-guides (or (dm/get-in file [:data :pages-index page-id :options :guides]) {})
|
(commit-change file
|
||||||
new-guides (dissoc old-guides id)]
|
{:type :set-guide
|
||||||
(-> file
|
:page-id page-id
|
||||||
(commit-change
|
:id id
|
||||||
{:type :set-option
|
:params nil})))
|
||||||
:page-id page-id
|
|
||||||
:option :guides
|
|
||||||
:value new-guides}))))
|
|
||||||
|
|
||||||
(defn update-guide
|
(defn update-guide
|
||||||
[file guide]
|
[file guide]
|
||||||
|
(let [page-id (:current-page-id file)]
|
||||||
(let [page-id (:current-page-id file)
|
(commit-change file
|
||||||
old-guides (or (dm/get-in file [:data :pages-index page-id :options :guides]) {})
|
{:type :set-guide
|
||||||
new-guides (assoc old-guides (:id guide) guide)]
|
:page-id page-id
|
||||||
(-> file
|
:id (:id guide)
|
||||||
(commit-change
|
:params guide})))
|
||||||
{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option :guides
|
|
||||||
:value new-guides}))))
|
|
||||||
|
|
||||||
(defn strip-image-extension [filename]
|
(defn strip-image-extension [filename]
|
||||||
(let [image-extensions-re #"(\.png)|(\.jpg)|(\.jpeg)|(\.webp)|(\.gif)|(\.svg)$"]
|
(let [image-extensions-re #"(\.png)|(\.jpg)|(\.jpeg)|(\.webp)|(\.gif)|(\.svg)$"]
|
||||||
|
|
|
@ -10,21 +10,25 @@
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.exceptions :as ex]
|
[app.common.exceptions :as ex]
|
||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.schema.desc-native :as smd]
|
[app.common.schema.desc-native :as smd]
|
||||||
|
[app.common.schema.generators :as sg]
|
||||||
[app.common.types.color :as ctc]
|
[app.common.types.color :as ctc]
|
||||||
[app.common.types.colors-list :as ctcl]
|
[app.common.types.colors-list :as ctcl]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
[app.common.types.components-list :as ctkl]
|
[app.common.types.components-list :as ctkl]
|
||||||
[app.common.types.container :as ctn]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.file :as ctf]
|
[app.common.types.file :as ctf]
|
||||||
|
[app.common.types.grid :as ctg]
|
||||||
[app.common.types.page :as ctp]
|
[app.common.types.page :as ctp]
|
||||||
[app.common.types.pages-list :as ctpl]
|
[app.common.types.pages-list :as ctpl]
|
||||||
[app.common.types.shape :as cts]
|
[app.common.types.shape :as cts]
|
||||||
[app.common.types.shape-tree :as ctst]
|
[app.common.types.shape-tree :as ctst]
|
||||||
[app.common.types.typographies-list :as ctyl]
|
[app.common.types.typographies-list :as ctyl]
|
||||||
[app.common.types.typography :as ctt]
|
[app.common.types.typography :as ctt]
|
||||||
|
[app.common.uuid :as uuid]
|
||||||
[clojure.set :as set]))
|
[clojure.set :as set]))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -60,6 +64,44 @@
|
||||||
[:type [:= :set-remote-synced]]
|
[:type [:= :set-remote-synced]]
|
||||||
[:remote-synced {:optional true} [:maybe :boolean]]]]])
|
[:remote-synced {:optional true} [:maybe :boolean]]]]])
|
||||||
|
|
||||||
|
(defn- set-default-grid-change-generator
|
||||||
|
[]
|
||||||
|
(->> (sg/elements #{:square :column :row})
|
||||||
|
(sg/mcat (fn [type]
|
||||||
|
(sg/fmap (fn [params]
|
||||||
|
{:page-id (uuid/next)
|
||||||
|
:type :mod-grid
|
||||||
|
:grid-type type
|
||||||
|
:params params})
|
||||||
|
|
||||||
|
(case type
|
||||||
|
:square (sg/generator ctg/schema:square-params)
|
||||||
|
:column (sg/generator ctg/schema:column-params)
|
||||||
|
:row (sg/generator ctg/schema:column-params)))))))
|
||||||
|
|
||||||
|
(def schema:set-default-grid-change
|
||||||
|
[:multi {:decode/json #(update % :grid-type keyword)
|
||||||
|
:gen/gen (set-default-grid-change-generator)
|
||||||
|
:dispatch :grid-type
|
||||||
|
::smd/simplified true}
|
||||||
|
[:square
|
||||||
|
[:map
|
||||||
|
[:page-id ::sm/uuid]
|
||||||
|
[:grid-type [:and :keyword [:= :square]]]
|
||||||
|
[:params [:maybe ctg/schema:square-params]]]]
|
||||||
|
|
||||||
|
[:column
|
||||||
|
[:map
|
||||||
|
[:page-id ::sm/uuid]
|
||||||
|
[:grid-type [:and :keyword [:= :column]]]
|
||||||
|
[:params [:maybe ctg/schema:column-params]]]]
|
||||||
|
|
||||||
|
[:row
|
||||||
|
[:map
|
||||||
|
[:page-id ::sm/uuid]
|
||||||
|
[:grid-type [:and :keyword [:= :row]]]
|
||||||
|
[:params [:maybe ctg/schema:column-params]]]]])
|
||||||
|
|
||||||
(def schema:change
|
(def schema:change
|
||||||
[:schema
|
[:schema
|
||||||
[:multi {:dispatch :type
|
[:multi {:dispatch :type
|
||||||
|
@ -67,13 +109,18 @@
|
||||||
:decode/json #(update % :type keyword)
|
:decode/json #(update % :type keyword)
|
||||||
::smd/simplified true}
|
::smd/simplified true}
|
||||||
[:set-option
|
[:set-option
|
||||||
[:map {:title "SetOptionChange"}
|
|
||||||
[:type [:= :set-option]]
|
;; DEPRECATED: remove before 2.3 release
|
||||||
|
;;
|
||||||
|
;; Is still there for not cause error when event is received
|
||||||
|
[:map {:title "SetOptionChange"}]]
|
||||||
|
|
||||||
|
[:set-comment-thread-position
|
||||||
|
[:map
|
||||||
|
[:comment-thread-id ::sm/uuid]
|
||||||
[:page-id ::sm/uuid]
|
[:page-id ::sm/uuid]
|
||||||
[:option [:union
|
[:frame-id [:maybe ::sm/uuid]]
|
||||||
[:keyword]
|
[:position [:maybe ::gpt/point]]]]
|
||||||
[:vector {:gen/max 10} :keyword]]]
|
|
||||||
[:value :any]]]
|
|
||||||
|
|
||||||
[:add-obj
|
[:add-obj
|
||||||
[:map {:title "AddObjChange"}
|
[:map {:title "AddObjChange"}
|
||||||
|
@ -103,6 +150,22 @@
|
||||||
[:component-id {:optional true} ::sm/uuid]
|
[:component-id {:optional true} ::sm/uuid]
|
||||||
[:ignore-touched {:optional true} :boolean]]]
|
[:ignore-touched {:optional true} :boolean]]]
|
||||||
|
|
||||||
|
[:set-guide
|
||||||
|
[:map {:title "SetGuideChange"}
|
||||||
|
[:page-id ::sm/uuid]
|
||||||
|
[:id ::sm/uuid]
|
||||||
|
[:params [:maybe ::ctp/guide]]]]
|
||||||
|
|
||||||
|
[:set-flow
|
||||||
|
[:map {:title "SetFlowChange"}
|
||||||
|
[:page-id ::sm/uuid]
|
||||||
|
[:id ::sm/uuid]
|
||||||
|
[:params [:maybe ::ctp/flow]]]]
|
||||||
|
|
||||||
|
;; Change used for all crud operation on persisted grid options on
|
||||||
|
;; the page.
|
||||||
|
[:set-default-grid schema:set-default-grid-change]
|
||||||
|
|
||||||
[:fix-obj
|
[:fix-obj
|
||||||
[:map {:title "FixObjChange"}
|
[:map {:title "FixObjChange"}
|
||||||
[:type [:= :fix-obj]]
|
[:type [:= :fix-obj]]
|
||||||
|
@ -143,7 +206,10 @@
|
||||||
[:map {:title "ModPageChange"}
|
[:map {:title "ModPageChange"}
|
||||||
[:type [:= :mod-page]]
|
[:type [:= :mod-page]]
|
||||||
[:id ::sm/uuid]
|
[:id ::sm/uuid]
|
||||||
[:name :string]]]
|
;; All props are optional, background can be nil because is the
|
||||||
|
;; way to remove already set background
|
||||||
|
[:background {:optional true} [:maybe ::ctc/rgb-color]]
|
||||||
|
[:name {:optional true} :string]]]
|
||||||
|
|
||||||
[:mod-plugin-data
|
[:mod-plugin-data
|
||||||
[:map {:title "ModPagePluginData"}
|
[:map {:title "ModPagePluginData"}
|
||||||
|
@ -356,14 +422,49 @@
|
||||||
#?(:clj (validate-shapes! data result items))
|
#?(:clj (validate-shapes! data result items))
|
||||||
result))))
|
result))))
|
||||||
|
|
||||||
|
;; DEPRECATED: remove before 2.3 release
|
||||||
(defmethod process-change :set-option
|
(defmethod process-change :set-option
|
||||||
[data {:keys [page-id option value]}]
|
[data _]
|
||||||
|
data)
|
||||||
|
|
||||||
|
;; --- Comment Threads
|
||||||
|
|
||||||
|
(defmethod process-change :set-comment-thread-position
|
||||||
|
[data {:keys [page-id comment-thread-id position frame-id]}]
|
||||||
(d/update-in-when data [:pages-index page-id]
|
(d/update-in-when data [:pages-index page-id]
|
||||||
(fn [data]
|
(fn [page]
|
||||||
(let [path (if (seqable? option) option [option])]
|
(if (and position frame-id)
|
||||||
(if value
|
(update page :comment-thread-positions assoc
|
||||||
(assoc-in data (into [:options] path) value)
|
comment-thread-id {:frame-id frame-id
|
||||||
(assoc data :options (d/dissoc-in (:options data) path)))))))
|
:position position})
|
||||||
|
(update page :comment-thread-positions dissoc
|
||||||
|
comment-thread-id)))))
|
||||||
|
|
||||||
|
;; --- Guides
|
||||||
|
|
||||||
|
(defmethod process-change :set-guide
|
||||||
|
[data {:keys [page-id id params]}]
|
||||||
|
(if (nil? params)
|
||||||
|
(d/update-in-when data [:pages-index page-id] update :guides dissoc id)
|
||||||
|
(d/update-in-when data [:pages-index page-id] update :guides assoc id params)))
|
||||||
|
|
||||||
|
;; --- Flows
|
||||||
|
|
||||||
|
(defmethod process-change :set-flow
|
||||||
|
[data {:keys [page-id id params]}]
|
||||||
|
(if (nil? params)
|
||||||
|
(d/update-in-when data [:pages-index page-id] update :flows dissoc id)
|
||||||
|
(d/update-in-when data [:pages-index page-id] update :flows assoc id params)))
|
||||||
|
|
||||||
|
;; --- Grids
|
||||||
|
|
||||||
|
(defmethod process-change :set-default-grid
|
||||||
|
[data {:keys [page-id grid-type params]}]
|
||||||
|
(if (nil? params)
|
||||||
|
(d/update-in-when data [:pages-index page-id] update :default-grids dissoc grid-type)
|
||||||
|
(d/update-in-when data [:pages-index page-id] update :default-grids assoc grid-type params)))
|
||||||
|
|
||||||
|
;; --- Shape / Obj
|
||||||
|
|
||||||
(defmethod process-change :add-obj
|
(defmethod process-change :add-obj
|
||||||
[data {:keys [id obj page-id component-id frame-id parent-id index ignore-touched]}]
|
[data {:keys [id obj page-id component-id frame-id parent-id index ignore-touched]}]
|
||||||
|
@ -603,8 +704,20 @@
|
||||||
(ctpl/add-page data page)))
|
(ctpl/add-page data page)))
|
||||||
|
|
||||||
(defmethod process-change :mod-page
|
(defmethod process-change :mod-page
|
||||||
[data {:keys [id name]}]
|
[data {:keys [id] :as params}]
|
||||||
(d/update-in-when data [:pages-index id] assoc :name name))
|
(d/update-in-when data [:pages-index id]
|
||||||
|
(fn [page]
|
||||||
|
(let [name (get params :name)
|
||||||
|
bg (get params :background :not-found)]
|
||||||
|
(cond-> page
|
||||||
|
(string? name)
|
||||||
|
(assoc :name name)
|
||||||
|
|
||||||
|
(string? bg)
|
||||||
|
(assoc :background bg)
|
||||||
|
|
||||||
|
(nil? bg)
|
||||||
|
(dissoc :background))))))
|
||||||
|
|
||||||
(defmethod process-change :mod-plugin-data
|
(defmethod process-change :mod-plugin-data
|
||||||
[data {:keys [object-type object-id page-id namespace key value]}]
|
[data {:keys [object-type object-id page-id namespace key value]}]
|
||||||
|
@ -660,6 +773,7 @@
|
||||||
[data _]
|
[data _]
|
||||||
data)
|
data)
|
||||||
|
|
||||||
|
|
||||||
;; -- Media
|
;; -- Media
|
||||||
|
|
||||||
(defmethod process-change :add-media
|
(defmethod process-change :add-media
|
||||||
|
|
|
@ -135,12 +135,6 @@
|
||||||
(or (contains? (meta changes) ::page-id)
|
(or (contains? (meta changes) ::page-id)
|
||||||
(contains? (meta changes) ::component-id))))
|
(contains? (meta changes) ::component-id))))
|
||||||
|
|
||||||
(defn- assert-page!
|
|
||||||
[changes]
|
|
||||||
(dm/assert!
|
|
||||||
"Call (with-page) before using this function"
|
|
||||||
(contains? (meta changes) ::page)))
|
|
||||||
|
|
||||||
(defn- assert-objects!
|
(defn- assert-objects!
|
||||||
[changes]
|
[changes]
|
||||||
(dm/assert!
|
(dm/assert!
|
||||||
|
@ -195,11 +189,30 @@
|
||||||
(apply-changes-local)))
|
(apply-changes-local)))
|
||||||
|
|
||||||
(defn mod-page
|
(defn mod-page
|
||||||
[changes page new-name]
|
([changes options]
|
||||||
(-> changes
|
(let [page (::page (meta changes))]
|
||||||
(update :redo-changes conj {:type :mod-page :id (:id page) :name new-name})
|
(mod-page changes page options)))
|
||||||
(update :undo-changes conj {:type :mod-page :id (:id page) :name (:name page)})
|
|
||||||
(apply-changes-local)))
|
([changes page {:keys [name background]}]
|
||||||
|
(let [change {:type :mod-page :id (:id page)}
|
||||||
|
redo (cond-> change
|
||||||
|
(some? name)
|
||||||
|
(assoc :name name)
|
||||||
|
|
||||||
|
(some? background)
|
||||||
|
(assoc :background background))
|
||||||
|
|
||||||
|
undo (cond-> change
|
||||||
|
(some? name)
|
||||||
|
(assoc :name (:name page))
|
||||||
|
|
||||||
|
(some? background)
|
||||||
|
(assoc :background (:background page)))]
|
||||||
|
|
||||||
|
(-> changes
|
||||||
|
(update :redo-changes conj redo)
|
||||||
|
(update :undo-changes conj undo)
|
||||||
|
(apply-changes-local)))))
|
||||||
|
|
||||||
(defn mod-plugin-data
|
(defn mod-plugin-data
|
||||||
([changes namespace key value]
|
([changes namespace key value]
|
||||||
|
@ -246,42 +259,77 @@
|
||||||
(update :undo-changes conj {:type :mov-page :id page-id :index prev-index})
|
(update :undo-changes conj {:type :mov-page :id page-id :index prev-index})
|
||||||
(apply-changes-local)))
|
(apply-changes-local)))
|
||||||
|
|
||||||
(defn set-page-option
|
|
||||||
[changes option-key option-val]
|
(defn set-guide
|
||||||
(assert-page! changes)
|
[changes id guide]
|
||||||
(let [page-id (::page-id (meta changes))
|
(let [page-id (::page-id (meta changes))
|
||||||
page (::page (meta changes))
|
page (::page (meta changes))
|
||||||
old-val (get-in page [:options option-key])]
|
old-val (dm/get-in page [:guides id])]
|
||||||
|
|
||||||
(-> changes
|
(-> changes
|
||||||
(update :redo-changes conj {:type :set-option
|
(update :redo-changes conj {:type :set-guide
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:option option-key
|
:id id
|
||||||
:value option-val})
|
:params guide})
|
||||||
(update :undo-changes conj {:type :set-option
|
(update :undo-changes conj {:type :set-guide
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:option option-key
|
:id id
|
||||||
:value old-val})
|
:params old-val}))))
|
||||||
(apply-changes-local))))
|
(defn set-flow
|
||||||
|
[changes id flow]
|
||||||
(defn update-page-option
|
|
||||||
[changes option-key update-fn & args]
|
|
||||||
(assert-page! changes)
|
|
||||||
(let [page-id (::page-id (meta changes))
|
(let [page-id (::page-id (meta changes))
|
||||||
page (::page (meta changes))
|
page (::page (meta changes))
|
||||||
old-val (get-in page [:options option-key])
|
old-val (dm/get-in page [:flows id])
|
||||||
new-val (apply update-fn old-val args)]
|
|
||||||
|
|
||||||
(-> changes
|
changes (-> changes
|
||||||
(update :redo-changes conj {:type :set-option
|
(update :redo-changes conj {:type :set-flow
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:option option-key
|
:id id
|
||||||
:value new-val})
|
:params flow})
|
||||||
(update :undo-changes conj {:type :set-option
|
(update :undo-changes conj {:type :set-flow
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:option option-key
|
:id id
|
||||||
:value old-val})
|
:params old-val}))]
|
||||||
(apply-changes-local))))
|
;; FIXME: not sure if we need this
|
||||||
|
(apply-changes-local changes)))
|
||||||
|
|
||||||
|
(defn set-comment-thread-position
|
||||||
|
[changes {:keys [id frame-id position] :as thread}]
|
||||||
|
(let [page-id (::page-id (meta changes))
|
||||||
|
page (::page (meta changes))
|
||||||
|
|
||||||
|
old-val (dm/get-in page [:comment-thread-positions id])
|
||||||
|
|
||||||
|
changes (-> changes
|
||||||
|
(update :redo-changes conj {:type :set-comment-thread-position
|
||||||
|
:comment-thread-id id
|
||||||
|
:page-id page-id
|
||||||
|
:frame-id frame-id
|
||||||
|
:position position})
|
||||||
|
(update :undo-changes conj {:type :set-comment-thread-position
|
||||||
|
:page-id page-id
|
||||||
|
:comment-thread-id id
|
||||||
|
:frame-id (:frame-id old-val)
|
||||||
|
:position (:position old-val)}))]
|
||||||
|
;; FIXME: not sure if we need this
|
||||||
|
(apply-changes-local changes)))
|
||||||
|
|
||||||
|
(defn set-default-grid
|
||||||
|
[changes type params]
|
||||||
|
(let [page-id (::page-id (meta changes))
|
||||||
|
page (::page (meta changes))
|
||||||
|
old-val (dm/get-in page [:grids type])
|
||||||
|
|
||||||
|
changes (update changes :redo-changes conj {:type :set-default-grid
|
||||||
|
:page-id page-id
|
||||||
|
:grid-type type
|
||||||
|
:params params})
|
||||||
|
changes (update changes :undo-changes conj {:type :set-default-grid
|
||||||
|
:page-id page-id
|
||||||
|
:grid-type type
|
||||||
|
:params old-val})]
|
||||||
|
;; FIXME: not sure if we need this
|
||||||
|
(apply-changes-local changes)))
|
||||||
|
|
||||||
;; Shape tree changes
|
;; Shape tree changes
|
||||||
|
|
||||||
|
|
|
@ -6,4 +6,4 @@
|
||||||
|
|
||||||
(ns app.common.files.defaults)
|
(ns app.common.files.defaults)
|
||||||
|
|
||||||
(def version 51)
|
(def version 52)
|
||||||
|
|
|
@ -1017,6 +1017,30 @@
|
||||||
(into {} (filter #(-> % val valid-color?) colors)))]
|
(into {} (filter #(-> % val valid-color?) colors)))]
|
||||||
(update data :colors update-colors)))
|
(update data :colors update-colors)))
|
||||||
|
|
||||||
|
(defn migrate-up-52
|
||||||
|
"This migration moves page options to the page level"
|
||||||
|
[data]
|
||||||
|
(let [update-page
|
||||||
|
(fn [{:keys [options] :as page}]
|
||||||
|
(cond-> page
|
||||||
|
(and (some? (:saved-grids options))
|
||||||
|
(not (contains? page :default-grids)))
|
||||||
|
(assoc :default-grids (:saved-grids options))
|
||||||
|
|
||||||
|
(and (some? (:flows options))
|
||||||
|
(not (contains? page :flows)))
|
||||||
|
(assoc :flows (:flows options))
|
||||||
|
|
||||||
|
(and (some? (:guides options))
|
||||||
|
(not (contains? page :guides)))
|
||||||
|
(assoc :guides (:guides options))
|
||||||
|
|
||||||
|
(and (some? (:comment-threads-position options))
|
||||||
|
(not (contains? page :comment-thread-positions)))
|
||||||
|
(assoc :comment-thread-positions (:comment-threads-position options))))]
|
||||||
|
|
||||||
|
(update data :pages-index d/update-vals update-page)))
|
||||||
|
|
||||||
(def migrations
|
(def migrations
|
||||||
"A vector of all applicable migrations"
|
"A vector of all applicable migrations"
|
||||||
[{:id 2 :migrate-up migrate-up-2}
|
[{:id 2 :migrate-up migrate-up-2}
|
||||||
|
@ -1059,4 +1083,5 @@
|
||||||
{:id 48 :migrate-up migrate-up-48}
|
{:id 48 :migrate-up migrate-up-48}
|
||||||
{:id 49 :migrate-up migrate-up-49}
|
{:id 49 :migrate-up migrate-up-49}
|
||||||
{:id 50 :migrate-up migrate-up-50}
|
{:id 50 :migrate-up migrate-up-50}
|
||||||
{:id 51 :migrate-up migrate-up-51}])
|
{:id 51 :migrate-up migrate-up-51}
|
||||||
|
{:id 52 :migrate-up migrate-up-52}])
|
||||||
|
|
|
@ -15,10 +15,10 @@
|
||||||
[old-page page check-attrs]
|
[old-page page check-attrs]
|
||||||
|
|
||||||
(let [old-objects (get old-page :objects)
|
(let [old-objects (get old-page :objects)
|
||||||
old-guides (or (get-in old-page [:options :guides]) [])
|
old-guides (or (get old-page :guides) [])
|
||||||
|
|
||||||
new-objects (get page :objects)
|
new-objects (get page :objects)
|
||||||
new-guides (or (get-in page [:options :guides]) [])
|
new-guides (or (get page :guides) [])
|
||||||
|
|
||||||
changed-object?
|
changed-object?
|
||||||
(fn [id]
|
(fn [id]
|
||||||
|
|
|
@ -1947,54 +1947,54 @@
|
||||||
|
|
||||||
(defn generate-duplicate-flows
|
(defn generate-duplicate-flows
|
||||||
[changes shapes page ids-map]
|
[changes shapes page ids-map]
|
||||||
(let [flows (-> page :options :flows)
|
(let [flows (get page :flows)
|
||||||
unames (volatile! (into #{} (map :name flows)))
|
unames (volatile! (cfh/get-used-names (vals flows)))
|
||||||
frames-with-flow (->> shapes
|
has-flow? (partial ctp/get-frame-flow flows)]
|
||||||
(filter #(= (:type %) :frame))
|
|
||||||
(filter #(some? (ctp/get-frame-flow flows (:id %)))))]
|
(reduce (fn [changes frame-id]
|
||||||
(if-not (empty? frames-with-flow)
|
(let [name (cfh/generate-unique-name @unames "Flow 1")
|
||||||
(let [update-flows (fn [flows]
|
frame-id (get ids-map frame-id)
|
||||||
(reduce
|
flow-id (uuid/next)
|
||||||
(fn [flows frame]
|
new-flow {:id flow-id
|
||||||
(let [name (cfh/generate-unique-name @unames "Flow 1")
|
:name name
|
||||||
_ (vswap! unames conj name)
|
:starting-frame frame-id}]
|
||||||
new-flow {:id (uuid/next)
|
|
||||||
:name name
|
(vswap! unames conj name)
|
||||||
:starting-frame (get ids-map (:id frame))}]
|
(pcb/set-flow changes flow-id new-flow)))
|
||||||
(ctp/add-flow flows new-flow)))
|
|
||||||
flows
|
changes
|
||||||
frames-with-flow))]
|
(->> shapes
|
||||||
(pcb/update-page-option changes :flows update-flows))
|
(filter cfh/frame-shape?)
|
||||||
changes)))
|
(map :id)
|
||||||
|
(filter has-flow?)))))
|
||||||
|
|
||||||
(defn generate-duplicate-guides
|
(defn generate-duplicate-guides
|
||||||
[changes shapes page ids-map delta]
|
[changes shapes page ids-map delta]
|
||||||
(let [guides (get-in page [:options :guides])
|
(let [guides (get page :guides)
|
||||||
frames (->> shapes (filter cfh/frame-shape?))
|
frames (filter cfh/frame-shape? shapes)]
|
||||||
|
|
||||||
new-guides
|
;; FIXME: this can be implemented efficiently just indexing guides
|
||||||
(reduce
|
;; by frame-id instead of iterate over all guides all the time
|
||||||
(fn [g frame]
|
|
||||||
(let [new-id (ids-map (:id frame))
|
|
||||||
new-frame (-> frame (gsh/move delta))
|
|
||||||
|
|
||||||
new-guides
|
(reduce (fn [changes frame]
|
||||||
(->> guides
|
(let [new-id (get ids-map (:id frame))
|
||||||
(vals)
|
new-frame (gsh/move frame delta)]
|
||||||
(filter #(= (:frame-id %) (:id frame)))
|
|
||||||
(map #(-> %
|
(reduce-kv (fn [changes _ guide]
|
||||||
(assoc :id (uuid/next))
|
(if (= (:id frame) (:frame-id guide))
|
||||||
(assoc :frame-id new-id)
|
(let [guide-id (uuid/next)
|
||||||
(assoc :position (if (= (:axis %) :x)
|
position (if (= (:axis guide) :x)
|
||||||
(+ (:position %) (- (:x new-frame) (:x frame)))
|
(+ (:position guide) (- (:x new-frame) (:x frame)))
|
||||||
(+ (:position %) (- (:y new-frame) (:y frame))))))))]
|
(+ (:position guide) (- (:y new-frame) (:y frame))))
|
||||||
(cond-> g
|
guide {:id guide-id
|
||||||
(not-empty new-guides)
|
:frame-id new-id
|
||||||
(conj (into {} (map (juxt :id identity) new-guides))))))
|
:position position}]
|
||||||
guides
|
(pcb/set-guide changes guide-id guide))
|
||||||
frames)]
|
changes))
|
||||||
(-> (pcb/with-page changes page)
|
changes
|
||||||
(pcb/set-page-option :guides new-guides))))
|
guides)))
|
||||||
|
(pcb/with-page changes page)
|
||||||
|
frames)))
|
||||||
|
|
||||||
(defn generate-duplicate-component-change
|
(defn generate-duplicate-component-change
|
||||||
[changes objects page component-root parent-id frame-id delta libraries library-data]
|
[changes objects page component-root parent-id frame-id delta libraries library-data]
|
||||||
|
|
|
@ -7,13 +7,11 @@
|
||||||
(ns app.common.logic.shapes
|
(ns app.common.logic.shapes
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
|
||||||
[app.common.files.changes-builder :as pcb]
|
[app.common.files.changes-builder :as pcb]
|
||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.types.component :as ctk]
|
[app.common.types.component :as ctk]
|
||||||
[app.common.types.container :as ctn]
|
[app.common.types.container :as ctn]
|
||||||
[app.common.types.page :as ctp]
|
|
||||||
[app.common.types.shape.interactions :as ctsi]
|
[app.common.types.shape.interactions :as ctsi]
|
||||||
[app.common.types.shape.layout :as ctl]
|
[app.common.types.shape.layout :as ctl]
|
||||||
[app.common.uuid :as uuid]))
|
[app.common.uuid :as uuid]))
|
||||||
|
@ -85,7 +83,9 @@
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/with-objects objects)
|
(pcb/with-objects objects)
|
||||||
(pcb/with-library-data file))
|
(pcb/with-library-data file))
|
||||||
|
|
||||||
lookup (d/getf objects)
|
lookup (d/getf objects)
|
||||||
|
|
||||||
groups-to-unmask
|
groups-to-unmask
|
||||||
(reduce (fn [group-ids id]
|
(reduce (fn [group-ids id]
|
||||||
;; When the shape to delete is the mask of a masked group,
|
;; When the shape to delete is the mask of a masked group,
|
||||||
|
@ -110,23 +110,14 @@
|
||||||
interactions)))
|
interactions)))
|
||||||
(vals objects))
|
(vals objects))
|
||||||
|
|
||||||
ids-set (set ids-to-delete)
|
changes
|
||||||
guides-to-remove
|
(reduce (fn [changes {:keys [id] :as flow}]
|
||||||
(->> (dm/get-in page [:options :guides])
|
(if (contains? ids-to-delete (:starting-frame flow))
|
||||||
(vals)
|
(pcb/set-flow changes id nil)
|
||||||
(filter #(contains? ids-set (:frame-id %)))
|
changes))
|
||||||
(map :id))
|
changes
|
||||||
|
(:flows page))
|
||||||
|
|
||||||
guides
|
|
||||||
(->> guides-to-remove
|
|
||||||
(reduce dissoc (dm/get-in page [:options :guides])))
|
|
||||||
|
|
||||||
starting-flows
|
|
||||||
(filter (fn [flow]
|
|
||||||
;; If any of the deleted is a frame that starts a flow,
|
|
||||||
;; this must be deleted, too.
|
|
||||||
(contains? ids-to-delete (:starting-frame flow)))
|
|
||||||
(-> page :options :flows))
|
|
||||||
|
|
||||||
all-parents
|
all-parents
|
||||||
(reduce (fn [res id]
|
(reduce (fn [res id]
|
||||||
|
@ -172,8 +163,18 @@
|
||||||
(into ids-to-delete all-children))
|
(into ids-to-delete all-children))
|
||||||
[])
|
[])
|
||||||
|
|
||||||
changes (-> changes
|
ids-set (set ids-to-delete)
|
||||||
(pcb/set-page-option :guides guides))
|
|
||||||
|
guides-to-delete
|
||||||
|
(->> (:guides page)
|
||||||
|
(vals)
|
||||||
|
(filter #(contains? ids-set (:frame-id %)))
|
||||||
|
(map :id))
|
||||||
|
|
||||||
|
changes (reduce (fn [changes guide-id]
|
||||||
|
(pcb/set-flow changes guide-id nil))
|
||||||
|
changes
|
||||||
|
guides-to-delete)
|
||||||
|
|
||||||
changes (reduce (fn [changes component-id]
|
changes (reduce (fn [changes component-id]
|
||||||
;; It's important to delete the component before the main instance, because we
|
;; It's important to delete the component before the main instance, because we
|
||||||
|
@ -181,6 +182,7 @@
|
||||||
(pcb/delete-component changes component-id (:id page)))
|
(pcb/delete-component changes component-id (:id page)))
|
||||||
changes
|
changes
|
||||||
components-to-delete)
|
components-to-delete)
|
||||||
|
|
||||||
changes (-> changes
|
changes (-> changes
|
||||||
(generate-update-shape-flags ids-to-hide objects {:hidden true})
|
(generate-update-shape-flags ids-to-hide objects {:hidden true})
|
||||||
(pcb/remove-objects all-children {:ignore-touched true})
|
(pcb/remove-objects all-children {:ignore-touched true})
|
||||||
|
@ -197,11 +199,7 @@
|
||||||
(into []
|
(into []
|
||||||
(remove #(and (ctsi/has-destination %)
|
(remove #(and (ctsi/has-destination %)
|
||||||
(contains? ids-to-delete (:destination %))))
|
(contains? ids-to-delete (:destination %))))
|
||||||
interactions)))))
|
interactions))))))]
|
||||||
(cond-> (seq starting-flows)
|
|
||||||
(pcb/update-page-option :flows (fn [flows]
|
|
||||||
(->> (map :id starting-flows)
|
|
||||||
(reduce ctp/remove-flow flows))))))]
|
|
||||||
[all-parents changes]))
|
[all-parents changes]))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
(ns app.common.types.grid
|
(ns app.common.types.grid
|
||||||
(:require
|
(:require
|
||||||
|
[app.common.colors :as clr]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.types.color :as ctc]))
|
[app.common.types.color :as ctc]))
|
||||||
|
|
||||||
|
@ -54,7 +55,7 @@
|
||||||
[:display :boolean]
|
[:display :boolean]
|
||||||
[:params schema:square-params]]]])
|
[:params schema:square-params]]]])
|
||||||
|
|
||||||
(def schema:saved-grids
|
(def schema:default-grids
|
||||||
[:map {:title "PageGrid"}
|
[:map {:title "PageGrid"}
|
||||||
[:square {:optional true} ::square-params]
|
[:square {:optional true} ::square-params]
|
||||||
[:row {:optional true} ::column-params]
|
[:row {:optional true} ::column-params]
|
||||||
|
@ -63,4 +64,24 @@
|
||||||
(sm/register! ::square-params schema:square-params)
|
(sm/register! ::square-params schema:square-params)
|
||||||
(sm/register! ::column-params schema:column-params)
|
(sm/register! ::column-params schema:column-params)
|
||||||
(sm/register! ::grid schema:grid)
|
(sm/register! ::grid schema:grid)
|
||||||
(sm/register! ::saved-grids schema:saved-grids)
|
(sm/register! ::default-grids schema:default-grids)
|
||||||
|
|
||||||
|
(def ^:private default-square-params
|
||||||
|
{:size 16
|
||||||
|
:color {:color clr/info
|
||||||
|
:opacity 0.4}})
|
||||||
|
|
||||||
|
(def ^:private default-layout-params
|
||||||
|
{:size 12
|
||||||
|
:type :stretch
|
||||||
|
:item-length nil
|
||||||
|
:gutter 8
|
||||||
|
:margin 0
|
||||||
|
:color {:color clr/default-layout
|
||||||
|
:opacity 0.1}})
|
||||||
|
|
||||||
|
(def default-grid-params
|
||||||
|
{:square default-square-params
|
||||||
|
:column default-layout-params
|
||||||
|
:row default-layout-params})
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.common.types.page
|
(ns app.common.types.page
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
|
[app.common.geom.point :as-alias gpt]
|
||||||
[app.common.schema :as sm]
|
[app.common.schema :as sm]
|
||||||
[app.common.types.color :as-alias ctc]
|
[app.common.types.color :as-alias ctc]
|
||||||
[app.common.types.grid :as ctg]
|
[app.common.types.grid :as ctg]
|
||||||
|
@ -24,38 +25,56 @@
|
||||||
[:name :string]
|
[:name :string]
|
||||||
[:starting-frame ::sm/uuid]])
|
[:starting-frame ::sm/uuid]])
|
||||||
|
|
||||||
|
(def schema:flows
|
||||||
|
[:map-of {:gen/max 2} ::sm/uuid schema:flow])
|
||||||
|
|
||||||
(def schema:guide
|
(def schema:guide
|
||||||
[:map {:title "Guide"}
|
[:map {:title "Guide"}
|
||||||
[:id ::sm/uuid]
|
[:id ::sm/uuid]
|
||||||
[:axis [::sm/one-of #{:x :y}]]
|
[:axis [::sm/one-of #{:x :y}]]
|
||||||
[:position ::sm/safe-number]
|
[:position ::sm/safe-number]
|
||||||
|
;; FIXME: remove maybe?
|
||||||
[:frame-id {:optional true} [:maybe ::sm/uuid]]])
|
[:frame-id {:optional true} [:maybe ::sm/uuid]]])
|
||||||
|
|
||||||
|
(def schema:guides
|
||||||
|
[:map-of {:gen/max 2} ::sm/uuid schema:guide])
|
||||||
|
|
||||||
|
(def schema:objects
|
||||||
|
[:map-of {:gen/max 5} ::sm/uuid ::cts/shape])
|
||||||
|
|
||||||
|
(def schema:comment-thread-position
|
||||||
|
[:map {:title "CommentThreadPosition"}
|
||||||
|
[:frame-id ::sm/uuid]
|
||||||
|
[:position ::gpt/point]])
|
||||||
|
|
||||||
(def schema:page
|
(def schema:page
|
||||||
[:map {:title "FilePage"}
|
[:map {:title "FilePage"}
|
||||||
[:id ::sm/uuid]
|
[:id ::sm/uuid]
|
||||||
[:name :string]
|
[:name :string]
|
||||||
[:objects
|
[:objects schema:objects]
|
||||||
[:map-of {:gen/max 5} ::sm/uuid ::cts/shape]]
|
[:default-grids {:optional true} ::ctg/default-grids]
|
||||||
|
[:flows {:optional true} schema:flows]
|
||||||
|
[:guides {:optional true} schema:guides]
|
||||||
|
[:plugin-data {:optional true} ::ctpg/plugin-data]
|
||||||
|
[:background {:optional true} ::ctc/rgb-color]
|
||||||
|
|
||||||
|
[:comment-thread-positions {:optional true}
|
||||||
|
[:map-of ::sm/uuid schema:comment-thread-position]]
|
||||||
|
|
||||||
[:options
|
[:options
|
||||||
[:map {:title "PageOptions"}
|
;; DEPERECATED: remove after 2.3 release
|
||||||
[:background {:optional true} ::ctc/rgb-color]
|
[:map {:title "PageOptions"}]]])
|
||||||
[:saved-grids {:optional true} ::ctg/saved-grids]
|
|
||||||
[:flows {:optional true}
|
|
||||||
[:vector {:gen/max 2} schema:flow]]
|
|
||||||
[:guides {:optional true}
|
|
||||||
[:map-of {:gen/max 2} ::sm/uuid schema:guide]]
|
|
||||||
[:plugin-data {:optional true} ::ctpg/plugin-data]]]])
|
|
||||||
|
|
||||||
(sm/register! ::page schema:page)
|
(sm/register! ::page schema:page)
|
||||||
(sm/register! ::guide schema:guide)
|
(sm/register! ::guide schema:guide)
|
||||||
(sm/register! ::flow schema:flow)
|
(sm/register! ::flow schema:flow)
|
||||||
|
|
||||||
(def check-page-guide!
|
(def valid-guide?
|
||||||
(sm/check-fn ::guide))
|
(sm/lazy-validator schema:guide))
|
||||||
|
|
||||||
|
;; FIXME: convert to validator
|
||||||
(def check-page!
|
(def check-page!
|
||||||
(sm/check-fn ::page))
|
(sm/check-fn schema:page))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;; INIT & HELPERS
|
;; INIT & HELPERS
|
||||||
|
@ -80,25 +99,6 @@
|
||||||
(assoc :id (or id (uuid/next)))
|
(assoc :id (or id (uuid/next)))
|
||||||
(assoc :name (or name "Page 1"))))
|
(assoc :name (or name "Page 1"))))
|
||||||
|
|
||||||
;; --- Helpers for flow
|
|
||||||
|
|
||||||
(defn rename-flow
|
|
||||||
[flow name]
|
|
||||||
(assoc flow :name name))
|
|
||||||
|
|
||||||
(defn add-flow
|
|
||||||
[flows flow]
|
|
||||||
(conj (or flows []) flow))
|
|
||||||
|
|
||||||
(defn remove-flow
|
|
||||||
[flows flow-id]
|
|
||||||
(d/removev #(= (:id %) flow-id) flows))
|
|
||||||
|
|
||||||
(defn update-flow
|
|
||||||
[flows flow-id update-fn]
|
|
||||||
(let [index (d/index-of-pred flows #(= (:id %) flow-id))]
|
|
||||||
(update flows index update-fn)))
|
|
||||||
|
|
||||||
(defn get-frame-flow
|
(defn get-frame-flow
|
||||||
[flows frame-id]
|
[flows frame-id]
|
||||||
(d/seek #(= (:starting-frame %) frame-id) flows))
|
(d/seek #(= (:starting-frame %) frame-id) (vals flows)))
|
||||||
|
|
|
@ -19,71 +19,6 @@
|
||||||
(binding [ffeat/*current* #{"components/v2"}]
|
(binding [ffeat/*current* #{"components/v2"}]
|
||||||
(ctf/make-file-data file-id page-id)))
|
(ctf/make-file-data file-id page-id)))
|
||||||
|
|
||||||
(t/deftest process-change-set-option
|
|
||||||
(let [file-id (uuid/custom 2 2)
|
|
||||||
page-id (uuid/custom 1 1)
|
|
||||||
data (make-file-data file-id page-id)]
|
|
||||||
(t/testing "Sets option single"
|
|
||||||
(let [chg {:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option :test
|
|
||||||
:value "test"}
|
|
||||||
res (ch/process-changes data [chg])]
|
|
||||||
(t/is (= "test" (get-in res [:pages-index page-id :options :test])))))
|
|
||||||
|
|
||||||
(t/testing "Sets option nested"
|
|
||||||
(let [chgs [{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option [:values :test :a]
|
|
||||||
:value "a"}
|
|
||||||
{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option [:values :test :b]
|
|
||||||
:value "b"}]
|
|
||||||
res (ch/process-changes data chgs)]
|
|
||||||
(t/is (= {:a "a" :b "b"}
|
|
||||||
(get-in res [:pages-index page-id :options :values :test])))))
|
|
||||||
|
|
||||||
(t/testing "Remove option single"
|
|
||||||
(let [chg {:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option :test
|
|
||||||
:value nil}
|
|
||||||
res (ch/process-changes data [chg])]
|
|
||||||
(t/is (empty? (keys (get-in res [:pages-index page-id :options]))))))
|
|
||||||
|
|
||||||
(t/testing "Remove option nested 1"
|
|
||||||
(let [chgs [{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option [:values :test :a]
|
|
||||||
:value "a"}
|
|
||||||
{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option [:values :test :b]
|
|
||||||
:value "b"}
|
|
||||||
{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option [:values :test]
|
|
||||||
:value nil}]
|
|
||||||
res (ch/process-changes data chgs)]
|
|
||||||
(t/is (empty? (keys (get-in res [:pages-index page-id :options]))))))
|
|
||||||
|
|
||||||
(t/testing "Remove option nested 2"
|
|
||||||
(let [chgs [{:type :set-option
|
|
||||||
:option [:values :test1 :a]
|
|
||||||
:page-id page-id
|
|
||||||
:value "a"}
|
|
||||||
{:type :set-option
|
|
||||||
:option [:values :test2 :b]
|
|
||||||
:page-id page-id
|
|
||||||
:value "b"}
|
|
||||||
{:type :set-option
|
|
||||||
:page-id page-id
|
|
||||||
:option [:values :test2]
|
|
||||||
:value nil}]
|
|
||||||
res (ch/process-changes data chgs)]
|
|
||||||
(t/is (= [:test1] (keys (get-in res [:pages-index page-id :options :values]))))))))
|
|
||||||
|
|
||||||
(t/deftest process-change-add-obj
|
(t/deftest process-change-add-obj
|
||||||
(let [file-id (uuid/custom 2 2)
|
(let [file-id (uuid/custom 2 2)
|
||||||
page-id (uuid/custom 1 1)
|
page-id (uuid/custom 1 1)
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
(let [position (select-keys thread [:position :frame-id])]
|
(let [position (select-keys thread [:position :frame-id])]
|
||||||
(-> state
|
(-> state
|
||||||
(update :comment-threads assoc id (dissoc thread :comment))
|
(update :comment-threads assoc id (dissoc thread :comment))
|
||||||
(update-in [:workspace-data :pages-index page-id :options :comment-threads-position] assoc id position)
|
(update-in [:workspace-data :pages-index page-id :comment-thread-positions] assoc id position)
|
||||||
(cond-> open?
|
(cond-> open?
|
||||||
(update :comments-local assoc :open id))
|
(update :comments-local assoc :open id))
|
||||||
(update :comments-local assoc :options nil)
|
(update :comments-local assoc :options nil)
|
||||||
|
@ -122,7 +122,7 @@
|
||||||
(let [position (select-keys thread [:position :frame-id])]
|
(let [position (select-keys thread [:position :frame-id])]
|
||||||
(-> state
|
(-> state
|
||||||
(update :comment-threads assoc id (dissoc thread :comment))
|
(update :comment-threads assoc id (dissoc thread :comment))
|
||||||
(update-in [:viewer :pages page-id :options :comment-threads-position] assoc id position)
|
(update-in [:viewer :pages page-id :comment-thread-positions] assoc id position)
|
||||||
(update :comments-local assoc :open id)
|
(update :comments-local assoc :open id)
|
||||||
(update :comments-local assoc :options nil)
|
(update :comments-local assoc :options nil)
|
||||||
(update :comments-local dissoc :draft)
|
(update :comments-local dissoc :draft)
|
||||||
|
@ -273,7 +273,7 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [page-id (:current-page-id state)]
|
(let [page-id (:current-page-id state)]
|
||||||
(-> state
|
(-> state
|
||||||
(update-in [:workspace-data :pages-index page-id :options :comment-threads-position] dissoc id)
|
(update-in [:workspace-data :pages-index page-id :comment-thread-positions] dissoc id)
|
||||||
(update :comments dissoc id)
|
(update :comments dissoc id)
|
||||||
(update :comment-threads dissoc id))))
|
(update :comment-threads dissoc id))))
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [page-id (:current-page-id state)]
|
(let [page-id (:current-page-id state)]
|
||||||
(-> state
|
(-> state
|
||||||
(update-in [:viewer :pages page-id :options :comment-threads-position] dissoc id)
|
(update-in [:viewer :pages page-id :comment-thread-positions] dissoc id)
|
||||||
(update :comments dissoc id)
|
(update :comments dissoc id)
|
||||||
(update :comment-threads dissoc id))))
|
(update :comment-threads dissoc id))))
|
||||||
|
|
||||||
|
@ -356,7 +356,7 @@
|
||||||
[file-id]
|
[file-id]
|
||||||
(dm/assert! (uuid? file-id))
|
(dm/assert! (uuid? file-id))
|
||||||
(letfn [(set-comment-threds [state comment-thread]
|
(letfn [(set-comment-threds [state comment-thread]
|
||||||
(let [path [:workspace-data :pages-index (:page-id comment-thread) :options :comment-threads-position (:id comment-thread)]
|
(let [path [:workspace-data :pages-index (:page-id comment-thread) :comment-thread-positions (:id comment-thread)]
|
||||||
thread-position (get-in state path)]
|
thread-position (get-in state path)]
|
||||||
(cond-> state
|
(cond-> state
|
||||||
(nil? thread-position)
|
(nil? thread-position)
|
||||||
|
|
|
@ -568,7 +568,7 @@
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [page (get-in state [:workspace-data :pages-index id])
|
(let [page (get-in state [:workspace-data :pages-index id])
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(pcb/mod-page page name))]
|
(pcb/mod-page page {:name name}))]
|
||||||
|
|
||||||
(rx/of (dch/commit-changes changes))))))
|
(rx/of (dch/commit-changes changes))))))
|
||||||
|
|
||||||
|
@ -2071,7 +2071,7 @@
|
||||||
page (wsh/lookup-page state page-id)
|
page (wsh/lookup-page state page-id)
|
||||||
changes (-> (pcb/empty-changes it)
|
changes (-> (pcb/empty-changes it)
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/set-page-option :background (:color color)))]
|
(pcb/mod-page {:background (:color color)}))]
|
||||||
(rx/of (dch/commit-changes changes)))))))
|
(rx/of (dch/commit-changes changes)))))))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
|
@ -132,21 +132,20 @@
|
||||||
(ptk/reify ::update-comment-thread-position
|
(ptk/reify ::update-comment-thread-position
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [thread-id (:id thread)
|
(let [page (wsh/lookup-page state)
|
||||||
page (wsh/lookup-page state)
|
page-id (:id page)
|
||||||
page-id (:id page)
|
objects (wsh/lookup-page-objects state page-id)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
frame-id (if (nil? frame-id)
|
||||||
new-frame-id (if (nil? frame-id)
|
(ctst/get-frame-id-by-position objects (gpt/point new-x new-y))
|
||||||
(ctst/get-frame-id-by-position objects (gpt/point new-x new-y))
|
(:frame-id thread))
|
||||||
(:frame-id thread))
|
|
||||||
thread (assoc thread
|
|
||||||
:position (gpt/point new-x new-y)
|
|
||||||
:frame-id new-frame-id)
|
|
||||||
|
|
||||||
changes
|
thread (-> thread
|
||||||
(-> (pcb/empty-changes it)
|
(assoc :position (gpt/point new-x new-y))
|
||||||
(pcb/with-page page)
|
(assoc :frame-id frame-id))
|
||||||
(pcb/update-page-option :comment-threads-position assoc thread-id (select-keys thread [:position :frame-id])))]
|
|
||||||
|
changes (-> (pcb/empty-changes it)
|
||||||
|
(pcb/with-page page)
|
||||||
|
(pcb/set-comment-thread-position thread))]
|
||||||
|
|
||||||
(rx/merge
|
(rx/merge
|
||||||
(rx/of (dch/commit-changes changes))
|
(rx/of (dch/commit-changes changes))
|
||||||
|
@ -164,25 +163,28 @@
|
||||||
(ptk/reify ::move-frame-comment-threads
|
(ptk/reify ::move-frame-comment-threads
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [objects (wsh/lookup-page-objects state)
|
(let [page (wsh/lookup-page state)
|
||||||
|
objects (get page :objects)
|
||||||
|
|
||||||
is-frame? (fn [id] (= :frame (get-in objects [id :type])))
|
is-frame? (fn [id] (= :frame (get-in objects [id :type])))
|
||||||
frame-ids? (into #{} (filter is-frame?) ids)
|
frame-ids? (into #{} (filter is-frame?) ids)
|
||||||
|
|
||||||
object-modifiers (:workspace-modifiers state)
|
threads-position-map
|
||||||
|
(get page :comment-thread-positions)
|
||||||
|
|
||||||
threads-position-map (:comment-threads-position (wsh/lookup-page-options state))
|
object-modifiers
|
||||||
|
(:workspace-modifiers state)
|
||||||
|
|
||||||
build-move-event
|
build-move-event
|
||||||
(fn [comment-thread]
|
(fn [comment-thread]
|
||||||
(let [frame (get objects (:frame-id comment-thread))
|
(let [frame (get objects (:frame-id comment-thread))
|
||||||
modifiers (get-in object-modifiers [(:frame-id comment-thread) :modifiers])
|
modifiers (get-in object-modifiers [(:frame-id comment-thread) :modifiers])
|
||||||
frame' (gsh/transform-shape frame modifiers)
|
frame' (gsh/transform-shape frame modifiers)
|
||||||
moved (gpt/to-vec (gpt/point (:x frame) (:y frame))
|
moved (gpt/to-vec (gpt/point (:x frame) (:y frame))
|
||||||
(gpt/point (:x frame') (:y frame')))
|
(gpt/point (:x frame') (:y frame')))
|
||||||
position (get-in threads-position-map [(:id comment-thread) :position])
|
position (get-in threads-position-map [(:id comment-thread) :position])
|
||||||
new-x (+ (:x position) (:x moved))
|
new-x (+ (:x position) (:x moved))
|
||||||
new-y (+ (:y position) (:y moved))]
|
new-y (+ (:y position) (:y moved))]
|
||||||
(update-comment-thread-position comment-thread [new-x new-y] (:id frame))))]
|
(update-comment-thread-position comment-thread [new-x new-y] (:id frame))))]
|
||||||
|
|
||||||
(->> (:comment-threads state)
|
(->> (:comment-threads state)
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
|
|
||||||
(ns app.main.data.workspace.grid
|
(ns app.main.data.workspace.grid
|
||||||
(:require
|
(:require
|
||||||
[app.common.colors :as clr]
|
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.files.changes-builder :as pcb]
|
[app.common.files.changes-builder :as pcb]
|
||||||
|
[app.common.types.grid :as ctg]
|
||||||
[app.main.data.changes :as dch]
|
[app.main.data.changes :as dch]
|
||||||
[app.main.data.workspace.shapes :as dwsh]
|
[app.main.data.workspace.shapes :as dwsh]
|
||||||
[app.main.data.workspace.state-helpers :as wsh]
|
[app.main.data.workspace.state-helpers :as wsh]
|
||||||
|
@ -20,25 +20,6 @@
|
||||||
;; Grid
|
;; Grid
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(defonce ^:private default-square-params
|
|
||||||
{:size 16
|
|
||||||
:color {:color clr/info
|
|
||||||
:opacity 0.4}})
|
|
||||||
|
|
||||||
(defonce ^:private default-layout-params
|
|
||||||
{:size 12
|
|
||||||
:type :stretch
|
|
||||||
:item-length nil
|
|
||||||
:gutter 8
|
|
||||||
:margin 0
|
|
||||||
:color {:color clr/default-layout
|
|
||||||
:opacity 0.1}})
|
|
||||||
|
|
||||||
(defonce default-grid-params
|
|
||||||
{:square default-square-params
|
|
||||||
:column default-layout-params
|
|
||||||
:row default-layout-params})
|
|
||||||
|
|
||||||
(defn add-frame-grid
|
(defn add-frame-grid
|
||||||
[frame-id]
|
[frame-id]
|
||||||
(dm/assert! (uuid? frame-id))
|
(dm/assert! (uuid? frame-id))
|
||||||
|
@ -46,9 +27,9 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
data (get-in state [:workspace-data :pages-index page-id])
|
page (dm/get-in state [:workspace-data :pages-index page-id])
|
||||||
params (or (get-in data [:options :saved-grids :square])
|
params (or (dm/get-in page [:grids :square])
|
||||||
(:square default-grid-params))
|
(:square ctg/default-grid-params))
|
||||||
grid {:type :square
|
grid {:type :square
|
||||||
:params params
|
:params params
|
||||||
:display true}]
|
:display true}]
|
||||||
|
@ -79,4 +60,4 @@
|
||||||
(rx/of (dch/commit-changes
|
(rx/of (dch/commit-changes
|
||||||
(-> (pcb/empty-changes it)
|
(-> (pcb/empty-changes it)
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/set-page-option [:saved-grids type] params))))))))
|
(pcb/set-default-grid type params))))))))
|
||||||
|
|
|
@ -17,18 +17,12 @@
|
||||||
[beicon.v2.core :as rx]
|
[beicon.v2.core :as rx]
|
||||||
[potok.v2.core :as ptk]))
|
[potok.v2.core :as ptk]))
|
||||||
|
|
||||||
(defn make-update-guide
|
|
||||||
[guide]
|
|
||||||
(fn [other]
|
|
||||||
(cond-> other
|
|
||||||
(= (:id other) (:id guide))
|
|
||||||
(merge guide))))
|
|
||||||
|
|
||||||
(defn update-guides
|
(defn update-guides
|
||||||
[guide]
|
[{:keys [id] :as guide}]
|
||||||
|
|
||||||
(dm/assert!
|
(dm/assert!
|
||||||
"expected valid guide"
|
"expected valid guide"
|
||||||
(ctp/check-page-guide! guide))
|
(ctp/valid-guide? guide))
|
||||||
|
|
||||||
(ptk/reify ::update-guides
|
(ptk/reify ::update-guides
|
||||||
ev/Event
|
ev/Event
|
||||||
|
@ -41,14 +35,15 @@
|
||||||
changes
|
changes
|
||||||
(-> (pcb/empty-changes it)
|
(-> (pcb/empty-changes it)
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/update-page-option :guides assoc (:id guide) guide))]
|
(pcb/set-guide id guide))]
|
||||||
(rx/of (dwc/commit-changes changes))))))
|
(rx/of (dwc/commit-changes changes))))))
|
||||||
|
|
||||||
(defn remove-guide
|
(defn remove-guide
|
||||||
[guide]
|
[{:keys [id] :as guide}]
|
||||||
|
|
||||||
(dm/assert!
|
(dm/assert!
|
||||||
"expected valid guide"
|
"expected valid guide"
|
||||||
(ctp/check-page-guide! guide))
|
(ctp/valid-guide? guide))
|
||||||
|
|
||||||
(ptk/reify ::remove-guide
|
(ptk/reify ::remove-guide
|
||||||
ev/Event
|
ev/Event
|
||||||
|
@ -57,7 +52,7 @@
|
||||||
ptk/UpdateEvent
|
ptk/UpdateEvent
|
||||||
(update [_ state]
|
(update [_ state]
|
||||||
(let [sdisj (fnil disj #{})]
|
(let [sdisj (fnil disj #{})]
|
||||||
(update-in state [:workspace-guides :hover] sdisj (:id guide))))
|
(update-in state [:workspace-guides :hover] sdisj id)))
|
||||||
|
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
|
@ -65,18 +60,22 @@
|
||||||
changes
|
changes
|
||||||
(-> (pcb/empty-changes it)
|
(-> (pcb/empty-changes it)
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/update-page-option :guides dissoc (:id guide)))]
|
(pcb/set-guide id nil))]
|
||||||
(rx/of (dwc/commit-changes changes))))))
|
(rx/of (dwc/commit-changes changes))))))
|
||||||
|
|
||||||
(defn remove-guides
|
(defn remove-guides
|
||||||
[ids]
|
[ids]
|
||||||
|
|
||||||
|
(dm/assert!
|
||||||
|
"expected a set of ids"
|
||||||
|
(every? uuid? ids))
|
||||||
|
|
||||||
(ptk/reify ::remove-guides
|
(ptk/reify ::remove-guides
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [page (wsh/lookup-page state)
|
(let [{:keys [guides] :as page} (wsh/lookup-page state)
|
||||||
guides (get-in page [:options :guides] {})
|
|
||||||
guides (-> (select-keys guides ids) (vals))]
|
guides (-> (select-keys guides ids) (vals))]
|
||||||
(rx/from (->> guides (mapv #(remove-guide %))))))))
|
(rx/from (mapv remove-guide guides))))))
|
||||||
|
|
||||||
(defmethod ptk/resolve ::move-frame-guides
|
(defmethod ptk/resolve ::move-frame-guides
|
||||||
[_ args]
|
[_ args]
|
||||||
|
@ -105,7 +104,7 @@
|
||||||
guide (update guide :position + (get moved (:axis guide)))]
|
guide (update guide :position + (get moved (:axis guide)))]
|
||||||
(update-guides guide)))
|
(update-guides guide)))
|
||||||
|
|
||||||
guides (-> state wsh/lookup-page-options :guides vals)]
|
guides (-> state wsh/lookup-page :guides vals)]
|
||||||
|
|
||||||
(->> guides
|
(->> guides
|
||||||
(filter (comp frame-ids? :frame-id))
|
(filter (comp frame-ids? :frame-id))
|
||||||
|
|
|
@ -43,18 +43,20 @@
|
||||||
(wsh/lookup-page state page-id)
|
(wsh/lookup-page state page-id)
|
||||||
(wsh/lookup-page state))
|
(wsh/lookup-page state))
|
||||||
|
|
||||||
flows (get-in page [:options :flows] [])
|
flows (get page :flows)
|
||||||
unames (cfh/get-used-names flows)
|
unames (cfh/get-used-names (vals flows))
|
||||||
name (or name (cfh/generate-unique-name unames "Flow 1"))
|
name (or name (cfh/generate-unique-name unames "Flow 1"))
|
||||||
|
|
||||||
new-flow {:id (or flow-id (uuid/next))
|
flow-id (or flow-id (uuid/next))
|
||||||
:name name
|
|
||||||
:starting-frame starting-frame}]
|
flow {:id flow-id
|
||||||
|
:name name
|
||||||
|
:starting-frame starting-frame}]
|
||||||
|
|
||||||
(rx/of (dch/commit-changes
|
(rx/of (dch/commit-changes
|
||||||
(-> (pcb/empty-changes it)
|
(-> (pcb/empty-changes it)
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/update-page-option :flows ctp/add-flow new-flow)))))))))
|
(pcb/set-flow flow-id flow)))))))))
|
||||||
|
|
||||||
(defn add-flow-selected-frame
|
(defn add-flow-selected-frame
|
||||||
[]
|
[]
|
||||||
|
@ -79,35 +81,40 @@
|
||||||
(rx/of (dch/commit-changes
|
(rx/of (dch/commit-changes
|
||||||
(-> (pcb/empty-changes it)
|
(-> (pcb/empty-changes it)
|
||||||
(pcb/with-page page)
|
(pcb/with-page page)
|
||||||
(pcb/update-page-option :flows ctp/remove-flow flow-id)))))))))
|
(pcb/set-flow flow-id nil)))))))))
|
||||||
|
|
||||||
(defn update-flow
|
(defn update-flow
|
||||||
[page-id flow-id update-fn]
|
[page-id flow-id update-fn]
|
||||||
(dm/assert! (uuid? flow-id))
|
|
||||||
|
(assert (uuid? flow-id) "expect valid flow-id")
|
||||||
|
(assert (uuid? page-id) "expect valid page-id")
|
||||||
|
|
||||||
(ptk/reify ::update-flow
|
(ptk/reify ::update-flow
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [it state _]
|
||||||
(let [page (if page-id
|
(let [page (if page-id
|
||||||
(wsh/lookup-page state page-id)
|
(wsh/lookup-page state page-id)
|
||||||
(wsh/lookup-page state))]
|
(wsh/lookup-page state))
|
||||||
(rx/of (dch/commit-changes
|
flow (dm/get-in page [:flows flow-id])
|
||||||
(-> (pcb/empty-changes it)
|
flow (some-> flow update-fn)]
|
||||||
(pcb/with-page page)
|
|
||||||
(pcb/update-page-option :flows ctp/update-flow flow-id update-fn))))))))
|
(when (some? flow)
|
||||||
|
(rx/of (dch/commit-changes
|
||||||
|
(-> (pcb/empty-changes it)
|
||||||
|
(pcb/with-page page)
|
||||||
|
(pcb/set-flow flow-id flow)))))))))
|
||||||
|
|
||||||
(defn rename-flow
|
(defn rename-flow
|
||||||
[flow-id name]
|
[flow-id name]
|
||||||
(dm/assert! (uuid? flow-id))
|
|
||||||
(dm/assert! (string? name))
|
(assert (uuid? flow-id) "expected valid flow-id")
|
||||||
|
(assert (string? name) "expected valid name")
|
||||||
|
|
||||||
(ptk/reify ::rename-flow
|
(ptk/reify ::rename-flow
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [it state _]
|
(watch [_ state _]
|
||||||
(let [page (wsh/lookup-page state)]
|
(let [page (wsh/lookup-page state)]
|
||||||
(rx/of (dch/commit-changes
|
(rx/of (update-flow (:id page) flow-id #(assoc % :name name)))))))
|
||||||
(-> (pcb/empty-changes it)
|
|
||||||
(pcb/with-page page)
|
|
||||||
(pcb/update-page-option :flows ctp/update-flow flow-id
|
|
||||||
#(ctp/rename-flow % name)))))))))
|
|
||||||
|
|
||||||
(defn start-rename-flow
|
(defn start-rename-flow
|
||||||
[id]
|
[id]
|
||||||
|
@ -153,13 +160,11 @@
|
||||||
ptk/WatchEvent
|
ptk/WatchEvent
|
||||||
(watch [_ state _]
|
(watch [_ state _]
|
||||||
(let [page-id (:current-page-id state)
|
(let [page-id (:current-page-id state)
|
||||||
objects (wsh/lookup-page-objects state page-id)
|
page (wsh/lookup-page state page-id)
|
||||||
|
objects (get page :objects)
|
||||||
frame (cfh/get-root-frame objects (:id shape))
|
frame (cfh/get-root-frame objects (:id shape))
|
||||||
flows (get-in state [:workspace-data
|
|
||||||
:pages-index
|
flows (get page :objects)
|
||||||
page-id
|
|
||||||
:options
|
|
||||||
:flows] [])
|
|
||||||
flow (ctp/get-frame-flow flows (:id frame))]
|
flow (ctp/get-frame-flow flows (:id frame))]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(rx/of (dwsh/update-shapes [(:id shape)]
|
(rx/of (dwsh/update-shapes [(:id shape)]
|
||||||
|
|
|
@ -20,15 +20,12 @@
|
||||||
([state page-id]
|
([state page-id]
|
||||||
(get-in state [:workspace-data :pages-index page-id])))
|
(get-in state [:workspace-data :pages-index page-id])))
|
||||||
|
|
||||||
(defn lookup-data-objects
|
|
||||||
[data page-id]
|
|
||||||
(dm/get-in data [:pages-index page-id :objects]))
|
|
||||||
|
|
||||||
(defn lookup-page-objects
|
(defn lookup-page-objects
|
||||||
([state]
|
([state]
|
||||||
(lookup-page-objects state (:current-page-id state)))
|
(lookup-page-objects state (:current-page-id state)))
|
||||||
([state page-id]
|
([state page-id]
|
||||||
(dm/get-in state [:workspace-data :pages-index page-id :objects])))
|
(-> (lookup-page state page-id)
|
||||||
|
(get :objects))))
|
||||||
|
|
||||||
(defn lookup-viewer-objects
|
(defn lookup-viewer-objects
|
||||||
([state page-id]
|
([state page-id]
|
||||||
|
@ -45,12 +42,6 @@
|
||||||
(lookup-page-objects state page-id)
|
(lookup-page-objects state page-id)
|
||||||
(lookup-library-objects state file-id page-id))))
|
(lookup-library-objects state file-id page-id))))
|
||||||
|
|
||||||
(defn lookup-page-options
|
|
||||||
([state]
|
|
||||||
(lookup-page-options state (:current-page-id state)))
|
|
||||||
([state page-id]
|
|
||||||
(dm/get-in state [:workspace-data :pages-index page-id :options])))
|
|
||||||
|
|
||||||
(defn lookup-local-components
|
(defn lookup-local-components
|
||||||
([state]
|
([state]
|
||||||
(dm/get-in state [:workspace-data :components])))
|
(dm/get-in state [:workspace-data :components])))
|
||||||
|
|
|
@ -182,6 +182,11 @@
|
||||||
[page-id [event [old-data new-data]]]
|
[page-id [event [old-data new-data]]]
|
||||||
(let [changes (:changes event)
|
(let [changes (:changes event)
|
||||||
|
|
||||||
|
lookup-data-objects
|
||||||
|
(fn [data page-id]
|
||||||
|
(dm/get-in data [:pages-index page-id :objects]))
|
||||||
|
|
||||||
|
|
||||||
extract-ids
|
extract-ids
|
||||||
(fn [{:keys [page-id type] :as change}]
|
(fn [{:keys [page-id type] :as change}]
|
||||||
(case type
|
(case type
|
||||||
|
@ -193,8 +198,8 @@
|
||||||
|
|
||||||
get-frame-ids
|
get-frame-ids
|
||||||
(fn get-frame-ids [id]
|
(fn get-frame-ids [id]
|
||||||
(let [old-objects (wsh/lookup-data-objects old-data page-id)
|
(let [old-objects (lookup-data-objects old-data page-id)
|
||||||
new-objects (wsh/lookup-data-objects new-data page-id)
|
new-objects (lookup-data-objects new-data page-id)
|
||||||
|
|
||||||
new-shape (get new-objects id)
|
new-shape (get new-objects id)
|
||||||
old-shape (get old-objects id)
|
old-shape (get old-objects id)
|
||||||
|
|
|
@ -281,6 +281,9 @@
|
||||||
(dm/get-in data [:pages-index page-id])))
|
(dm/get-in data [:pages-index page-id])))
|
||||||
st/state))
|
st/state))
|
||||||
|
|
||||||
|
(def workspace-page-flows
|
||||||
|
(l/derived #(-> % :flows not-empty) workspace-page))
|
||||||
|
|
||||||
(defn workspace-page-objects-by-id
|
(defn workspace-page-objects-by-id
|
||||||
[page-id]
|
[page-id]
|
||||||
(l/derived #(wsh/lookup-page-objects % page-id) st/state =))
|
(l/derived #(wsh/lookup-page-objects % page-id) st/state =))
|
||||||
|
@ -343,9 +346,6 @@
|
||||||
(into [] (keep (d/getf objects)) children-ids)))
|
(into [] (keep (d/getf objects)) children-ids)))
|
||||||
workspace-page-objects =))
|
workspace-page-objects =))
|
||||||
|
|
||||||
(def workspace-page-options
|
|
||||||
(l/derived :options workspace-page))
|
|
||||||
|
|
||||||
(def workspace-frames
|
(def workspace-frames
|
||||||
(l/derived ctt/get-frames workspace-page-objects =))
|
(l/derived ctt/get-frames workspace-page-objects =))
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@
|
||||||
shapes (cfh/get-immediate-children objects)
|
shapes (cfh/get-immediate-children objects)
|
||||||
dim (calculate-dimensions objects aspect-ratio)
|
dim (calculate-dimensions objects aspect-ratio)
|
||||||
vbox (format-viewbox dim)
|
vbox (format-viewbox dim)
|
||||||
bgcolor (dm/get-in data [:options :background] default-color)
|
bgcolor (get data :background default-color)
|
||||||
|
|
||||||
shape-wrapper
|
shape-wrapper
|
||||||
(mf/use-memo
|
(mf/use-memo
|
||||||
|
@ -232,7 +232,7 @@
|
||||||
:fill "none"}
|
:fill "none"}
|
||||||
|
|
||||||
(when include-metadata
|
(when include-metadata
|
||||||
[:& export/export-page {:id (:id data) :options (:options data)}])
|
[:& export/export-page {:page data}])
|
||||||
|
|
||||||
(let [shapes (->> shapes
|
(let [shapes (->> shapes
|
||||||
(remove cfh/frame-shape?)
|
(remove cfh/frame-shape?)
|
||||||
|
|
|
@ -187,14 +187,16 @@
|
||||||
:axis (d/name axis)}])])
|
:axis (d/name axis)}])])
|
||||||
|
|
||||||
(mf/defc export-page
|
(mf/defc export-page
|
||||||
[{:keys [id options]}]
|
{::mf/props :obj}
|
||||||
(let [saved-grids (get options :saved-grids)
|
[{:keys [page]}]
|
||||||
flows (get options :flows)
|
(let [id (get page :id)
|
||||||
guides (get options :guides)]
|
grids (get page :grids)
|
||||||
|
flows (get page :flows)
|
||||||
|
guides (get page :guides)]
|
||||||
[:> "penpot:page" #js {:id id}
|
[:> "penpot:page" #js {:id id}
|
||||||
(when (d/not-empty? saved-grids)
|
(when (d/not-empty? grids)
|
||||||
(let [parse-grid (fn [[type params]] {:type type :params params})
|
(let [parse-grid (fn [[type params]] {:type type :params params})
|
||||||
grids (->> saved-grids (mapv parse-grid))]
|
grids (mapv parse-grid grids)]
|
||||||
[:& export-grid-data {:grids grids}]))
|
[:& export-grid-data {:grids grids}]))
|
||||||
|
|
||||||
(when (d/not-empty? flows)
|
(when (d/not-empty? flows)
|
||||||
|
|
|
@ -139,7 +139,7 @@
|
||||||
:viewport-size)
|
:viewport-size)
|
||||||
|
|
||||||
tpos-ref (mf/with-memo [page-id]
|
tpos-ref (mf/with-memo [page-id]
|
||||||
(-> (l/in [:pages page-id :options :comment-threads-position])
|
(-> (l/in [:pages page-id :comment-thread-positions])
|
||||||
(l/derived refs/viewer-data)))
|
(l/derived refs/viewer-data)))
|
||||||
|
|
||||||
positions (mf/deref tpos-ref)
|
positions (mf/deref tpos-ref)
|
||||||
|
|
|
@ -221,13 +221,14 @@
|
||||||
(mf/defc flows-menu
|
(mf/defc flows-menu
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]}
|
||||||
[{:keys [page index]}]
|
[{:keys [page index]}]
|
||||||
(let [flows (dm/get-in page [:options :flows])
|
(let [flows (:flows page)
|
||||||
frames (:frames page)
|
frames (:frames page)
|
||||||
frame (get frames index)
|
|
||||||
current-flow* (mf/use-state
|
|
||||||
#(ctp/get-frame-flow flows (:id frame)))
|
|
||||||
|
|
||||||
current-flow (deref current-flow*)
|
frame (get frames index)
|
||||||
|
current-flow* (mf/use-state
|
||||||
|
#(ctp/get-frame-flow flows (:id frame)))
|
||||||
|
|
||||||
|
current-flow (deref current-flow*)
|
||||||
|
|
||||||
show-dropdown?* (mf/use-state false)
|
show-dropdown?* (mf/use-state false)
|
||||||
show-dropdown? (deref show-dropdown?*)
|
show-dropdown? (deref show-dropdown?*)
|
||||||
|
|
|
@ -373,26 +373,25 @@
|
||||||
:on-click do-lock-shape}])]))
|
:on-click do-lock-shape}])]))
|
||||||
|
|
||||||
(mf/defc context-menu-prototype
|
(mf/defc context-menu-prototype
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [shapes]}]
|
[{:keys [shapes]}]
|
||||||
(let [options (mf/deref refs/workspace-page-options)
|
(let [flows (mf/deref refs/workspace-page-flows)
|
||||||
options-mode (mf/deref refs/options-mode-global)
|
options-mode (mf/deref refs/options-mode-global)
|
||||||
do-add-flow #(st/emit! (dwi/add-flow-selected-frame))
|
do-add-flow #(st/emit! (dwi/add-flow-selected-frame))
|
||||||
do-remove-flow #(st/emit! (dwi/remove-flow (:id %)))
|
do-remove-flow #(st/emit! (dwi/remove-flow (:id %)))
|
||||||
flows (:flows options)
|
|
||||||
|
|
||||||
prototype? (= options-mode :prototype)
|
prototype? (= options-mode :prototype)
|
||||||
single? (= (count shapes) 1)
|
single? (= (count shapes) 1)
|
||||||
has-frame? (->> shapes (d/seek cfh/frame-shape?))
|
|
||||||
|
has-frame? (d/seek cfh/frame-shape? shapes)
|
||||||
is-frame? (and single? has-frame?)]
|
is-frame? (and single? has-frame?)]
|
||||||
|
|
||||||
(when (and prototype? is-frame?)
|
(when (and prototype? is-frame?)
|
||||||
(let [flow (ctp/get-frame-flow flows (-> shapes first :id))]
|
(if-let [flow (ctp/get-frame-flow flows (-> shapes first :id))]
|
||||||
(if (some? flow)
|
[:& menu-entry {:title (tr "workspace.shape.menu.delete-flow-start")
|
||||||
[:& menu-entry {:title (tr "workspace.shape.menu.delete-flow-start")
|
:on-click (do-remove-flow flow)}]
|
||||||
:on-click (do-remove-flow flow)}]
|
[:& menu-entry {:title (tr "workspace.shape.menu.flow-start")
|
||||||
|
:on-click do-add-flow}]))))
|
||||||
[:& menu-entry {:title (tr "workspace.shape.menu.flow-start")
|
|
||||||
:on-click do-add-flow}])))))
|
|
||||||
|
|
||||||
(mf/defc context-menu-layout
|
(mf/defc context-menu-layout
|
||||||
{::mf/props :obj}
|
{::mf/props :obj}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.geom.grid :as gg]
|
[app.common.geom.grid :as gg]
|
||||||
|
[app.common.types.grid :as ctg]
|
||||||
[app.main.data.workspace.grid :as dw]
|
[app.main.data.workspace.grid :as dw]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
|
@ -22,8 +23,8 @@
|
||||||
[okulary.core :as l]
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def workspace-saved-grids
|
(def lens:default-grids
|
||||||
(l/derived :saved-grids refs/workspace-page-options))
|
(l/derived :default-grids refs/workspace-data))
|
||||||
|
|
||||||
(defn- get-size-options []
|
(defn- get-size-options []
|
||||||
[{:value nil :label (tr "workspace.options.grid.auto")}
|
[{:value nil :label (tr "workspace.options.grid.auto")}
|
||||||
|
@ -297,10 +298,16 @@
|
||||||
has-frame-grids? (or (= :multiple frame-grids) (some? (seq frame-grids)))
|
has-frame-grids? (or (= :multiple frame-grids) (some? (seq frame-grids)))
|
||||||
|
|
||||||
toggle-content (mf/use-fn #(swap! state* not))
|
toggle-content (mf/use-fn #(swap! state* not))
|
||||||
|
|
||||||
id (:id shape)
|
id (:id shape)
|
||||||
saved-grids (mf/deref workspace-saved-grids)
|
default-grids (mf/deref lens:default-grids)
|
||||||
default-grid-params (mf/use-memo (mf/deps saved-grids) #(merge dw/default-grid-params saved-grids))
|
default-grid-params (mf/with-memo [default-grids]
|
||||||
handle-create-grid (mf/use-fn (mf/deps id) #(st/emit! (dw/add-frame-grid id)))]
|
(merge ctg/default-grid-params default-grids))
|
||||||
|
|
||||||
|
handle-create-grid
|
||||||
|
(mf/use-fn
|
||||||
|
(mf/deps id)
|
||||||
|
#(st/emit! (dw/add-frame-grid id)))]
|
||||||
|
|
||||||
[:div {:class (stl/css :element-set)}
|
[:div {:class (stl/css :element-set)}
|
||||||
[:& title-bar {:collapsable has-frame-grids?
|
[:& title-bar {:collapsable has-frame-grids?
|
||||||
|
|
|
@ -154,19 +154,21 @@
|
||||||
i/remove-icon]]))
|
i/remove-icon]]))
|
||||||
|
|
||||||
(mf/defc page-flows
|
(mf/defc page-flows
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [flows]}]
|
[{:keys [flows]}]
|
||||||
(when (seq flows)
|
(when flows
|
||||||
[:div {:class (stl/css :interaction-options)}
|
[:div {:class (stl/css :interaction-options)}
|
||||||
[:& title-bar {:collapsable false
|
[:& title-bar {:collapsable false
|
||||||
:title (tr "workspace.options.flows.flow-starts")
|
:title (tr "workspace.options.flows.flow-starts")
|
||||||
:class (stl/css :title-spacing-layout-flow)}]
|
:class (stl/css :title-spacing-layout-flow)}]
|
||||||
(for [flow flows]
|
(for [[id flow] flows]
|
||||||
[:& flow-item {:flow flow :key (str (:id flow))}])]))
|
[:& flow-item {:flow flow :key (dm/str id)}])]))
|
||||||
|
|
||||||
(mf/defc shape-flows
|
(mf/defc shape-flows
|
||||||
|
{::mf/props :obj}
|
||||||
[{:keys [flows shape]}]
|
[{:keys [flows shape]}]
|
||||||
(when (= (:type shape) :frame)
|
(when (cfh/frame-shape? shape)
|
||||||
(let [flow (ctp/get-frame-flow flows (:id shape))
|
(let [flow (ctp/get-frame-flow flows (:id shape))
|
||||||
add-flow (mf/use-fn #(st/emit! (dwi/add-flow-selected-frame)))]
|
add-flow (mf/use-fn #(st/emit! (dwi/add-flow-selected-frame)))]
|
||||||
|
|
||||||
[:div {:class (stl/css :element-set)}
|
[:div {:class (stl/css :element-set)}
|
||||||
|
@ -179,8 +181,8 @@
|
||||||
:on-click add-flow}
|
:on-click add-flow}
|
||||||
i/add])]
|
i/add])]
|
||||||
|
|
||||||
(when flow
|
(when (some? flow)
|
||||||
[:& flow-item {:flow flow :key (str (:id flow))}])])))
|
[:& flow-item {:flow flow :key (dm/str (:id flow))}])])))
|
||||||
|
|
||||||
(def ^:private corner-center-icon
|
(def ^:private corner-center-icon
|
||||||
(i/icon-xref :corner-center (stl/css :corner-icon)))
|
(i/icon-xref :corner-center (stl/css :corner-icon)))
|
||||||
|
@ -695,11 +697,12 @@
|
||||||
:on-change change-offset-effect}]]]])])])]))
|
:on-change change-offset-effect}]]]])])])]))
|
||||||
|
|
||||||
(mf/defc interactions-menu
|
(mf/defc interactions-menu
|
||||||
[{:keys [shape] :as props}]
|
{::mf/props :obj}
|
||||||
(let [interactions (get shape :interactions [])
|
[{:keys [shape]}]
|
||||||
|
(let [interactions
|
||||||
|
(get shape :interactions [])
|
||||||
|
|
||||||
options (mf/deref refs/workspace-page-options)
|
flows (mf/deref refs/workspace-page-flows)
|
||||||
flows (:flows options)
|
|
||||||
|
|
||||||
add-interaction
|
add-interaction
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
(:require-macros [app.main.style :as stl])
|
(:require-macros [app.main.style :as stl])
|
||||||
(:require
|
(:require
|
||||||
[app.common.colors :as clr]
|
[app.common.colors :as clr]
|
||||||
|
[app.common.data :as d]
|
||||||
[app.main.data.workspace :as dw]
|
[app.main.data.workspace :as dw]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.refs :as refs]
|
[app.main.refs :as refs]
|
||||||
|
@ -16,16 +17,21 @@
|
||||||
[app.main.ui.components.title-bar :refer [title-bar]]
|
[app.main.ui.components.title-bar :refer [title-bar]]
|
||||||
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
[app.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]
|
||||||
[app.util.i18n :as i18n :refer [tr]]
|
[app.util.i18n :as i18n :refer [tr]]
|
||||||
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
|
(def lens:background-color
|
||||||
|
(-> (l/key :background)
|
||||||
|
(l/derived refs/workspace-page)))
|
||||||
|
|
||||||
(mf/defc options
|
(mf/defc options
|
||||||
{::mf/wrap [mf/memo]
|
{::mf/wrap [mf/memo]
|
||||||
::mf/wrap-props false}
|
::mf/wrap-props false}
|
||||||
[]
|
[]
|
||||||
(let [options (mf/deref refs/workspace-page-options)
|
(let [background (mf/deref lens:background-color)
|
||||||
on-change (mf/use-fn #(st/emit! (dw/change-canvas-color %)))
|
on-change (mf/use-fn #(st/emit! (dw/change-canvas-color %)))
|
||||||
on-open (mf/use-fn #(st/emit! (dwu/start-undo-transaction :options)))
|
on-open (mf/use-fn #(st/emit! (dwu/start-undo-transaction :options)))
|
||||||
on-close (mf/use-fn #(st/emit! (dwu/commit-undo-transaction :options)))]
|
on-close (mf/use-fn #(st/emit! (dwu/commit-undo-transaction :options)))]
|
||||||
[:div {:class (stl/css :element-set)}
|
[:div {:class (stl/css :element-set)}
|
||||||
[:div {:class (stl/css :element-title)}
|
[:div {:class (stl/css :element-title)}
|
||||||
[:& title-bar {:collapsable false
|
[:& title-bar {:collapsable false
|
||||||
|
@ -37,7 +43,7 @@
|
||||||
:disable-opacity true
|
:disable-opacity true
|
||||||
:disable-image true
|
:disable-image true
|
||||||
:title (tr "workspace.options.canvas-background")
|
:title (tr "workspace.options.canvas-background")
|
||||||
:color {:color (get options :background clr/canvas)
|
:color {:color (d/nilv background clr/canvas)
|
||||||
:opacity 1}
|
:opacity 1}
|
||||||
:on-change on-change
|
:on-change on-change
|
||||||
:on-open on-open
|
:on-open on-open
|
||||||
|
|
|
@ -92,28 +92,24 @@
|
||||||
|
|
||||||
vbox' (mf/use-debounce 100 vbox)
|
vbox' (mf/use-debounce 100 vbox)
|
||||||
|
|
||||||
;; CONTEXT
|
|
||||||
page-id (mf/use-ctx ctx/current-page-id)
|
|
||||||
|
|
||||||
;; DEREFS
|
;; DEREFS
|
||||||
drawing (mf/deref refs/workspace-drawing)
|
drawing (mf/deref refs/workspace-drawing)
|
||||||
options (mf/deref refs/workspace-page-options)
|
|
||||||
focus (mf/deref refs/workspace-focus-selected)
|
focus (mf/deref refs/workspace-focus-selected)
|
||||||
|
|
||||||
objects-ref (mf/use-memo #(refs/workspace-page-objects-by-id page-id))
|
page (mf/deref refs/workspace-page)
|
||||||
objects (mf/deref objects-ref)
|
objects (get page :objects)
|
||||||
base-objects (-> objects (ui-hooks/with-focus-objects focus))
|
page-id (get page :id)
|
||||||
|
background (get page :background clr/canvas)
|
||||||
|
|
||||||
|
base-objects (ui-hooks/with-focus-objects objects focus)
|
||||||
|
|
||||||
modifiers (mf/deref refs/workspace-modifiers)
|
modifiers (mf/deref refs/workspace-modifiers)
|
||||||
text-modifiers (mf/deref refs/workspace-text-modifier)
|
text-modifiers (mf/deref refs/workspace-text-modifier)
|
||||||
|
|
||||||
objects-modified (mf/with-memo
|
objects-modified (mf/with-memo [base-objects text-modifiers modifiers]
|
||||||
[base-objects text-modifiers modifiers]
|
|
||||||
(apply-modifiers-to-selected selected base-objects text-modifiers modifiers))
|
(apply-modifiers-to-selected selected base-objects text-modifiers modifiers))
|
||||||
|
|
||||||
selected-shapes (->> selected (keep (d/getf objects-modified)))
|
selected-shapes (keep (d/getf objects-modified) selected)
|
||||||
|
|
||||||
background (get options :background clr/canvas)
|
|
||||||
|
|
||||||
;; STATE
|
;; STATE
|
||||||
alt? (mf/use-state false)
|
alt? (mf/use-state false)
|
||||||
|
@ -305,7 +301,6 @@
|
||||||
(when picking-color?
|
(when picking-color?
|
||||||
[:& pixel-overlay/pixel-overlay {:vport vport
|
[:& pixel-overlay/pixel-overlay {:vport vport
|
||||||
:vbox vbox
|
:vbox vbox
|
||||||
:options options
|
|
||||||
:layout layout
|
:layout layout
|
||||||
:viewport-ref viewport-ref}])]
|
:viewport-ref viewport-ref}])]
|
||||||
|
|
||||||
|
@ -338,7 +333,7 @@
|
||||||
[:stop {:offset "100%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]]]
|
[:stop {:offset "100%" :stop-color (str "color-mix(in srgb-linear, " background " 90%, #777)") :stop-opacity 1}]]]
|
||||||
|
|
||||||
(when (dbg/enabled? :show-export-metadata)
|
(when (dbg/enabled? :show-export-metadata)
|
||||||
[:& use/export-page {:options options}])
|
[:& use/export-page {:page page}])
|
||||||
|
|
||||||
;; We need a "real" background shape so layer transforms work properly in firefox
|
;; We need a "real" background shape so layer transforms work properly in firefox
|
||||||
[:rect {:width (:width vbox 0)
|
[:rect {:width (:width vbox 0)
|
||||||
|
@ -486,7 +481,7 @@
|
||||||
|
|
||||||
(when show-prototypes?
|
(when show-prototypes?
|
||||||
[:& widgets/frame-flows
|
[:& widgets/frame-flows
|
||||||
{:flows (:flows options)
|
{:flows (:flows page)
|
||||||
:objects objects-modified
|
:objects objects-modified
|
||||||
:selected selected
|
:selected selected
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
|
@ -556,11 +551,11 @@
|
||||||
:show-rulers? show-rulers?}])
|
:show-rulers? show-rulers?}])
|
||||||
|
|
||||||
(when (and show-rulers? show-grids?)
|
(when (and show-rulers? show-grids?)
|
||||||
[:& guides/viewport-guides
|
[:> guides/viewport-guides*
|
||||||
{:zoom zoom
|
{:zoom zoom
|
||||||
:vbox vbox
|
:vbox vbox
|
||||||
:hover-frame guide-frame
|
:hover-frame guide-frame
|
||||||
:disabled-guides? disabled-guides?
|
:disabled-guides disabled-guides?
|
||||||
:modifiers modifiers}])
|
:modifiers modifiers}])
|
||||||
|
|
||||||
;; DEBUG LAYOUT DROP-ZONES
|
;; DEBUG LAYOUT DROP-ZONES
|
||||||
|
|
|
@ -41,7 +41,8 @@
|
||||||
|
|
||||||
positions-ref
|
positions-ref
|
||||||
(mf/with-memo [page-id]
|
(mf/with-memo [page-id]
|
||||||
(-> (l/in [:workspace-data :pages-index page-id :options :comment-threads-position])
|
;; FIXME: use lookup helpers here
|
||||||
|
(-> (l/in [:workspace-data :pages-index page-id :comment-thread-positions])
|
||||||
(l/derived st/state)))
|
(l/derived st/state)))
|
||||||
|
|
||||||
positions (mf/deref positions-ref)
|
positions (mf/deref positions-ref)
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
(ns app.main.ui.workspace.viewport.guides
|
(ns app.main.ui.workspace.viewport.guides
|
||||||
(:require
|
(:require
|
||||||
[app.common.colors :as colors]
|
[app.common.colors :as colors]
|
||||||
|
[app.common.data.macros :as dm]
|
||||||
[app.common.files.helpers :as cfh]
|
[app.common.files.helpers :as cfh]
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
[app.main.ui.formats :as fmt]
|
[app.main.ui.formats :as fmt]
|
||||||
[app.main.ui.workspace.viewport.rulers :as rulers]
|
[app.main.ui.workspace.viewport.rulers :as rulers]
|
||||||
[app.util.dom :as dom]
|
[app.util.dom :as dom]
|
||||||
|
[okulary.core :as l]
|
||||||
[rumext.v2 :as mf]))
|
[rumext.v2 :as mf]))
|
||||||
|
|
||||||
(def guide-width 1)
|
(def guide-width 1)
|
||||||
|
@ -256,14 +258,15 @@
|
||||||
(and (>= (:position guide) (:y frame))
|
(and (>= (:position guide) (:y frame))
|
||||||
(<= (:position guide) (+ (:y frame) (:height frame))))))
|
(<= (:position guide) (+ (:y frame) (:height frame))))))
|
||||||
|
|
||||||
(mf/defc guide
|
(mf/defc guide*
|
||||||
{::mf/wrap [mf/memo]}
|
{::mf/wrap [mf/memo]
|
||||||
[{:keys [guide hover? on-guide-change get-hover-frame vbox zoom hover-frame disabled-guides? frame-modifier]}]
|
::mf/props :obj}
|
||||||
|
[{:keys [guide is-hover on-guide-change get-hover-frame vbox zoom hover-frame disabled-guides frame-modifier]}]
|
||||||
|
|
||||||
(let [axis (:axis guide)
|
(let [axis (:axis guide)
|
||||||
|
|
||||||
handle-change-position
|
handle-change-position
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps on-guide-change)
|
(mf/deps on-guide-change)
|
||||||
(fn [changes]
|
(fn [changes]
|
||||||
(when on-guide-change
|
(when on-guide-change
|
||||||
|
@ -296,7 +299,7 @@
|
||||||
(and (cfh/root-frame? frame)
|
(and (cfh/root-frame? frame)
|
||||||
(not (ctst/rotated-frame? frame))))
|
(not (ctst/rotated-frame? frame))))
|
||||||
[:g.guide-area {:opacity (when frame-guide-outside? 0)}
|
[:g.guide-area {:opacity (when frame-guide-outside? 0)}
|
||||||
(when-not disabled-guides?
|
(when-not disabled-guides
|
||||||
(let [{:keys [x y width height]} (guide-area-axis pos vbox zoom frame axis)]
|
(let [{:keys [x y width height]} (guide-area-axis pos vbox zoom frame axis)]
|
||||||
[:rect {:x x
|
[:rect {:x x
|
||||||
:y y
|
:y y
|
||||||
|
@ -318,7 +321,7 @@
|
||||||
l3-x1 l3-y1 l3-x2 l3-y2]}
|
l3-x1 l3-y1 l3-x2 l3-y2]}
|
||||||
(guide-line-axis pos vbox frame axis)]
|
(guide-line-axis pos vbox frame axis)]
|
||||||
[:g
|
[:g
|
||||||
(when (or hover? (:hover @state))
|
(when (or is-hover (:hover @state))
|
||||||
[:line {:x1 l1-x1
|
[:line {:x1 l1-x1
|
||||||
:y1 l1-y1
|
:y1 l1-y1
|
||||||
:x2 l1-x2
|
:x2 l1-x2
|
||||||
|
@ -334,10 +337,10 @@
|
||||||
:y2 l2-y2
|
:y2 l2-y2
|
||||||
:style {:stroke guide-color
|
:style {:stroke guide-color
|
||||||
:stroke-width guide-width
|
:stroke-width guide-width
|
||||||
:stroke-opacity (if (or hover? (:hover @state))
|
:stroke-opacity (if (or is-hover (:hover @state))
|
||||||
guide-opacity-hover
|
guide-opacity-hover
|
||||||
guide-opacity)}}]
|
guide-opacity)}}]
|
||||||
(when (or hover? (:hover @state))
|
(when (or is-hover (:hover @state))
|
||||||
[:line {:x1 l3-x1
|
[:line {:x1 l3-x1
|
||||||
:y1 l3-y1
|
:y1 l3-y1
|
||||||
:x2 l3-x2
|
:x2 l3-x2
|
||||||
|
@ -355,11 +358,11 @@
|
||||||
:y2 y2
|
:y2 y2
|
||||||
:style {:stroke guide-color
|
:style {:stroke guide-color
|
||||||
:stroke-width guide-width
|
:stroke-width guide-width
|
||||||
:stroke-opacity (if (or hover? (:hover @state))
|
:stroke-opacity (if (or is-hover (:hover @state))
|
||||||
guide-opacity-hover
|
guide-opacity-hover
|
||||||
guide-opacity)}}]))
|
guide-opacity)}}]))
|
||||||
|
|
||||||
(when (or hover? (:hover @state))
|
(when (or is-hover (:hover @state))
|
||||||
(let [{:keys [rect-x rect-y rect-width rect-height text-x text-y]}
|
(let [{:keys [rect-x rect-y rect-width rect-height text-x text-y]}
|
||||||
(guide-pill-axis pos vbox zoom axis)]
|
(guide-pill-axis pos vbox zoom axis)]
|
||||||
[:g.guide-pill
|
[:g.guide-pill
|
||||||
|
@ -382,16 +385,17 @@
|
||||||
;; If the guide is associated to a frame we show the position relative to the frame
|
;; If the guide is associated to a frame we show the position relative to the frame
|
||||||
(fmt/format-number (- pos (if (= axis :x) (:x frame) (:y frame))))]]))])))
|
(fmt/format-number (- pos (if (= axis :x) (:x frame) (:y frame))))]]))])))
|
||||||
|
|
||||||
(mf/defc new-guide-area
|
(mf/defc new-guide-area*
|
||||||
[{:keys [vbox zoom axis get-hover-frame disabled-guides?]}]
|
{::mf/props :obj}
|
||||||
|
[{:keys [vbox zoom axis get-hover-frame disabled-guides]}]
|
||||||
|
|
||||||
(let [on-guide-change
|
(let [on-guide-change
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps vbox)
|
(mf/deps vbox)
|
||||||
(fn [guide]
|
(fn [guide]
|
||||||
(let [guide (-> guide
|
(let [guide (-> guide
|
||||||
(assoc :id (uuid/next)
|
(assoc :id (uuid/next))
|
||||||
:axis axis))]
|
(assoc :axis axis))]
|
||||||
(when (guide-inside-vbox? zoom vbox guide)
|
(when (guide-inside-vbox? zoom vbox guide)
|
||||||
(st/emit! (dw/update-guides guide))))))
|
(st/emit! (dw/update-guides guide))))))
|
||||||
|
|
||||||
|
@ -402,10 +406,11 @@
|
||||||
on-lost-pointer-capture
|
on-lost-pointer-capture
|
||||||
on-pointer-move
|
on-pointer-move
|
||||||
state
|
state
|
||||||
frame]} (use-guide on-guide-change get-hover-frame zoom {:axis axis})]
|
frame]}
|
||||||
|
(use-guide on-guide-change get-hover-frame zoom {:axis axis})]
|
||||||
|
|
||||||
[:g.new-guides
|
[:g.new-guides
|
||||||
(when-not disabled-guides?
|
(when-not disabled-guides
|
||||||
(let [{:keys [x y width height]} (guide-creation-area vbox zoom axis)]
|
(let [{:keys [x y width height]} (guide-creation-area vbox zoom axis)]
|
||||||
[:rect {:x x
|
[:rect {:x x
|
||||||
:y y
|
:y y
|
||||||
|
@ -422,25 +427,25 @@
|
||||||
:pointer-events "fill"}}]))
|
:pointer-events "fill"}}]))
|
||||||
|
|
||||||
(when (:new-position @state)
|
(when (:new-position @state)
|
||||||
[:& guide {:guide {:axis axis
|
[:& guide* {:guide {:axis axis :position (:new-position @state)}
|
||||||
:position (:new-position @state)}
|
:get-hover-frame get-hover-frame
|
||||||
:get-hover-frame get-hover-frame
|
:vbox vbox
|
||||||
:vbox vbox
|
:zoom zoom
|
||||||
:zoom zoom
|
:is-hover true
|
||||||
:hover? true
|
:hover-frame frame}])]))
|
||||||
:hover-frame frame}])]))
|
|
||||||
|
|
||||||
(mf/defc viewport-guides
|
(def ^:private lens:workspace-guides
|
||||||
{::mf/wrap [mf/memo]}
|
(-> (l/key :guides)
|
||||||
[{:keys [zoom vbox hover-frame disabled-guides? modifiers]}]
|
(l/derived refs/workspace-page)))
|
||||||
|
|
||||||
(let [page (mf/deref refs/workspace-page)
|
(mf/defc viewport-guides*
|
||||||
|
{::mf/wrap [mf/memo]
|
||||||
guides (mf/use-memo
|
::mf/props :obj}
|
||||||
(mf/deps page vbox)
|
[{:keys [zoom vbox hover-frame disabled-guides modifiers]}]
|
||||||
#(->> (get-in page [:options :guides] {})
|
(let [guides (mf/deref lens:workspace-guides)
|
||||||
(vals)
|
guides (mf/with-memo [guides vbox]
|
||||||
(filter (guide-inside-vbox? zoom vbox))))
|
(->> (vals guides)
|
||||||
|
(filter (partial guide-inside-vbox? zoom vbox))))
|
||||||
|
|
||||||
focus (mf/deref refs/workspace-focus-selected)
|
focus (mf/deref refs/workspace-focus-selected)
|
||||||
|
|
||||||
|
@ -449,46 +454,42 @@
|
||||||
;; We use the ref to not redraw every guide everytime the hovering frame change
|
;; We use the ref to not redraw every guide everytime the hovering frame change
|
||||||
;; we're only interested to get the frame in the guide we're moving
|
;; we're only interested to get the frame in the guide we're moving
|
||||||
get-hover-frame
|
get-hover-frame
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(fn []
|
#(mf/ref-val hover-frame-ref))
|
||||||
(mf/ref-val hover-frame-ref)))
|
|
||||||
|
|
||||||
on-guide-change
|
on-guide-change
|
||||||
(mf/use-callback
|
(mf/use-fn
|
||||||
(mf/deps vbox)
|
(mf/deps vbox)
|
||||||
(fn [guide]
|
(fn [guide]
|
||||||
(if (guide-inside-vbox? zoom vbox guide)
|
(if (guide-inside-vbox? zoom vbox guide)
|
||||||
(st/emit! (dw/update-guides guide))
|
(st/emit! (dw/update-guides guide))
|
||||||
(st/emit! (dw/remove-guide guide)))))]
|
(st/emit! (dw/remove-guide guide)))))]
|
||||||
|
|
||||||
(mf/use-effect
|
(mf/with-effect [hover-frame]
|
||||||
(mf/deps hover-frame)
|
(mf/set-ref-val! hover-frame-ref hover-frame))
|
||||||
(fn []
|
|
||||||
(mf/set-ref-val! hover-frame-ref hover-frame)))
|
|
||||||
|
|
||||||
[:g.guides {:pointer-events "none"}
|
[:g.guides {:pointer-events "none"}
|
||||||
[:& new-guide-area {:vbox vbox
|
[:> new-guide-area* {:vbox vbox
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:axis :x
|
:axis :x
|
||||||
:get-hover-frame get-hover-frame
|
:get-hover-frame get-hover-frame
|
||||||
:disabled-guides? disabled-guides?}]
|
:disabled-guides disabled-guides}]
|
||||||
|
|
||||||
[:& new-guide-area {:vbox vbox
|
[:> new-guide-area* {:vbox vbox
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:axis :y
|
:axis :y
|
||||||
:get-hover-frame get-hover-frame
|
:get-hover-frame get-hover-frame
|
||||||
:disabled-guides? disabled-guides?}]
|
:disabled-guides disabled-guides}]
|
||||||
|
|
||||||
(for [current guides]
|
(for [current guides]
|
||||||
(when (or (nil? (:frame-id current))
|
(when (or (nil? (:frame-id current))
|
||||||
(empty? focus)
|
(empty? focus)
|
||||||
(contains? focus (:frame-id current)))
|
(contains? focus (:frame-id current)))
|
||||||
[:& guide {:key (str "guide-" (:id current))
|
[:> guide* {:key (dm/str "guide-" (:id current))
|
||||||
:guide current
|
:guide current
|
||||||
:vbox vbox
|
:vbox vbox
|
||||||
:zoom zoom
|
:zoom zoom
|
||||||
:frame-modifier (get-in modifiers [(:frame-id current) :modifiers])
|
:frame-modifier (dm/get-in modifiers [(:frame-id current) :modifiers])
|
||||||
:get-hover-frame get-hover-frame
|
:get-hover-frame get-hover-frame
|
||||||
:on-guide-change on-guide-change
|
:on-guide-change on-guide-change
|
||||||
:disabled-guides? disabled-guides?}]))]))
|
:disabled-guides disabled-guides}]))]))
|
||||||
|
|
||||||
|
|
|
@ -53,10 +53,10 @@
|
||||||
(mf/defc pixel-overlay
|
(mf/defc pixel-overlay
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [vport (unchecked-get props "vport")
|
(let [vport (unchecked-get props "vport")
|
||||||
|
|
||||||
viewport-ref (unchecked-get props "viewport-ref")
|
viewport-ref (unchecked-get props "viewport-ref")
|
||||||
viewport-node (mf/ref-val viewport-ref)
|
viewport-node (mf/ref-val viewport-ref)
|
||||||
|
|
||||||
canvas (get-offscreen-canvas (:width vport) (:height vport))
|
canvas (get-offscreen-canvas (:width vport) (:height vport))
|
||||||
canvas-context (.getContext canvas "2d" #js {:willReadFrequently true})
|
canvas-context (.getContext canvas "2d" #js {:willReadFrequently true})
|
||||||
|
|
|
@ -282,6 +282,7 @@
|
||||||
on-frame-leave (unchecked-get props "on-frame-leave")
|
on-frame-leave (unchecked-get props "on-frame-leave")
|
||||||
on-frame-select (unchecked-get props "on-frame-select")]
|
on-frame-select (unchecked-get props "on-frame-select")]
|
||||||
[:g.frame-flows
|
[:g.frame-flows
|
||||||
|
;; FIXME: enumerate is not necessary here
|
||||||
(for [[index flow] (d/enumerate flows)]
|
(for [[index flow] (d/enumerate flows)]
|
||||||
(let [frame (get objects (:starting-frame flow))]
|
(let [frame (get objects (:starting-frame flow))]
|
||||||
[:& frame-flow {:key (dm/str (:id frame) "-" index)
|
[:& frame-flow {:key (dm/str (:id frame) "-" index)
|
||||||
|
|
|
@ -126,7 +126,7 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [page (u/proxy->page self)]
|
(let [page (u/proxy->page self)]
|
||||||
(dm/get-in page [:options :plugin-data (keyword "plugin" (str $plugin)) key]))))
|
(dm/get-in page [:plugin-data (keyword "plugin" (str $plugin)) key]))))
|
||||||
|
|
||||||
(setPluginData
|
(setPluginData
|
||||||
[_ key value]
|
[_ key value]
|
||||||
|
@ -146,7 +146,7 @@
|
||||||
(getPluginDataKeys
|
(getPluginDataKeys
|
||||||
[self]
|
[self]
|
||||||
(let [page (u/proxy->page self)]
|
(let [page (u/proxy->page self)]
|
||||||
(apply array (keys (dm/get-in page [:options :plugin-data (keyword "plugin" (str $plugin))])))))
|
(apply array (keys (dm/get-in page [:plugin-data (keyword "plugin" (str $plugin))])))))
|
||||||
|
|
||||||
(getSharedPluginData
|
(getSharedPluginData
|
||||||
[self namespace key]
|
[self namespace key]
|
||||||
|
@ -159,7 +159,7 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [page (u/proxy->page self)]
|
(let [page (u/proxy->page self)]
|
||||||
(dm/get-in page [:options :plugin-data (keyword "shared" namespace) key]))))
|
(dm/get-in page [:plugin-data (keyword "shared" namespace) key]))))
|
||||||
|
|
||||||
(setSharedPluginData
|
(setSharedPluginData
|
||||||
[_ namespace key value]
|
[_ namespace key value]
|
||||||
|
@ -188,7 +188,7 @@
|
||||||
|
|
||||||
:else
|
:else
|
||||||
(let [page (u/proxy->page self)]
|
(let [page (u/proxy->page self)]
|
||||||
(apply array (keys (dm/get-in page [:options :plugin-data (keyword "shared" namespace)]))))))
|
(apply array (keys (dm/get-in page [:plugin-data (keyword "shared" namespace)]))))))
|
||||||
|
|
||||||
(openPage
|
(openPage
|
||||||
[_]
|
[_]
|
||||||
|
@ -385,7 +385,7 @@
|
||||||
|
|
||||||
{:name "background"
|
{:name "background"
|
||||||
:enumerable false
|
:enumerable false
|
||||||
:get #(or (-> % u/proxy->page :options :background) cc/canvas)
|
:get #(or (-> % u/proxy->page :background) cc/canvas)
|
||||||
:set
|
:set
|
||||||
(fn [_ value]
|
(fn [_ value]
|
||||||
(cond
|
(cond
|
||||||
|
@ -401,13 +401,13 @@
|
||||||
{:name "flows"
|
{:name "flows"
|
||||||
:get
|
:get
|
||||||
(fn [self]
|
(fn [self]
|
||||||
(let [flows (d/nilv (-> (u/proxy->page self) :options :flows) [])]
|
(let [flows (d/nilv (-> (u/proxy->page self) :flows) [])]
|
||||||
(format/format-array #(flow-proxy plugin-id file-id id (:id %)) flows)))}
|
(format/format-array #(flow-proxy plugin-id file-id id (:id %)) flows)))}
|
||||||
|
|
||||||
{:name "rulerGuides"
|
{:name "rulerGuides"
|
||||||
:get
|
:get
|
||||||
(fn [self]
|
(fn [self]
|
||||||
(let [guides (-> (u/proxy->page self) :options :guides)]
|
(let [guides (-> (u/proxy->page self) :guides)]
|
||||||
(->> guides
|
(->> guides
|
||||||
(vals)
|
(vals)
|
||||||
(filter #(nil? (:frame-id %)))
|
(filter #(nil? (:frame-id %)))
|
||||||
|
|
|
@ -120,7 +120,7 @@
|
||||||
flow-id (obj/get proxy "$id")
|
flow-id (obj/get proxy "$id")
|
||||||
page (locate-page file-id page-id)]
|
page (locate-page file-id page-id)]
|
||||||
(when (some? page)
|
(when (some? page)
|
||||||
(d/seek #(= (:id %) flow-id) (-> page :options :flows)))))
|
(d/seek #(= (:id %) flow-id) (:flows page)))))
|
||||||
|
|
||||||
(defn proxy->ruler-guide
|
(defn proxy->ruler-guide
|
||||||
[proxy]
|
[proxy]
|
||||||
|
|
|
@ -211,11 +211,11 @@
|
||||||
|
|
||||||
(defn add-page
|
(defn add-page
|
||||||
"Adds page information"
|
"Adds page information"
|
||||||
[snap-data {:keys [objects options] :as page}]
|
[snap-data {:keys [objects guides] :as page}]
|
||||||
(let [frames (ctst/get-frames objects)
|
(let [frames (ctst/get-frames objects)
|
||||||
shapes (->> (vals (:objects page))
|
shapes (->> (vals (:objects page))
|
||||||
(remove cfh/frame-shape?))
|
(remove cfh/frame-shape?))
|
||||||
guides (vals (:guides options))
|
guides (vals guides)
|
||||||
|
|
||||||
page-data
|
page-data
|
||||||
(as-> {} $
|
(as-> {} $
|
||||||
|
|
|
@ -452,22 +452,28 @@
|
||||||
|
|
||||||
(defn import-page
|
(defn import-page
|
||||||
[context file [page-id page-name content]]
|
[context file [page-id page-name content]]
|
||||||
(let [nodes (->> content parser/node-seq)
|
(let [nodes (parser/node-seq content)
|
||||||
file-id (:id file)
|
file-id (:id file)
|
||||||
resolve (:resolve context)
|
resolve (:resolve context)
|
||||||
page-data (-> (parser/parse-page-data content)
|
page-data (-> (parser/parse-page-data content)
|
||||||
(assoc :name page-name)
|
(assoc :name page-name)
|
||||||
(assoc :id (resolve page-id)))
|
(assoc :id (resolve page-id)))
|
||||||
flows (->> (get-in page-data [:options :flows])
|
flows (->> (get page-data :flows)
|
||||||
(mapv #(update % :starting-frame resolve)))
|
(update-vals #(update % :starting-frame resolve))
|
||||||
|
(not-empty))
|
||||||
|
|
||||||
guides (-> (get-in page-data [:options :guides])
|
guides (-> (get page-data :guides)
|
||||||
(update-vals #(update % :frame-id resolve)))
|
(update-vals #(update % :frame-id resolve))
|
||||||
|
(not-empty))
|
||||||
|
|
||||||
page-data (-> page-data
|
page-data (cond-> page-data
|
||||||
(d/assoc-in-when [:options :flows] flows)
|
flows
|
||||||
(d/assoc-in-when [:options :guides] guides))
|
(assoc :flows flows)
|
||||||
file (-> file (fb/add-page page-data))
|
|
||||||
|
guides
|
||||||
|
(assoc :guides guides))
|
||||||
|
|
||||||
|
file (fb/add-page file page-data)
|
||||||
|
|
||||||
;; Preprocess nodes to parallel upload the images. Store the result in a table
|
;; Preprocess nodes to parallel upload the images. Store the result in a table
|
||||||
;; old-node => node with image
|
;; old-node => node with image
|
||||||
|
|
|
@ -1136,16 +1136,16 @@
|
||||||
guides (parse-guides node)]
|
guides (parse-guides node)]
|
||||||
(cond-> {}
|
(cond-> {}
|
||||||
(some? background)
|
(some? background)
|
||||||
(assoc-in [:options :background] background)
|
(assoc :background background)
|
||||||
|
|
||||||
(d/not-empty? grids)
|
(d/not-empty? grids)
|
||||||
(assoc-in [:options :saved-grids] grids)
|
(assoc :default-grids grids)
|
||||||
|
|
||||||
(d/not-empty? flows)
|
(d/not-empty? flows)
|
||||||
(assoc-in [:options :flows] flows)
|
(assoc :flows flows)
|
||||||
|
|
||||||
(d/not-empty? guides)
|
(d/not-empty? guides)
|
||||||
(assoc-in [:options :guides] guides))))
|
(assoc :guides guides))))
|
||||||
|
|
||||||
(defn parse-interactions
|
(defn parse-interactions
|
||||||
[node]
|
[node]
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
(ns app.worker.thumbnails
|
(ns app.worker.thumbnails
|
||||||
(:require
|
(:require
|
||||||
["react-dom/server" :as rds]
|
["react-dom/server" :as rds]
|
||||||
[app.common.data.macros :as dm]
|
|
||||||
[app.common.logging :as log]
|
[app.common.logging :as log]
|
||||||
[app.common.uri :as u]
|
[app.common.uri :as u]
|
||||||
[app.config :as cf]
|
[app.config :as cf]
|
||||||
|
@ -63,7 +62,7 @@
|
||||||
(binding [fonts/loaded-hints (l/atom #{})]
|
(binding [fonts/loaded-hints (l/atom #{})]
|
||||||
(let [objects (:objects page)
|
(let [objects (:objects page)
|
||||||
frame (some->> page :thumbnail-frame-id (get objects))
|
frame (some->> page :thumbnail-frame-id (get objects))
|
||||||
background-color (dm/get-in page [:options :background])
|
background-color (:background page)
|
||||||
element (if frame
|
element (if frame
|
||||||
(mf/element render/frame-svg #js
|
(mf/element render/frame-svg #js
|
||||||
{:objects objects
|
{:objects objects
|
||||||
|
|
|
@ -46,7 +46,6 @@
|
||||||
page' (cthf/current-page file')
|
page' (cthf/current-page file')
|
||||||
|
|
||||||
guide' (-> page'
|
guide' (-> page'
|
||||||
:options
|
|
||||||
:guides
|
:guides
|
||||||
(vals)
|
(vals)
|
||||||
(first))]
|
(first))]
|
||||||
|
|
|
@ -391,9 +391,9 @@
|
||||||
|
|
||||||
(t/testing "Update global guide"
|
(t/testing "Update global guide"
|
||||||
(let [guide {:position 50 :axis :x}
|
(let [guide {:position 50 :axis :x}
|
||||||
file (-> (fb/create-file "Test")
|
file (-> (fb/create-file "Test")
|
||||||
(fb/add-page {:name "Page 1"})
|
(fb/add-page {:name "Page 1"})
|
||||||
(fb/add-guide guide))
|
(fb/add-guide guide))
|
||||||
|
|
||||||
guide-id (:last-id file)
|
guide-id (:last-id file)
|
||||||
guide (assoc guide :id guide-id)
|
guide (assoc guide :id guide-id)
|
||||||
|
@ -403,7 +403,7 @@
|
||||||
|
|
||||||
frame-id (:last-id file)
|
frame-id (:last-id file)
|
||||||
page (fb/get-current-page file)
|
page (fb/get-current-page file)
|
||||||
data (-> (sd/make-snap-data) (sd/add-page page))
|
data (-> (sd/make-snap-data) (sd/add-page page))
|
||||||
|
|
||||||
new-page (-> (fb/update-guide file (assoc guide :position 150))
|
new-page (-> (fb/update-guide file (assoc guide :position 150))
|
||||||
(fb/get-current-page))
|
(fb/get-current-page))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue