mirror of https://github.com/logseq/logseq
parent
e978a8f972
commit
15cafea8c5
|
@ -7,6 +7,7 @@
|
|||
[frontend.handler.draw :as draw]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.extensions.video.youtube :as youtube]
|
||||
[frontend.search :as search]
|
||||
[frontend.state :as state]
|
||||
[frontend.util :as util]
|
||||
|
@ -269,6 +270,8 @@
|
|||
["Embed Youtube Video" [[:editor/input "{{youtube }}" {:last-pattern slash
|
||||
:backward-pos 2}]]]
|
||||
|
||||
["Embed Youtube Timestamp" [[:youtube/insert-timestamp]]]
|
||||
|
||||
["Embed Vimeo Video" [[:editor/input "{{vimeo }}" {:last-pattern slash
|
||||
:backward-pos 2}]]]
|
||||
|
||||
|
@ -563,6 +566,11 @@
|
|||
(defmethod handle-step :editor/show-zotero [[_]]
|
||||
(state/set-editor-show-zotero! true))
|
||||
|
||||
(defmethod handle-step :youtube/insert-timestamp [[_]]
|
||||
(let [input-id (state/get-edit-input-id)
|
||||
macro (youtube/gen-youtube-ts-macro)]
|
||||
(insert! input-id macro {})))
|
||||
|
||||
(defmethod handle-step :editor/show-date-picker [[_ type]]
|
||||
(if (and
|
||||
(contains? #{:scheduled :deadline} type)
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
[frontend.extensions.sci :as sci]
|
||||
[frontend.extensions.pdf.assets :as pdf-assets]
|
||||
[frontend.extensions.zotero :as zotero]
|
||||
[frontend.extensions.video.youtube :as youtube]
|
||||
[frontend.format.block :as block]
|
||||
[frontend.format.mldoc :as mldoc]
|
||||
[frontend.components.plugins :as plugins]
|
||||
|
@ -1084,17 +1085,11 @@
|
|||
:else
|
||||
(nth (util/safe-re-find YouTube-regex url) 5))]
|
||||
(when-not (string/blank? youtube-id)
|
||||
(let [width (min (- (util/get-width) 96)
|
||||
560)
|
||||
height (int (* width (/ 315 560)))]
|
||||
[:iframe
|
||||
{:allow-full-screen "allowfullscreen"
|
||||
:allow
|
||||
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
|
||||
:frame-border "0"
|
||||
:src (str "https://www.youtube.com/embed/" youtube-id)
|
||||
:height height
|
||||
:width width}])))))
|
||||
(youtube/youtube-video youtube-id)))))
|
||||
|
||||
(= name "youtube-timestamp")
|
||||
(when-let [seconds (first arguments)]
|
||||
(youtube/timestamp seconds))
|
||||
|
||||
(= name "tutorial-video")
|
||||
(tutorial-video)
|
||||
|
|
|
@ -518,6 +518,15 @@
|
|||
[:path {:d "M2 0.5H6.78272L13.5 7.69708V18C13.5 18.8284 12.8284 19.5 12 19.5H2C1.17157 19.5 0.5 18.8284 0.5 18V2C0.5 1.17157 1.17157 0.5 2 0.5Z", :fill "var(--ls-active-primary-color)"}]
|
||||
[:path {:d "M7 5.5V0L14 7.5H9C7.89543 7.5 7 6.60457 7 5.5Z", :fill "var(--ls-active-secondary-color)"}]])
|
||||
|
||||
(def clock
|
||||
[:svg.h-5.w-5
|
||||
{:fill "currentColor", :viewBox "0 0 20 20"}
|
||||
[:path
|
||||
{:clip-rule "evenodd",
|
||||
:d
|
||||
"M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z",
|
||||
:fill-rule "evenodd"}]])
|
||||
|
||||
(def online
|
||||
(hero-icon "M8.111 16.404a5.5 5.5 0 017.778 0M12 20h.01m-7.08-7.071c3.904-3.905 10.236-3.905 14.141 0M1.394 9.393c5.857-5.857 15.355-5.857 21.213 0"))
|
||||
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
(ns frontend.extensions.video.youtube
|
||||
(:require [rum.core :as rum]
|
||||
[cljs.core.async :refer [<! >! chan go go-loop] :as a]
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.state :as state]
|
||||
[frontend.util :as util]
|
||||
[goog.object :as gobj]
|
||||
[clojure.string :as str]))
|
||||
|
||||
(defn- load-yt-script []
|
||||
(js/console.log "load yt script")
|
||||
(let [tag (js/document.createElement "script")
|
||||
first-script-tag (first (js/document.getElementsByTagName "script"))
|
||||
parent-node (.-parentNode first-script-tag)]
|
||||
(set! (.-src tag) "https://www.youtube.com/iframe_api")
|
||||
(.insertBefore parent-node tag first-script-tag)))
|
||||
|
||||
(defn load-youtube-api []
|
||||
(let [c (chan)]
|
||||
(if js/window.YT
|
||||
(a/close! c)
|
||||
(do
|
||||
(set! js/window.onYouTubeIframeAPIReady #(a/close! c))
|
||||
(load-yt-script)))
|
||||
c))
|
||||
|
||||
(defn register-player [state]
|
||||
(let [id (first (:rum/args state))
|
||||
player (js/window.YT.Player.
|
||||
(rum/dom-node state)
|
||||
(clj->js
|
||||
{:events
|
||||
{"onReady" (fn [e] (js/console.log id " ready"))}}))]
|
||||
(state/update-state! [:youtube/players]
|
||||
(fn [players]
|
||||
(assoc players id player)))))
|
||||
|
||||
(rum/defcs youtube-video <
|
||||
rum/reactive
|
||||
(rum/local nil ::player)
|
||||
{:did-mount
|
||||
(fn [state]
|
||||
(go
|
||||
(<! (load-youtube-api))
|
||||
(register-player state))
|
||||
state)}
|
||||
[state id]
|
||||
(let [width (min (- (util/get-width) 96)
|
||||
560)
|
||||
height (int (* width (/ 315 560)))]
|
||||
[:iframe
|
||||
{:id (str "youtube-player-" id)
|
||||
:allow-full-screen "allowfullscreen"
|
||||
:allow "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
|
||||
:frame-border "0"
|
||||
:src (str "https://www.youtube.com/embed/" id "?enablejsapi=1")
|
||||
:height height
|
||||
:width width}]))
|
||||
|
||||
(defn seconds->display [seconds]
|
||||
(let [seconds (int seconds)
|
||||
minutes (Math/floor (/ seconds 60))
|
||||
remaining-seconds (- seconds (* 60 minutes))
|
||||
remaining-seconds (if (zero? remaining-seconds) "00" remaining-seconds)]
|
||||
(str minutes ":" remaining-seconds)))
|
||||
|
||||
(defn dom-after-video-node? [video-node target]
|
||||
(not (zero?
|
||||
(bit-and
|
||||
(.compareDocumentPosition video-node target)
|
||||
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" "")]
|
||||
(str/includes? src "youtube.com"))))
|
||||
(filter #(dom-after-video-node? % target))
|
||||
last)]
|
||||
(let [id (gobj/get iframe "id" "")
|
||||
id (str/replace-first id #"youtube-player-" "")]
|
||||
(get (get @state/state :youtube/players) id))))
|
||||
|
||||
|
||||
(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)))}
|
||||
svg/clock
|
||||
(seconds->display seconds)])
|
||||
|
||||
(defn gen-youtube-ts-macro []
|
||||
(when-let [player (get-player (state/get-input))]
|
||||
(util/format "{{youtube-timestamp %s}}" (Math/floor (.getCurrentTime ^js player)))))
|
|
@ -160,6 +160,8 @@
|
|||
#{})
|
||||
:date-picker/date nil
|
||||
|
||||
:youtube/players {}
|
||||
|
||||
;; command palette
|
||||
:command-palette/commands []
|
||||
|
||||
|
|
Loading…
Reference in New Issue