diff --git a/tl/src/tl/subs.cljs b/tl/src/tl/subs.cljs index e95dd9d..fd1a253 100644 --- a/tl/src/tl/subs.cljs +++ b/tl/src/tl/subs.cljs @@ -83,16 +83,18 @@ (->> (:groups scene) (keep (fn [[gid g]] (when (and (= :annotation (:type g)) (= ctx (:parent g))) - (let [src-segs (scene/resolve scene gid) + (let [src-segs (when-not (get-in g [:meta :hidden]) (scene/resolve scene gid)) bars (scene/merge-bars (mapcat (fn [{[a b] :src}] (scene/pieces segs a b)) src-segs)) - reason (scene/broken-reason scene gid)] + reason (scene/broken-reason scene gid) + hidden (get-in g [:meta :hidden])] {:id gid :name (:name g) :color (or (:color g) "#4e8fc2") :content (:content g) :children (count (:marks g)) :nested (get nested gid 0) :draft (boolean (:draft g)) :script (:script g) ; pdf highlights linked to this group :broken (boolean reason) :reason reason + :hidden (boolean hidden) :start (or (ffirst bars) 0) :bars bars})))) (sort-by (juxt :broken :start)) ; broken annotations sink to the bottom vec)))) diff --git a/tl/src/tl/views.cljs b/tl/src/tl/views.cljs index 88171ad..39eb4de 100644 --- a/tl/src/tl/views.cljs +++ b/tl/src/tl/views.cljs @@ -377,11 +377,12 @@ (reset! scrolled-on-load? true) (scroll-to-seg-track! segs playhead)) ;; clip-following: only while the playhead is actually inside a bar of - ;; an annotation that opts in (:meta :scroll-to) — scroll each of its - ;; clips into view as the playhead crosses onto a new bar (discontinuity). + ;; an annotation that opts in (:meta :scroll-to) and is not hidden — + ;; scroll each of its clips into view as the playhead crosses onto a new bar (discontinuity). ;; Track [ann-id bar-idx] to avoid scrolling within the same bar. (when-let [current-bar (some (fn [a] - (when (and (ann-scroll-to? (get-in scene [:groups (:id a)])) + (when (and (not (get-in (get-in scene [:groups (:id a)]) [:meta :hidden])) + (ann-scroll-to? (get-in scene [:groups (:id a)])) (some (fn [[lo hi]] (<= lo playhead hi)) (:bars a))) [(:id a) (first (keep-indexed (fn [j [lo hi]] (when (<= lo playhead hi) j)) @@ -414,7 +415,8 @@ [:div.ann-lanes {:style {:height lane-h :width width} :on-mouse-down #(scrub! @content fps zoom %)} ;; annotation bars — solid for saved, dashed for the in-progress draft - (for [[i a] (map-indexed vector anns) + ;; visible annotations: full bars with labels + (for [[i a] (map-indexed vector (filter (fn [a] (not (get-in (get-in scene [:groups (:id a)]) [:meta :hidden]))) anns)) [j [lo hi]] (map-indexed vector (:bars a))] ^{:key (str (:id a) "-" j)} [:div.ann-bar {:title (:name a) @@ -430,10 +432,27 @@ :cursor (if (:draft a) "default" "pointer") :border-radius 2 :border (str (if (:draft a) "1px dashed " "1px solid ") (:color a))}}]) - (for [[i a] (map-indexed vector anns) :let [[lo _] (first (:bars a))] :when lo] + ;; visible annotation labels + (for [[i a] (map-indexed vector (filter (fn [a] (not (get-in (get-in scene [:groups (:id a)]) [:meta :hidden]))) anns)) :let [[lo _] (first (:bars a))] :when lo] ^{:key (str "lbl-" (:id a))} [:div.ann-bar-label {:style {:top (* i 18) - :left (+ 4 (px lo fps zoom))}} (:name a)])]]] + :left (+ 4 (px lo fps zoom))}} (:name a)]) + ;; hidden annotations: tiny colored dots with dither pattern — click to unhide + (for [[i a] (map-indexed vector (filter (fn [a] (get-in (get-in scene [:groups (:id a)]) [:meta :hidden])) anns)) :let [[lo _] (first (:bars a))] :when lo] + ^{:key (str "hidden-" (:id a))} + [:div.ann-hidden {:title (str (:name a) " (click to unhide)") + :on-click #(do (.stopPropagation %) + (rf/dispatch [::events/put-group (:id a) + (update (get-in scene [:groups (:id a)]) + :meta dissoc :hidden)])) + :style {:top (+ 6 (* i 18)) :height 6 + :left (px lo fps zoom) :width 12 + :background (str (:color a) "33") + :cursor "pointer" + :border-radius 1 + :border (str "1px solid " (:color a) "88") + :background-image "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='2' height='2'%3E%3Crect width='2' height='2' fill='%23ffffff'/%3E%3Crect width='1' height='1' fill='%23000000'/%3E%3Crect x='1' y='1' width='1' height='1' fill='%23000000'/%3E%3C/svg%3E\")" + :background-size "2px 2px"}}])]]] [:div.timeline-body-scroll {:ref (fn [n] (reset! body-scroll-el n)) :style {:padding-top (+ lane-h 24)}} [:div.gutter-tracks @@ -846,7 +865,11 @@ [:label.form-check {:title "During playback, scroll each of this annotation's clips into view as the playhead reaches it"} [:input {:type "checkbox" :checked (boolean (get-in d [:meta :scroll-to])) :on-change #(put (assoc-in d [:meta :scroll-to] (.. % -target -checked)))}] - [:span "Follow clips during playback"]]]) + [:span "Follow clips during playback"]] + [:label.form-check {:title "Hide this annotation from the timeline lane (still usable in links)"} + [:input {:type "checkbox" :checked (boolean (get-in d [:meta :hidden])) + :on-change #(put (assoc-in d [:meta :hidden] (.. % -target -checked)))}] + [:span "Hide from timeline"]]]) [:div.form-marks-label "Content"] ^{:key gid} [content-editor gid (:content orig)] (if (and linking (= gid (:gid linking)))