Browse Source

improve(pdf): support toggle area highlight mode from toolbar

charlie 4 years ago
parent
commit
cdc000efbf

+ 6 - 0
src/main/frontend/components/svg.cljs

@@ -606,6 +606,12 @@
    [:svg {:fill "none" :width size :height size :viewBox "0 0 24 24" :stroke "currentColor"}
     [:path {:stroke-linecap "round" :stroke-linejoin "round" :stroke-width "2" :d "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0zM13 10H7"}]]))
 
+(defn area
+  ([] area 16)
+  ([size]
+   [:svg {:viewBox "0 0 1024 1024" :version "1.1" :width size :height size :stroke "currentColor"}
+    [:path {:d "M844.992 115.008H179.008c-35.328 0-64 28.672-64 64v665.984c0 35.328 28.672 64 64 64h665.984c35.328 0 64-28.672 64-64V179.008c0-35.328-28.672-64-64-64zM364.672 844.992H217.6L844.992 217.6v147.072l-480.32 480.32z m480.32-401.152v147.2l-254.016 253.952H443.84l401.152-401.152z m-187.648-264.832h147.072l-625.408 625.408V657.28l478.336-478.336zM179.008 578.112V431.04l252.032-252.032h147.136L179.008 578.112z m172.864-399.104l-172.864 172.8v-172.8h172.864z m318.272 665.984l174.848-174.848v174.848h-174.848z" :fill "currentColor"}]]))
+
 (defn view-list
   ([] (view-list 16))
   ([size]

+ 47 - 25
src/main/frontend/extensions/pdf/highlights.cljs

@@ -12,6 +12,7 @@
             [frontend.config :as config]
             [frontend.storage :as storage]
             [frontend.components.svg :as svg]
+            [frontend.rum :refer [use-atom]]
             [medley.core :as medley]
             [frontend.fs :as fs]
             [clojure.string :as string]
@@ -20,6 +21,8 @@
 (defn dd [& args]
   (apply js/console.debug args))
 
+(def *area-mode? (atom false))
+
 (defn reset-current-pdf!
   []
   (state/set-state! :pdf/current nil))
@@ -304,10 +307,13 @@
         *sta-el (rum/use-ref nil)
         *cnt-rect (rum/use-ref nil)
 
-        should-start (fn [^js e] (and e (.-altKey e)))
-
         [start-coord, set-start-coord!] (rum/use-state nil)
         [end-coord, set-end-coord!] (rum/use-state nil)
+        [_ set-area-mode!] (use-atom *area-mode?)
+
+        should-start (fn [^js e]
+                       (when (.closest (.-target e) ".page")
+                         (and e (or (.-altKey e) @*area-mode?))))
 
         reset-coords #(do
                         (set-start-coord! nil)
@@ -386,7 +392,9 @@
                                        ":page" page-number
                                        ":offset" page-pos
                                        ":vw-pos" vw-pos
-                                       ":sc-pos" sc-pos)))
+                                       ":sc-pos" sc-pos))
+
+                                 (set-area-mode! false))
 
                                ;; reset
                                (reset-coords)))
@@ -671,7 +679,7 @@
                   ops) parent))) items)])]))
 
 (rum/defc pdf-outline
-  [^js viewer visible? hide!]
+  [^js viewer visible? set-visible!]
   (when-let [^js pdf-doc (and viewer (.-pdfDocument viewer))]
     (let [*el-outline (rum/use-ref nil)
           [outline-data, set-outline-data!] (rum/use-state [])
@@ -698,7 +706,7 @@
         (fn []
           (let [el-outline (rum/deref *el-outline)
                 cb (fn [^js e]
-                     (and (= e.which 27) (hide!)))]
+                     (and (= e.which 27) (set-visible! false)))]
 
             (js/setTimeout #(.focus el-outline))
             (.addEventListener el-outline "keyup" cb)
@@ -710,7 +718,7 @@
         :on-click (fn [^js/MouseEvent e]
                     (let [target (.-target e)]
                       (when-not (.contains (rum/deref *el-outline) target)
-                        (hide!))))}
+                        (set-visible! false))))}
 
        [:div.extensions__pdf-outline.hls-popup-box
         {:ref       *el-outline
@@ -737,13 +745,13 @@
 
    [:div.flex.items-center.justify-center.pt-2.pb--2
     (ui/button "Copy all"
-      :on-click
-      (fn []
-        (let [text (.-innerText (js/document.querySelector "#pdf-docinfo > .inner-text"))
-              text (string/replace-all text #"[\n\t]+" "\n")]
-          (front-utils/copy-to-clipboard! text)
-          (notification/show! "Copied!" :success)
-          (close-fn!))))]])
+               :on-click
+               (fn []
+                 (let [text (.-innerText (js/document.querySelector "#pdf-docinfo > .inner-text"))
+                       text (string/replace-all text #"[\n\t]+" "\n")]
+                   (front-utils/copy-to-clipboard! text)
+                   (notification/show! "Copied!" :success)
+                   (close-fn!))))]])
 
 (defn make-docinfo-in-modal
   [info]
@@ -752,7 +760,8 @@
 
 (rum/defc pdf-toolbar
   [^js viewer]
-  (let [[outline-visible?, set-outline-visible!] (rum/use-state false)
+  (let [[area-mode? set-area-mode!] (use-atom *area-mode?)
+        [outline-visible?, set-outline-visible!] (rum/use-state false)
         [settings-visible?, set-settings-visible!] (rum/use-state false)
         [viewer-theme, set-viewer-theme!] (rum/use-state (or (storage/get "ls-pdf-viewer-theme") "light"))]
 
@@ -774,25 +783,37 @@
 
          ;; appearance
          [:a.button
-          {:on-click #(set-settings-visible! (not settings-visible?))}
+          {:title    "More settings"
+           :on-click #(set-settings-visible! (not settings-visible?))}
           (svg/adjustments 18)]
 
+         ;; selection
+         [:a.button
+          {:title    "Area highlight (Alt)"
+           :class (if area-mode? "is-active")
+           :on-click #(set-area-mode! (not area-mode?))}
+          (svg/area 18)]
+
          ;; zoom
          [:a.button
-          {:on-click (partial pdf-utils/zoom-out-viewer viewer)}
+          {:title    "Zoom out"
+           :on-click (partial pdf-utils/zoom-out-viewer viewer)}
           (svg/zoom-out 18)]
 
          [:a.button
-          {:on-click (partial pdf-utils/zoom-in-viewer viewer)}
+          {:title    "Zoom in"
+           :on-click (partial pdf-utils/zoom-in-viewer viewer)}
           (svg/zoom-in 18)]
 
          [:a.button
-          {:on-click #(set-outline-visible! (not outline-visible?))}
+          {:title    "Outline"
+           :on-click #(set-outline-visible! (not outline-visible?))}
           (svg/view-list 16)]
 
          ;; metadata
          [:a.button.is-info
-          {:on-click #(do
+          {:title    "Document info"
+           :on-click #(do
                         (p/let [ret (pdf-utils/get-meta-data$ viewer)]
                           (state/set-modal! (make-docinfo-in-modal ret))))}
           (svg/info)]
@@ -802,14 +823,15 @@
           (t :close)]]]
 
        ;; contents outline
-       (pdf-outline viewer outline-visible? #(set-outline-visible! false))
+       (pdf-outline viewer outline-visible? set-outline-visible!)
 
        ;; settings
-       (and settings-visible? (pdf-settings
-                                viewer
-                                viewer-theme
-                                {:hide-settings! #(set-settings-visible! false)
-                                 :select-theme!  #(set-viewer-theme! %)}))])))
+       (and settings-visible?
+            (pdf-settings
+              viewer
+              viewer-theme
+              {:hide-settings! #(set-settings-visible! false)
+               :select-theme!  #(set-viewer-theme! %)}))])))
 
 (rum/defc pdf-viewer
   [url initial-hls ^js pdf-document ops]

+ 11 - 3
src/main/frontend/extensions/pdf/pdf.css

@@ -73,12 +73,21 @@
           display: flex;
           align-items: center;
           margin-left: 8px;
-          padding: 4px 6px;
+          margin-right: 8px;
+          padding: 4px 2px;
           color: var(--ls-icon-color);
+          background-color: transparent;
+          transition: none;
 
           &.is-info {
             opacity: .3;
           }
+
+          &.is-active {
+            opacity: 1;
+            border-bottom: 2px solid #969494;
+            border-radius: 0;
+          }
         }
       }
     }
@@ -175,7 +184,7 @@
   &-settings {
     &-inner.hls-popup-box {
       position: absolute;
-      right: 96px;
+      right: 206px;
       width: 178px;
       padding: 15px 10px;
     }
@@ -541,7 +550,6 @@
 
     .hl-area {
       display: block;
-      padding: 10px 0;
 
       img {
         margin: 0;

+ 26 - 0
src/main/frontend/rum.cljs

@@ -2,6 +2,7 @@
   (:require [clojure.string :as s]
             [clojure.set :as set]
             [clojure.walk :as w]
+            [rum.core :refer [use-state use-effect!]]
             [cljs-bean.core :as bean]))
 
 ;; copy from https://github.com/priornix/antizer/blob/35ba264cf48b84e6597743e28b3570d8aa473e74/src/antizer/core.cljs
@@ -63,3 +64,28 @@
         ;; sablono html-to-dom-attrs does not work for nested hashmaps
         (bean/->js (map-keys->camel-case new-options :html-props true))
         new-children)))))
+
+(defn use-atom-fn
+  [a getter-fn setter-fn]
+  (let [[val set-val] (use-state (getter-fn @a))]
+    (use-effect!
+      (fn []
+        (let [id (str (random-uuid))]
+          (add-watch a id (fn [_ _ prev-state next-state]
+                            (let [prev-value (getter-fn prev-state)
+                                  next-value (getter-fn next-state)]
+                              (when-not (= prev-value next-value)
+                                (set-val next-value)))))
+          #(remove-watch a id)))
+      [])
+    [val #(swap! a setter-fn %)]))
+
+(defn use-atom
+  "(use-atom my-atom)"
+  [a]
+  (use-atom-fn a identity (fn [_ v] v)))
+
+(defn use-atom-in
+  "(use-atom my-atom [:path :to :data])"
+  [a path]
+  (use-atom-fn a #(get-in % path) #(assoc-in %1 path %2)))