0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-02-23 23:35:58 -05:00

♻️ Refactor workspace layout initialization and persistence

This commit is contained in:
Andrey Antukh 2022-03-07 23:23:10 +01:00 committed by Andrés Moya
parent 965148f3a6
commit 19f4faa03f
4 changed files with 229 additions and 144 deletions

View file

@ -34,6 +34,7 @@
[app.main.data.workspace.guides :as dwgu]
[app.main.data.workspace.interactions :as dwi]
[app.main.data.workspace.layers :as dwly]
[app.main.data.workspace.layout :as layout]
[app.main.data.workspace.libraries :as dwl]
[app.main.data.workspace.notifications :as dwn]
[app.main.data.workspace.path :as dwdp]
@ -53,12 +54,10 @@
[app.util.http :as http]
[app.util.i18n :as i18n]
[app.util.router :as rt]
[app.util.storage :refer [storage]]
[app.util.timers :as tm]
[app.util.webapi :as wapi]
[beicon.core :as rx]
[cljs.spec.alpha :as s]
[clojure.set :as set]
[cuerdas.core :as str]
[potok.core :as ptk]))
@ -74,69 +73,9 @@
;; --- Initialize Workspace
(s/def ::layout-flag
#{:sitemap
:layers
:comments
:assets
:document-history
:colorpalette
:element-options
:rules
:display-grid
:snap-grid
:scale-text
:dynamic-alignment
:display-artboard-names
:snap-guides})
(s/def ::layout-flags (s/coll-of ::layout-flag))
(def default-workspace-layout
#{:sitemap
:layers
:element-options
:rules
:display-grid
:snap-grid
:dynamic-alignment
:display-artboard-names
:snap-guides})
(def layout-presets
{:assets
{:del #{:sitemap :layers :document-history}
:add #{:assets}}
:document-history
{:del #{:assets :layers :sitemap}
:add #{:document-history}}
:layers
{:del #{:document-history :assets}
:add #{:sitemap :layers}}})
(s/def ::options-mode #{:design :prototype})
(def default-workspace-global
{:options-mode :design})
(def default-workspace-local
{:zoom 1})
(defn ensure-layout
[lname]
(ptk/reify ::ensure-layout
ptk/UpdateEvent
(update [_ state]
(update state :workspace-layout
(fn [stored]
(let [todel (get-in layout-presets [lname :del] #{})
toadd (get-in layout-presets [lname :add] #{})]
(-> stored
(set/difference todel)
(set/union toadd))))))))
(defn initialize
[lname]
(us/verify (s/nilable ::us/keyword) lname)
@ -144,14 +83,14 @@
ptk/UpdateEvent
(update [_ state]
(-> state
(update :workspace-layout #(or % default-workspace-layout))
(update :workspace-global #(or % default-workspace-global))))
(update :workspace-layout #(or % layout/default-layout))
(update :workspace-global #(or % layout/default-global))))
ptk/WatchEvent
(watch [_ _ _]
(if (and lname (contains? layout-presets lname))
(rx/of (ensure-layout lname))
(rx/of (ensure-layout :layers))))))
(if (and lname (contains? layout/presets lname))
(rx/of (layout/ensure-layout lname))
(rx/of (layout/ensure-layout :layers))))))
(defn initialize-file
[project-id file-id]
@ -247,7 +186,6 @@
(rx/observe-on :async))))))
(declare go-to-page)
(declare load-flag)
(defn initialize-page
[page-id]
@ -272,12 +210,8 @@
(assoc :current-page-id id)
(assoc :trimmed-page (dm/select-keys page [:id :name]))
(assoc :workspace-local local)
(update :workspace-layout
#(if (load-flag :colorpalette false)
(conj % :colorpalette)
(disj % :colorpalette)))
(assoc-in [:workspace-local :selected-palette] (load-flag :selected-palette :recent))
(assoc-in [:workspace-local :selected-palette-colorpicker] (load-flag :selected-palette-colorpicker :recent))
(update :workspace-layout layout/load-layout-flags)
(update :workspace-global layout/load-layout-state)
(update :workspace-global assoc :background-color (-> page :options :background))
(update-in [:route :params :query] assoc :page-id (dm/str id))))
state))))
@ -395,76 +329,39 @@
(->> (rp/mutation :rename-file params)
(rx/ignore))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Local storage Flags Manipulation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(def storeable-layout-flags #{:colorpalette})
(def storeable-workspace-local-flags #{:selected-palette :selected-palette-colorpicker})
(defn store-layout-flags!
[state flags]
(doseq [item (filter storeable-layout-flags flags)]
(swap! storage assoc item (contains? (:workspace-layout state) item))))
(defn store-workspace-local-flag!
[flag value]
(when (contains? storeable-workspace-local-flags flag)
(swap! storage assoc flag value)))
(defn load-flag
[flag default]
(or (flag @storage) default))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Workspace State Manipulation
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; --- Toggle layout flag
;; --- Layout Flags
(dm/export layout/toggle-layout-flag)
(dm/export layout/remove-layout-flag)
;; --- Nudge
(defn update-nudge
[{:keys [big small] :as params}]
(ptk/reify ::update-nudge
IDeref
(-deref [_] (d/without-nils params))
(defn toggle-layout-flags
[& flags]
(ptk/reify ::toggle-layout-flags
ptk/UpdateEvent
(update [_ state]
(let [new-state (update state :workspace-layout
(fn [stored]
(reduce (fn [flags flag]
(if (contains? flags flag)
(disj flags flag)
(conj flags flag)))
stored
(d/concat-set flags))))]
(store-layout-flags! new-state flags)
new-state))))
(update-in state [:profile :props :nudge]
(fn [nudge]
(cond-> nudge
(number? big) (assoc :big big)
(number? small) (assoc :small small)))))
(defn remove-layout-flags
[& flags]
(ptk/reify ::remove-layout-flags
ptk/UpdateEvent
(update [_ state]
(let [new-state (update state :workspace-layout
(fn [stored]
(reduce disj stored (d/concat-set flags))))]
(store-layout-flags! (:workspace-layout new-state) flags)
new-state))))
;; --- Set workspace flag
(defn set-workspace-local-flag!
[state flag value]
(store-workspace-local-flag! flag value)
(assoc-in state [:workspace-local flag] value))
ptk/WatchEvent
(watch [_ state _]
(let [nudge (get-in state [:profile :props :nudge])]
(rx/of (du/update-profile-props {:nudge nudge}))))))
;; --- Set element options mode
(defn set-options-mode
[mode]
(us/assert ::options-mode mode)
(ptk/reify ::set-options-mode
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :options-mode] mode))))
(dm/export layout/set-options-mode)
;; --- Tooltip
@ -1100,8 +997,8 @@
(defn go-to-layout
[layout]
(us/verify ::layout-flag layout)
(ptk/reify ::set-workspace-layout
(us/verify ::layout/flag layout)
(ptk/reify ::go-to-layout
IDeref
(-deref [_] {:layout layout})
@ -1154,7 +1051,7 @@
(defn go-to-component
[component-id]
(ptk/reify ::set-workspace-layout-component
(ptk/reify ::go-to-component
IDeref
(-deref [_] {:layout :assets})

View file

@ -9,8 +9,8 @@
[app.common.colors :as clr]
[app.common.data :as d]
[app.main.data.modal :as md]
[app.main.data.workspace :as dw]
[app.main.data.workspace.changes :as dch]
[app.main.data.workspace.layout :as layout]
[app.main.data.workspace.state-helpers :as wsh]
[app.main.data.workspace.texts :as dwt]
[app.main.repo :as rp]
@ -46,7 +46,12 @@
(ptk/reify ::change-palette-selected
ptk/UpdateEvent
(update [_ state]
(dw/set-workspace-local-flag! state :selected-palette selected))))
(assoc-in state [:workspace-global :selected-palette] selected))
ptk/EffectEvent
(effect [_ state _]
(let [wglobal (:workspace-global state)]
(layout/persist-layout-state! wglobal)))))
(defn change-palette-selected-colorpicker
"Change the library used by the color picker"
@ -54,7 +59,12 @@
(ptk/reify ::change-palette-selected-colorpicker
ptk/UpdateEvent
(update [_ state]
(dw/set-workspace-local-flag! state :selected-palette-colorpicker selected))))
(assoc-in state [:workspace-global :selected-palette-colorpicker] selected))
ptk/EffectEvent
(effect [_ state _]
(let [wglobal (:workspace-global state)]
(layout/persist-layout-state! wglobal)))))
(defn show-palette
"Show the palette tool and change the library it uses"
@ -62,9 +72,16 @@
(ptk/reify ::show-palette
ptk/UpdateEvent
(update [_ state]
(-> state
(update :workspace-layout conj :colorpalette)
(dw/set-workspace-local-flag! :selected-palette selected)))))
(assoc-in state [:workspace-global :selected-palette] selected))
ptk/WatchEvent
(watch [_ _ _]
(rx/of (layout/toggle-layout-flag :colorpalette :force? true)))
ptk/EffectEvent
(effect [_ state _]
(let [wglobal (:workspace-global state)]
(layout/persist-layout-state! wglobal)))))
(defn start-picker
[]

View file

@ -0,0 +1,171 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) UXBOX Labs SL
(ns app.main.data.workspace.layout
"Workspace layout management events and helpers."
(:require
[app.common.spec :as us]
[app.util.storage :refer [storage]]
[cljs.spec.alpha :as s]
[clojure.set :as set]
[potok.core :as ptk]))
(s/def ::flag
#{:sitemap
:layers
:comments
:assets
:document-history
:colorpalette
:element-options
:rules
:display-grid
:snap-grid
:scale-text
:dynamic-alignment
:display-artboard-names
:snap-guides})
(def presets
{:assets
{:del #{:sitemap :layers :document-history}
:add #{:assets}}
:document-history
{:del #{:assets :layers :sitemap}
:add #{:document-history}}
:layers
{:del #{:document-history :assets}
:add #{:sitemap :layers}}})
(s/def ::options-mode #{:design :prototype})
(def default-layout
#{:sitemap
:layers
:element-options
:rules
:display-grid
:snap-grid
:dynamic-alignment
:display-artboard-names
:snap-guides})
(def default-global
{:options-mode :design})
(defn ensure-layout
[name]
(ptk/reify ::ensure-layout
ptk/UpdateEvent
(update [_ state]
(update state :workspace-layout
(fn [stored]
(let [todel (get-in presets [name :del] #{})
toadd (get-in presets [name :add] #{})]
(-> stored
(set/difference todel)
(set/union toadd))))))))
(declare persist-layout-flags!)
(defn toggle-layout-flag
[flag & {:keys [force?] :as opts}]
(ptk/reify ::toggle-layout-flag
IDeref
(-deref [_] {:name flag})
ptk/UpdateEvent
(update [_ state]
(update state :workspace-layout
(fn [flags]
(if force?
(conj flags flag)
(if (contains? flags flag)
(disj flags flag)
(conj flags flag))))))
ptk/EffectEvent
(effect [_ state _]
(let [flags (:workspace-layout state)]
(persist-layout-flags! flags)))))
(defn remove-layout-flag
[flag]
(ptk/reify ::remove-layout-flag
ptk/UpdateEvent
(update [_ state]
(update state :workspace-layout
(fn [flags]
(disj flags flag))))
ptk/EffectEvent
(effect [_ state _]
(let [flags (:workspace-layout state)]
(persist-layout-flags! flags)))))
(defn set-options-mode
[mode]
(us/assert ::options-mode mode)
(ptk/reify ::set-options-mode
ptk/UpdateEvent
(update [_ state]
(assoc-in state [:workspace-global :options-mode] mode))))
(def layout-flags-persistence-mapping
"A map of layout flags that should be persisted in local storage; the
value corresponds to the key that will be used for save the data in
storage object. It should be namespace qualified."
{:colorpalette :app.main.data.workspace/show-colorpalette?
:textpalette :app.main.data.workspace/show-textpalette?})
(defn load-layout-flags
"Given the current layout flags, and updates them with the data
stored in Storage."
[layout]
(reduce (fn [layout [flag key]]
(condp = (get @storage key ::none)
::none layout
false (disj layout flag)
true (conj layout flag)))
layout
layout-flags-persistence-mapping))
(defn persist-layout-flags!
"Given a set of layout flags, and persist a subset of them to the Storage."
[layout]
(doseq [[flag key] layout-flags-persistence-mapping]
(swap! storage assoc key (contains? layout flag))))
(def layout-state-persistence-mapping
"A mapping of keys that need to be persisted from `:workspace-global` into Storage."
{:selected-palette :app.main.data.workspace/selected-palette
:selected-palette-colorpicker :app.main.data.workspace/selected-palette-colorpicker})
(defn load-layout-state
"Given state (the :workspace-global) and update it with layout related
props that are previously persisted in the Storage."
[state]
(reduce (fn [state [key skey]]
(let [val (get @storage skey ::none)]
(if (= val ::none)
state
(assoc state key val))))
state
layout-state-persistence-mapping))
(defn persist-layout-state!
"Given state (the :workspace-global) and persists a subset of layout
related props to the Storage."
[state]
(doseq [[key skey] layout-state-persistence-mapping]
(let [val (get state key ::does-not-exist)]
(if (= val ::does-not-exist)
(swap! storage dissoc skey)
(swap! storage assoc skey val)))))

View file

@ -81,7 +81,7 @@
(update [_ state]
(let [text-state (some->> content ted/import-content)
attrs (d/merge txt/default-text-attrs
(get-in state [:workspace-local :defaults :font]))
(get-in state [:workspace-global :default-font]))
editor (cond-> (ted/create-editor-state text-state decorator)
(and (nil? content) (some? attrs))
(ted/update-editor-current-block-data attrs))]
@ -406,5 +406,5 @@
(let [multiple? (->> data vals (d/seek #(= % :multiple)))]
(cond-> state
(not multiple?)
(assoc-in [:workspace-local :defaults :font] data))))))
(assoc-in [:workspace-global :default-font] data))))))