(ns heyarne.all-my-friends.views (:require [reagent.core :as r] [heyarne.all-my-friends.facemesh :refer [webcam-facemesh]])) ;; minimalistic re-frame-like event handling (defonce state (r/atom {:status :welcome-message})) (def events {:welcome/continue (fn [db _] (assoc db :status :running)) :running/snapshot (fn [db result] (assoc-in db [:snapshots :current] result))}) (defn dispatch [[event data]] (when-let [handler (events event)] (js/requestAnimationFrame #(swap! state handler data)))) ;; views (defn welcome-message [{:keys [hidden?]}] [:section#welcome-message {:class (str (when hidden? "hidden"))} [:h1 "Hi Freund!"] [:p "Ich möchte dir kurz erklären, was dich hier erwartet: Seit der globalen Covid19-Pandemie sind wir alle dazu gezwungen, auf physischen Kontakt weitgehend zu verzichten. Ein Großteil der Zeit, die ich mit euch verbringe, hat sich ins Digitale verlagert."] [:p "Das fühlt sich sicher bald komplett normal an -- vorher möchte ich aber gerne irgendwas mit dem komischen Gefühl machen, das das hinterlässt."] [:p "Ich würde mich freuen, wenn du mir dabei hilfst. Folge dazu einfach den Anweisungen. Das Ergebnis wird hoffentlich eine schöne Sammlung von Webcambildern und 3D-Modellen eurer Köpfe."] [:button {:on-click #(dispatch [:welcome/continue])} "Cool cool, weiter bitte"]]) (defn video-snapshot [video-elem] (let [canvas (js/document.createElement "canvas") ctx (.getContext canvas "2d")] (set! (.-width canvas) (.-videoWidth video-elem)) (set! (.-height canvas) (.-videoHeight video-elem)) (.drawImage ctx video-elem 0 0 (.-width canvas) (.-height canvas)) (.getImageData ctx 0 0 (.-width canvas) (.-height canvas)))) (defn running [{:keys [on-faces-detected halt?]}] (let [result (atom {:video nil :predictions nil})] (fn [{:keys [on-faces-detected halt?]}] [:div.container [:p "Tippe auf den Button um ein Bild zu machen."] [webcam-facemesh {:on-faces-detected (fn [ctx video predictions] (swap! result assoc :video video :predictions predictions) (on-faces-detected ctx video predictions)) :halt? halt?}] [:button {:on-click #(dispatch [:running/snapshot (update @result :video video-snapshot)])} "Cheese"]]))) (defn app [{:keys [on-faces-detected]}] (let [state @state status (:status state) halt? (some? (get-in state [:snapshots :current]))] [:<> [welcome-message {:hidden? (not= :welcome-message status)}] (case status :permission-rejected [:div "Sad :("] :running [running {:on-faces-detected on-faces-detected :halt? halt?}] ;; default nil)]))