penpot/frontend/src/app/main/ui/handoff.cljs
2021-01-14 11:48:32 +01:00

135 lines
4.2 KiB
Clojure

;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; This Source Code Form is "Incompatible With Secondary Licenses", as
;; defined by the Mozilla Public License, v. 2.0.
;;
;; Copyright (c) 2020 UXBOX Labs SL
(ns app.main.ui.handoff
(:require
[app.common.exceptions :as ex]
[app.main.data.viewer :as dv]
[app.main.refs :as refs]
[app.main.store :as st]
[app.main.ui.components.fullscreen :as fs]
[app.main.ui.handoff.left-sidebar :refer [left-sidebar]]
[app.main.ui.handoff.render :refer [render-frame-svg]]
[app.main.ui.handoff.right-sidebar :refer [right-sidebar]]
[app.main.ui.hooks :as hooks]
[app.main.ui.icons :as i]
[app.main.ui.keyboard :as kbd]
[app.main.ui.viewer.header :refer [header]]
[app.main.ui.viewer.thumbnails :refer [thumbnails-panel]]
[app.util.dom :as dom]
[app.util.i18n :as i18n :refer [t tr]]
[beicon.core :as rx]
[goog.events :as events]
[okulary.core :as l]
[rumext.alpha :as mf])
(:import goog.events.EventType))
(defn handle-select-frame [frame]
#(do (dom/prevent-default %)
(dom/stop-propagation %)
(st/emit! (dv/select-shape (:id frame)))))
(mf/defc render-panel
[{:keys [data state index page-id file-id]}]
(let [locale (mf/deref i18n/locale)
frames (:frames data [])
objects (:objects data)
frame (get frames index)]
(mf/use-effect
(mf/deps index)
(fn []
(st/emit! (dv/set-current-frame (:id frame))
(dv/select-shape (:id frame)))))
[:section.viewer-preview
(cond
(empty? frames)
[:section.empty-state
[:span (t locale "viewer.empty-state")]]
(nil? frame)
[:section.empty-state
[:span (t locale "viewer.frame-not-found")]]
:else
[:*
[:& left-sidebar {:frame frame}]
[:div.handoff-svg-wrapper {:on-click (handle-select-frame frame)}
[:div.handoff-svg-container
[:& render-frame-svg {:frame-id (:id frame)
:zoom (:zoom state)
:objects objects}]]]
[:& right-sidebar {:frame frame
:page-id page-id
:file-id file-id}]])]))
(mf/defc handoff-content
[{:keys [data state index page-id file-id] :as props}]
(let [on-mouse-wheel
(mf/use-callback
(fn [event]
(when (kbd/ctrl? event)
(dom/prevent-default event)
(let [event (.getBrowserEvent ^js event)
delta (+ (.-deltaY ^js event)
(.-deltaX ^js event))]
(if (pos? delta)
(st/emit! dv/decrease-zoom)
(st/emit! dv/increase-zoom))))))
on-mount
(fn []
;; bind with passive=false to allow the event to be cancelled
;; https://stackoverflow.com/a/57582286/3219895
(let [key1 (events/listen goog/global EventType.WHEEL
on-mouse-wheel #js {"passive" false})]
(fn []
(events/unlistenByKey key1))))]
(mf/use-effect on-mount)
(hooks/use-shortcuts dv/shortcuts)
[:& fs/fullscreen-wrapper {}
[:div.handoff-layout
[:& header
{:data data
:state state
:index index
:section :handoff}]
[:div.viewer-content
(when (:show-thumbnails state)
[:& thumbnails-panel {:index index
:data data
:screen :handoff}])
[:& render-panel {:data data
:state state
:index index
:page-id page-id
:file-id file-id}]]]]))
(mf/defc handoff
[{:keys [file-id page-id index token] :as props}]
(mf/use-effect
(mf/deps file-id page-id token)
(fn []
(st/emit! (dv/initialize props))))
(let [data (mf/deref refs/viewer-data)
state (mf/deref refs/viewer-local)]
(when (and data state)
[:& handoff-content
{:file-id file-id
:page-id page-id
:index index
:state state
:data data}])))