Write upload handler

This commit is contained in:
heyarne 2020-05-10 23:27:55 +02:00
commit 9fa17f6f6c
3 changed files with 68 additions and 12 deletions

View file

@ -1,5 +1,7 @@
(ns heyarne.all-my-friends.views
(:require [reagent.core :as r]
[cljs-http.client :as http]
[cljs.core.async :refer [<! go]]
[heyarne.all-my-friends.facemesh :refer [webcam-facemesh]]
[heyarne.all-my-friends.visualize :as vis]))
@ -7,13 +9,41 @@
(defonce state (r/atom {:status :welcome-message}))
(declare dispatch)
(def events
{:welcome/continue (fn [db _]
(assoc db :status :running))
:running/snapshot (fn [db result]
(assoc-in db [:snapshots :current] result))
:running/discard-snapshot (fn [db _]
(update db :snapshots dissoc :current))})
(update db :snapshots dissoc :current))
:upload/post (fn [db post-body]
;; TODO: This is a bit dirty compared to the others because it
;; shoehorns http requests and database changes together
(let [req (http/post "/upload" {:multipart-params post-body})]
(println "request started")
(go (let [{:keys [success body error-text] :as res} (<! req)]
(prn res)
(if success
(dispatch [:upload/done (:message body)])
(dispatch [:upload/error error-text]))
(println "request finished")))
(assoc db :in-progress? true)))
:upload/error (fn [db message]
(dispatch [:message/show {:message message, :type :error}])
(dissoc db :in-progress?))
:upload/done (fn [db _]
(dispatch [:message/show {:message "Tippi toppi!", :type :success}])
(dissoc db :in-progress?))
:message/show (fn [db {:keys [message type]}]
(let [message-id (* (Math/random) (js/Date.now))]
(when (= type :success)
(js/window.setTimeout #(dispatch [:message/hide message-id]) 2500))
(assoc-in db [:messages message-id] {:type type
:message message})))
:message/hide (fn [db message-id]
(update db :messages dissoc message-id))})
(defn dispatch [[event data]]
(when-let [handler (events event)]
@ -39,6 +69,14 @@ Seit der globalen Covid19-Pandemie sind wir alle dazu gezwungen, auf physischen
(.drawImage ctx video-elem 0 0 (.-width canvas) (.-height canvas))
(.getImageData ctx 0 0 (.-width canvas) (.-height canvas))))
(defn image-data->blob [img-data cb]
(let [canvas (js/document.createElement "canvas")
ctx (.getContext canvas "2d")]
(set! (.-width canvas) (.-width img-data))
(set! (.-height canvas) (.-height img-data))
(.putImageData ctx img-data 0 0)
(.toBlob canvas cb "image/png")))
(defn preview [{{:keys [video predictions]} :snapshot}]
(let [canvas (js/document.createElement "canvas")
ctx (.getContext canvas "2d")]
@ -55,9 +93,20 @@ Seit der globalen Covid19-Pandemie sind wir alle dazu gezwungen, auf physischen
[:div#snapshot-preview.container
[:p compliment]
[preview {:snapshot current-snapshot}]
[:button {:on-click #(println "submit")} "Abschicken"]
[:button {:on-click #(image-data->blob (:video current-snapshot)
(fn [blob]
(dispatch
[:upload/post {:snapshot blob
:predictions (js/JSON.stringify (:predictions current-snapshot))}])))}
"Abschicken"]
[:button {:on-click #(dispatch [:running/discard-snapshot])} "Lieber noch eins"]]))
(defn notifications [{:keys [messages]}]
[:ul.notifications
(for [[id {:keys [type message]}] messages]
^{:key id} [:li.message {:class (name type)
:on-click #(dispatch [:message/hide id])} message])])
(defn running [{:keys [on-faces-detected halt?]}]
(let [result (atom {:video nil
:predictions nil})]
@ -75,15 +124,20 @@ Seit der globalen Covid19-Pandemie sind wir alle dazu gezwungen, auf physischen
(defn app []
(let [state @state
status (:status state)
current-snapshot (get-in state [:snapshots :current])]
messages (:messages state)
current-snapshot (get-in state [:snapshots :current])
uploading? (some? (get-in state [:http/requests "/upload"]))]
(prn messages)
[:<>
[welcome-message {:hidden? (not= :welcome-message status)}]
[notifications {:messages messages}]
(when uploading?
[:p "Bild wird hochgeladen"])
(when current-snapshot
[snapshot {:current-snapshot current-snapshot}])
(case status
:permission-rejected [:div "Sad :("]
:running [running {:on-faces-detected vis/draw-sketch
:halt? (some? current-snapshot)}]
;; default
nil)]))