perf: stop toolbar/share-menu re-rendering every frame in playback
Both derefed the raw ::playhead in their render bodies, so the whole toolbar (zoom/row sliders) and the share menu (even while closed) reconciled 60fps during playback. toolbar now subscribes coarse ::at-start?/::at-end? edges (flip only at the timeline ends) and reads the exact playhead at click time; share-menu reads the playhead at click time too. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
05514f3522
commit
0c5456d6df
2 changed files with 21 additions and 8 deletions
|
|
@ -71,6 +71,13 @@
|
||||||
::playhead
|
::playhead
|
||||||
(fn [db _] (scene/playhead (:view db) (peek (get-in db [:view :stack])))))
|
(fn [db _] (scene/playhead (:view db) (peek (get-in db [:view :stack])))))
|
||||||
|
|
||||||
|
;; coarse boolean edges of the playhead — subscribing these (instead of the raw
|
||||||
|
;; playhead) keeps a component from re-rendering every frame during playback: they
|
||||||
|
;; only flip at the timeline ends. Read ::playhead itself at click time for the
|
||||||
|
;; actual value.
|
||||||
|
(rf/reg-sub ::at-start? :<- [::playhead] (fn [ph _] (<= ph 0)))
|
||||||
|
(rf/reg-sub ::at-end? :<- [::playhead] :<- [::length] (fn [[ph len] _] (>= ph len)))
|
||||||
|
|
||||||
;; breadcrumb trail of the stack
|
;; breadcrumb trail of the stack
|
||||||
(rf/reg-sub
|
(rf/reg-sub
|
||||||
::breadcrumbs
|
::breadcrumbs
|
||||||
|
|
|
||||||
|
|
@ -1167,19 +1167,24 @@
|
||||||
:on-click #(rf/dispatch [::events/pop-to id])} name]]))])))
|
:on-click #(rf/dispatch [::events/pop-to id])} name]]))])))
|
||||||
|
|
||||||
(defn toolbar []
|
(defn toolbar []
|
||||||
|
;; NB: subscribe the coarse ::at-start?/::at-end? edges, not the raw playhead —
|
||||||
|
;; else the whole toolbar (sliders included) re-renders every frame in playback.
|
||||||
|
;; The step buttons read the exact playhead at click time.
|
||||||
(let [zoom @(rf/subscribe [::subs/zoom]) row-h @(rf/subscribe [::subs/row-h])
|
(let [zoom @(rf/subscribe [::subs/zoom]) row-h @(rf/subscribe [::subs/row-h])
|
||||||
playing? @(rf/subscribe [::subs/playing?])
|
playing? @(rf/subscribe [::subs/playing?])
|
||||||
ph (js/Math.round @(rf/subscribe [::subs/playhead]))
|
start? @(rf/subscribe [::subs/at-start?])
|
||||||
|
end? @(rf/subscribe [::subs/at-end?])
|
||||||
len @(rf/subscribe [::subs/length])
|
len @(rf/subscribe [::subs/length])
|
||||||
authed? @(rf/subscribe [::subs/authed?])
|
authed? @(rf/subscribe [::subs/authed?])
|
||||||
authoring? (some? @(rf/subscribe [::subs/draft-group]))]
|
authoring? (some? @(rf/subscribe [::subs/draft-group]))
|
||||||
|
ph-now #(js/Math.round @(rf/subscribe [::subs/playhead]))]
|
||||||
[:div.toolbar
|
[:div.toolbar
|
||||||
[:div.transport
|
[:div.transport
|
||||||
[:button.step-btn {:title "Previous frame" :disabled (<= ph 0)
|
[:button.step-btn {:title "Previous frame" :disabled start?
|
||||||
:on-click #(goto! (max 0 (dec ph)))} "◁"]
|
:on-click #(goto! (max 0 (dec (ph-now))))} "◁"]
|
||||||
[:button.play-btn {:on-click toggle-play! :title "Play / pause"} (if playing? "❚❚" "▶")]
|
[:button.play-btn {:on-click toggle-play! :title "Play / pause"} (if playing? "❚❚" "▶")]
|
||||||
[:button.step-btn {:title "Next frame" :disabled (>= ph len)
|
[:button.step-btn {:title "Next frame" :disabled end?
|
||||||
:on-click #(goto! (min len (inc ph)))} "▷"]]
|
:on-click #(goto! (min len (inc (ph-now))))} "▷"]]
|
||||||
(when (and authed? (not authoring?))
|
(when (and authed? (not authoring?))
|
||||||
[:button.add-annotation {:title "Add annotation"
|
[:button.add-annotation {:title "Add annotation"
|
||||||
:on-click #(rf/dispatch [::events/open-draft])}
|
:on-click #(rf/dispatch [::events/open-draft])}
|
||||||
|
|
@ -1540,7 +1545,6 @@
|
||||||
(fn []
|
(fn []
|
||||||
(let [proj @(rf/subscribe [::subs/project])
|
(let [proj @(rf/subscribe [::subs/project])
|
||||||
stack @(rf/subscribe [::subs/stack])
|
stack @(rf/subscribe [::subs/stack])
|
||||||
playhead @(rf/subscribe [::subs/playhead])
|
|
||||||
id (:id proj)
|
id (:id proj)
|
||||||
grab (fn [rel which]
|
grab (fn [rel which]
|
||||||
(copy-text! (abs-url rel))
|
(copy-text! (abs-url rel))
|
||||||
|
|
@ -1552,7 +1556,9 @@
|
||||||
[:<>
|
[:<>
|
||||||
[:div.menu-backdrop {:on-click #(reset! open? false)}]
|
[:div.menu-backdrop {:on-click #(reset! open? false)}]
|
||||||
[:div.menu-pop
|
[:div.menu-pop
|
||||||
[:button {:on-click #(grab (routes/project-url id stack playhead) :moment)}
|
;; read the playhead at click time, not in render, so this menu
|
||||||
|
;; doesn't re-render every frame during playback
|
||||||
|
[:button {:on-click #(grab (routes/project-url id stack @(rf/subscribe [::subs/playhead])) :moment)}
|
||||||
(if (= @copied :moment) "✓ Link copied" "Copy link to this moment")]
|
(if (= @copied :moment) "✓ Link copied" "Copy link to this moment")]
|
||||||
[:button {:on-click #(grab (routes/project-url id [:root] nil) :project)}
|
[:button {:on-click #(grab (routes/project-url id [:root] nil) :project)}
|
||||||
(if (= @copied :project) "✓ Link copied" "Copy link to the whole project")]]])]))))
|
(if (= @copied :project) "✓ Link copied" "Copy link to the whole project")]]])]))))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue