Notify library updates when really needed

This commit is contained in:
Andrés Moya 2023-05-04 09:34:38 +02:00
parent 568338ad68
commit 8a42a53522
32 changed files with 373 additions and 195 deletions

View file

@ -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))

View file

@ -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)

View file

@ -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

View file

@ -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?

View file

@ -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)

View file

@ -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)))))

View file

@ -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)

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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
[]

View file

@ -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