|
1 | 1 | (ns portfolio.ui.components.canvas |
2 | 2 | (:require [clojure.string :as str] |
3 | 3 | [dumdom.core :as d] |
| 4 | + [goog.object :as o] |
4 | 5 | [portfolio.adapter :as adapter] |
5 | 6 | [portfolio.ui.actions :as actions] |
6 | 7 | [portfolio.ui.canvas.protocols :as canvas] |
|
33 | 34 | (defn render-scene [el {:keys [scene tools opt]}] |
34 | 35 | (let [iframe (get-iframe el) |
35 | 36 | canvas (some-> iframe .-contentDocument (.getElementById "canvas")) |
36 | | - error (.querySelector el ".error-container")] |
| 37 | + error (.querySelector el ".error-container") |
| 38 | + scene-id-str (->> [(namespace (:id scene)) |
| 39 | + (name (:id scene))] |
| 40 | + (remove empty?) |
| 41 | + (str/join "/")) |
| 42 | + finalize-fn (fn [] |
| 43 | + (doseq [tool tools] |
| 44 | + (try |
| 45 | + (canvas/finalize-canvas tool el opt) |
| 46 | + (catch :default e |
| 47 | + (-> (str "Failed to finalize canvas with " (:id tool)) |
| 48 | + (report-error e scene))))) |
| 49 | + (when-let [win (.-contentWindow iframe)] |
| 50 | + (.postMessage |
| 51 | + win |
| 52 | + (clj->js {:event "scene-rendered" |
| 53 | + :scene-id scene-id-str}) "*")))] |
37 | 54 | (when error |
38 | 55 | (.removeChild (.-parentNode error) error) |
39 | 56 | (set! (.. iframe -style -display) "block")) |
|
44 | 61 | (-> (str "Failed to prepare canvas with " (:id tool)) |
45 | 62 | (report-error e scene))))) |
46 | 63 | (try |
47 | | - (adapter/render-component (assoc scene :component ((:component-fn scene))) canvas) |
48 | | - (js/setTimeout |
49 | | - (fn [] |
50 | | - (doseq [tool tools] |
51 | | - (try |
52 | | - (canvas/finalize-canvas tool el opt) |
53 | | - (catch :default e |
54 | | - (-> (str "Failed to finalize canvas with " (:id tool)) |
55 | | - (report-error e scene))))) |
56 | | - (when-let [win (.-contentWindow iframe)] |
57 | | - (.postMessage |
58 | | - win |
59 | | - (clj->js {:event "scene-rendered" |
60 | | - :scene-id (->> [(namespace (:id scene)) |
61 | | - (name (:id scene))] |
62 | | - (remove empty?) |
63 | | - (str/join "/"))}) "*"))) |
64 | | - 50) |
| 64 | + (case (:render-mode scene :mount) |
| 65 | + :mount |
| 66 | + (do |
| 67 | + (adapter/render-component (assoc scene :component ((:component-fn scene))) canvas) |
| 68 | + (js/setTimeout finalize-fn 50)) |
| 69 | + |
| 70 | + :iframe |
| 71 | + (let [set-scene! #(some-> iframe .-contentWindow |
| 72 | + (.postMessage #js {:set_scene scene-id-str |
| 73 | + :opt (pr-str opt)}))] |
| 74 | + (js/window.addEventListener |
| 75 | + "message" |
| 76 | + (fn finalize [e] |
| 77 | + (when (and (identical? (.-contentWindow iframe) (.-source e)) |
| 78 | + (o/getValueByKeys e "data" "portfolio_render")) |
| 79 | + (js/window.removeEventListener "message" finalize) |
| 80 | + (js/setTimeout finalize-fn 50)))) |
| 81 | + (if (-> iframe .-contentWindow (o/get "portfolioReady")) |
| 82 | + (set-scene!) |
| 83 | + (js/window.addEventListener |
| 84 | + "message" |
| 85 | + (fn set-the-scene [e] |
| 86 | + (when (and (identical? (.-contentWindow iframe) (.-source e)) |
| 87 | + (o/getValueByKeys e "data" "portfolio_ready")) |
| 88 | + (js/window.removeEventListener "message" set-the-scene) |
| 89 | + (set-scene!))))))) |
65 | 90 | (catch :default e |
66 | 91 | (-> (str "Failed to render " (str "'" (:title scene) "'")) |
67 | 92 | (report-error e scene)))))) |
|
80 | 105 | (.appendChild (.-body doc) el))) |
81 | 106 | (f)))))) |
82 | 107 |
|
| 108 | +(defn- pad-canvas [data document] |
| 109 | + (let [[t r b l] (:viewport/padding (:opt data))] |
| 110 | + (when t (set! (.. document -body -style -paddingTop) (str t "px"))) |
| 111 | + (when r (set! (.. document -body -style -paddingBottom) (str r "px"))) |
| 112 | + (when b (set! (.. document -documentElement -style -paddingLeft) (str b "px"))) |
| 113 | + (when l (set! (.. document -documentElement -style -paddingRight) (str l "px"))))) |
| 114 | + |
83 | 115 | (defn init-canvas [el data f] |
84 | 116 | (let [iframe (get-iframe el) |
85 | 117 | document (get-iframe-document el) |
|
122 | 154 | (.appendChild head link))) |
123 | 155 |
|
124 | 156 | ;; Set padding properties |
125 | | - (let [[t r b l] (:viewport/padding (:opt data))] |
126 | | - (when t (set! (.. document -body -style -paddingTop) (str t "px"))) |
127 | | - (when r (set! (.. document -body -style -paddingBottom) (str r "px"))) |
128 | | - (when b (set! (.. document -documentElement -style -paddingLeft) (str b "px"))) |
129 | | - (when l (set! (.. document -documentElement -style -paddingRight) (str l "px")))))) |
| 157 | + (pad-canvas data document))) |
130 | 158 |
|
131 | 159 | (defn get-rendered-data [{:keys [scene opt]}] |
132 | 160 | {:rendered (:rendered-data scene) |
|
181 | 209 | :height (when (number? (:viewport/height (:opt data))) |
182 | 210 | (:viewport/height (:opt data)))}}]]) |
183 | 211 |
|
| 212 | +(d/defcomponent IframeCanvas |
| 213 | + :on-mount (fn [el data] |
| 214 | + (enqueue-render-data el data) |
| 215 | + (on-mounted |
| 216 | + (get-iframe el) |
| 217 | + (fn [] |
| 218 | + (pad-canvas data (get-iframe-document el)) |
| 219 | + (set! (.-renderFromQueue el) true) |
| 220 | + (process-render-queue el)))) |
| 221 | + :on-update (fn [el data] |
| 222 | + (enqueue-render-data el data)) |
| 223 | + [data] |
| 224 | + [:div {:style {:background (or (:background/background-color (:opt data)) |
| 225 | + "var(--canvas-bg)") |
| 226 | + :display "flex" |
| 227 | + :transition "width 0.25s, height 0.25s"}} |
| 228 | + [:iframe.canvas |
| 229 | + {:src |
| 230 | + (str (doto (new js/URL js/window.location) |
| 231 | + (set! -search (new js/URLSearchParams #js {"portfolio.embed" true})))) |
| 232 | + :title "Component scene" |
| 233 | + :style {:border "none" |
| 234 | + :flex-grow "1" |
| 235 | + :width (or (when (number? (:viewport/width (:opt data))) |
| 236 | + (:viewport/width (:opt data))) |
| 237 | + "100%") |
| 238 | + :height (when (number? (:viewport/height (:opt data))) |
| 239 | + (:viewport/height (:opt data)))}}]]) |
| 240 | + |
184 | 241 | (d/defcomponent Toolbar [{:keys [buttons]}] |
185 | 242 | [:nav {:style {:background "var(--bg)" |
186 | 243 | :color "var(--fg)" |
|
242 | 299 | (if (or (not (:component-fn (:scene data))) |
243 | 300 | (:error (:scene data))) |
244 | 301 | (Error (:error (:scene data))) |
245 | | - (Canvas data)))] |
| 302 | + (case (:render-mode (:scene data) :mount) |
| 303 | + :mount |
| 304 | + (Canvas data) |
| 305 | + :iframe |
| 306 | + (IframeCanvas data))))] |
246 | 307 | (remove nil?))]) |
247 | 308 |
|
248 | 309 | (def direction |
|
0 commit comments