瀏覽代碼

Merge pull request #7492 from logseq/enhance/mobile-ux-2

Enhance/mobile UX
Tienson Qin 2 年之前
父節點
當前提交
b7f74d12de

+ 10 - 0
resources/css/common.css

@@ -904,3 +904,13 @@ html[data-theme='dark'] .keyboard-shortcut > code {
 .katex .tag {
     overflow-x: clip;
 }
+
+html.is-mobile {
+  h1.title {
+    margin-bottom: 10px;
+  }
+
+  #journals .journal-item:first-child {
+    margin-top: 5px;
+  }
+}

+ 37 - 39
src/main/frontend/components/block.cljs

@@ -1688,23 +1688,22 @@
     (when (and (coll? children)
                (seq children)
                (not collapsed?))
-      (let [doc-mode? (state/sub :document/mode?)]
-        [:div.block-children-container.flex {:style {:margin-left (if doc-mode? 18 29)}}
-         [:div.block-children-left-border
-          {:on-click (fn [_]
-                       (editor-handler/toggle-open-block-children! (:block/uuid block)))}]
-         [:div.block-children.w-full {:style    {:display     (if collapsed? "none" "")}}
-          (for [child children]
-            (when (map? child)
-              (let [child (dissoc child :block/meta)
-                    config (cond->
-                            (-> config
-                                (assoc :block/uuid (:block/uuid child))
-                                (dissoc :breadcrumb-show? :embed-parent))
-                             (or ref? query?)
-                             (assoc :ref-query-child? true))]
-                (rum/with-key (block-container config child)
-                  (:block/uuid child)))))]]))))
+      [:div.block-children-container.flex
+       [:div.block-children-left-border
+        {:on-click (fn [_]
+                     (editor-handler/toggle-open-block-children! (:block/uuid block)))}]
+       [:div.block-children.w-full {:style {:display (if collapsed? "none" "")}}
+        (for [child children]
+          (when (map? child)
+            (let [child  (dissoc child :block/meta)
+                  config (cond->
+                           (-> config
+                               (assoc :block/uuid (:block/uuid child))
+                               (dissoc :breadcrumb-show? :embed-parent))
+                           (or ref? query?)
+                           (assoc :ref-query-child? true))]
+              (rum/with-key (block-container config child)
+                            (:block/uuid child)))))]])))
 
 (defn- block-content-empty?
   [{:block/keys [properties title body]}]
@@ -1718,30 +1717,29 @@
    (every? #(= % ["Horizontal_Rule"]) body)))
 
 (rum/defcs block-control < rum/reactive
-  [state config block uuid block-id collapsed? *control-show? edit?]
+  [state config block uuid block-id collapsed? *control-show? edit? has-child?]
   (let [doc-mode? (state/sub :document/mode?)
         control-show? (util/react *control-show?)
         ref? (:ref? config)
-        empty-content? (block-content-empty? block)]
-    [:div.mr-1.flex.flex-row.items-center.sm:mr-2
-     {:style {:height 24
-              :margin-top 0
-              :float "left"}}
-
-     [:a.block-control
-      {:id (str "control-" uuid)
-       :on-click (fn [event]
-                   (util/stop event)
-                   (state/clear-edit!)
-                   (if ref?
-                     (state/toggle-collapsed-block! uuid)
-                     (if collapsed?
-                       (editor-handler/expand-block! uuid)
-                       (editor-handler/collapse-block! uuid))))}
-      [:span {:class (if (and control-show?
-                              (or collapsed?
-                                  (editor-handler/collapsable? uuid {:semantic? true}))) "control-show cursor-pointer" "control-hide")}
-       (ui/rotating-arrow collapsed?)]]
+        empty-content? (block-content-empty? block)
+        fold-button-right? (state/enable-fold-button-right?)]
+    [:div.block-control-wrap.mr-1.flex.flex-row.items-center.sm:mr-2
+     (when (or (not fold-button-right?) has-child?)
+       [:a.block-control
+        {:id       (str "control-" uuid)
+         :on-click (fn [event]
+                     (util/stop event)
+                     (state/clear-edit!)
+                     (if ref?
+                       (state/toggle-collapsed-block! uuid)
+                       (if collapsed?
+                         (editor-handler/expand-block! uuid)
+                         (editor-handler/collapse-block! uuid))))}
+        [:span {:class (if (and control-show?
+                                (or collapsed?
+                                    (editor-handler/collapsable? uuid {:semantic? true}))) "control-show cursor-pointer" "control-hide")}
+         (ui/rotating-arrow collapsed?)]])
+
      (let [bullet [:a {:on-click (fn [event]
                                    (bullet-on-click event block uuid))}
                    [:span.bullet-container.cursor
@@ -2775,7 +2773,7 @@
        :on-mouse-leave (fn [e]
                          (block-mouse-leave e *control-show? block-id doc-mode?))}
       (when (not slide?)
-        (block-control config block uuid block-id collapsed? *control-show? edit?))
+        (block-control config block uuid block-id collapsed? *control-show? edit? has-child?))
 
       (when @*show-left-menu?
         (block-left-menu config block))

+ 80 - 71
src/main/frontend/components/block.css

@@ -116,7 +116,7 @@
 .block-body ul,
 .block-body ol,
 .block-body dl {
-  margin-bottom: 0em;
+  margin-bottom: 0;
 
   > li {
     margin: 0;
@@ -137,6 +137,7 @@
 
 .block-children-container {
   position: relative;
+  margin-left: 29px;
 }
 
 .block-children-left-border {
@@ -171,6 +172,11 @@
   }
 }
 
+.block-control-wrap {
+  height: 24px;
+  margin-top: 0;
+}
+
 .block-control, .block-control:hover {
   text-decoration: none;
   cursor: default;
@@ -310,9 +316,9 @@
   padding: 2px 4px;
   opacity: 0.7;
   font-size: 85%;
-  margin: 0 2px 0 0px;
+  margin: 0 2px 0 0;
   font-weight: 650;
-  border: 0px;
+  border: 0;
 }
 
 .marker-switch {
@@ -362,14 +368,14 @@
 
 .ls-block h3,
 .editor-inner .h3.uniline-block {
-  font-size: 1.17em;
-  min-height: 1.17em;
+  font-size: 1.2em;
+  min-height: 1.2em;
 }
 
 .ls-block h4,
 .editor-inner .h4.uniline-block {
-  font-size: 1.12em;
-  min-height: 1.12em;
+  font-size: 1em;
+  min-height: 1em;
 }
 
 .ls-block h5,
@@ -393,7 +399,8 @@
 .ls-block :is(h1, h2),
 .editor-inner .uniline-block:is(.h1, .h2) {
   border-bottom: 1px solid var(--ls-quaternary-background-color);
-  margin: 0.4em 0 0;
+  margin: 0.125em 0;
+  padding-bottom: 0.125em;
 }
 
 .block-ref .ls-block :is(h1, h2),
@@ -406,86 +413,80 @@
   font-size: 1rem;
 }
 
-.document-mode .ls-block h1,
-.document-mode .editor-inner .h1 {
-  margin: 0.67em 0;
-}
-
-.document-mode .ls-block h2,
-.document-mode .editor-inner .h2 {
-  margin: 0.75em 0;
-}
-
-.document-mode .ls-block h3,
-.document-mode .editor-inner .h3 {
-  margin: 0.83em 0;
-}
+.document-mode {
+  & .ls-block h1,
+  & .editor-inner .h1 {
+    margin: 0.67em 0;
+  }
 
-.document-mode .ls-block h4,
-.document-mode .editor-inner .h4 {
-  margin: 1.12em 0;
-}
+  & .ls-block h2,
+  & .editor-inner .h2 {
+    margin: 0.75em 0;
+  }
 
-.document-mode .ls-block h5,
-.document-mode .editor-inner .h5 {
-  margin: 1.5em 0;
-}
+  & .ls-block h3,
+  & .editor-inner .h3 {
+    margin: 0.83em 0;
+  }
 
-.document-mode .ls-block h6,
-.document-mode .editor-inner .h6 {
-  margin: 1.67em 0;
-}
+  & .ls-block h4,
+  & .editor-inner .h4 {
+    margin: 1.12em 0;
+  }
 
-.document-mode .block-children {
-  border-left: 0px solid;
-}
+  & .ls-block h5,
+  & .editor-inner .h5 {
+    margin: 1.5em 0;
+  }
 
-.document-mode .ls-block {
-  margin-bottom: 1rem;
+  & .ls-block h6,
+  & .editor-inner .h6 {
+    margin: 1.67em 0;
+  }
 }
 
 .color-level {
   background-color: var(--color-level-1);
-}
 
-.color-level .color-level {
-  background-color: var(--color-level-2);
-}
+  & .color-level {
+    background-color: var(--color-level-2);
 
-.color-level .color-level .color-level {
-  background-color: var(--color-level-3);
-}
+    & .color-level {
+      background-color: var(--color-level-3);
 
-.color-level .color-level .color-level .color-level {
-  background-color: var(--color-level-4);
-}
+      & .color-level {
+        background-color: var(--color-level-4);
 
-.color-level .color-level .color-level .color-level .color-level {
-  background-color: var(--color-level-5);
-}
+        & .color-level {
+          background-color: var(--color-level-5);
 
-.color-level .color-level .color-level .color-level .color-level .color-level {
-  background-color: var(--color-level-6);
-}
+          & .color-level {
+            background-color: var(--color-level-6);
 
-.color-level .color-level .color-level .color-level .color-level .color-level .color-level {
-  background-color: var(--color-level-4);
-}
+            & .color-level {
+              background-color: var(--color-level-4);
 
-.color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level {
-  background-color: var(--color-level-5);
-}
+              & .color-level {
+                background-color: var(--color-level-5);
 
-.color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level {
-  background-color: var(--color-level-6);
-}
+                & .color-level {
+                  background-color: var(--color-level-6);
 
-.color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level {
-  background-color: var(--color-level-4);
-}
+                  & .color-level {
+                    background-color: var(--color-level-4);
 
-.color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level .color-level {
-  background-color: var(--color-level-5);
+                    & .color-level {
+                      background-color: var(--color-level-6);
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
 }
 
 .bullet-container {
@@ -521,16 +522,24 @@ a:hover > .bullet-container {
   background-color: var(--ls-block-bullet-border-color, #ced9e0);
 }
 
-.doc-mode {
+.content.doc-mode {
   margin-left: -16px;
 
   .block-children-left-border {
     display: none;
   }
 
+  .block-children {
+    border-left: none;
+  }
+
   .hide-inner-bullet .bullet {
     display: none;
   }
+
+  .block-children-container {
+    margin-left: 18px;
+  }
 }
 
 /* copied from https://github.com/drdogbot7/tailwindcss-responsive-embed */
@@ -648,4 +657,4 @@ html.is-mac {
       cursor: pointer;
     }
   }
-}
+}

+ 8 - 4
src/main/frontend/components/header.cljs

@@ -194,10 +194,14 @@
                                           :native-android (mobile-util/native-android?)}])
       :on-double-click (fn [^js e]
                          (when-let [target (.-target e)]
-                           (when (and (util/electron?)
-                                      (.. target -classList (contains "drag-region")))
-                             (js/window.apis.toggleMaxOrMinActiveWindow))))
-      :style           {:fontSize  50}}
+                           (cond
+                             (and (util/electron?)
+                                  (.. target -classList (contains "drag-region")))
+                             (js/window.apis.toggleMaxOrMinActiveWindow)
+
+                             (mobile-util/native-platform?)
+                             (util/scroll-to-top true))))
+      :style           {:fontSize 50}}
      [:div.l.flex.drag-region
       (when-not (mobile-util/native-platform?)
         [left-menu

+ 1 - 1
src/main/frontend/components/header.css

@@ -242,7 +242,7 @@ html.is-native-ipad {
     }
 
     .page {
-      margin-top: 24px;
+      margin-top: 15px;
     }
   }
 

+ 4 - 4
src/main/frontend/components/page.cljs

@@ -304,7 +304,7 @@
                         (reset! *edit? true))))}
        (when (not= icon "") [:span.page-icon icon])
        [:div.page-title-sizer-wrapper.relative
-        (when (rum/react *edit?)
+        (when @*edit?
           (page-title-editor {:*title-value *title-value
                               :*edit? *edit?
                               :*input-value *input-value
@@ -314,9 +314,9 @@
                               :untitled? untitled?
                               :whiteboard-page? whiteboard-page?}))
         [:span.title.block
-         {:data-value (rum/react *input-value)
-          :data-ref page-name
-          :style {:opacity (when @*edit? 0)}}
+         {:data-value @*input-value
+          :data-ref   page-name
+          :style      {:opacity (when @*edit? 0)}}
          (cond @*edit? [:span {:style {:white-space "pre"}} (rum/react *input-value)]
                untitled? [:span.opacity-50 (t :untitled)]
                :else title)]]])))

+ 2 - 2
src/main/frontend/components/page.css

@@ -270,7 +270,7 @@ a.page-title {
 }
 
 .page-title-sizer-wrapper {
-  @apply w-full;
+  @apply w-full overflow-x-auto;
 
   :empty::before {
     content: '\200b';
@@ -290,7 +290,7 @@ html.is-native-ipad,
 html.is-native-iphone,
 html.is-native-iphone-without-notch {
   .ls-page-title {
-    margin: 0 0 24px -15px;
+    margin: 0 0 10px -15px;
     padding: 0 !important;
   }
 }

+ 3 - 3
src/main/frontend/components/reference.cljs

@@ -59,7 +59,7 @@
     [:div.ls-filters.filters
      [:div.sm:flex.sm:items-start
       [:div.mx-auto.flex-shrink-0.flex.items-center.justify-center.h-12.w-12.rounded-full.bg-gray-200.text-gray-500.sm:mx-0.sm:h-10.sm:w-10
-       (ui/icon "filter" {:style {:fontSize 20}})]
+       (ui/icon "filter" {:size 20})]
       [:div.mt-3.text-center.sm:mt-0.sm:ml-4.sm:text-left.pb-2
        [:h3#modal-headline.text-lg.leading-6.font-medium "Filter"]
        [:span.text-xs
@@ -146,14 +146,14 @@
                                       {:center? true}))}
        (ui/icon "filter" {:class (cond
                                    (empty? filter-state)
-                                   ""
+                                   "opacity-60 hover:opacity-100"
                                    (every? true? (vals filter-state))
                                    "text-success"
                                    (every? false? (vals filter-state))
                                    "text-error"
                                    :else
                                    "text-warning")
-                          :style {:fontSize 24}})]]
+                          :size  22})]]
 
      (fn []
        (references-inner page-name filters filtered-ref-blocks))

+ 1 - 1
src/main/frontend/components/right_sidebar.cljs

@@ -27,7 +27,7 @@
       [:button.button.icon.toggle-right-sidebar
        {:title "Toggle right sidebar"
         :on-click ui-handler/toggle-right-sidebar!}
-       (ui/icon "layout-sidebar-right" {:style {:fontSize "20px"}})])))
+       (ui/icon "layout-sidebar-right" {:size 20})])))
 
 (rum/defc block-cp < rum/reactive
   [repo idx block]

+ 1 - 0
src/main/frontend/components/settings.cljs

@@ -594,6 +594,7 @@
      (workflow-row t preferred-workflow)
      ;; (enable-block-timestamps-row t enable-block-timestamps?)
      (show-brackets-row t show-brackets?)
+
      (when (util/electron?) (switch-spell-check-row t))
      (outdenting-row t logical-outdenting?)
      (preferred-pasting-file t preferred-pasting-file?)

+ 6 - 4
src/main/frontend/components/sidebar.cljs

@@ -735,6 +735,7 @@
         edit? (:editor/editing? @state/state)
         default-home (get-default-home-if-valid)
         logged? (user-handler/logged-in?)
+        fold-button-on-right? (state/enable-fold-button-right?)
         show-action-bar? (state/sub :mobile/show-action-bar?)
         show-recording-bar? (state/sub :mobile/show-recording-bar?)
         preferred-language (state/sub [:preferred-language])]
@@ -757,10 +758,11 @@
                        (util/fix-open-external-with-shift! e))}
 
      [:main.theme-inner
-      {:class (util/classnames [{:ls-left-sidebar-open left-sidebar-open?
-                                 :ls-right-sidebar-open sidebar-open?
-                                 :ls-wide-mode wide-mode?
-                                 :ls-hl-colored ls-block-hl-colored?}])}
+      {:class (util/classnames [{:ls-left-sidebar-open    left-sidebar-open?
+                                 :ls-right-sidebar-open   sidebar-open?
+                                 :ls-wide-mode            wide-mode?
+                                 :ls-fold-button-on-right fold-button-on-right?
+                                 :ls-hl-colored           ls-block-hl-colored?}])}
 
       [:button#skip-to-main
        {:on-click #(ui/focus-element (ui/main-node))

+ 1 - 1
src/main/frontend/components/sidebar.css

@@ -361,7 +361,7 @@
   }
 
   &.is-touching {
-    width: 100%;
+    width: 100% !important;
     transition: none;
 
     .left-sidebar-inner {

+ 57 - 2
src/main/frontend/components/theme.css

@@ -1,7 +1,6 @@
 :root {
   scrollbar-width: thin;
-  scrollbar-color: var(--ls-scrollbar-foreground-color)
-    var(--ls-scrollbar-background-color);
+  scrollbar-color: var(--ls-scrollbar-foreground-color) var(--ls-scrollbar-background-color);
 
   --ls-z-index-level-0: 0;
   --ls-z-index-level-1: 9;
@@ -114,3 +113,59 @@ html.is-resizing-buf {
     }
   }
 }
+
+main.ls-fold-button-on-right {
+  #main-content-container {
+    padding-right: 18px;
+    padding-left: 18px;
+    padding-top: 4px;
+
+    .page-blocks-inner {
+      margin-left: 0 !important;
+    }
+
+    .block-control-wrap {
+      /* hack for toggling enable-opts */
+      height: 23px;
+      background: transparent;
+    }
+  }
+
+  .cp__sidebar-left-layout {
+    width: 15px;
+
+    &.is-open {
+      width: 100%;
+    }
+  }
+
+  .ls-block {
+    .block-control {
+      @apply absolute -right-3 pr-2 top-1 bottom-1 z-[1] active:opacity-100;
+
+      -webkit-tap-highlight-color: transparent;
+
+      .rotating-arrow.collapsed svg {
+        transform: rotate(180deg);
+      }
+    }
+
+    &[haschild="true"] {
+      .control-hide {
+        display: block !important;
+      }
+    }
+
+    .block-content-wrapper {
+      width: 100%;
+    }
+  }
+
+  .block-children-container {
+    margin-left: 7px;
+
+    .block-children {
+      padding-left: 10px;
+    }
+  }
+}

+ 1 - 1
src/main/frontend/handler/config.cljs

@@ -27,7 +27,7 @@
             ks (if (vector? k) k [k])
             new-result (rewrite/assoc-in result ks v)
             new-content (str new-result)]
-        (file-handler/set-file-content! repo path new-content)))))
+        (file-handler/set-file-content! repo path new-content) nil))))
 
 (defn set-config!
   ([k v]

+ 19 - 15
src/main/frontend/mobile/index.css

@@ -67,9 +67,6 @@
   position: fixed;
   bottom: 0;
   transition: bottom 260ms;
-  /* transition-timing-function: cubic-bezier(.29, 1.01, 1, -0.68); */
-  /* transition-timing-function: steps(10, jump-end); */
-  /* transition-timing-function: steps(5, end); */
   transition-timing-function: ease-out;
   left: 0;
   width: 100%;
@@ -78,18 +75,20 @@
   justify-content: space-between;
 
   button {
-    padding: 7px 10px;
-  }
+    @apply flex items-center py-2 px-2;
+
+    .submenu {
+      z-index: 100;
+      box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.02);
+      background-color: var(--ls-secondary-background-color);
+      overflow-x: overlay;
+      overflow-y: hidden;
+      height: 40px;
+    }
 
-  .submenu {
-    z-index: 100;
-    background-color: var(--ls-secondary-background-color);
-    overflow-x: overlay;
-    overflow-y: hidden;
-    height: 45px;
-  }
-  .show-submenu {
-    display: flex;
+    .show-submenu {
+      display: block;
+    }
   }
 
   .toolbar-commands {
@@ -98,7 +97,12 @@
     align-items: center;
     overflow-x: overlay;
     overflow-y: hidden;
+    overflow-scrolling: touch;
     width: 95%;
+
+    &::-webkit-scrollbar {
+      height: 4px;
+    }
   }
 
   .toolbar-hide-keyboard {
@@ -241,4 +245,4 @@ html.is-zoomed-native-ios {
       }
     }
   }
-}
+}

+ 5 - 0
src/main/frontend/state.cljs

@@ -582,6 +582,11 @@ Similar to re-frame subscriptions"
   []
   (not (false? (:feature/enable-timetracking? (sub-config)))))
 
+(defn enable-fold-button-right?
+  []
+  (let [_ (sub :ui/viewport)]
+    (util/md-breakpoint?)))
+
 (defn enable-journals?
   ([]
    (enable-journals? (get-current-repo)))

+ 7 - 1
src/main/frontend/ui.css

@@ -226,7 +226,13 @@ html.is-native-iphone-without-notch
 
 html.is-mobile {
   .ui__modal {
-    @apply bottom-0 inset-x-0;
+    @apply bottom-0 inset-x-0 top-20;
+  }
+
+  .ui__modal-panel .panel-content {
+    width: calc(98vw - 2rem);
+    padding-top: 24px;
+    padding-bottom: 0;
   }
 }
 

+ 11 - 4
src/main/frontend/util.cljc

@@ -1305,7 +1305,7 @@
              vw-height   (or (.-height js/window.visualViewport)
                              (.-clientHeight js/document.documentElement))
              ;; mobile toolbar height: 40px
-             scroll      (- cursor-y (- vw-height (+ @keyboard-height 40)))]
+             scroll      (- cursor-y (- vw-height (+ @keyboard-height (+ 40 4))))]
          (cond
            (and to-vw-one-quarter? (> cursor-y (* vw-height 0.4)))
            (set! (.-scrollTop main-node) (+ scroll-top (- cursor-y (/ vw-height 4))))
@@ -1327,9 +1327,16 @@
            nil)))))
 
 #?(:cljs
-   (defn sm-breakpoint?
-     []
-     (< (.-offsetWidth js/document.documentElement) 640)))
+   (do
+     (defn breakpoint?
+       [size]
+       (< (.-offsetWidth js/document.documentElement) size))
+
+     (defn sm-breakpoint?
+       [] (breakpoint? 640))
+
+     (defn md-breakpoint?
+       [] (breakpoint? 768))))
 
 #?(:cljs
    (defn event-is-composing?