mirror of
https://github.com/penpot/penpot.git
synced 2025-06-06 12:52:56 +02:00
Merge pull request #988 from penpot/alotor/small-improvements
Small improvements
This commit is contained in:
commit
53cb36dd8a
22 changed files with 207 additions and 105 deletions
|
@ -40,6 +40,7 @@
|
||||||
"draft-js": "^0.11.7",
|
"draft-js": "^0.11.7",
|
||||||
"highlight.js": "^10.6.0",
|
"highlight.js": "^10.6.0",
|
||||||
"js-beautify": "^1.13.5",
|
"js-beautify": "^1.13.5",
|
||||||
|
"jszip": "^3.6.0",
|
||||||
"luxon": "^1.26.0",
|
"luxon": "^1.26.0",
|
||||||
"mousetrap": "^1.6.5",
|
"mousetrap": "^1.6.5",
|
||||||
"opentype.js": "^1.3.3",
|
"opentype.js": "^1.3.3",
|
||||||
|
|
|
@ -148,8 +148,10 @@
|
||||||
:version "1.1"
|
:version "1.1"
|
||||||
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
:xmlnsXlink "http://www.w3.org/1999/xlink"
|
||||||
:xmlns "http://www.w3.org/2000/svg"
|
:xmlns "http://www.w3.org/2000/svg"
|
||||||
:xmlns:penpot "https://penpot.app/xmlns"}
|
:xmlns:penpot "https://penpot.app/xmlns"
|
||||||
[:& background {:vbox dim :color background-color}]
|
:style {:width "100%"
|
||||||
|
:height "100%"
|
||||||
|
:background background-color}}
|
||||||
(for [item shapes]
|
(for [item shapes]
|
||||||
(let [frame? (= (:type item) :frame)]
|
(let [frame? (= (:type item) :frame)]
|
||||||
(cond
|
(cond
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
(fn [{:keys [status body] :as response}]
|
(fn [{:keys [status body] :as response}]
|
||||||
(js/console.log status body)
|
(js/console.log status body)
|
||||||
(if (= status 200)
|
(if (= status 200)
|
||||||
(we/trigger-download (:name shape) body)
|
(dom/trigger-download (:name shape) body)
|
||||||
(st/emit! (dm/error (t locale "errors.unexpected-error")))))
|
(st/emit! (dm/error (t locale "errors.unexpected-error")))))
|
||||||
(constantly nil)
|
(constantly nil)
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -75,7 +75,7 @@
|
||||||
:y y
|
:y y
|
||||||
:width width
|
:width width
|
||||||
:height height
|
:height height
|
||||||
:style {:fill "transparent"
|
:style {:fill "none"
|
||||||
:stroke select-color
|
:stroke select-color
|
||||||
:stroke-width selection-rect-width}}]]))
|
:stroke-width selection-rect-width}}]]))
|
||||||
|
|
||||||
|
|
|
@ -177,7 +177,7 @@
|
||||||
:y y
|
:y y
|
||||||
:width width
|
:width width
|
||||||
:height height
|
:height height
|
||||||
:style {:fill "transparent"
|
:style {:fill "none"
|
||||||
:stroke hover-color
|
:stroke hover-color
|
||||||
:stroke-width selection-rect-width}}]]))
|
:stroke-width selection-rect-width}}]]))
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@
|
||||||
;; we setup the default fill as transparent (instead of black)
|
;; we setup the default fill as transparent (instead of black)
|
||||||
(and (not (contains? shape :svg-attrs))
|
(and (not (contains? shape :svg-attrs))
|
||||||
(not (#{ :svg-raw :group } (:type shape))))
|
(not (#{ :svg-raw :group } (:type shape))))
|
||||||
{:fill "transparent"}
|
{:fill "none"}
|
||||||
|
|
||||||
:else
|
:else
|
||||||
{})
|
{})
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
#js {:d pdata}))]
|
#js {:d pdata}))]
|
||||||
(if background?
|
(if background?
|
||||||
[:g
|
[:g
|
||||||
[:path {:stroke "transparent"
|
[:path {:stroke "none"
|
||||||
:fill "transparent"
|
:fill "none"
|
||||||
:stroke-width "20px"
|
:stroke-width "20px"
|
||||||
:d pdata}]
|
:d pdata}]
|
||||||
[:& shape-custom-stroke {:shape shape
|
[:& shape-custom-stroke {:shape shape
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
:height height
|
:height height
|
||||||
:transform (or transform "none")
|
:transform (or transform "none")
|
||||||
:style {:stroke color
|
:style {:stroke color
|
||||||
:fill "transparent"
|
:fill "none"
|
||||||
:stroke-width "1px"
|
:stroke-width "1px"
|
||||||
:pointer-events "none"}}])
|
:pointer-events "none"}}])
|
||||||
|
|
||||||
|
|
|
@ -86,10 +86,11 @@
|
||||||
:on-mouse-down on-mouse-down
|
:on-mouse-down on-mouse-down
|
||||||
:on-mouse-enter on-enter
|
:on-mouse-enter on-enter
|
||||||
:on-mouse-leave on-leave
|
:on-mouse-leave on-leave
|
||||||
|
:pointer-events (when-not preview? "visible")
|
||||||
:style {:cursor (cond
|
:style {:cursor (cond
|
||||||
(= edit-mode :draw) cur/pen-node
|
(= edit-mode :draw) cur/pen-node
|
||||||
(= edit-mode :move) cur/pointer-node)
|
(= edit-mode :move) cur/pointer-node)
|
||||||
:fill "transparent"}}]]))
|
:fill "none"}}]]))
|
||||||
|
|
||||||
(mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode snap-angle?]}]
|
(mf/defc path-handler [{:keys [index prefix point handler zoom selected? hover? edit-mode snap-angle?]}]
|
||||||
(when (and point handler)
|
(when (and point handler)
|
||||||
|
@ -111,7 +112,7 @@
|
||||||
(= edit-mode :move)
|
(= edit-mode :move)
|
||||||
(st/emit! (drp/start-move-handler index prefix))))]
|
(st/emit! (drp/start-move-handler index prefix))))]
|
||||||
|
|
||||||
[:g.handler {:pointer-events (when (= edit-mode :draw))}
|
[:g.handler {:pointer-events (if (= edit-mode :draw) "none" "visible")}
|
||||||
[:line
|
[:line
|
||||||
{:x1 (:x point)
|
{:x1 (:x point)
|
||||||
:y1 (:y point)
|
:y1 (:y point)
|
||||||
|
@ -147,12 +148,12 @@
|
||||||
:on-mouse-enter on-enter
|
:on-mouse-enter on-enter
|
||||||
:on-mouse-leave on-leave
|
:on-mouse-leave on-leave
|
||||||
:style {:cursor (when (= edit-mode :move) cur/pointer-move)
|
:style {:cursor (when (= edit-mode :move) cur/pointer-move)
|
||||||
:fill "transparent"}}]])))
|
:fill "none"}}]])))
|
||||||
|
|
||||||
(mf/defc path-preview [{:keys [zoom command from]}]
|
(mf/defc path-preview [{:keys [zoom command from]}]
|
||||||
[:g.preview {:style {:pointer-events "none"}}
|
[:g.preview {:style {:pointer-events "none"}}
|
||||||
(when (not= :move-to (:command command))
|
(when (not= :move-to (:command command))
|
||||||
[:path {:style {:fill "transparent"
|
[:path {:style {:fill "none"
|
||||||
:stroke pc/black-color
|
:stroke pc/black-color
|
||||||
:stroke-width (/ 1 zoom)
|
:stroke-width (/ 1 zoom)
|
||||||
:stroke-dasharray (/ 4 zoom)}
|
:stroke-dasharray (/ 4 zoom)}
|
||||||
|
@ -274,6 +275,7 @@
|
||||||
[:g.drag-handler {:pointer-events "none"}
|
[:g.drag-handler {:pointer-events "none"}
|
||||||
[:& path-handler {:point last-p
|
[:& path-handler {:point last-p
|
||||||
:handler drag-handler
|
:handler drag-handler
|
||||||
|
:edit-mode edit-mode
|
||||||
:zoom zoom}]])
|
:zoom zoom}]])
|
||||||
|
|
||||||
(when @hover-point
|
(when @hover-point
|
||||||
|
@ -325,6 +327,7 @@
|
||||||
(when prev-handler
|
(when prev-handler
|
||||||
[:g.prev-handler {:pointer-events "none"}
|
[:g.prev-handler {:pointer-events "none"}
|
||||||
[:& path-handler {:point last-p
|
[:& path-handler {:point last-p
|
||||||
|
:edit-mode edit-mode
|
||||||
:handler prev-handler
|
:handler prev-handler
|
||||||
:zoom zoom}]])
|
:zoom zoom}]])
|
||||||
|
|
||||||
|
|
|
@ -29,21 +29,6 @@
|
||||||
:name (:name shape)
|
:name (:name shape)
|
||||||
:exports exports}))
|
:exports exports}))
|
||||||
|
|
||||||
(defn- trigger-download
|
|
||||||
[filename blob]
|
|
||||||
(let [link (dom/create-element "a")
|
|
||||||
uri (dom/create-uri blob)
|
|
||||||
extension (dom/mtype->extension (.-type ^js blob))
|
|
||||||
filename (if extension
|
|
||||||
(str filename "." extension)
|
|
||||||
filename)]
|
|
||||||
(obj/set! link "href" uri)
|
|
||||||
(obj/set! link "download" filename)
|
|
||||||
(obj/set! (.-style ^js link) "display" "none")
|
|
||||||
(.appendChild (.-body ^js js/document) link)
|
|
||||||
(.click link)
|
|
||||||
(.remove link)))
|
|
||||||
|
|
||||||
(mf/defc exports-menu
|
(mf/defc exports-menu
|
||||||
[{:keys [shape page-id file-id] :as props}]
|
[{:keys [shape page-id file-id] :as props}]
|
||||||
(let [locale (mf/deref i18n/locale)
|
(let [locale (mf/deref i18n/locale)
|
||||||
|
@ -64,7 +49,7 @@
|
||||||
(->> (request-export (assoc shape :page-id page-id :file-id file-id) exports)
|
(->> (request-export (assoc shape :page-id page-id :file-id file-id) exports)
|
||||||
(rx/subs
|
(rx/subs
|
||||||
(fn [body]
|
(fn [body]
|
||||||
(trigger-download filename body))
|
(dom/trigger-download filename body))
|
||||||
(fn [error]
|
(fn [error]
|
||||||
(swap! loading? not)
|
(swap! loading? not)
|
||||||
(st/emit! (dm/error (tr "errors.unexpected-error"))))
|
(st/emit! (dm/error (tr "errors.unexpected-error"))))
|
||||||
|
|
|
@ -45,6 +45,6 @@
|
||||||
:width width
|
:width width
|
||||||
:height height
|
:height height
|
||||||
:style {:stroke "#1FDEA7"
|
:style {:stroke "#1FDEA7"
|
||||||
:fill "transparent"
|
:fill "none"
|
||||||
:stroke-width (/ 1 zoom)}}])))
|
:stroke-width (/ 1 zoom)}}])))
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
:opacity color-opacity}
|
:opacity color-opacity}
|
||||||
#js {:stroke color-value
|
#js {:stroke color-value
|
||||||
:strokeOpacity color-opacity
|
:strokeOpacity color-opacity
|
||||||
:fill "transparent"})]
|
:fill "none"})]
|
||||||
[:g.grid
|
[:g.grid
|
||||||
(for [{:keys [x y width height]} (gg/grid-areas frame grid)]
|
(for [{:keys [x y width height]} (gg/grid-areas frame grid)]
|
||||||
(do
|
(do
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
"translate(" (* zoom x) ", " (* zoom y) ")")}]
|
"translate(" (* zoom x) ", " (* zoom y) ")")}]
|
||||||
(when arrow-dir
|
(when arrow-dir
|
||||||
[:path {:stroke "#31EFB8"
|
[:path {:stroke "#31EFB8"
|
||||||
:fill "transparent"
|
:fill "none"
|
||||||
:stroke-width 2
|
:stroke-width 2
|
||||||
:d arrow-pdata
|
:d arrow-pdata
|
||||||
:transform (str
|
:transform (str
|
||||||
|
@ -134,14 +134,16 @@
|
||||||
|
|
||||||
(if-not selected?
|
(if-not selected?
|
||||||
[:path {:stroke "#B1B2B5"
|
[:path {:stroke "#B1B2B5"
|
||||||
:fill "transparent"
|
:fill "none"
|
||||||
|
:pointer-events "visible"
|
||||||
:stroke-width (/ 2 zoom)
|
:stroke-width (/ 2 zoom)
|
||||||
:d pdata
|
:d pdata
|
||||||
:on-mouse-down #(on-mouse-down % orig-shape selected)}]
|
:on-mouse-down #(on-mouse-down % orig-shape selected)}]
|
||||||
|
|
||||||
[:g {:on-mouse-down #(on-mouse-down % orig-shape selected)}
|
[:g {:on-mouse-down #(on-mouse-down % orig-shape selected)}
|
||||||
[:path {:stroke "#31EFB8"
|
[:path {:stroke "#31EFB8"
|
||||||
:fill "transparent"
|
:fill "none"
|
||||||
|
:pointer-events "visible"
|
||||||
:stroke-width (/ 2 zoom)
|
:stroke-width (/ 2 zoom)
|
||||||
:d pdata}]
|
:d pdata}]
|
||||||
[:& interaction-marker {:x orig-x
|
[:& interaction-marker {:x orig-x
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
:path "path"
|
:path "path"
|
||||||
"rect")
|
"rect")
|
||||||
|
|
||||||
common {:fill "transparent"
|
common {:fill "none"
|
||||||
:stroke color
|
:stroke color
|
||||||
:strokeWidth (/ 1 zoom)
|
:strokeWidth (/ 1 zoom)
|
||||||
:pointerEvents "none"
|
:pointerEvents "none"
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
:on-mouse-down on-move-selected
|
:on-mouse-down on-move-selected
|
||||||
:style {:stroke color
|
:style {:stroke color
|
||||||
:stroke-width (/ selection-rect-width zoom)
|
:stroke-width (/ selection-rect-width zoom)
|
||||||
:fill "transparent"}}])))
|
:fill "none"}}])))
|
||||||
|
|
||||||
(defn- handlers-for-selection [{:keys [x y width height]} {:keys [type]} zoom]
|
(defn- handlers-for-selection [{:keys [x y width height]} {:keys [type]} zoom]
|
||||||
(let [zoom-width (* width zoom)
|
(let [zoom-width (* width zoom)
|
||||||
|
@ -142,7 +142,7 @@
|
||||||
:y y
|
:y y
|
||||||
:width size
|
:width size
|
||||||
:height size
|
:height size
|
||||||
:fill (if (debug? :rotation-handler) "blue" "transparent")
|
:fill (if (debug? :rotation-handler) "blue" "none")
|
||||||
:transform transform
|
:transform transform
|
||||||
:on-mouse-down on-rotate}]))
|
:on-mouse-down on-rotate}]))
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@
|
||||||
:width resize-point-circle-radius
|
:width resize-point-circle-radius
|
||||||
:height resize-point-circle-radius
|
:height resize-point-circle-radius
|
||||||
:transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy'))
|
:transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy'))
|
||||||
:style {:fill (if (debug? :resize-handler) "red" "transparent")
|
:style {:fill (if (debug? :resize-handler) "red" "none")
|
||||||
:cursor cursor}
|
:cursor cursor}
|
||||||
:on-mouse-down #(on-resize {:x cx' :y cy'} %)}])
|
:on-mouse-down #(on-resize {:x cx' :y cy'} %)}])
|
||||||
|
|
||||||
|
@ -187,7 +187,7 @@
|
||||||
:r (/ resize-point-circle-radius zoom)
|
:r (/ resize-point-circle-radius zoom)
|
||||||
:cx cx'
|
:cx cx'
|
||||||
:cy cy'
|
:cy cy'
|
||||||
:style {:fill (if (debug? :resize-handler) "red" "transparent")
|
:style {:fill (if (debug? :resize-handler) "red" "none")
|
||||||
:cursor cursor}}])
|
:cursor cursor}}])
|
||||||
)]))
|
)]))
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@
|
||||||
:transform (gmt/multiply transform
|
:transform (gmt/multiply transform
|
||||||
(gmt/rotate-matrix angle (gpt/point x y)))
|
(gmt/rotate-matrix angle (gpt/point x y)))
|
||||||
:on-mouse-down #(on-resize res-point %)
|
:on-mouse-down #(on-resize res-point %)
|
||||||
:style {:fill (if (debug? :resize-handler) "yellow" "transparent")
|
:style {:fill (if (debug? :resize-handler) "yellow" "none")
|
||||||
:cursor (if (#{:left :right} position)
|
:cursor (if (#{:left :right} position)
|
||||||
(cur/resize-ew rotation)
|
(cur/resize-ew rotation)
|
||||||
(cur/resize-ns rotation)) }}]))
|
(cur/resize-ns rotation)) }}]))
|
||||||
|
@ -245,7 +245,7 @@
|
||||||
transform (geom/transform-matrix shape {:no-flip true})]
|
transform (geom/transform-matrix shape {:no-flip true})]
|
||||||
|
|
||||||
(when (not (#{:move :rotate} current-transform))
|
(when (not (#{:move :rotate} current-transform))
|
||||||
[:g.controls {:pointer-events (when disable-handlers "none")}
|
[:g.controls {:pointer-events (if disable-handlers "none" "visible")}
|
||||||
|
|
||||||
;; Selection rect
|
;; Selection rect
|
||||||
[:& selection-rect {:rect selrect
|
[:& selection-rect {:rect selrect
|
||||||
|
@ -282,10 +282,11 @@
|
||||||
:transform (geom/transform-matrix shape)
|
:transform (geom/transform-matrix shape)
|
||||||
:width width
|
:width width
|
||||||
:height height
|
:height height
|
||||||
|
:pointer-events "visible"
|
||||||
:style {:stroke color
|
:style {:stroke color
|
||||||
:stroke-width "0.5"
|
:stroke-width "0.5"
|
||||||
:stroke-opacity "1"
|
:stroke-opacity "1"
|
||||||
:fill "transparent"}}]]))
|
:fill "none"}}]]))
|
||||||
|
|
||||||
(mf/defc multiple-selection-handlers
|
(mf/defc multiple-selection-handlers
|
||||||
[{:keys [shapes selected zoom color disable-handlers on-move-selected] :as props}]
|
[{:keys [shapes selected zoom color disable-handlers on-move-selected] :as props}]
|
||||||
|
|
|
@ -26,3 +26,7 @@
|
||||||
(defn ask-buffered!
|
(defn ask-buffered!
|
||||||
[message]
|
[message]
|
||||||
(uw/ask-buffered! instance message))
|
(uw/ask-buffered! instance message))
|
||||||
|
|
||||||
|
(defn ask-many!
|
||||||
|
[message]
|
||||||
|
(uw/ask-many! instance message))
|
||||||
|
|
|
@ -54,6 +54,10 @@
|
||||||
[id]
|
[id]
|
||||||
(dom/getElement id))
|
(dom/getElement id))
|
||||||
|
|
||||||
|
(defn get-elements-by-tag
|
||||||
|
[node tag]
|
||||||
|
(.getElementsByTagName node tag))
|
||||||
|
|
||||||
(defn stop-propagation
|
(defn stop-propagation
|
||||||
[e]
|
[e]
|
||||||
(when e
|
(when e
|
||||||
|
@ -279,13 +283,14 @@
|
||||||
(defn mtype->extension [mtype]
|
(defn mtype->extension [mtype]
|
||||||
;; https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
|
;; https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types
|
||||||
(case mtype
|
(case mtype
|
||||||
"image/apng" "apng"
|
"image/apng" "apng"
|
||||||
"image/avif" "avif"
|
"image/avif" "avif"
|
||||||
"image/gif" "gif"
|
"image/gif" "gif"
|
||||||
"image/jpeg" "jpg"
|
"image/jpeg" "jpg"
|
||||||
"image/png" "png"
|
"image/png" "png"
|
||||||
"image/svg+xml" "svg"
|
"image/svg+xml" "svg"
|
||||||
"image/webp" "webp"
|
"image/webp" "webp"
|
||||||
|
"application/zip" "zip"
|
||||||
nil))
|
nil))
|
||||||
|
|
||||||
(defn set-attribute [^js node ^string attr value]
|
(defn set-attribute [^js node ^string attr value]
|
||||||
|
@ -311,3 +316,21 @@
|
||||||
(>= (.-left rect) 0)
|
(>= (.-left rect) 0)
|
||||||
(<= (.-bottom rect) height)
|
(<= (.-bottom rect) height)
|
||||||
(<= (.-right rect) width))))
|
(<= (.-right rect) width))))
|
||||||
|
|
||||||
|
(defn trigger-download-uri
|
||||||
|
[filename mtype uri]
|
||||||
|
(let [link (create-element "a")
|
||||||
|
extension (mtype->extension mtype)
|
||||||
|
filename (if extension
|
||||||
|
(str filename "." extension)
|
||||||
|
filename)]
|
||||||
|
(obj/set! link "href" uri)
|
||||||
|
(obj/set! link "download" filename)
|
||||||
|
(obj/set! (.-style ^js link) "display" "none")
|
||||||
|
(.appendChild (.-body ^js js/document) link)
|
||||||
|
(.click link)
|
||||||
|
(.remove link)))
|
||||||
|
|
||||||
|
(defn trigger-download
|
||||||
|
[filename blob]
|
||||||
|
(trigger-download-uri filename (.-type ^js blob) (dom/create-uri blob)))
|
||||||
|
|
|
@ -14,14 +14,25 @@
|
||||||
(declare handle-response)
|
(declare handle-response)
|
||||||
(defrecord Worker [instance stream])
|
(defrecord Worker [instance stream])
|
||||||
|
|
||||||
(defn- send-message! [worker {sender-id :sender-id :as message}]
|
(defn- send-message!
|
||||||
(let [data (t/encode message)
|
([worker message]
|
||||||
instance (:instance worker)]
|
(send-message! worker message nil))
|
||||||
(.postMessage instance data)
|
|
||||||
(->> (:stream worker)
|
([worker {sender-id :sender-id :as message} {:keys [many?] :or {many? false}}]
|
||||||
(rx/filter #(= (:reply-to %) sender-id))
|
(let [take-messages
|
||||||
(rx/take 1)
|
(fn [ob]
|
||||||
(rx/map handle-response))))
|
(if many?
|
||||||
|
(rx/take-while #(not (:completed %)) ob)
|
||||||
|
(rx/take 1 ob)))
|
||||||
|
|
||||||
|
data (t/encode message)
|
||||||
|
instance (:instance worker)]
|
||||||
|
|
||||||
|
(.postMessage instance data)
|
||||||
|
(->> (:stream worker)
|
||||||
|
(rx/filter #(= (:reply-to %) sender-id))
|
||||||
|
(take-messages)
|
||||||
|
(rx/map handle-response)))))
|
||||||
|
|
||||||
(defn ask!
|
(defn ask!
|
||||||
[worker message]
|
[worker message]
|
||||||
|
@ -30,6 +41,14 @@
|
||||||
{:sender-id (uuid/next)
|
{:sender-id (uuid/next)
|
||||||
:payload message}))
|
:payload message}))
|
||||||
|
|
||||||
|
(defn ask-many!
|
||||||
|
[worker message]
|
||||||
|
(send-message!
|
||||||
|
worker
|
||||||
|
{:sender-id (uuid/next)
|
||||||
|
:payload message}
|
||||||
|
{:many? true}))
|
||||||
|
|
||||||
(defn ask-buffered!
|
(defn ask-buffered!
|
||||||
[worker message]
|
[worker message]
|
||||||
(send-message!
|
(send-message!
|
||||||
|
|
|
@ -6,14 +6,47 @@
|
||||||
|
|
||||||
(ns app.util.zip
|
(ns app.util.zip
|
||||||
"Helpers for make zip file (using jszip)."
|
"Helpers for make zip file (using jszip)."
|
||||||
(:require [vendor.jszip]
|
(:require
|
||||||
[beicon.core :as rx]))
|
["jszip" :as zip]
|
||||||
|
[app.common.data :as d]
|
||||||
|
[beicon.core :as rx]
|
||||||
|
[promesa.core :as p]))
|
||||||
|
|
||||||
(defn build
|
(defn compress-files
|
||||||
[files]
|
[files]
|
||||||
(letfn [(attach-file [zobj [name content]]
|
(letfn [(attach-file [zobj [name content]]
|
||||||
(.file zobj name content))]
|
(.file zobj name content))]
|
||||||
(let [zobj (js/JSZip.)]
|
(let [zobj (zip.)]
|
||||||
(run! (partial attach-file zobj) files)
|
(run! (partial attach-file zobj) files)
|
||||||
(->> (.generateAsync zobj #js {:type "blob"})
|
(->> (.generateAsync zobj #js {:type "blob"})
|
||||||
(rx/from)))))
|
(rx/from)))))
|
||||||
|
|
||||||
|
(defn extract-files
|
||||||
|
"Creates a stream that will emit values for every file in the zip"
|
||||||
|
[file]
|
||||||
|
(rx/create
|
||||||
|
(fn [subs]
|
||||||
|
(let [process-entry
|
||||||
|
(fn [path entry]
|
||||||
|
(if (.-dir entry)
|
||||||
|
(rx/push! subs {:dir path})
|
||||||
|
(p/then
|
||||||
|
(.async entry "text")
|
||||||
|
(fn [content]
|
||||||
|
(rx/push! subs
|
||||||
|
{:path path
|
||||||
|
:content content})))))]
|
||||||
|
|
||||||
|
(p/let [response (js/fetch file)
|
||||||
|
data (.blob response)
|
||||||
|
content (zip/loadAsync data)]
|
||||||
|
|
||||||
|
(let [promises (atom [])]
|
||||||
|
(.forEach content
|
||||||
|
(fn [path entry]
|
||||||
|
(let [current (process-entry path entry)]
|
||||||
|
(swap! promises conj current))))
|
||||||
|
|
||||||
|
(p/then (p/all @promises)
|
||||||
|
#(rx/end! subs))))
|
||||||
|
nil))))
|
||||||
|
|
|
@ -43,35 +43,42 @@
|
||||||
"Process the message and returns to the client"
|
"Process the message and returns to the client"
|
||||||
[{:keys [sender-id payload] :as message}]
|
[{:keys [sender-id payload] :as message}]
|
||||||
(us/assert ::message message)
|
(us/assert ::message message)
|
||||||
(try
|
(letfn [(post [msg]
|
||||||
(let [result (impl/handler payload)]
|
(let [msg (-> msg (assoc :reply-to sender-id) (t/encode))]
|
||||||
(cond
|
(.postMessage js/self msg)))
|
||||||
(p/promise? result)
|
|
||||||
(p/handle result
|
|
||||||
(fn [msg]
|
|
||||||
(.postMessage js/self (t/encode
|
|
||||||
{:reply-to sender-id
|
|
||||||
:payload msg})))
|
|
||||||
(fn [err]
|
|
||||||
(.postMessage js/self (t/encode
|
|
||||||
{:reply-to sender-id
|
|
||||||
:error {:data (ex-data err)
|
|
||||||
:message (ex-message err)}}))))
|
|
||||||
|
|
||||||
(or (rx/observable? result)
|
(reply [result]
|
||||||
(rx/subject? result))
|
(post {:payload result}))
|
||||||
(throw (ex-info "not implemented" {}))
|
|
||||||
|
|
||||||
:else
|
(reply-error [err]
|
||||||
(.postMessage js/self (t/encode
|
(.error js/console "error" err)
|
||||||
{:reply-to sender-id
|
(post {:error {:data (ex-data err)
|
||||||
:payload result}))))
|
:message (ex-message err)}}))
|
||||||
(catch :default e
|
|
||||||
(.error js/console "error" e)
|
(reply-completed
|
||||||
(let [message {:reply-to sender-id
|
([] (reply-completed nil))
|
||||||
:error {:data (ex-data e)
|
([msg] (post {:payload msg
|
||||||
:message (ex-message e)}}]
|
:completed true})))]
|
||||||
(.postMessage js/self (t/encode message))))))
|
|
||||||
|
(try
|
||||||
|
(let [result (impl/handler payload)
|
||||||
|
promise? (p/promise? result)
|
||||||
|
stream? (or (rx/observable? result) (rx/subject? result))]
|
||||||
|
|
||||||
|
(cond
|
||||||
|
promise?
|
||||||
|
(-> result
|
||||||
|
(p/then reply-completed)
|
||||||
|
(p/catch reply-error))
|
||||||
|
|
||||||
|
stream?
|
||||||
|
(rx/subscribe result reply reply-error reply-completed)
|
||||||
|
|
||||||
|
:else
|
||||||
|
(reply result)))
|
||||||
|
|
||||||
|
(catch :default err
|
||||||
|
(reply-error err)))))
|
||||||
|
|
||||||
(defn- drop-message
|
(defn- drop-message
|
||||||
"Sends to the client a notifiction that its messages have been dropped"
|
"Sends to the client a notifiction that its messages have been dropped"
|
||||||
|
|
|
@ -31,17 +31,12 @@
|
||||||
(defn- request-page
|
(defn- request-page
|
||||||
[file-id page-id]
|
[file-id page-id]
|
||||||
(let [uri "/api/rpc/query/page"]
|
(let [uri "/api/rpc/query/page"]
|
||||||
(p/create
|
(->> (http/send!
|
||||||
(fn [resolve reject]
|
{:uri uri
|
||||||
(->> (http/send! {:uri uri
|
:query {:file-id file-id :id page-id :strip-thumbnails true}
|
||||||
:query {:file-id file-id :id page-id :strip-thumbnails true}
|
:method :get})
|
||||||
:method :get})
|
(rx/map http/conditional-decode-transit)
|
||||||
(rx/map http/conditional-decode-transit)
|
(rx/mapcat handle-response))))
|
||||||
(rx/mapcat handle-response)
|
|
||||||
(rx/subs (fn [body]
|
|
||||||
(resolve body))
|
|
||||||
(fn [error]
|
|
||||||
(reject error))))))))
|
|
||||||
|
|
||||||
(defonce cache (atom {}))
|
(defonce cache (atom {}))
|
||||||
|
|
||||||
|
@ -57,8 +52,8 @@
|
||||||
|
|
||||||
(defmethod impl/handler :thumbnails/generate
|
(defmethod impl/handler :thumbnails/generate
|
||||||
[{:keys [file-id page-id] :as message}]
|
[{:keys [file-id page-id] :as message}]
|
||||||
(p/then
|
(->> (request-page file-id page-id)
|
||||||
(request-page file-id page-id)
|
(rx/map
|
||||||
(fn [data]
|
(fn [data]
|
||||||
{:svg (render-page data #{file-id page-id})
|
{:svg (render-page data #{file-id page-id})
|
||||||
:fonts @fonts/loaded})))
|
:fonts @fonts/loaded}))))
|
||||||
|
|
|
@ -2375,6 +2375,11 @@ ieee754@^1.1.4:
|
||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||||
|
|
||||||
|
immediate@~3.0.5:
|
||||||
|
version "3.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||||
|
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
|
||||||
|
|
||||||
immutable@~3.7.4:
|
immutable@~3.7.4:
|
||||||
version "3.7.6"
|
version "3.7.6"
|
||||||
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b"
|
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.7.6.tgz#13b4d3cb12befa15482a26fe1b2ebae640071e4b"
|
||||||
|
@ -2838,6 +2843,16 @@ jsprim@^1.2.2:
|
||||||
json-schema "0.2.3"
|
json-schema "0.2.3"
|
||||||
verror "1.10.0"
|
verror "1.10.0"
|
||||||
|
|
||||||
|
jszip@^3.6.0:
|
||||||
|
version "3.6.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.6.0.tgz#839b72812e3f97819cc13ac4134ffced95dd6af9"
|
||||||
|
integrity sha512-jgnQoG9LKnWO3mnVNBnfhkh0QknICd1FGSrXcgrl67zioyJ4wgx25o9ZqwNtrROSflGBCGYnJfjrIyRIby1OoQ==
|
||||||
|
dependencies:
|
||||||
|
lie "~3.3.0"
|
||||||
|
pako "~1.0.2"
|
||||||
|
readable-stream "~2.3.6"
|
||||||
|
set-immediate-shim "~1.0.1"
|
||||||
|
|
||||||
just-debounce@^1.0.0:
|
just-debounce@^1.0.0:
|
||||||
version "1.1.0"
|
version "1.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.1.0.tgz#2f81a3ad4121a76bc7cb45dbf704c0d76a8e5ddf"
|
resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.1.0.tgz#2f81a3ad4121a76bc7cb45dbf704c0d76a8e5ddf"
|
||||||
|
@ -2920,6 +2935,13 @@ lead@^1.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
flush-write-stream "^1.0.2"
|
flush-write-stream "^1.0.2"
|
||||||
|
|
||||||
|
lie@~3.3.0:
|
||||||
|
version "3.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
|
||||||
|
integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
|
||||||
|
dependencies:
|
||||||
|
immediate "~3.0.5"
|
||||||
|
|
||||||
liftoff@^3.1.0:
|
liftoff@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3"
|
resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3"
|
||||||
|
@ -3762,7 +3784,7 @@ p-try@^2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||||
|
|
||||||
pako@~1.0.5:
|
pako@~1.0.2, pako@~1.0.5:
|
||||||
version "1.0.11"
|
version "1.0.11"
|
||||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
||||||
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
|
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
|
||||||
|
@ -4521,6 +4543,11 @@ set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||||
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||||
|
|
||||||
|
set-immediate-shim@~1.0.1:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
|
||||||
|
integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
|
||||||
|
|
||||||
set-value@^2.0.0, set-value@^2.0.1:
|
set-value@^2.0.0, set-value@^2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
|
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue