mirror of https://github.com/logseq/logseq
enhance(mobile): fixed position of head-bar & mobile-bar (#3360)
enhance(mobile): fixed position of head-bar & mobile-bar Co-authored-by: charlie <xyhp915@qq.com>pull/3355/head^2
parent
74c2606300
commit
d9452bd739
|
@ -9,6 +9,8 @@
|
|||
--ls-scrollbar-width: 6px;
|
||||
--ls-border-radius-low: 4px;
|
||||
--ls-border-radius-medium: 8px;
|
||||
--ls-headbar-height: 3rem;
|
||||
--ls-headbar-inner-top-padding: 0px;
|
||||
--ls-left-sidebar-width: 240px;
|
||||
--ls-left-sidebar-nav-btn-size: 38px;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
[frontend.components.search :as search]
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.config :as config]
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.db :as db]
|
||||
[frontend.extensions.zotero :as zotero]
|
||||
[frontend.handler.editor :as editor-handler :refer [get-state]]
|
||||
|
@ -217,91 +218,99 @@
|
|||
|
||||
(rum/defc mobile-bar < rum/reactive
|
||||
[parent-state parent-id]
|
||||
[:div#mobile-editor-toolbar.bg-base-2.fix-ios-fixed-bottom
|
||||
[:div.flex.justify-around.w-full
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(editor-handler/indent-outdent true))}
|
||||
(ui/icon "arrow-bar-right"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(editor-handler/indent-outdent false))}
|
||||
(ui/icon "arrow-bar-left"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
((editor-handler/move-up-down true)))}
|
||||
(ui/icon "arrow-bar-to-up"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
((editor-handler/move-up-down false)))}
|
||||
(ui/icon "arrow-bar-to-down"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(commands/simple-insert! parent-id "\n"
|
||||
{:forward-pos 1})
|
||||
;; TODO: should we add this focus step to `simple-insert!`?
|
||||
(when-let [input (gdom/getElement parent-id)]
|
||||
(.focus input)))}
|
||||
(ui/icon "arrow-back"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(editor-handler/cycle-todo!))}
|
||||
(ui/icon "checkbox"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(commands/simple-insert!
|
||||
parent-id "[[]]"
|
||||
{:backward-pos 2
|
||||
:check-fn (fn [_ _ new-pos]
|
||||
(reset! commands/*slash-caret-pos new-pos)
|
||||
(commands/handle-step [:editor/search-page]))})
|
||||
(when-let [input (gdom/getElement parent-id)]
|
||||
(.focus input)))}
|
||||
(ui/icon "brackets"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(commands/simple-insert!
|
||||
parent-id "(())"
|
||||
{:backward-pos 2
|
||||
:check-fn (fn [_ _ new-pos]
|
||||
(reset! commands/*slash-caret-pos new-pos)
|
||||
(commands/handle-step [:editor/search-block]))})
|
||||
(when-let [input (gdom/getElement parent-id)]
|
||||
(.focus input)))}
|
||||
(ui/icon "parentheses"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(commands/simple-insert! parent-id "/" {})
|
||||
(when-let [input (gdom/getElement parent-id)]
|
||||
(.focus input)))}
|
||||
(ui/icon "command"
|
||||
{:style {:fontSize ui/icon-size}})]]]])
|
||||
(let [vw-state (state/sub :ui/visual-viewport-state)
|
||||
vw-pending? (state/sub :ui/visual-viewport-pending?)]
|
||||
[:div#mobile-editor-toolbar.bg-base-2
|
||||
{:style {:bottom (if (and vw-state)
|
||||
(- (.-clientHeight js/document.documentElement)
|
||||
(:height vw-state)
|
||||
(:offset-top vw-state))
|
||||
0)}
|
||||
:class (util/classnames [{:is-vw-pending (boolean vw-pending?)}])}
|
||||
[:div.flex.justify-around.w-full
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(editor-handler/indent-outdent true))}
|
||||
(ui/icon "arrow-bar-right"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(editor-handler/indent-outdent false))}
|
||||
(ui/icon "arrow-bar-left"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
((editor-handler/move-up-down true)))}
|
||||
(ui/icon "arrow-bar-to-up"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
((editor-handler/move-up-down false)))}
|
||||
(ui/icon "arrow-bar-to-down"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(commands/simple-insert! parent-id "\n"
|
||||
{:forward-pos 1})
|
||||
;; TODO: should we add this focus step to `simple-insert!`?
|
||||
(when-let [input (gdom/getElement parent-id)]
|
||||
(.focus input)))}
|
||||
(ui/icon "arrow-back"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(editor-handler/cycle-todo!))}
|
||||
(ui/icon "checkbox"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(commands/simple-insert!
|
||||
parent-id "[[]]"
|
||||
{:backward-pos 2
|
||||
:check-fn (fn [_ _ new-pos]
|
||||
(reset! commands/*slash-caret-pos new-pos)
|
||||
(commands/handle-step [:editor/search-page]))})
|
||||
(when-let [input (gdom/getElement parent-id)]
|
||||
(.focus input)))}
|
||||
(ui/icon "brackets"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(commands/simple-insert!
|
||||
parent-id "(())"
|
||||
{:backward-pos 2
|
||||
:check-fn (fn [_ _ new-pos]
|
||||
(reset! commands/*slash-caret-pos new-pos)
|
||||
(commands/handle-step [:editor/search-block]))})
|
||||
(when-let [input (gdom/getElement parent-id)]
|
||||
(.focus input)))}
|
||||
(ui/icon "parentheses"
|
||||
{:style {:fontSize ui/icon-size}})]]
|
||||
[:div
|
||||
[:button.bottom-action
|
||||
{:on-mouse-down (fn [e]
|
||||
(util/stop e)
|
||||
(commands/simple-insert! parent-id "/" {})
|
||||
(when-let [input (gdom/getElement parent-id)]
|
||||
(.focus input)))}
|
||||
(ui/icon "command"
|
||||
{:style {:fontSize ui/icon-size}})]]]]))
|
||||
|
||||
(rum/defcs input < rum/reactive
|
||||
(rum/local {} ::input-value)
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
#mobile-editor-toolbar {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
height: 2.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
z-index: 9999;
|
||||
|
||||
transition: top 0.3s;
|
||||
transition: none;
|
||||
|
||||
button {
|
||||
padding: 10px;
|
||||
|
|
|
@ -161,6 +161,8 @@
|
|||
(let [repos (->> (state/sub [:me :repos])
|
||||
(remove #(= (:url %) config/local-repo)))
|
||||
electron-mac? (and util/mac? (util/electron?))
|
||||
vw-state (state/sub :ui/visual-viewport-state)
|
||||
vw-pending? (state/sub :ui/visual-viewport-pending?)
|
||||
show-open-folder? (and (or (nfs/supported?)
|
||||
(mobile-util/is-native-platform?))
|
||||
(empty? repos)
|
||||
|
@ -168,15 +170,17 @@
|
|||
refreshing? (state/sub :nfs/refreshing?)]
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
[:div.cp__header#head
|
||||
{:class (cond electron-mac? "electron-mac"
|
||||
(mobile-util/native-ios?) "native-ios"
|
||||
(mobile-util/native-android?) "native-android")
|
||||
{:class (util/classnames [{:electron-mac electron-mac?
|
||||
:native-ios (mobile-util/native-ios?)
|
||||
:native-android (mobile-util/native-android?)
|
||||
:is-vw-pending (boolean vw-pending?)}])
|
||||
:on-double-click (fn [^js e]
|
||||
(when-let [target (.-target e)]
|
||||
(when (and (util/electron?)
|
||||
(or (.. target -classList (contains "cp__header"))))
|
||||
(js/window.apis.toggleMaxOrMinActiveWindow))))
|
||||
:style {:fontSize 50}}
|
||||
:style {:fontSize 50
|
||||
:transform (str "translateY(" (or (:offset-top vw-state) 0) "px)")}}
|
||||
[:div.l.flex
|
||||
(left-menu-button {:on-click (fn []
|
||||
(open-fn)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
.cp__header {
|
||||
@apply shadow z-10 h-12;
|
||||
@apply shadow z-10;
|
||||
-webkit-app-region: drag;
|
||||
|
||||
padding-right: 0.5rem;
|
||||
padding-top: var(--ls-headbar-inner-top-padding);
|
||||
height: calc(var(--ls-headbar-height) + var(--ls-headbar-inner-top-padding));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
@ -170,3 +172,23 @@ a.button {
|
|||
.is-mac.is-electron :is(.cp__header, .cp__right-sidebar-topbar) :is(button, .button, a) {
|
||||
cursor: default !important;
|
||||
}
|
||||
|
||||
html.is-native-ios,
|
||||
html.is-ios.is-safari {
|
||||
#main-container {
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.cp__header {
|
||||
position: fixed !important;
|
||||
background-color: var(--ls-primary-background-color);
|
||||
}
|
||||
|
||||
.is-vw-pending {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
html.is-native-ios {
|
||||
--ls-headbar-inner-top-padding: 36px;
|
||||
}
|
|
@ -568,8 +568,9 @@
|
|||
:close-fn close-fn
|
||||
:route-match route-match})
|
||||
|
||||
[:div.#app-container.h-screen.flex {:style {:padding-top (ui/main-content-top-padding)}}
|
||||
[:div.flex-1.h-full.flex.flex-col#left-container.relative
|
||||
[:div.#app-container
|
||||
{:style {:padding-top (ui/main-content-top-padding)}}
|
||||
[:div#left-container
|
||||
{:class (if (state/sub :ui/sidebar-open?) "overflow-hidden" "w-full")}
|
||||
(header/header {:open-fn open-fn
|
||||
:white? white?
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
@supports(padding: max(0px)) {
|
||||
.post {
|
||||
padding-left: max(12px, env(safe-area-inset-left));
|
||||
padding-right: max(12px, env(safe-area-inset-right));
|
||||
}
|
||||
@supports (padding: max(0px)) {
|
||||
.post {
|
||||
padding-left: max(12px, env(safe-area-inset-left));
|
||||
padding-right: max(12px, env(safe-area-inset-right));
|
||||
}
|
||||
}
|
||||
|
||||
#app-container {
|
||||
|
@ -21,9 +21,14 @@
|
|||
}
|
||||
|
||||
#app-container {
|
||||
display: flex;
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
|
||||
#left-container {
|
||||
@apply flex flex-1 flex-col relative h-screen;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
|
@ -44,6 +49,12 @@ html.is-mobile {
|
|||
#main-content.is-left-sidebar-open {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.left-sidebar-inner {
|
||||
> .wrap {
|
||||
padding-top: 64px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#left-sidebar {
|
||||
|
@ -64,8 +75,8 @@ html.is-mobile {
|
|||
|
||||
#left-bar {
|
||||
background-color: var(--ls-primary-background-color);
|
||||
width: 70vw;
|
||||
max-width: 300px;
|
||||
width: 70vw;
|
||||
max-width: 300px;
|
||||
|
||||
> .head-wrap {
|
||||
background-color: var(--ls-search-background-color);
|
||||
|
@ -100,10 +111,11 @@ html.is-mobile {
|
|||
overflow: auto;
|
||||
|
||||
> .wrap {
|
||||
padding-top: 24px;
|
||||
@screen md {
|
||||
padding-top: 60px;
|
||||
}
|
||||
padding-top: 24px;
|
||||
|
||||
@screen md {
|
||||
padding-top: 55px;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-wrapper {
|
||||
|
|
|
@ -62,12 +62,6 @@
|
|||
#(when system-theme?
|
||||
(ui/setup-system-theme-effect!))
|
||||
[system-theme?])
|
||||
|
||||
(rum/use-effect!
|
||||
#(when (mobile-util/native-ios?)
|
||||
(ui/setup-patch-ios-fixed-bottom-position!))
|
||||
[edit?])
|
||||
|
||||
[:div
|
||||
{:class (str theme "-theme")
|
||||
:on-click on-click}
|
||||
|
|
|
@ -17,7 +17,9 @@
|
|||
(ui/inject-document-devices-envs!)
|
||||
(ui/inject-dynamic-style-node!)
|
||||
(plugin-handler/host-mounted!)
|
||||
(let [teardown-fn (ui/setup-active-keystroke!)]
|
||||
(let [teardown-fn (comp
|
||||
(ui/setup-active-keystroke!)
|
||||
(ui/setup-patch-ios-visual-viewport-state!))]
|
||||
(assoc state ::teardown teardown-fn)))
|
||||
:will-unmount (fn [state]
|
||||
(let [teardown (::teardown state)]
|
||||
|
|
|
@ -82,6 +82,8 @@
|
|||
:ui/shortcut-tooltip? (if (false? (storage/get :ui/shortcut-tooltip?))
|
||||
false
|
||||
true)
|
||||
:ui/visual-viewport-pending? false
|
||||
:ui/visual-viewport-state nil
|
||||
|
||||
:document/mode? document-mode?
|
||||
|
||||
|
@ -1578,3 +1580,11 @@
|
|||
(defn get-last-key-code
|
||||
[]
|
||||
(:editor/last-key-code @state))
|
||||
|
||||
(defn set-visual-viewport-state
|
||||
[input]
|
||||
(set-state! :ui/visual-viewport-state input))
|
||||
|
||||
(defn get-visual-viewport-state
|
||||
[]
|
||||
(:ui/visual-viewport-state @state))
|
|
@ -50,7 +50,6 @@
|
|||
:else
|
||||
0))
|
||||
|
||||
|
||||
(defonce icon-size (if (mobile-util/is-native-platform?) 23 20))
|
||||
|
||||
(rum/defc ls-textarea
|
||||
|
@ -305,35 +304,37 @@
|
|||
(.appendChild js/document.head node))
|
||||
style)))
|
||||
|
||||
(defn setup-patch-ios-fixed-bottom-position!
|
||||
"fix a common issue about ios webpage viewport
|
||||
when soft keyboard setup"
|
||||
(defn setup-patch-ios-visual-viewport-state!
|
||||
[]
|
||||
(when (and
|
||||
(util/ios?)
|
||||
(not (nil? js/window.visualViewport)))
|
||||
(let [viewport js/visualViewport
|
||||
style (get-dynamic-style-node)
|
||||
sheet (.-sheet style)
|
||||
raf-pending? (atom false)
|
||||
(when-let [^js vp (and (or (and (util/mobile?) (util/safari?))
|
||||
(mobile-util/native-ios?))
|
||||
js/window.visualViewport)]
|
||||
(let [raf-pending? (atom false)
|
||||
set-raf-pending! #(reset! raf-pending? %)
|
||||
handler
|
||||
on-viewport-changed
|
||||
(fn []
|
||||
(when-not @raf-pending?
|
||||
(let [f (fn []
|
||||
(set-raf-pending! false)
|
||||
(let [vh (+ (.-offsetTop viewport) (.-height viewport))
|
||||
rule (.. sheet -rules (item 0))
|
||||
set-top #(set! (.. rule -style -top) (str % "px"))]
|
||||
(set-top vh)))]
|
||||
(set-raf-pending! true)
|
||||
(js/window.requestAnimationFrame f))))]
|
||||
(.insertRule sheet ".fix-ios-fixed-bottom {bottom:unset !important; transform: translateY(-100%); top: 100vh;}")
|
||||
(.addEventListener viewport "resize" handler)
|
||||
(.addEventListener viewport "scroll" handler)
|
||||
(let [update-vw-state
|
||||
(util/debounce 20
|
||||
(fn []
|
||||
(state/set-visual-viewport-state {:height (.-height vp)
|
||||
:page-top (.-pageTop vp)
|
||||
:offset-top (.-offsetTop vp)})
|
||||
(state/set-state! :ui/visual-viewport-pending? false)))]
|
||||
(when-not @raf-pending?
|
||||
(let [f (fn []
|
||||
(set-raf-pending! false)
|
||||
(update-vw-state))]
|
||||
(set-raf-pending! true)
|
||||
(state/set-state! :ui/visual-viewport-pending? true)
|
||||
(js/window.requestAnimationFrame f)))))]
|
||||
|
||||
(.addEventListener vp "resize" on-viewport-changed)
|
||||
(.addEventListener vp "scroll" on-viewport-changed)
|
||||
|
||||
(fn []
|
||||
(.removeEventListener viewport "resize" handler)
|
||||
(.removeEventListener viewport "scroll" handler)))))
|
||||
(.removeEventListener vp "resize" on-viewport-changed)
|
||||
(.removeEventListener vp "scroll" on-viewport-changed)
|
||||
(state/set-visual-viewport-state nil)))))
|
||||
|
||||
(defn setup-system-theme-effect!
|
||||
[]
|
||||
|
@ -471,14 +472,14 @@
|
|||
(str/split #" |\+"))
|
||||
sequence)]
|
||||
[:span.keyboard-shortcut
|
||||
(map-indexed (fn [i key]
|
||||
[:code {:key i}
|
||||
(map-indexed (fn [i key]
|
||||
[:code {:key i}
|
||||
;; Display "cmd" rather than "meta" to the user to describe the Mac
|
||||
;; mod key, because that's what the Mac keyboards actually say.
|
||||
(if (or (= :meta key) (= "meta" key))
|
||||
(util/meta-key-name)
|
||||
(name key))])
|
||||
sequence)]))
|
||||
(if (or (= :meta key) (= "meta" key))
|
||||
(util/meta-key-name)
|
||||
(name key))])
|
||||
sequence)]))
|
||||
|
||||
(defn keyboard-shortcut-from-config [shortcut-name]
|
||||
(let [default-binding (:binding (get shortcut-config/all-default-keyboard-shortcuts shortcut-name))
|
||||
|
|
Loading…
Reference in New Issue