From 12ab7c4fcae8b37ed53182478c1d22623d4b01a4 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 17 Sep 2026 15:54:11 -0400 Subject: [PATCH] fix: bind repeated marks to their own occurrence in their own context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A mark that repeats an earlier part produced bars for every occurrence of that part, so all of an annotation's marks lit up at once inside it. In the annotation's own context the local ranges are already the truth — merge those instead of re-projecting the part across the parent's segments. Other contexts still project, which is what makes a repeat visible from outside. Co-Authored-By: Claude Opus 5 --- tl/src/tl/subs.cljs | 10 +++++++--- tl/test/tl/flow_test.cljs | 22 ++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/tl/src/tl/subs.cljs b/tl/src/tl/subs.cljs index 1e87f39..5699b2a 100644 --- a/tl/src/tl/subs.cljs +++ b/tl/src/tl/subs.cljs @@ -264,12 +264,16 @@ (defn- binding-bars [scene ctx segs annotations bound] (vec (mapcat (fn [gid] - (let [g (get-in scene [:groups gid])] + (let [g (get-in scene [:groups gid]) + segments (scene/resolve scene gid) + bars #(if (= gid ctx) + (scene/merge-bars (map :local %)) + (scene/project-bars % segs))] (concat (when (seq (bound g)) - [{:gids (bound g) :bars (scene/project-bars (scene/resolve scene gid) segs)}]) + [{:gids (bound g) :bars (bars segments)}]) (for [m (:marks g) :when (seq (bound m))] - {:gids (bound m) :bars (scene/mark-bars scene gid (:id m) segs)})))) + {:gids (bound m) :bars (bars (filter #(= (:id m) (:mark %)) segments))})))) (conj (set (map :id annotations)) ctx)))) (rf/reg-sub ::drawing-bars diff --git a/tl/test/tl/flow_test.cljs b/tl/test/tl/flow_test.cljs index aca2f6d..db9e84a 100644 --- a/tl/test/tl/flow_test.cljs +++ b/tl/test/tl/flow_test.cljs @@ -157,6 +157,28 @@ (is (= [:d] (mapv :id @(rf/subscribe [::subs/active-drawings])))) (is (= #{:n} @(rf/subscribe [::subs/active-note-set]))))) +(deftest repeated-marks-bind-to-own-occurrences-but-project-in-other-contexts + (rf-test/run-test-sync + (let [marks (mapv (fn [i [a b]] + (assoc (fixture/mark i (fixture/part :a a b)) + :drawings [i] :notes [i])) + [:d1 :d2 :d3 :d4] [[12 72] [51 96] [22 77] [22 90]]) + sc (reduce #(assoc-in %1 [:groups %2] {:type :drawing :strokes []}) + (apply fixture/annotation fixture/base :repeat [:root] marks) + [:d1 :d2 :d3 :d4])] + (setup! sc [:root :repeat]) + (doseq [[frame expected] [[0 #{:d1}] [55 #{:d1}] [59 #{:d1}] + [60 #{:d2}] [104 #{:d2}] [105 #{:d3}] + [159 #{:d3}] [160 #{:d4}] [227 #{:d4}] [228 #{}]]] + (rf/dispatch [::ev/set-playhead :repeat frame]) + (is (= expected (set (map :id @(rf/subscribe [::subs/active-drawings]))))) + (is (= expected @(rf/subscribe [::subs/active-note-set])))) + (setup! sc [:root]) + (rf/dispatch [::ev/set-playhead :root 67]) + (is (= #{:d1 :d2 :d3 :d4} + (set (map :id @(rf/subscribe [::subs/active-drawings]))))) + (is (= #{:d1 :d2 :d3 :d4} @(rf/subscribe [::subs/active-note-set])))))) + (deftest nested-repeat-projection-is-shared-by-editor-and-lane (rf-test/run-test-sync (setup! fixture/base [:root])