fix: youtube timestamp on web/electron

This commit is contained in:
Tienson Qin
2026-01-01 21:42:20 +08:00
parent 10846fdaa3
commit 4d46c5e9b7

View File

@@ -26,19 +26,27 @@
(load-yt-script)))
c))
(defn- use-youtube-wrapper? []
(mobile-util/native-platform?))
(defn register-player [state]
(try
(let [id (first (:rum/args state))
node (rum/dom-node state)]
(when node
(let [player (js/window.YT.Player.
(let [*player (atom nil)
player (js/window.YT.Player.
node
(clj->js
{:events
{"onReady" (fn [_e] (js/console.log id " ready"))}}))]
(state/update-state! [:youtube/players]
(fn [players]
(assoc players id player))))))
{"onReady"
(fn [_e]
(state/update-state! [:youtube/players]
(fn [players]
(assoc players id @*player)))
(js/console.log id " ready"))}}))]
(reset! *player player)
player)))
(catch :default _e
nil)))
@@ -47,18 +55,31 @@
(rum/local nil ::player)
{:did-mount
(fn [state]
(go
(<! (load-youtube-api))
(register-player state))
(when-not (use-youtube-wrapper?)
(go
(<! (load-youtube-api))
(register-player state)))
state)}
[state id {:keys [width height start] :as _opts}]
(let [width (or width (min (- (util/get-width) 96)
560))
height (or height (int (* width (/ 315 560))))
url (str "https://logseq.com/youtube.html?v=" id "&enablejsapi=1")
url (if start
(str url "&start=" start)
url)]
origin (.. js/window -location -origin)
origin-valid? (and (string? origin)
(re-matches #"^https?://.+" origin))
base-url (str "https://www.youtube-nocookie.com/embed/"
(js/encodeURIComponent id)
"?enablejsapi=1"
(when origin-valid?
(str "&origin=" (js/encodeURIComponent origin))))
direct-url (if start
(str base-url "&start=" start)
base-url)
wrapper-url (str "https://logseq.com/youtube.html?v=" id "&enablejsapi=1")
wrapper-url (if start
(str wrapper-url "&start=" start)
wrapper-url)
url (if (use-youtube-wrapper?) wrapper-url direct-url)]
[:iframe.aspect-video
{:id (str "youtube-player-" id)
:allow-full-screen "allowfullscreen"
@@ -90,37 +111,70 @@
js/Node.DOCUMENT_POSITION_FOLLOWING))))
(defn get-player [target]
(when-let [iframe (->> (js/document.getElementsByTagName "iframe")
(filter
(fn [node]
(let [src (gobj/get node "src" "")]
(string/includes? src "youtube.com"))))
(filter #(dom-after-video-node? % target))
last)]
(let [id (gobj/get iframe "id" "")
id (string/replace-first id #"youtube-player-" "")]
(get (get @state/state :youtube/players) id))))
(when-not (use-youtube-wrapper?)
(when-let [iframe (->> (js/document.getElementsByTagName "iframe")
(filter
(fn [node]
(let [src (gobj/get node "src" "")]
(or
(string/includes? src "youtube-nocookie.com/embed")
(string/includes? src "youtube.com/embed")
(string/includes? src "youtube.com")))))
(filter #(dom-after-video-node? % target))
last)]
(let [id (gobj/get iframe "id" "")
id (string/replace-first id #"youtube-player-" "")]
(get (get @state/state :youtube/players) id)))))
(defn- notify-timestamp-unavailable! []
(notification/show!
"YouTube timestamps aren't available on mobile yet."
:warning
false))
(defn- player-method [player method]
(let [f (gobj/get player method)]
(when (fn? f) f)))
(rum/defc timestamp
[seconds]
[:a.svg-small.youtube-timestamp
{:on-click (fn [e]
(util/stop e)
(when-let [player (get-player (.-target e))]
(.seekTo ^js player seconds true)))}
(if (use-youtube-wrapper?)
(notify-timestamp-unavailable!)
(when-let [player (get-player (.-target e))]
(if-let [seek-to (player-method player "seekTo")]
(.call seek-to player seconds true)
(notification/show!
"YouTube player isn't ready yet."
:warning
false)))))}
svg/clock
(seconds->display seconds)])
(defn gen-youtube-ts-macro []
(if-let [player (get-player (state/get-input))]
(util/format "{{youtube-timestamp %s}}" (Math/floor (.getCurrentTime ^js player)))
(when (mobile-util/native-platform?)
(notification/show!
"Please embed a YouTube video at first, then use this icon.
(if (use-youtube-wrapper?)
(do
(notify-timestamp-unavailable!)
nil)
(if-let [player (get-player (state/get-input))]
(if-let [get-current-time (player-method player "getCurrentTime")]
(util/format "{{youtube-timestamp %s}}"
(Math/floor (.call get-current-time player)))
(do
(notification/show!
"YouTube player isn't ready yet."
:warning
false)
nil))
(when (mobile-util/native-platform?)
(notification/show!
"Please embed a YouTube video at first, then use this icon.
Remember: You can paste a raw YouTube url as embedded video on mobile."
:warning
false)
nil)))
:warning
false)
nil))))
(defn parse-timestamp [timestamp']
(let [reg #"^(?:(\d+):)?([0-5]?\d):([0-5]?\d)$"