mirror of
https://github.com/penpot/penpot.git
synced 2025-05-29 05:16:13 +02:00
♻️ Integrate new storage subsystem.
This commit is contained in:
parent
3d88749976
commit
ab944fb9ae
48 changed files with 950 additions and 632 deletions
|
@ -15,6 +15,7 @@
|
|||
[app.common.version :as v]
|
||||
[app.util.object :as obj]
|
||||
[app.util.dom :as dom]
|
||||
[app.util.avatars :as avatars]
|
||||
[cuerdas.core :as str]))
|
||||
|
||||
;; --- Auxiliar Functions
|
||||
|
@ -72,7 +73,7 @@
|
|||
(def worker-uri (obj/get global "appWorkerURI" "/js/worker.js"))
|
||||
(def public-uri (or (obj/get global "appPublicURI")
|
||||
(.-origin ^js js/location)))
|
||||
(def media-uri (str public-uri "/media"))
|
||||
(def media-uri (str public-uri "/assets"))
|
||||
(def version (delay (parse-version global)))
|
||||
(def target (delay (parse-target global)))
|
||||
(def browser (delay (parse-browser)))
|
||||
|
@ -85,7 +86,6 @@
|
|||
|
||||
;; --- Helper Functions
|
||||
|
||||
|
||||
(defn ^boolean check-browser? [candidate]
|
||||
(us/verify ::browser candidate)
|
||||
(= candidate @browser))
|
||||
|
@ -94,9 +94,22 @@
|
|||
(us/verify ::platform candidate)
|
||||
(= candidate @platform))
|
||||
|
||||
(defn resolve-media-path
|
||||
[path]
|
||||
(when path
|
||||
(if (str/starts-with? path "data:")
|
||||
path
|
||||
(str media-uri "/" path))))
|
||||
(defn resolve-profile-photo-url
|
||||
[{:keys [photo-id fullname name] :as profile}]
|
||||
(if (nil? photo-id)
|
||||
(avatars/generate {:name (or fullname name)})
|
||||
(str public-uri "/assets/by-id/" photo-id)))
|
||||
|
||||
(defn resolve-team-photo-url
|
||||
[{:keys [photo-id name] :as team}]
|
||||
(if (nil? photo-id)
|
||||
(avatars/generate {:name name})
|
||||
(str public-uri "/assets/by-id/" photo-id)))
|
||||
|
||||
(defn resolve-file-media
|
||||
([media]
|
||||
(resolve-file-media media false))
|
||||
([{:keys [id] :as media} thumnail?]
|
||||
(str public-uri "/assets/by-file-media-id/" id (when thumnail? "/thumbnail"))))
|
||||
|
||||
|
||||
|
|
|
@ -74,14 +74,13 @@
|
|||
(watch [_ state stream]
|
||||
(let [profile (:profile state)]
|
||||
(->> (rp/query :team params)
|
||||
(rx/map #(avatars/assoc-avatar % :name))
|
||||
(rx/map #(partial fetched %))))))))
|
||||
|
||||
(defn fetch-team-members
|
||||
[{:keys [id] :as params}]
|
||||
(us/assert ::us/uuid id)
|
||||
(letfn [(fetched [members state]
|
||||
(->> (map #(avatars/assoc-avatar % :name) members)
|
||||
(->> members
|
||||
(d/index-by :id)
|
||||
(assoc-in state [:team-members id])))]
|
||||
(ptk/reify ::fetch-team-members
|
||||
|
|
|
@ -25,10 +25,24 @@
|
|||
[cuerdas.core :as str]
|
||||
[potok.core :as ptk]))
|
||||
|
||||
;; --- Predicates
|
||||
|
||||
(defn ^boolean file?
|
||||
[o]
|
||||
(instance? js/File o))
|
||||
|
||||
(defn ^boolean blob?
|
||||
[o]
|
||||
(instance? js/Blob o))
|
||||
|
||||
|
||||
;; --- Specs
|
||||
|
||||
(s/def ::js-file #(instance? js/Blob %))
|
||||
(s/def ::js-files (s/coll-of ::js-file))
|
||||
(s/def ::blob blob?)
|
||||
(s/def ::blobs (s/coll-of ::blob))
|
||||
|
||||
(s/def ::file file?)
|
||||
(s/def ::files (s/coll-of ::file))
|
||||
|
||||
;; --- Utility functions
|
||||
|
||||
|
|
|
@ -59,9 +59,6 @@
|
|||
(update [_ state]
|
||||
(assoc state :profile
|
||||
(cond-> data
|
||||
(empty? (:photo data))
|
||||
(assoc :photo (avatars/generate {:name fullname}))
|
||||
|
||||
(nil? (:lang data))
|
||||
(assoc :lang cfg/default-language)
|
||||
|
||||
|
@ -197,7 +194,7 @@
|
|||
[{:keys [team-id] :as params}]
|
||||
(us/assert ::us/uuid team-id)
|
||||
(letfn [(fetched [users state]
|
||||
(->> (map #(avatars/assoc-avatar % :fullname) users)
|
||||
(->> users
|
||||
(d/index-by :id)
|
||||
(assoc state :users)))]
|
||||
(ptk/reify ::fetch-team-users
|
||||
|
|
|
@ -116,8 +116,7 @@
|
|||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [objects (:objects page)
|
||||
frames (extract-frames objects)
|
||||
users (map #(avatars/assoc-avatar % :fullname) users)]
|
||||
frames (extract-frames objects)]
|
||||
(assoc state
|
||||
:viewer-libraries (d/index-by :id libraries)
|
||||
:viewer-data {:project project
|
||||
|
|
|
@ -1185,8 +1185,7 @@
|
|||
(prepare-object [objects selected {:keys [type] :as obj}]
|
||||
(let [obj (maybe-translate obj objects selected)]
|
||||
(if (= type :image)
|
||||
(let [path (get-in obj [:metadata :path])
|
||||
url (cfg/resolve-media-path path)]
|
||||
(let [url (cfg/resolve-file-media (:metadata obj))]
|
||||
(->> (http/fetch-as-data-url url)
|
||||
(rx/map #(assoc obj ::data %))
|
||||
(rx/take 1)))
|
||||
|
@ -1314,7 +1313,7 @@
|
|||
(fn [blob]
|
||||
{:name (:name imgpart)
|
||||
:file-id file-id
|
||||
:content (list blob (:file-name imgpart))
|
||||
:content blob
|
||||
:is-local true}))
|
||||
(rx/mapcat #(rp/mutation! :upload-media-object %))
|
||||
(rx/map (fn [media]
|
||||
|
@ -1441,7 +1440,7 @@
|
|||
(let [file-id (get-in state [:workspace-file :id])
|
||||
params {:file-id file-id
|
||||
:local? true
|
||||
:js-files [image]}]
|
||||
:data [image]}]
|
||||
(rx/of (dwp/upload-media-objects
|
||||
(with-meta params
|
||||
{:on-success image-uploaded})))))))
|
||||
|
@ -1560,6 +1559,7 @@
|
|||
(d/export dwp/link-file-to-library)
|
||||
(d/export dwp/unlink-file-from-library)
|
||||
(d/export dwp/upload-media-objects)
|
||||
(d/export dwp/clone-media-object)
|
||||
|
||||
;; Selection
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[app.common.data :as d]
|
||||
[app.common.spec :as us]
|
||||
[app.common.uuid :as uuid]
|
||||
[app.common.pages :as cp]
|
||||
[app.common.geom.point :as gpt]
|
||||
[app.common.geom.shapes :as geom]
|
||||
[app.main.data.messages :as dm]
|
||||
|
@ -109,8 +110,9 @@
|
|||
(ptk/reify ::add-media
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [rchg {:type :add-media
|
||||
:object media}
|
||||
(let [obj (select-keys media [:id :name :width :height :mtype])
|
||||
rchg {:type :add-media
|
||||
:object obj}
|
||||
uchg {:type :del-media
|
||||
:id id}]
|
||||
(rx/of (dwc/commit-changes [rchg] [uchg] {:commit-local? true}))))))
|
||||
|
@ -370,7 +372,7 @@
|
|||
|
||||
update-new-shape
|
||||
(fn [new-shape original-shape]
|
||||
(let [new-name
|
||||
(let [new-name
|
||||
(dwc/generate-unique-name @unames (:name new-shape))]
|
||||
|
||||
(swap! unames conj new-name)
|
||||
|
|
|
@ -147,8 +147,7 @@
|
|||
(let [session {:id id
|
||||
:fullname (:fullname profile)
|
||||
:updated-at (dt/now)
|
||||
:photo-uri (or (and (:photo profile) (cfg/resolve-media-path (:photo profile)))
|
||||
(avatars/generate {:name (:fullname profile)}))}
|
||||
:photo-uri (cfg/resolve-profile-photo-url profile)}
|
||||
session (assign-color sessions session)]
|
||||
(assoc sessions id session)))
|
||||
|
||||
|
|
|
@ -239,14 +239,13 @@
|
|||
|
||||
ptk/UpdateEvent
|
||||
(update [_ state]
|
||||
(let [users (map avatars/assoc-profile-avatar users)]
|
||||
(assoc state
|
||||
:users (d/index-by :id users)
|
||||
:workspace-undo {}
|
||||
:workspace-project project
|
||||
:workspace-file file
|
||||
:workspace-data (:data file)
|
||||
:workspace-libraries (d/index-by :id libraries))))))
|
||||
(assoc state
|
||||
:users (d/index-by :id users)
|
||||
:workspace-undo {}
|
||||
:workspace-project project
|
||||
:workspace-file file
|
||||
:workspace-data (:data file)
|
||||
:workspace-libraries (d/index-by :id libraries)))))
|
||||
|
||||
|
||||
;; --- Set File shared
|
||||
|
@ -339,70 +338,108 @@
|
|||
(assoc-in state [:workspace-pages id] page))))
|
||||
|
||||
|
||||
;; --- Upload local media objects
|
||||
;; --- Upload File Media objects
|
||||
|
||||
(s/def ::local? ::us/boolean)
|
||||
(s/def ::uri ::us/string)
|
||||
(s/def ::data ::di/blobs)
|
||||
(s/def ::name ::us/string)
|
||||
(s/def ::uri ::us/string)
|
||||
(s/def ::uris (s/coll-of ::uri))
|
||||
|
||||
(s/def ::upload-media-objects-params
|
||||
(s/keys :req-un [::file-id ::local?]
|
||||
:opt-un [::uri ::di/js-files]))
|
||||
(s/def ::upload-media-objects
|
||||
(s/and
|
||||
(s/keys :req-un [::file-id ::local?]
|
||||
:opt-in [::name ::data ::uris])
|
||||
(fn [props]
|
||||
(or (contains? props :data)
|
||||
(contains? props :uris)))))
|
||||
|
||||
(defn upload-media-objects
|
||||
[{:keys [file-id local? js-files uri name] :as params}]
|
||||
(us/assert ::upload-media-objects-params params)
|
||||
(ptk/reify ::upload-media-objects
|
||||
[{:keys [file-id local? data name uris] :as params}]
|
||||
(us/assert ::upload-media-objects params)
|
||||
(ptk/reify ::upload-media-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity}} (meta params)
|
||||
|
||||
prepare-file
|
||||
(fn [blob]
|
||||
(let [name (or name (if (di/file? blob) (.-name blob) "blob"))]
|
||||
{:name name
|
||||
:file-id file-id
|
||||
:content blob
|
||||
:is-local local?}))
|
||||
|
||||
prepare-uri
|
||||
(fn [uri]
|
||||
{:file-id file-id
|
||||
:is-local local?
|
||||
:url uri
|
||||
:name name})]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dm/show {:content (tr "media.loading")
|
||||
:type :info
|
||||
:timeout nil
|
||||
:tag :media-loading}))
|
||||
(->> (if (seq uris)
|
||||
(->> (rx/from uris)
|
||||
(rx/map prepare-uri)
|
||||
(rx/mapcat #(rp/mutation! :create-file-media-object-from-url %)))
|
||||
(->> (rx/from data)
|
||||
(rx/map di/validate-file)
|
||||
(rx/map prepare-file)
|
||||
(rx/mapcat #(rp/mutation! :upload-file-media-object %))))
|
||||
(rx/do on-success)
|
||||
(rx/catch (fn [error]
|
||||
(cond
|
||||
(= (:code error) :media-type-not-allowed)
|
||||
(rx/of (dm/error (tr "errors.media-type-not-allowed")))
|
||||
|
||||
(= (:code error) :media-type-mismatch)
|
||||
(rx/of (dm/error (tr "errors.media-type-mismatch")))
|
||||
|
||||
(fn? on-error)
|
||||
(do
|
||||
(on-error error)
|
||||
(rx/empty))
|
||||
|
||||
:else
|
||||
(rx/throw error))))
|
||||
(rx/finalize (fn []
|
||||
(st/emit! (dm/hide-tag :media-loading))))))))))
|
||||
|
||||
|
||||
;; --- Upload File Media objects
|
||||
|
||||
(s/def ::object-id ::us/uuid)
|
||||
|
||||
(s/def ::clone-media-objects-params
|
||||
(s/keys :req-un [::file-id ::local? ::object-id]))
|
||||
|
||||
(defn clone-media-object
|
||||
[{:keys [file-id local? object-id] :as params}]
|
||||
(us/assert ::clone-media-objects-params params)
|
||||
(ptk/reify ::clone-media-objects
|
||||
ptk/WatchEvent
|
||||
(watch [_ state stream]
|
||||
(let [{:keys [on-success on-error]
|
||||
:or {on-success identity}} (meta params)
|
||||
|
||||
is-library (not= file-id (:id (:workspace-file state)))
|
||||
prepare-js-file
|
||||
(fn [js-file]
|
||||
{:name (.-name js-file)
|
||||
:file-id file-id
|
||||
:content js-file
|
||||
:is-local local?})
|
||||
|
||||
prepare-uri
|
||||
(fn [uri]
|
||||
{:file-id file-id
|
||||
:is-local local?
|
||||
:url uri
|
||||
:name name})]
|
||||
:or {on-success identity
|
||||
on-error identity}} (meta params)
|
||||
params {:is-local local?
|
||||
:file-id file-id
|
||||
:id object-id}]
|
||||
|
||||
(rx/concat
|
||||
(rx/of (dm/show {:content (tr "media.loading")
|
||||
:type :info
|
||||
:timeout nil
|
||||
:tag :media-loading}))
|
||||
(->> (if (string? uri)
|
||||
(->> (rx/of uri)
|
||||
(rx/map prepare-uri)
|
||||
(rx/mapcat #(rp/mutation! :add-media-object-from-url %)))
|
||||
(->> (rx/from js-files)
|
||||
(rx/map di/validate-file)
|
||||
(rx/map prepare-js-file)
|
||||
(rx/mapcat #(rp/mutation! :upload-media-object %))))
|
||||
(->> (rp/mutation! :clone-file-media-object params)
|
||||
(rx/do on-success)
|
||||
(rx/catch (fn [error]
|
||||
(cond
|
||||
(= (:code error) :media-type-not-allowed)
|
||||
(rx/of (dm/error (tr "errors.media-type-not-allowed")))
|
||||
|
||||
(= (:code error) :media-type-mismatch)
|
||||
(rx/of (dm/error (tr "errors.media-type-mismatch")))
|
||||
|
||||
(fn? on-error)
|
||||
(do
|
||||
(on-error error)
|
||||
(rx/empty))
|
||||
|
||||
:else
|
||||
(rx/throw error))))
|
||||
(rx/finalize (fn []
|
||||
(st/emit! (dm/hide-tag :media-loading))))))))))
|
||||
(rx/catch on-error)
|
||||
(rx/finalize #(st/emit! (dm/hide-tag :media-loading)))))))))
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
(->> (http/send! {:method :post :uri uri})
|
||||
(rx/mapcat handle-response))))
|
||||
|
||||
(defmethod mutation :upload-media-object
|
||||
(defmethod mutation :upload-file-media-object
|
||||
[id params]
|
||||
(let [form (js/FormData.)]
|
||||
(run! (fn [[key val]]
|
||||
|
|
|
@ -248,7 +248,7 @@
|
|||
[:div.comment
|
||||
[:div.author
|
||||
[:div.avatar
|
||||
[:img {:src (cfg/resolve-media-path (:photo owner))}]]
|
||||
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
|
||||
[:div.name
|
||||
[:div.fullname (:fullname owner)]
|
||||
[:div.timeago (dt/timeago (:modified-at comment))]]
|
||||
|
@ -366,7 +366,7 @@
|
|||
:unread (pos? (:count-unread-comments item)))}
|
||||
(:seqn item)]
|
||||
[:div.avatar
|
||||
[:img {:src (cfg/resolve-media-path (:photo owner))}]]
|
||||
[:img {:src (cfg/resolve-profile-photo-url owner)}]]
|
||||
[:div.name
|
||||
[:div.fullname (:fullname owner) ", "]
|
||||
[:div.timeago (dt/timeago (:modified-at item))]]]
|
||||
|
|
|
@ -136,8 +136,6 @@
|
|||
(mf/deps (:id team))
|
||||
(fn []
|
||||
(->> (rp/query! :teams)
|
||||
(rx/map (fn [teams]
|
||||
(mapv #(avatars/assoc-avatar % :name) teams)))
|
||||
(rx/subs #(reset! teams %)))))
|
||||
|
||||
[:ul.dropdown.teams-dropdown
|
||||
|
@ -151,7 +149,7 @@
|
|||
[:* {:key (:id team)}
|
||||
[:li.team-name {:on-click (partial go-projects (:id team))}
|
||||
[:span.team-icon
|
||||
[:img {:src (cfg/resolve-media-path (:photo team))}]]
|
||||
[:img {:src (cfg/resolve-team-photo-url team)}]]
|
||||
[:span.team-text {:title (:name team)} (:name team)]]])
|
||||
|
||||
[:hr]
|
||||
|
@ -329,7 +327,7 @@
|
|||
[:span.team-text (t locale "dashboard.default-team-name")]]
|
||||
[:div.team-name
|
||||
[:span.team-icon
|
||||
[:img {:src (cfg/resolve-media-path (:photo team))}]]
|
||||
[:img {:src (cfg/resolve-team-photo-url team)}]]
|
||||
[:span.team-text {:title (:name team)} (:name team)]])
|
||||
|
||||
[:span.switch-icon
|
||||
|
@ -427,7 +425,7 @@
|
|||
(mf/defc profile-section
|
||||
[{:keys [profile locale team] :as props}]
|
||||
(let [show (mf/use-state false)
|
||||
photo (cfg/resolve-media-path (:photo profile))
|
||||
photo (cfg/resolve-profile-photo-url profile)
|
||||
|
||||
on-click
|
||||
(mf/use-callback
|
||||
|
|
|
@ -283,7 +283,7 @@
|
|||
[:div.name (:name team)]
|
||||
[:div.icon
|
||||
[:span.update-overlay {:on-click on-image-click} i/exit]
|
||||
[:img {:src (cfg/resolve-media-path (:photo team))}]
|
||||
[:img {:src (cfg/resolve-team-photo-url team)}]
|
||||
[:& file-uploader {:accept "image/jpeg,image/png"
|
||||
:multi false
|
||||
:input-ref finput
|
||||
|
@ -292,7 +292,7 @@
|
|||
[:div.block.owner-block
|
||||
[:div.label (tr "dashboard.team-members")]
|
||||
[:div.owner
|
||||
[:span.icon [:img {:src (cfg/resolve-media-path (:photo owner))}]]
|
||||
[:span.icon [:img {:src (cfg/resolve-profile-photo-url owner)}]]
|
||||
[:span.text (str (:name owner) " (" (tr "labels.owner") ")") ]]
|
||||
[:div.summary
|
||||
[:span.icon i/user]
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
[:div.attributes-block {:key (str "image-" (:id shape))}
|
||||
[:div.attributes-image-row
|
||||
[:div.attributes-image
|
||||
[:img {:src (cfg/resolve-media-path (-> shape :metadata :path))}]]]
|
||||
[:img {:src (cfg/resolve-file-media (-> shape :metadata))}]]]
|
||||
|
||||
[:div.attributes-unit-row
|
||||
[:div.attributes-label (t locale "handoff.attributes.image.width")]
|
||||
|
@ -41,5 +41,5 @@
|
|||
(let [filename (last (str/split (-> shape :metadata :path) "/"))]
|
||||
[:a.download-button {:target "_blank"
|
||||
:download filename
|
||||
:href (cfg/resolve-media-path (-> shape :metadata :path))}
|
||||
:href (cfg/resolve-file-media (-> shape :metadata))}
|
||||
(t locale "handoff.attributes.image.download")])])))
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
(ns app.main.ui.settings.profile
|
||||
(:require
|
||||
[app.config :as cfg]
|
||||
[app.common.spec :as us]
|
||||
[app.main.data.messages :as dm]
|
||||
[app.main.data.modal :as modal]
|
||||
|
@ -91,11 +92,7 @@
|
|||
[{:keys [locale] :as props}]
|
||||
(let [file-input (mf/use-ref nil)
|
||||
profile (mf/deref refs/profile)
|
||||
photo (:photo profile)
|
||||
photo (if (or (str/empty? photo) (nil? photo))
|
||||
"images/avatar.jpg"
|
||||
(cfg/resolve-media-path photo))
|
||||
|
||||
photo (cfg/resolve-profile-photo-url profile)
|
||||
on-image-click #(dom/click (mf/ref-val file-input))
|
||||
|
||||
on-file-selected
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
|
||||
(let [shape (unchecked-get props "shape")
|
||||
{:keys [id x y width height rotation metadata]} shape
|
||||
uri (cfg/resolve-media-path (:path metadata))
|
||||
uri (cfg/resolve-file-media metadata)
|
||||
embed-resources? (mf/use-ctx muc/embed-ctx)
|
||||
data-uri (mf/use-state (when (not embed-resources?) uri))]
|
||||
data-uri (mf/use-state (when (not embed-resources?) uri))]
|
||||
|
||||
(mf/use-effect
|
||||
(mf/deps uri)
|
||||
|
|
|
@ -31,25 +31,25 @@
|
|||
|
||||
on-uploaded
|
||||
(mf/use-callback
|
||||
(fn [{:keys [id name] :as image}]
|
||||
(let [shape {:name name
|
||||
:width (:width image)
|
||||
:height (:height image)
|
||||
:metadata {:width (:width image)
|
||||
:height (:height image)
|
||||
:id (:id image)
|
||||
:path (:path image)}}
|
||||
aspect-ratio (/ (:width image) (:height image))]
|
||||
(st/emit! (dw/create-and-add-shape :image 0 0 shape)))))
|
||||
(fn [image]
|
||||
(->> {:name (:name image)
|
||||
:width (:width image)
|
||||
:height (:height image)
|
||||
:metadata {:width (:width image)
|
||||
:height (:height image)
|
||||
:mtype (:mtype image)
|
||||
:id (:id image)}}
|
||||
(dw/create-and-add-shape :image 0 0)
|
||||
(st/emit!))))
|
||||
|
||||
on-files-selected
|
||||
(mf/use-callback
|
||||
(mf/deps file)
|
||||
(fn [js-files]
|
||||
(fn [blobs]
|
||||
(st/emit! (dw/upload-media-objects
|
||||
(with-meta {:file-id (:id file)
|
||||
:local? true
|
||||
:js-files js-files}
|
||||
:data (seq blobs)}
|
||||
{:on-success on-uploaded})))))]
|
||||
|
||||
[:li.tooltip.tooltip-right
|
||||
|
|
|
@ -163,10 +163,10 @@
|
|||
on-selected
|
||||
(mf/use-callback
|
||||
(mf/deps file-id)
|
||||
(fn [js-files]
|
||||
(fn [blobs]
|
||||
(let [params (with-meta {:file-id file-id
|
||||
:local? false
|
||||
:js-files js-files}
|
||||
:data (seq blobs)}
|
||||
{:on-success on-media-uploaded})]
|
||||
(st/emit! (dw/upload-media-objects params)))))
|
||||
|
||||
|
@ -212,8 +212,8 @@
|
|||
|
||||
on-drag-start
|
||||
(mf/use-callback
|
||||
(fn [path name event]
|
||||
(dnd/set-data! event "text/uri-list" (cfg/resolve-media-path path))
|
||||
(fn [{:keys [name id]} event]
|
||||
(dnd/set-data! event "text/asset-id" (str id))
|
||||
(dnd/set-data! event "text/asset-name" name)
|
||||
(dnd/set-allowed-effect! event "move")))]
|
||||
|
||||
|
@ -234,8 +234,8 @@
|
|||
[:div.grid-cell {:key (:id object)
|
||||
:draggable true
|
||||
:on-context-menu (on-context-menu (:id object))
|
||||
:on-drag-start (partial on-drag-start (:path object) (:name object))}
|
||||
[:img {:src (cfg/resolve-media-path (:thumb-path object))
|
||||
:on-drag-start (partial on-drag-start object)}
|
||||
[:img {:src (cfg/resolve-file-media object true)
|
||||
:draggable false}] ;; Also need to add css pointer-events: none
|
||||
|
||||
#_[:div.cell-name (:name object)]
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
[app.util.object :as obj]
|
||||
[app.util.perf :as perf]
|
||||
[app.util.timers :as timers]
|
||||
[app.util.http :as http]
|
||||
[beicon.core :as rx]
|
||||
[clojure.set :as set]
|
||||
[cuerdas.core :as str]
|
||||
|
@ -437,7 +438,8 @@
|
|||
(when (or (dnd/has-type? e "app/shape")
|
||||
(dnd/has-type? e "app/component")
|
||||
(dnd/has-type? e "Files")
|
||||
(dnd/has-type? e "text/uri-list"))
|
||||
(dnd/has-type? e "text/uri-list")
|
||||
(dnd/has-type? e "text/asset-id"))
|
||||
(dom/prevent-default e))))
|
||||
|
||||
on-drag-over
|
||||
|
@ -446,24 +448,24 @@
|
|||
(when (or (dnd/has-type? e "app/shape")
|
||||
(dnd/has-type? e "app/component")
|
||||
(dnd/has-type? e "Files")
|
||||
(dnd/has-type? e "text/uri-list"))
|
||||
(dnd/has-type? e "text/uri-list")
|
||||
(dnd/has-type? e "text/asset-id"))
|
||||
(dom/prevent-default e))))
|
||||
|
||||
;; TODO: seems duplicated callback is the same as one located
|
||||
;; in left_toolbar
|
||||
on-uploaded
|
||||
(mf/use-callback
|
||||
(fn [{:keys [id name] :as image} {:keys [x y]}]
|
||||
(let [shape {:name name
|
||||
:width (:width image)
|
||||
:height (:height image)
|
||||
:x (- x (/ (:width image) 2))
|
||||
:y (- y (/ (:height image) 2))
|
||||
:metadata {:width (:width image)
|
||||
(fn [image {:keys [x y]}]
|
||||
(prn "on-uploaded" image x y)
|
||||
(let [shape {:name (:name image)
|
||||
:width (:width image)
|
||||
:height (:height image)
|
||||
:x (- x (/ (:width image) 2))
|
||||
:y (- y (/ (:height image) 2))
|
||||
:metadata {:width (:width image)
|
||||
:height (:height image)
|
||||
:id (:id image)
|
||||
:path (:path image)}}
|
||||
aspect-ratio (/ (:width image) (:height image))]
|
||||
:name (:name image)
|
||||
:id (:id image)
|
||||
:mtype (:mtype image)}}]
|
||||
(st/emit! (dw/create-and-add-shape :image x y shape)))))
|
||||
|
||||
on-drop
|
||||
|
@ -492,28 +494,36 @@
|
|||
(gpt/point final-x final-y))))
|
||||
|
||||
(dnd/has-type? event "text/uri-list")
|
||||
(let [data (dnd/get-data event "text/uri-list")
|
||||
name (dnd/get-data event "text/asset-name")
|
||||
(let [data (dnd/get-data event "text/uri-list")
|
||||
name (dnd/get-data event "text/asset-name")
|
||||
lines (str/lines data)
|
||||
urls (filter #(and (not (str/blank? %))
|
||||
(not (str/starts-with? % "#")))
|
||||
lines)]
|
||||
(->> urls
|
||||
(map (fn [uri]
|
||||
(with-meta {:file-id (:id file)
|
||||
:local? true
|
||||
:uri uri
|
||||
:name name}
|
||||
{:on-success #(on-uploaded % viewport-coord)})))
|
||||
(map dw/upload-media-objects)
|
||||
(apply st/emit!)))
|
||||
urls (filter #(and (not (str/blank? %))
|
||||
(not (str/starts-with? % "#")))
|
||||
lines)]
|
||||
(st/emit!
|
||||
(dw/upload-media-objects
|
||||
(with-meta {:file-id (:id file)
|
||||
:local? true
|
||||
:uris urls
|
||||
:name name}
|
||||
{:on-success #(on-uploaded % viewport-coord)}))))
|
||||
|
||||
(dnd/has-type? event "text/asset-id")
|
||||
(let [id (-> (dnd/get-data event "text/asset-id") uuid/uuid)
|
||||
name (dnd/get-data event "text/asset-name")
|
||||
params {:file-id (:id file)
|
||||
:local? true
|
||||
:object-id id
|
||||
:name name}]
|
||||
(st/emit! (dw/clone-media-object
|
||||
(with-meta params
|
||||
{:on-success #(on-uploaded % viewport-coord)}))))
|
||||
|
||||
:else
|
||||
(let [js-files (dnd/get-files event)
|
||||
params {:file-id (:id file)
|
||||
:local? true
|
||||
:js-files js-files
|
||||
}]
|
||||
(let [files (dnd/get-files event)
|
||||
params {:file-id (:id file)
|
||||
:local? true
|
||||
:data (seq files)}]
|
||||
(st/emit! (dw/upload-media-objects
|
||||
(with-meta params
|
||||
{:on-success #(on-uploaded % viewport-coord)}))))))))
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[app.util.object :as obj]
|
||||
["randomcolor" :as rdcolor]))
|
||||
|
||||
(defn generate
|
||||
(defn generate*
|
||||
[{:keys [name color size]
|
||||
:or {color "#000000" size 128}}]
|
||||
(let [parts (str/words (str/upper name))
|
||||
|
@ -36,13 +36,5 @@
|
|||
|
||||
(.toDataURL canvas)))
|
||||
|
||||
(defn assoc-avatar
|
||||
[{:keys [photo] :as object} key]
|
||||
(cond-> object
|
||||
(or (nil? photo) (empty? photo))
|
||||
(assoc :photo (generate {:name (get object key)}))))
|
||||
|
||||
(defn assoc-profile-avatar
|
||||
[object]
|
||||
(assoc-avatar object :fullname))
|
||||
(def generate (memoize generate*))
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue