mirror of
https://github.com/penpot/penpot.git
synced 2025-06-11 00:41:38 +02:00
✨ Notify library updates when really needed
This commit is contained in:
parent
568338ad68
commit
8a42a53522
32 changed files with 373 additions and 195 deletions
|
@ -260,12 +260,11 @@
|
|||
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [ignore-until (-> state :workspace-file :ignore-sync-until)
|
||||
file-id (-> state :workspace-file :id)
|
||||
needs-update? (some #(and (> (:modified-at %) (:synced-at %))
|
||||
(or (not ignore-until)
|
||||
(> (:modified-at %) ignore-until)))
|
||||
libraries)]
|
||||
(let [file-data (:workspace-data state)
|
||||
ignore-until (dm/get-in state [:workspace-file :ignore-sync-until])
|
||||
file-id (dm/get-in state [:workspace-file :id])
|
||||
needs-update? (seq (filter #(dwl/assets-need-sync % file-data ignore-until)
|
||||
libraries))]
|
||||
(when needs-update?
|
||||
(rx/of (dwl/notify-sync-file file-id)))))))
|
||||
|
||||
|
@ -1633,7 +1632,7 @@
|
|||
;; Check if the shape is an instance whose master is defined in a
|
||||
;; library that is not linked to the current file
|
||||
(foreign-instance? [shape paste-objects state]
|
||||
(let [root (cph/get-root-shape paste-objects shape)
|
||||
(let [root (ctn/get-component-shape paste-objects shape)
|
||||
root-file-id (:component-file root)]
|
||||
(and (some? root)
|
||||
(not= root-file-id (:current-file-id state))
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
|
||||
;; Shapes that are in a component, but are not root, must be detached,
|
||||
;; because they will be now children of a non instance group.
|
||||
shapes-to-detach (filter ctk/in-component-instance-not-root? shapes)
|
||||
shapes-to-detach (filter ctk/in-component-copy-not-root? shapes)
|
||||
|
||||
;; Look at the `get-empty-groups-after-group-creation`
|
||||
;; docstring to understand the real purpose of this code
|
||||
|
@ -124,7 +124,7 @@
|
|||
|
||||
;; Shapes that are in a component (including root) must be detached,
|
||||
;; because cannot be easyly synchronized back to the main component.
|
||||
shapes-to-detach (filter ctk/in-component-instance?
|
||||
shapes-to-detach (filter ctk/in-component-copy?
|
||||
(cph/get-children-with-self objects (:id group)))]
|
||||
|
||||
(-> (pcb/empty-changes it page-id)
|
||||
|
|
|
@ -605,7 +605,7 @@
|
|||
container (cph/get-container local-file :page page-id)
|
||||
shape (ctn/get-shape container id)]
|
||||
|
||||
(when (ctk/in-component-instance? shape)
|
||||
(when (ctk/instance-head? shape)
|
||||
(let [libraries (wsh/get-libraries state)
|
||||
|
||||
changes
|
||||
|
@ -801,6 +801,8 @@
|
|||
(rx/of (dch/commit-changes (assoc changes :file-id file-id))))))))
|
||||
|
||||
(def ignore-sync
|
||||
"Mark the file as ignore syncs. All library changes before this moment will not
|
||||
ber notified to sync."
|
||||
(ptk/reify ::ignore-sync
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
|
@ -812,13 +814,26 @@
|
|||
{:file-id (get-in state [:workspace-file :id])
|
||||
:date (dt/now)}))))
|
||||
|
||||
(defn assets-need-sync
|
||||
"Get a lazy sequence of all the assets of each type in the library that have
|
||||
been modified after the last sync of the library. The sync date may be
|
||||
overriden by providing a ignore-until parameter.
|
||||
|
||||
The sequence items are tuples of (page-id shape-id asset-id asset-type)."
|
||||
([library file-data] (assets-need-sync library file-data nil))
|
||||
([library file-data ignore-until]
|
||||
(let [sync-date (max (:synced-at library) (or ignore-until 0))]
|
||||
(when (> (:modified-at library) sync-date)
|
||||
(ctf/used-assets-changed-since file-data library sync-date)))))
|
||||
|
||||
(defn notify-sync-file
|
||||
[file-id]
|
||||
(us/assert ::us/uuid file-id)
|
||||
(ptk/reify ::notify-sync-file
|
||||
ptk/WatchEvent
|
||||
(watch [_ state _]
|
||||
(let [libraries-need-sync (filter #(> (:modified-at %) (:synced-at %))
|
||||
(let [file-data (:workspace-data state)
|
||||
libraries-need-sync (filter #(seq (assets-need-sync % file-data))
|
||||
(vals (get state :workspace-libraries)))
|
||||
do-update #(do (apply st/emit! (map (fn [library]
|
||||
(sync-file (:current-file-id state)
|
||||
|
@ -828,14 +843,15 @@
|
|||
do-dismiss #(do (st/emit! ignore-sync)
|
||||
(st/emit! dm/hide))]
|
||||
|
||||
(rx/of (dm/info-dialog
|
||||
(tr "workspace.updates.there-are-updates")
|
||||
:inline-actions
|
||||
[{:label (tr "workspace.updates.update")
|
||||
:callback do-update}
|
||||
{:label (tr "workspace.updates.dismiss")
|
||||
:callback do-dismiss}]
|
||||
:sync-dialog))))))
|
||||
(when (seq libraries-need-sync)
|
||||
(rx/of (dm/info-dialog
|
||||
(tr "workspace.updates.there-are-updates")
|
||||
:inline-actions
|
||||
[{:label (tr "workspace.updates.update")
|
||||
:callback do-update}
|
||||
{:label (tr "workspace.updates.dismiss")
|
||||
:callback do-dismiss}]
|
||||
:sync-dialog)))))))
|
||||
|
||||
(defn watch-component-changes
|
||||
"Watch the state for changes that affect to any main instance. If a change is detected will throw
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
(if (and (= (count shapes) 1)
|
||||
(or (and (= (:type (first shapes)) :group) (not components-v2))
|
||||
(= (:type (first shapes)) :frame))
|
||||
(not (ctk/instance-root? (first shapes))))
|
||||
(not (ctk/instance-head? (first shapes))))
|
||||
[(first shapes) (-> (pcb/empty-changes it page-id)
|
||||
(pcb/with-objects objects))]
|
||||
(let [root-name (if (= 1 (count shapes))
|
||||
|
@ -111,7 +111,7 @@
|
|||
page-id
|
||||
shapes
|
||||
root-name
|
||||
(not (ctk/instance-root? (first shapes))))
|
||||
(not (ctk/instance-head? (first shapes))))
|
||||
(prepare-create-board changes
|
||||
(uuid/next)
|
||||
(:parent-id (first shapes))
|
||||
|
@ -203,7 +203,7 @@
|
|||
(defn- generate-detach-recursive
|
||||
[changes container shape-id first]
|
||||
(let [shape (ctn/get-shape container shape-id)]
|
||||
(if (and (ctk/instance-root? shape) (not first))
|
||||
(if (and (ctk/instance-head? shape) (not first))
|
||||
;; Subinstances are not detached, but converted in top instances
|
||||
(pcb/update-shapes changes [(:id shape)] #(assoc % :component-root? true))
|
||||
;; Otherwise, detach the shape and all children
|
||||
|
@ -530,7 +530,7 @@
|
|||
[changes libraries container shape-id reset? components-v2]
|
||||
(log/debug :msg "Sync shape direct" :shape (str shape-id) :reset? reset?)
|
||||
(let [shape-inst (ctn/get-shape container shape-id)]
|
||||
(if (ctk/in-component-instance? shape-inst)
|
||||
(if (ctk/in-component-copy? shape-inst)
|
||||
(let [library (dm/get-in libraries [(:component-file shape-inst) :data])
|
||||
component (or (ctkl/get-component library (:component-id shape-inst))
|
||||
(and reset?
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
[app.common.pages.common :as cpc]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.spec :as us]
|
||||
[app.common.types.container :as ctn]
|
||||
[app.common.types.modifiers :as ctm]
|
||||
[app.common.types.shape.layout :as ctl]
|
||||
[app.main.constants :refer [zoom-half-pixel-precision]]
|
||||
|
@ -54,7 +55,7 @@
|
|||
shape
|
||||
|
||||
(nil? root)
|
||||
(cph/get-root-shape objects shape)
|
||||
(ctn/get-component-shape objects shape {:allow-main? true})
|
||||
|
||||
:else root)
|
||||
|
||||
|
@ -64,7 +65,7 @@
|
|||
transformed-shape
|
||||
|
||||
(nil? transformed-root)
|
||||
(as-> (cph/get-root-shape objects transformed-shape) $
|
||||
(as-> (ctn/get-component-shape objects transformed-shape {:allow-main? true}) $
|
||||
(gsh/transform-shape (merge $ (get modif-tree (:id $)))))
|
||||
|
||||
:else transformed-root)
|
||||
|
|
|
@ -189,7 +189,7 @@
|
|||
;; but hidden (to be able to recover them more easily).
|
||||
(let [shape (get objects shape-id)
|
||||
component-shape (ctn/get-component-shape objects shape)]
|
||||
(and (ctk/in-component-instance? shape)
|
||||
(and (ctk/in-component-copy? shape)
|
||||
(not= shape component-shape)
|
||||
(not (ctk/main-instance? component-shape)))))
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
(mf/defc element-icon
|
||||
[{:keys [shape main-instance?] :as props}]
|
||||
(if (ctk/instance-root? shape)
|
||||
(if (ctk/instance-head? shape)
|
||||
(if main-instance?
|
||||
i/component
|
||||
i/component-copy)
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
(mf/defc element-icon-refactor
|
||||
[{:keys [shape main-instance?] :as props}]
|
||||
(if (ctk/instance-root? shape)
|
||||
(if (ctk/instance-head? shape)
|
||||
(if main-instance?
|
||||
i/component-refactor
|
||||
i/copy-refactor)
|
||||
|
|
|
@ -438,7 +438,7 @@
|
|||
|
||||
has-component? (some true? (map #(contains? % :component-id) shapes))
|
||||
is-component? (and single? (-> shapes first :component-id some?))
|
||||
is-non-root? (and single? (ctk/in-component-instance-not-root? (first shapes)))
|
||||
is-non-root? (and single? (ctk/in-component-copy-not-root? (first shapes)))
|
||||
|
||||
first-shape (first shapes)
|
||||
{:keys [shape-id component-id component-file main-instance?]} first-shape
|
||||
|
|
|
@ -224,7 +224,7 @@
|
|||
#(as-> (get objects %) obj
|
||||
(and (cph/root-frame? obj)
|
||||
(d/not-empty? (:shapes obj))
|
||||
(not (ctk/instance-root? obj))
|
||||
(not (ctk/instance-head? obj))
|
||||
(not (ctk/main-instance? obj))))
|
||||
|
||||
;; Set with the elements to remove from the hover list
|
||||
|
|
|
@ -22,12 +22,13 @@
|
|||
["date-fns/locale/ru" :default dateFnsLocalesRu]
|
||||
["date-fns/locale/tr" :default dateFnsLocalesTr]
|
||||
["date-fns/locale/zh-CN" :default dateFnsLocalesZhCn]
|
||||
["luxon" :as lxn]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.time :as common-time]
|
||||
[app.util.object :as obj]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
(def DateTime lxn/DateTime)
|
||||
(def Duration lxn/Duration)
|
||||
(dm/export common-time/DateTime)
|
||||
(dm/export common-time/Duration)
|
||||
|
||||
(defprotocol ITimeMath
|
||||
(plus [_ o])
|
||||
|
@ -89,9 +90,7 @@
|
|||
:rfc2822 (.fromRFC2822 ^js DateTime s #js {:zone zone :setZone force-zone})
|
||||
:http (.fromHTTP ^js DateTime s #js {:zone zone :setZone force-zone})))))
|
||||
|
||||
(defn now
|
||||
[]
|
||||
(.local ^js DateTime))
|
||||
(dm/export common-time/now)
|
||||
|
||||
(defn utc-now
|
||||
[]
|
||||
|
|
|
@ -295,18 +295,20 @@
|
|||
nil))
|
||||
|
||||
(defn dump-tree'
|
||||
([state] (dump-tree' state false false))
|
||||
([state show-ids] (dump-tree' state show-ids false))
|
||||
([state show-ids show-touched]
|
||||
([state] (dump-tree' state false false false))
|
||||
([state show-ids] (dump-tree' state show-ids false false))
|
||||
([state show-ids show-touched] (dump-tree' state show-ids show-touched false))
|
||||
([state show-ids show-touched show-modified]
|
||||
(let [page-id (get state :current-page-id)
|
||||
file-data (get state :workspace-data)
|
||||
libraries (get state :workspace-libraries)]
|
||||
(ctf/dump-tree file-data page-id libraries show-ids show-touched))))
|
||||
(ctf/dump-tree file-data page-id libraries show-ids show-touched show-modified))))
|
||||
|
||||
(defn ^:export dump-tree
|
||||
([] (dump-tree' @st/state))
|
||||
([show-ids] (dump-tree' @st/state show-ids))
|
||||
([show-ids show-touched] (dump-tree' @st/state show-ids show-touched)))
|
||||
([show-ids] (dump-tree' @st/state show-ids false false))
|
||||
([show-ids show-touched] (dump-tree' @st/state show-ids show-touched false))
|
||||
([show-ids show-touched show-modified] (dump-tree' @st/state show-ids show-touched show-modified)))
|
||||
|
||||
(when *assert*
|
||||
(defonce debug-subscription
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue