Merge remote-tracking branch 'upstream/master' into whiteboards

This commit is contained in:
Peng Xiao
2022-05-23 21:54:07 +08:00
55 changed files with 903 additions and 709 deletions

View File

@@ -4,7 +4,6 @@
["chokidar" :as watcher]
[electron.utils :as utils]
["electron" :refer [app]]
[frontend.util.fs :as util-fs]
[electron.window :as window]))
;; TODO: explore different solutions for different platforms
@@ -30,10 +29,15 @@
(defn- publish-file-event!
[dir path event]
(send-file-watcher! dir event {:dir (utils/fix-win-path! dir)
:path (utils/fix-win-path! path)
:content (utils/read-file path)
:stat (fs/statSync path)}))
(let [content (when (and (not= event "unlink")
(utils/should-read-content? path))
(utils/read-file path))
stat (when (not= event "unlink")
(fs/statSync path))]
(send-file-watcher! dir event {:dir (utils/fix-win-path! dir)
:path (utils/fix-win-path! path)
:content content
:stat stat})))
(defn watch-dir!
"Watch a directory if no such file watcher exists"
@@ -43,7 +47,7 @@
(let [watcher (.watch watcher dir
(clj->js
{:ignored (fn [path]
(util-fs/ignored-path? dir path))
(utils/ignored-path? dir path))
:ignoreInitial false
:ignorePermissionErrors true
:interval polling-interval
@@ -63,9 +67,7 @@
(publish-file-event! dir path "change")))
(.on watcher "unlink"
(fn [path]
(send-file-watcher! dir "unlink"
{:dir (utils/fix-win-path! dir)
:path (utils/fix-win-path! path)})))
(publish-file-event! dir path "unlink")))
(.on watcher "error"
(fn [path]
(println "Watch error happened: "

View File

@@ -62,27 +62,27 @@
(when-let [agent (cfgs/get-item :settings/agent)]
(set-fetch-agent agent)))
;; keep same as ignored-path? in src/main/frontend/util/fs.cljs
;; TODO: merge them
(defn ignored-path?
"Ignore given path from file-watcher notification"
[dir path]
(when (string? path)
(or
(some #(string/starts-with? path (str dir "/" %))
["." ".recycle" "assets" "node_modules" "logseq/bak"])
["." ".recycle" "node_modules" "logseq/bak" "version-files"])
(some #(string/includes? path (str "/" % "/"))
["." ".recycle" "assets" "node_modules" "logseq/bak"])
(string/ends-with? path ".DS_Store")
["." ".recycle" "node_modules" "logseq/bak" "version-files"])
(some #(string/ends-with? path %)
[".DS_Store" "logseq/graphs-txid.edn" "logseq/broken-config.edn"])
;; hidden directory or file
(let [relpath (path/relative dir path)]
(or (re-find #"/\.[^.]+" relpath)
(re-find #"^\.[^.]+" relpath)))
(let [path (string/lower-case path)]
(and
(not (string/blank? (path/extname path)))
(not
(some #(string/ends-with? path %)
[".md" ".markdown" ".org" ".js" ".edn" ".css"])))))))
(re-find #"^\.[^.]+" relpath))))))
(defn should-read-content?
"Skip reading content of file while using file-watcher"
[path]
(let [ext (string/lower-case (path/extname path))]
(contains? #{".md" ".markdown" ".org" ".js" ".edn" ".css"} ext)))
(defn fix-win-path!
[path]
@@ -131,4 +131,4 @@
(defn normalize-lc
[s]
(normalize (string/lower-case s)))
(normalize (string/lower-case s)))

View File

@@ -273,21 +273,16 @@
["Query table function" [[:editor/input "{{function }}" {:backward-pos 2}]] "Create a query table function"]
["Calculator" [[:editor/input "```calc\n\n```" {:backward-pos 4}]
[:codemirror/focus]] "Insert a calculator"]
["draw" (draw-handler/initialize-excalidarw-file) "Draw a graph with Excalidraw"]
(when (util/zh-CN-supported?)
["Embed Bilibili video" [[:editor/input "{{bilibili }}" {:last-pattern (state/get-editor-command-trigger)
:backward-pos 2}]]])
["Embed HTML " (->inline "html")]
["Embed Youtube video" [[:editor/input "{{youtube }}" {:last-pattern (state/get-editor-command-trigger)
:backward-pos 2}]]]
["Embed Video URL" [[:editor/input "{{video }}" {:last-pattern (state/get-editor-command-trigger)
:backward-pos 2}]]]
["Embed Youtube timestamp" [[:youtube/insert-timestamp]]]
["Embed Vimeo video" [[:editor/input "{{vimeo }}" {:last-pattern (state/get-editor-command-trigger)
:backward-pos 2}]]]
["Embed Twitter tweet" [[:editor/input "{{tweet }}" {:last-pattern (state/get-editor-command-trigger)
:backward-pos 2}]]]]

View File

@@ -264,14 +264,14 @@
(let [src (::src state)
granted? (state/sub [:nfs/user-granted? (state/get-current-repo)])
href (config/get-local-asset-absolute-path href)]
(when (or granted? (util/electron?) (mobile-util/is-native-platform?))
(when (or granted? (util/electron?) (mobile-util/native-platform?))
(p/then (editor-handler/make-asset-url href) #(reset! src %)))
(when @src
(let [ext (keyword (util/get-file-ext @src))
share-fn (fn [event]
(util/stop event)
(when (mobile-util/is-native-platform?)
(when (mobile-util/native-platform?)
(p/let [url (str (config/get-repo-dir (state/get-current-repo)) href)]
(.share Share #js {:url url
:title "Open file with your favorite app"}))))]
@@ -884,7 +884,7 @@
(state/set-state! :pdf/current current)))}
label-text]
(mobile-util/is-native-platform?)
(mobile-util/native-platform?)
(asset-link config label-text s metadata full_text))
(contains? (config/doc-formats) ext)
@@ -1113,42 +1113,80 @@
(defn- macro-vimeo-cp
[_config arguments]
(when-let [url (first arguments)]
(let [Vimeo-regex #"^((?:https?:)?//)?((?:www).)?((?:player.vimeo.com|vimeo.com)?)((?:/video/)?)([\w-]+)(\S+)?$"]
(when-let [vimeo-id (nth (util/safe-re-find Vimeo-regex url) 5)]
(when-not (string/blank? vimeo-id)
(let [width (min (- (util/get-width) 96)
560)
height (int (* width (/ 315 560)))]
[:iframe
{:allow-full-screen "allowfullscreen"
:allow
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
:frame-border "0"
:src (str "https://player.vimeo.com/video/" vimeo-id)
:height height
:width width}]))))))
(when-let [vimeo-id (nth (util/safe-re-find text/vimeo-regex url) 5)]
(when-not (string/blank? vimeo-id)
(let [width (min (- (util/get-width) 96)
560)
height (int (* width (/ 315 560)))]
[:iframe
{:allow-full-screen "allowfullscreen"
:allow
"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
:frame-border "0"
:src (str "https://player.vimeo.com/video/" vimeo-id)
:height height
:width width}])))))
(defn- macro-bilibili-cp
[_config arguments]
(when-let [url (first arguments)]
(let [id-regex #"https?://www\.bilibili\.com/video/([^? ]+)"]
(when-let [id (cond
(<= (count url) 15) url
:else
(last (util/safe-re-find id-regex url)))]
(when-not (string/blank? id)
(let [width (min (- (util/get-width) 96)
560)
height (int (* width (/ 315 560)))]
[:iframe
{:allowfullscreen true
:framespacing "0"
:frameborder "no"
:border "0"
:scrolling "no"
:src (str "https://player.bilibili.com/player.html?bvid=" id "&high_quality=1")
:width width
:height (max 500 height)}]))))))
(when-let [id (cond
(<= (count url) 15) url
:else
(nth (util/safe-re-find text/bilibili-regex url) 5))]
(when-not (string/blank? id)
(let [width (min (- (util/get-width) 96)
560)
height (int (* width (/ 315 560)))]
[:iframe
{:allowfullscreen true
:framespacing "0"
:frameborder "no"
:border "0"
:scrolling "no"
:src (str "https://player.bilibili.com/player.html?bvid=" id "&high_quality=1")
:width width
:height (max 500 height)}])))))
(defn- macro-video-cp
[_config arguments]
(when-let [url (first arguments)]
(let [width (min (- (util/get-width) 96)
560)
height (int (* width (/ 315 560)))
results (text/get-matched-video url)
src (match results
[_ _ _ (:or "youtube.com" "youtu.be" "y2u.be") _ id _]
(if (= (count id) 11) ["youtube-player" id] url)
[_ _ _ "youtube-nocookie.com" _ id _]
(str "https://www.youtube-nocookie.com/embed/" id)
[_ _ _ "loom.com" _ id _]
(str "https://www.loom.com/embed/" id)
[_ _ _ (_ :guard #(string/ends-with? % "vimeo.com")) _ id _]
(str "https://player.vimeo.com/video/" id)
[_ _ _ "bilibili.com" _ id _]
(str "https://player.bilibili.com/player.html?bvid=" id "&high_quality=1")
:else
url)]
(if (and (coll? src)
(= (first src) "youtube-player"))
(youtube/youtube-video (last src))
(when src
[:iframe
{:allowfullscreen true
:allow "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope"
:framespacing "0"
:frameborder "no"
:border "0"
:scrolling "no"
:src src
:width width
:height height}])))))
(defn- macro-else-cp
[name config arguments]
@@ -1261,13 +1299,12 @@
(= name "youtube")
(when-let [url (first arguments)]
(let [YouTube-regex #"^((?:https?:)?//)?((?:www|m).)?((?:youtube.com|youtu.be))(/(?:[\w-]+\?v=|embed/|v/)?)([\w-]+)(\S+)?$"]
(when-let [youtube-id (cond
(== 11 (count url)) url
:else
(nth (util/safe-re-find YouTube-regex url) 5))]
(when-not (string/blank? youtube-id)
(youtube/youtube-video youtube-id)))))
(when-let [youtube-id (cond
(== 11 (count url)) url
:else
(nth (util/safe-re-find text/youtube-regex url) 5))]
(when-not (string/blank? youtube-id)
(youtube/youtube-video youtube-id))))
(= name "youtube-timestamp")
(when-let [timestamp (first arguments)]
@@ -1290,6 +1327,9 @@
(= name "bilibili")
(macro-bilibili-cp config arguments)
(= name "video")
(macro-video-cp config arguments)
(contains? #{"tweet" "twitter"} name)
(when-let [url (first arguments)]
(let [id-regex #"/status/(\d+)"]
@@ -1535,7 +1575,7 @@
"hide-inner-bullet"))}
[:span.bullet {:blockid (str uuid)}]]]]
(cond
(and (or (mobile-util/is-native-platform?)
(and (or (mobile-util/native-platform?)
(:ui/show-empty-bullets? (state/get-config)))
(not doc-mode?))
bullet
@@ -1869,35 +1909,40 @@
(.stopPropagation e)
(let [target (gobj/get e "target")
button (gobj/get e "buttons")
shift? (gobj/get e "shiftKey")]
(when (contains? #{1 0} button)
(when-not (target-forbidden-edit? target)
(if (and shift? (state/get-selection-start-block))
(editor-handler/highlight-selection-area! block-id)
(do
(editor-handler/clear-selection!)
(editor-handler/unhighlight-blocks!)
(let [f #(let [block (or (db/pull [:block/uuid (:block/uuid block)]) block)
cursor-range (util/caret-range (gdom/getElement block-id))
{:block/keys [content format]} block
content (->> content
(property/remove-built-in-properties format)
(drawer/remove-logbook))]
;; save current editing block
(let [{:keys [value] :as state} (editor-handler/get-state)]
(editor-handler/save-block! state value))
(state/set-editing!
edit-input-id
content
block
cursor-range
false))]
;; wait a while for the value of the caret range
(if (util/ios?)
(f)
(js/setTimeout f 5))
shift? (gobj/get e "shiftKey")
meta? (util/meta-key? e)]
(if (and meta? (not (state/get-edit-input-id)))
(do
(util/stop e)
(state/conj-selection-block! (gdom/getElement block-id) :down))
(when (contains? #{1 0} button)
(when-not (target-forbidden-edit? target)
(if (and shift? (state/get-selection-start-block))
(editor-handler/highlight-selection-area! block-id)
(do
(editor-handler/clear-selection!)
(editor-handler/unhighlight-blocks!)
(let [f #(let [block (or (db/pull [:block/uuid (:block/uuid block)]) block)
cursor-range (util/caret-range (gdom/getElement block-id))
{:block/keys [content format]} block
content (->> content
(property/remove-built-in-properties format)
(drawer/remove-logbook))]
;; save current editing block
(let [{:keys [value] :as state} (editor-handler/get-state)]
(editor-handler/save-block! state value))
(state/set-editing!
edit-input-id
content
block
cursor-range
false))]
;; wait a while for the value of the caret range
(if (util/ios?)
(f)
(js/setTimeout f 5))
(when block-id (state/set-selection-start-block! block-id)))))))))
(when block-id (state/set-selection-start-block! block-id))))))))))
(rum/defc dnd-separator-wrapper < rum/reactive
[block block-id slide? top? block-content?]
@@ -1970,7 +2015,8 @@
(when (and
(state/in-selection-mode?)
(not (string/includes? content "```"))
(not (gobj/get e "shiftKey")))
(not (gobj/get e "shiftKey"))
(not (util/meta-key? e)))
;; clear highlighted text
(util/clear-selection!)))}
(not slide?)
@@ -2227,20 +2273,21 @@
(defn- block-mouse-over
[uuid e *control-show? block-id doc-mode?]
(util/stop e)
(when (or
(model/block-collapsed? uuid)
(editor-handler/collapsable? uuid {:semantic? true}))
(reset! *control-show? true))
(when-let [parent (gdom/getElement block-id)]
(let [node (.querySelector parent ".bullet-container")]
(when doc-mode?
(dom/remove-class! node "hide-inner-bullet"))))
(when (and
(state/in-selection-mode?)
(non-dragging? e))
(when-not @*dragging?
(util/stop e)
(editor-handler/highlight-selection-area! block-id)))
(when (or
(model/block-collapsed? uuid)
(editor-handler/collapsable? uuid {:semantic? true}))
(reset! *control-show? true))
(when-let [parent (gdom/getElement block-id)]
(let [node (.querySelector parent ".bullet-container")]
(when doc-mode?
(dom/remove-class! node "hide-inner-bullet"))))
(when (and
(state/in-selection-mode?)
(non-dragging? e))
(util/stop e)
(editor-handler/highlight-selection-area! block-id))))
(defn- block-mouse-leave
[e *control-show? block-id doc-mode?]

View File

@@ -185,14 +185,6 @@
}
}
html.is-mobile,
html.is-native-iphone,
html.is-native-android {
.references .block-control {
margin-left: -20px;
}
}
.block-ref {
border-bottom: 0.5px solid;
border-bottom-color: var(--ls-block-ref-link-text-color);

View File

@@ -7,9 +7,6 @@
[frontend.components.datetime :as datetime-comp]
[frontend.components.search :as search]
[frontend.components.svg :as svg]
[frontend.mobile.camera :as mobile-camera]
[frontend.mobile.util :as mobile-util]
[frontend.config :as config]
[frontend.db :as db]
[frontend.db.model :as db-model]
[frontend.extensions.zotero :as zotero]
@@ -27,9 +24,7 @@
[goog.dom :as gdom]
[promesa.core :as p]
[rum.core :as rum]
[frontend.handler.history :as history]
[frontend.mobile.footer :as footer]
[frontend.handler.config :as config-handler]))
[frontend.mobile.footer :as footer]))
(rum/defc commands < rum/reactive
[id format]
@@ -232,88 +227,6 @@
template)
:class "black"}))))))
(rum/defc mobile-bar-indent-outdent [indent? icon]
[:div
[:button.bottom-action
{:on-mouse-down (fn [e]
(util/stop e)
(editor-handler/indent-outdent indent?))}
(ui/icon icon {:style {:fontSize ui/icon-size}})]])
(def ^:private mobile-bar-icons-keywords
[:checkbox :brackets :parentheses :command :tag :a-b :list :camera
:brand-youtube :link :rotate :rotate-clockwise :code :bold :italic :strikethrough :paint])
(def ^:private mobile-bar-commands-stats
(atom (into {}
(mapv (fn [name] [name {:counts 0}])
mobile-bar-icons-keywords))))
(defn set-command-stats [icon]
(let [key (keyword icon)
counts (get-in @mobile-bar-commands-stats [key :counts])]
(swap! mobile-bar-commands-stats
assoc-in [key :counts] (inc counts))
(config-handler/set-config!
:mobile/toolbar-stats @mobile-bar-commands-stats)))
(rum/defc mobile-bar-command
[command-handler icon & [count? event?]]
[:div
[:button.bottom-action
{:on-mouse-down (fn [e]
(util/stop e)
(when count?
(set-command-stats icon))
(if event?
(command-handler e)
(command-handler)))}
(ui/icon icon {:style {:fontSize ui/icon-size}})]])
(defn mobile-bar-commands
[_parent-state parent-id]
(let [viewport-fn (fn [] (when-let [input (gdom/getElement parent-id)]
(util/make-el-cursor-position-into-center-viewport input)
(.focus input)))]
(zipmap mobile-bar-icons-keywords
[(mobile-bar-command editor-handler/cycle-todo! "checkbox" true)
(mobile-bar-command #(editor-handler/toggle-page-reference-embed parent-id) "brackets" true)
(mobile-bar-command #(editor-handler/toggle-block-reference-embed parent-id) "parentheses" true)
(mobile-bar-command #(do (viewport-fn) (commands/simple-insert! parent-id "/" {})) "command" true)
(mobile-bar-command #(do (viewport-fn) (commands/simple-insert! parent-id "#" {})) "tag" true)
(mobile-bar-command editor-handler/cycle-priority! "a-b" true)
(mobile-bar-command editor-handler/toggle-list! "list" true)
(mobile-bar-command #(mobile-camera/embed-photo parent-id) "camera" true)
(mobile-bar-command commands/insert-youtube-timestamp "brand-youtube" true)
(mobile-bar-command editor-handler/html-link-format! "link" true)
(mobile-bar-command history/undo! "rotate" true true)
(mobile-bar-command history/redo! "rotate-clockwise" true true)
(mobile-bar-command #(do (viewport-fn) (commands/simple-insert! parent-id "<" {})) "code" true)
(mobile-bar-command editor-handler/bold-format! "bold" true)
(mobile-bar-command editor-handler/italics-format! "italic" true)
(mobile-bar-command editor-handler/strike-through-format! "strikethrough" true)
(mobile-bar-command editor-handler/highlight-format! "paint" true)])))
(rum/defc mobile-bar < rum/reactive
[parent-state parent-id]
(when-let [config-toolbar-stats (:mobile/toolbar-stats (state/get-config))]
(reset! mobile-bar-commands-stats config-toolbar-stats))
(let [commands (mobile-bar-commands parent-state parent-id)
sorted-commands (sort-by (comp :counts second) > @mobile-bar-commands-stats)]
[:div#mobile-editor-toolbar.bg-base-2
[:div.toolbar-commands
(mobile-bar-indent-outdent false "arrow-bar-left")
(mobile-bar-indent-outdent true "arrow-bar-right")
(mobile-bar-command (editor-handler/move-up-down true) "arrow-bar-to-up")
(mobile-bar-command (editor-handler/move-up-down false) "arrow-bar-to-down")
(mobile-bar-command #(if (state/sub :document/mode?)
(editor-handler/insert-new-block! nil)
(commands/simple-insert! parent-id "\n" {})) "arrow-back")
(for [command sorted-commands]
((first command) commands))]
[:div.toolbar-hide-keyboard
(mobile-bar-command #(state/clear-edit!) "keyboard-show")]]))
(rum/defcs input < rum/reactive
(rum/local {} ::input-value)
(mixins/event-mixin
@@ -607,7 +520,7 @@
(mixins/event-mixin setup-key-listener!)
(shortcut/mixin :shortcut.handler/block-editing-only)
lifecycle/lifecycle
[state {:keys [format block]} id config]
[state {:keys [format block]} id _config]
(let [content (state/sub-edit-content)
heading-class (get-editor-style-class content format)]
[:div.editor-inner {:class (if block "block-editor" "non-block-editor")}
@@ -616,11 +529,6 @@
[:div#audio-record-toolbar
(footer/audio-record-cp)])
(when (and (or (mobile-util/is-native-platform?)
config/mobile?)
(not (:review-cards? config)))
(mobile-bar state id))
(ui/ls-textarea
{:id id
:cacheMeasurements (editor-row-height-unchanged?) ;; check when content updated (as the content variable is binded)
@@ -629,7 +537,6 @@
:on-click (editor-handler/editor-on-click! id)
:on-change (editor-handler/editor-on-change! block id search-timeout)
:on-paste (editor-handler/editor-on-paste! id)
:on-height-change (editor-handler/editor-on-height-change! id)
:auto-focus false
:class heading-class})

View File

@@ -1,33 +1,3 @@
#mobile-editor-toolbar {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
/* height: 2.5rem; */
z-index: 9999;
transition: none;
display: flex;
justify-content: space-between;
button {
padding: 7px 10px;
}
.toolbar-commands {
justify-content: space-between;
display: flex;
align-items: center;
overflow-x: overlay;
overflow-y: hidden;
width: 95%;
}
.toolbar-hide-keyboard {
border-left: 1px solid;
border-color: var(--ls-quaternary-background-color);
}
}
#audio-record-toolbar {
position: fixed;
background-color: var(--ls-secondary-background-color);

View File

@@ -224,11 +224,10 @@
(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)
show-open-folder? (and (nfs/supported?)
(or (empty? repos)
(nil? (state/sub :git/current-repo)))
(not (mobile-util/is-native-platform?))
(not (mobile-util/native-platform?))
(not config/publishing?))]
[:div.cp__header#head
{:class (util/classnames [{:electron-mac electron-mac?
@@ -239,8 +238,7 @@
(when (and (util/electron?)
(.. target -classList (contains "cp__header")))
(js/window.apis.toggleMaxOrMinActiveWindow))))
:style {:fontSize 50
:transform (str "translateY(" (or (:offset-top vw-state) 0) "px)")}}
:style {:fontSize 50}}
[:div.l.flex
(left-menu-button {:on-click (fn []
(open-fn)
@@ -271,7 +269,7 @@
(mobile-util/native-ios?))
(back-and-forward))
(when-not (mobile-util/is-native-platform?)
(when-not (mobile-util/native-platform?)
(new-block-mode))
(when show-open-folder?

View File

@@ -16,6 +16,7 @@
user-select: none;
line-height: 1;
white-space: nowrap;
background-color: var(--ls-primary-background-color);
> .l {
width: var(--ls-left-sidebar-width);
@@ -221,7 +222,9 @@ html.is-native-iphone-without-notch,
html.is-native-ipad {
#main-container {
padding-top: 0px;
padding-top: 0px;
display: flex;
flex-direction: column;
}
#main-content-container {

View File

@@ -71,10 +71,10 @@
[:section.a
[:strong "Lets get you set up."]
[:small (str "Where on your " DEVICE " do you want to save your work?")
(when (mobile-util/is-native-platform?)
(when (mobile-util/native-platform?)
(mobile-intro))]
(if (or (nfs/supported?) (mobile-util/is-native-platform?))
(if (or (nfs/supported?) (mobile-util/native-platform?))
[:div.choose.flex.flex-col.items-center
{:on-click #(page-handler/ls-dir-files!
(fn []

View File

@@ -183,7 +183,7 @@
(ui/foldable
[:h2.font-bold.opacity-50 (util/format "Pages tagged with \"%s\"" tag)]
[:ul.mt-2
(for [[original-name name] (sort pages)]
(for [[original-name name] (sort-by last pages)]
[:li {:key (str "tagged-page-" name)}
[:a {:href (rfe/href :page {:name name})}
original-name]])]
@@ -231,7 +231,6 @@
(when (gp-util/wrapped-by-quotes? @*title-value)
(swap! *title-value gp-util/unquote-string)
(gobj/set (rum/deref input-ref) "value" @*title-value))
(state/set-state! :editor/editing-page-title? false)
(cond
(= old-name @*title-value)
(reset! *edit? false)
@@ -266,7 +265,6 @@
(reset! *title-value old-name)
(reset! *edit? false)))}]]
[:a.page-title {:on-mouse-down (fn [e]
(state/set-state! :editor/editing-page-title? true)
(when (util/right-click? e)
(state/set-state! :page-title/context {:page page-name})))
:on-click (fn [e]
@@ -364,7 +362,7 @@
[:div.relative
(when (and (not sidebar?) (not block?))
[:div.flex.flex-row.space-between
(when (or (mobile-util/is-native-platform?) (util/mobile?))
(when (or (mobile-util/native-platform?) (util/mobile?))
[:div.flex.flex-row.pr-2
{:style {:margin-left -15}
:on-mouse-over (fn [e]

View File

@@ -84,7 +84,7 @@
(page-handler/unfavorite-page! page-original-name)
(page-handler/favorite-page! page-original-name)))}}
(when-not (mobile-util/is-native-platform?)
(when-not (mobile-util/native-platform?)
{:title (t :page/presentation-mode)
:options {:on-click (fn []
(state/sidebar-add-block!
@@ -103,7 +103,7 @@
:options {:on-click #(js/window.apis.openPath file-path)}}])
(when (or (util/electron?)
(mobile-util/is-native-platform?))
(mobile-util/native-platform?))
{:title (t :page/copy-page-url)
:options {:on-click #(util/copy-to-clipboard!
(url-util/get-logseq-graph-page-url nil repo page-original-name))}})

View File

@@ -44,7 +44,7 @@
[:div.pl-1.content.mt-3
[:div.flex.flex-row.my-4
(when (or (nfs-handler/supported?)
(mobile-util/is-native-platform?))
(mobile-util/native-platform?))
[:div.mr-8
(ui/button
(t :open-a-directory)
@@ -102,7 +102,7 @@
(when (and nfs-repo?
(not= current-repo config/local-repo)
(or (nfs-handler/supported?)
(mobile-util/is-native-platform?)))
(mobile-util/native-platform?)))
{:title (t :sync-from-local-files)
:hover-detail (t :sync-from-local-files-detail)
:options {:on-click

View File

@@ -132,7 +132,7 @@
:href href
:on-click on-click))]
(when-not (or (util/mobile?)
(mobile-util/is-native-platform?))
(mobile-util/native-platform?))
[:div.text-sm desc])]])
(defn edit-config-edn []
@@ -161,7 +161,7 @@
(ui/toggle show-brackets?
config-handler/toggle-ui-show-brackets!
true)]]
(when (not (or (util/mobile?) (mobile-util/is-native-platform?)))
(when (not (or (util/mobile?) (mobile-util/native-platform?)))
[:div {:style {:text-align "right"}}
(ui/render-keyboard-shortcut (shortcut-helper/gen-shortcut-seq :ui/toggle-brackets))])])
@@ -543,9 +543,9 @@
(show-brackets-row t show-brackets?)
(when (util/electron?) (switch-spell-check-row t))
(outdenting-row t logical-outdenting?)
(when-not (or (util/mobile?) (mobile-util/is-native-platform?))
(when-not (or (util/mobile?) (mobile-util/native-platform?))
(shortcut-tooltip-row t enable-shortcut-tooltip?))
(when-not (or (util/mobile?) (mobile-util/is-native-platform?))
(when-not (or (util/mobile?) (mobile-util/native-platform?))
(tooltip-row t enable-tooltip?))
(timetracking-row t enable-timetracking?)
(journal-row t enable-journals?)
@@ -595,7 +595,7 @@
[:div.panel-wrap.is-advanced
(when (and util/mac? (util/electron?)) (app-auto-update-row t))
(usage-diagnostics-row t instrument-disabled?)
(when-not (mobile-util/is-native-platform?) (developer-mode-row t developer-mode?))
(when-not (mobile-util/native-platform?) (developer-mode-row t developer-mode?))
(when (util/electron?) (plugin-system-switcher-row))
(when (util/electron?) (https-user-agent-row https-agent-opts))
(clear-cache-row t)
@@ -633,7 +633,7 @@
(for [[label text icon]
[[:general (t :settings-page/tab-general) (ui/icon "adjustments" {:style {:font-size 20}})]
[:editor (t :settings-page/tab-editor) (ui/icon "writing" {:style {:font-size 20}})]
(when-not (mobile-util/is-native-platform?)
(when-not (mobile-util/native-platform?)
[:git (t :settings-page/tab-version-control) (ui/icon "history" {:style {:font-size 20}})])
[:advanced (t :settings-page/tab-advanced) (ui/icon "bulb" {:style {:font-size 20}})]
(when plugins-of-settings

View File

@@ -4,37 +4,38 @@
[frontend.components.command-palette :as command-palette]
[frontend.components.header :as header]
[frontend.components.journal :as journal]
[frontend.components.onboarding :as onboarding]
[frontend.components.plugins :as plugins]
[frontend.components.repo :as repo]
[frontend.components.right-sidebar :as right-sidebar]
[frontend.components.select :as select]
[frontend.components.svg :as svg]
[frontend.components.theme :as theme]
[frontend.components.widgets :as widgets]
[frontend.components.plugins :as plugins]
[frontend.components.select :as select]
[frontend.config :as config]
[frontend.context.i18n :refer [t]]
[frontend.db :as db]
[frontend.db.model :as db-model]
[frontend.components.svg :as svg]
[frontend.db-mixins :as db-mixins]
[frontend.db.model :as db-model]
[frontend.extensions.pdf.assets :as pdf-assets]
[frontend.extensions.srs :as srs]
[frontend.handler.editor :as editor-handler]
[frontend.handler.route :as route-handler]
[frontend.handler.mobile.swipe :as swipe]
[frontend.handler.page :as page-handler]
[frontend.handler.route :as route-handler]
[frontend.handler.user :as user-handler]
[frontend.mixins :as mixins]
[frontend.mobile.footer :as footer]
[frontend.mobile.util :as mobile-util]
[frontend.mobile.mobile-bar :refer [mobile-bar]]
[frontend.modules.shortcut.data-helper :as shortcut-dh]
[frontend.state :as state]
[frontend.ui :as ui]
[frontend.util :as util]
[reitit.frontend.easy :as rfe]
[goog.dom :as gdom]
[goog.object :as gobj]
[rum.core :as rum]
[frontend.extensions.srs :as srs]
[frontend.extensions.pdf.assets :as pdf-assets]
[frontend.mobile.util :as mobile-util]
[frontend.handler.mobile.swipe :as swipe]
[frontend.components.onboarding :as onboarding]
[frontend.mobile.footer :as footer]))
[reitit.frontend.easy :as rfe]
[rum.core :as rum]))
(rum/defc nav-content-item
[name {:keys [class]} child]
@@ -305,7 +306,10 @@
:data-is-full-width (or margin-less-pages?
(contains? #{:all-files :all-pages :my-publishing} route-name))}
(when (and (not (mobile-util/is-native-platform?))
(mobile-bar)
(footer/footer)
(when (and (not (mobile-util/native-platform?))
(contains? #{:page :home} route-name))
(widgets/demo-graph-alert))
@@ -378,7 +382,10 @@
[page :page])]
(state/sidebar-add-block! current-repo db-id block-type)))
(reset! sidebar-inited? true))))
state)}
state)
:did-mount (fn [state]
(state/set-state! :mobile/show-tabbar? true)
state)}
[]
(let [default-home (get-default-home-if-valid)
current-repo (state/sub :git/current-repo)
@@ -465,7 +472,8 @@
(defn- hide-context-menu-and-clear-selection
[e]
(state/hide-custom-context-menu!)
(when-not (gobj/get e "shiftKey")
(when-not (or (gobj/get e "shiftKey")
(util/meta-key? e))
(editor-handler/clear-selection!)))
(rum/defcs ^:large-vars/cleanup-todo sidebar <
@@ -550,12 +558,7 @@
:indexeddb-support? indexeddb-support?
:light? light?
:db-restoring? db-restoring?
:main-content main-content})
(when (and (mobile-util/is-native-platform?)
current-repo
(not (state/sub :modal/show?)))
(footer/footer))]
:main-content main-content})]
(right-sidebar/sidebar)

View File

@@ -12,8 +12,8 @@
[]
[:div.flex.flex-col
[:h1.title (t :on-boarding/add-graph)]
(let [nfs-supported? (or (nfs/supported?) (mobile-util/is-native-platform?))]
(if (mobile-util/is-native-platform?)
(let [nfs-supported? (or (nfs/supported?) (mobile-util/native-platform?))]
(if (mobile-util/native-platform?)
[:div.text-sm
(ui/button "Open a local directory"
:on-click #(page-handler/ls-dir-files! shortcut/refresh!))

View File

@@ -315,7 +315,7 @@
(and (util/electron?) (local-db? repo-url))
(get-local-dir repo-url)
(and (mobile-util/is-native-platform?) (local-db? repo-url))
(and (mobile-util/native-platform?) (local-db? repo-url))
(let [dir (get-local-dir repo-url)]
(if (string/starts-with? dir "file:")
dir
@@ -328,7 +328,7 @@
(defn get-repo-path
[repo-url path]
(if (and (or (util/electron?) (mobile-util/is-native-platform?))
(if (and (or (util/electron?) (mobile-util/native-platform?))
(local-db? repo-url))
path
(util/node-path.join (get-repo-dir repo-url) path)))

View File

@@ -23,7 +23,7 @@
(defn get-repo-name
[repo]
(cond
(mobile-util/is-native-platform?)
(mobile-util/native-platform?)
(text/get-graph-name-from-path repo)
(config/local-db? repo)
@@ -36,7 +36,7 @@
"repo-path: output of `get-repo-name`"
[repo-path]
(if (or (util/electron?)
(mobile-util/is-native-platform?))
(mobile-util/native-platform?))
(text/get-file-basename repo-path)
repo-path))

View File

@@ -409,6 +409,29 @@
f))
form))
(defn get-sorted-page-block-ids
[page-id]
(let [root (db-utils/entity page-id)]
(loop [result []
children (sort-by-left (:block/_parent root) root)]
(if (seq children)
(let [child (first children)]
(recur (conj result (:db/id child))
(concat
(sort-by-left (:block/_parent child) child)
(rest children))))
result))))
(defn sort-page-random-blocks
"Blocks could be non consecutive."
[blocks]
(assert (every? #(= (:block/page %) (:block/page (first blocks))) blocks) "Blocks must to be in a same page.")
(let [page-id (:db/id (:block/page (first blocks)))
;; TODO: there's no need to sort all the blocks
sorted-ids (get-sorted-page-block-ids page-id)
blocks-map (zipmap (map :db/id blocks) blocks)]
(keep blocks-map sorted-ids)))
(defn has-children?
([block-id]
(has-children? (conn/get-db) block-id))
@@ -584,6 +607,57 @@
(recur parent)))
false)))))
(defn get-prev-sibling
[db id]
(when-let [e (d/entity db id)]
(let [left (:block/left e)]
(when (not= (:db/id left) (:db/id (:block/parent e)))
left))))
(defn get-right-sibling
[db db-id]
(when-let [block (d/entity db db-id)]
(get-by-parent-&-left db
(:db/id (:block/parent block))
db-id)))
(defn last-child-block?
"The child block could be collapsed."
[db parent-id child-id]
(when-let [child (d/entity db child-id)]
(cond
(= parent-id child-id)
true
(get-right-sibling db child-id)
false
:else
(last-child-block? db parent-id (:db/id (:block/parent child))))))
(defn- consecutive-block?
[block-1 block-2]
(let [db (conn/get-db)
aux-fn (fn [block-1 block-2]
(and (= (:block/page block-1) (:block/page block-2))
(or
;; sibling or child
(= (:db/id (:block/left block-2)) (:db/id block-1))
(when-let [prev-sibling (get-prev-sibling db (:db/id block-2))]
(last-child-block? db (:db/id prev-sibling) (:db/id block-1))))))]
(or (aux-fn block-1 block-2) (aux-fn block-2 block-1))))
(defn get-non-consecutive-blocks
[blocks]
(vec
(keep-indexed
(fn [i _block]
(when (< (inc i) (count blocks))
(when-not (consecutive-block? (nth blocks i)
(nth blocks (inc i)))
(nth blocks i))))
blocks)))
(defn- get-start-id-for-pagination-query
[repo-url current-db {:keys [db-before tx-meta] :as tx-report}
result outliner-op page-id block-id tx-block-ids]

View File

@@ -109,7 +109,7 @@
(defn gen-youtube-ts-macro []
(if-let [player (get-player (state/get-input))]
(util/format "{{youtube-timestamp %s}}" (Math/floor (.getCurrentTime ^js player)))
(when (mobile-util/is-native-platform?)
(when (mobile-util/native-platform?)
(notification/show!
"Please embed a YouTube video at first, then use this icon.
Remember: You can paste a raw YouTube url as embedded video on mobile."
@@ -123,9 +123,9 @@ Remember: You can paste a raw YouTube url as embedded video on mobile."
reg-number #"^\d+$"
timestamp (str timestamp)
total-seconds (-> (re-matches reg-number timestamp)
parse-long)
util/safe-parse-int)
[_ hours minutes seconds] (re-matches reg timestamp)
[hours minutes seconds] (map parse-long [hours minutes seconds])]
[hours minutes seconds] (map util/safe-parse-int [hours minutes seconds])]
(cond
total-seconds
total-seconds

View File

@@ -32,7 +32,7 @@
(and (util/electron?) (not bfs-local?))
node-record
(mobile-util/is-native-platform?)
(mobile-util/native-platform?)
mobile-record
(local-db? dir)
@@ -109,7 +109,7 @@
:else
(let [[old-path new-path]
(map #(if (or (util/electron?) (mobile-util/is-native-platform?))
(map #(if (or (util/electron?) (mobile-util/native-platform?))
%
(str (config/get-repo-dir repo) "/" %))
[old-path new-path])]
@@ -125,7 +125,7 @@
(util/electron?)
node-record
(mobile-util/is-native-platform?)
(mobile-util/native-platform?)
mobile-record
:else
@@ -136,7 +136,7 @@
(let [record (get-record)]
(p/let [result (protocol/open-dir record ok-handler)]
(if (or (util/electron?)
(mobile-util/is-native-platform?))
(mobile-util/native-platform?))
(let [[dir & paths] (bean/->clj result)]
[(:path dir) paths])
result))))
@@ -145,7 +145,7 @@
[path-or-handle ok-handler]
(let [record (get-record)
electron? (util/electron?)
mobile? (mobile-util/is-native-platform?)]
mobile? (mobile-util/native-platform?)]
(p/let [result (protocol/get-files record path-or-handle ok-handler)]
(if (or electron? mobile?)
(let [result (bean/->clj result)]

View File

@@ -93,7 +93,7 @@
(and (not (seq (db/get-files config/local-repo)))
;; Not native local directory
(not (some config/local-db? (map :url repos)))
(not (mobile-util/is-native-platform?)))
(not (mobile-util/native-platform?)))
;; will execute `(state/set-db-restoring! false)` inside
(repo-handler/setup-local-repo-if-not-exists!)
@@ -193,7 +193,7 @@
(p/let [repos (get-repos)]
(state/set-repos! repos)
(restore-and-setup! repos db-schema)
(when (mobile-util/is-native-platform?)
(when (mobile-util/native-platform?)
(p/do! (mobile-util/hide-splash))))
(reset! db/*sync-search-indice-f search/sync-search-indice!)

View File

@@ -1,13 +1,15 @@
(ns frontend.handler.editor
(:require ["/frontend/utils" :as utils]
["path" :as path]
[cljs.core.match :refer [match]]
[clojure.set :as set]
[clojure.string :as string]
[clojure.walk :as w]
[dommy.core :as dom]
[frontend.commands :as commands
:refer [*angle-bracket-caret-pos *show-block-commands
*show-commands *slash-caret-pos]]
:refer [*angle-bracket-caret-pos
*show-block-commands *show-commands
*slash-caret-pos]]
[frontend.config :as config]
[frontend.date :as date]
[frontend.db :as db]
@@ -25,12 +27,12 @@
[frontend.handler.notification :as notification]
[frontend.handler.repeated :as repeated]
[frontend.handler.route :as route-handler]
[frontend.image :as image]
[frontend.idb :as idb]
[frontend.image :as image]
[frontend.mobile.util :as mobile-util]
[frontend.modules.outliner.core :as outliner-core]
[frontend.modules.outliner.tree :as tree]
[frontend.modules.outliner.transaction :as outliner-tx]
[frontend.modules.outliner.tree :as tree]
[frontend.search :as search]
[frontend.state :as state]
[frontend.template :as template]
@@ -40,21 +42,20 @@
[frontend.util.clock :as clock]
[frontend.util.cursor :as cursor]
[frontend.util.drawer :as drawer]
[frontend.util.marker :as marker]
[frontend.util.property :as property]
[frontend.util.priority :as priority]
[frontend.util.thingatpt :as thingatpt]
[frontend.util.keycode :as keycode]
[frontend.util.list :as list]
[frontend.util.marker :as marker]
[frontend.util.priority :as priority]
[frontend.util.property :as property]
[frontend.util.thingatpt :as thingatpt]
[goog.dom :as gdom]
[goog.dom.classes :as gdom-classes]
[goog.object :as gobj]
[lambdaisland.glogi :as log]
[promesa.core :as p]
[frontend.util.keycode :as keycode]
[logseq.graph-parser.util :as gp-util]
[logseq.graph-parser.mldoc :as gp-mldoc]
[logseq.graph-parser.block :as gp-block]
["path" :as path]))
[logseq.graph-parser.block :as gp-block]))
;; FIXME: should support multiple images concurrently uploading
@@ -1411,7 +1412,7 @@
(util/electron?)
(str "assets://" repo-dir path)
(mobile-util/is-native-platform?)
(mobile-util/native-platform?)
(mobile-util/convert-file-src (str repo-dir path))
:else
@@ -1677,7 +1678,8 @@
(move-nodes blocks))
(when-let [input-id (state/get-edit-input-id)]
(when-let [input (gdom/getElement input-id)]
(.focus input))))
(.focus input)
(js/setTimeout #(util/scroll-editor-cursor input) 100))))
(let [ids (state/get-selection-block-ids)]
(when (seq ids)
(let [lookup-refs (map (fn [id] [:block/uuid id]) ids)
@@ -2630,7 +2632,7 @@
;; FIXME: On mobile, a backspace click to call keydown-backspace-handler
;; does not work sometimes in an empty block, hence the empty block
;; can't be deleted. Need to figure out why and find a better solution.
(and (mobile-util/is-native-platform?)
(and (mobile-util/native-platform?)
(= key "Backspace")
(= value ""))
(do
@@ -2813,24 +2815,9 @@
[id]
(fn [_e]
(let [input (gdom/getElement id)]
(util/scroll-editor-cursor input)
(close-autocomplete-if-outside input))))
(defonce mobile-toolbar-height 40)
(defn editor-on-height-change!
[id]
(fn [box-height ^js row-height]
(let [row-height (:rowHeight (js->clj row-height :keywordize-keys true))
input (gdom/getElement id)
caret (cursor/get-caret-pos input)
cursor-bottom (if caret (+ row-height (:top caret)) box-height)
box-top (gobj/get (.getBoundingClientRect input) "top")
cursor-y (+ cursor-bottom box-top)
vw-height (.-height js/window.visualViewport)]
(when (< vw-height (+ cursor-y mobile-toolbar-height))
(let [main-node (gdom/getElement "main-content-container")
scroll-top (.-scrollTop main-node)]
(set! (.-scrollTop main-node) (+ scroll-top row-height)))))))
(defn editor-on-change!
[block id search-timeout]
(fn [e]
@@ -2842,7 +2829,9 @@
(js/setTimeout
#(edit-box-on-change! e block id)
timeout)))
(edit-box-on-change! e block id))))
(let [input (gdom/getElement id)]
(edit-box-on-change! e block id)
(util/scroll-editor-cursor input)))))
(defn- paste-text-parseable
[format text]
@@ -2878,6 +2867,18 @@
(recur (remove (set (map :block/uuid result)) (rest ids)) result))
result)))
(defn wrap-macro-url
[url]
(cond
(boolean (text/get-matched-video url))
(util/format "{{video %s}}" url)
(string/includes? url "twitter.com")
(util/format "{{twitter %s}}" url)
:else
(notification/show! (util/format "No macro is available for %s" url) :warning)))
(defn- paste-copied-blocks-or-text
[text e]
(let [copied-blocks (state/get-copied-blocks)
@@ -2905,18 +2906,7 @@
(and (gp-util/url? text)
(not (string/blank? (util/get-selected-text))))
(html-link-format! text)
(and (gp-util/url? text)
(or (string/includes? text "youtube.com")
(string/includes? text "youtu.be"))
(mobile-util/is-native-platform?))
(commands/simple-insert! (state/get-edit-input-id) (util/format "{{youtube %s}}" text) nil)
(and (gp-util/url? text)
(string/includes? text "twitter.com")
(mobile-util/is-native-platform?))
(commands/simple-insert! (state/get-edit-input-id) (util/format "{{twitter %s}}" text) nil)
(and (text/block-ref? text)
(wrapped-by? input "((" "))"))
(commands/simple-insert! (state/get-edit-input-id) (text/get-block-ref text) nil)
@@ -2953,7 +2943,10 @@
(utils/getClipText
(fn [clipboard-data]
(when-let [_ (state/get-input)]
(state/append-current-edit-content! clipboard-data)))
(let [data (if (gp-util/url? clipboard-data)
(wrap-macro-url clipboard-data)
clipboard-data)]
(state/append-current-edit-content! data))))
(fn [error]
(js/console.error error))))
@@ -2964,7 +2957,8 @@
(let [text (.getData (gobj/get e "clipboardData") "text")
input (state/get-input)]
(if-not (string/blank? text)
(if (thingatpt/org-admonition&src-at-point input)
(if (or (thingatpt/markdown-src-at-point input)
(thingatpt/org-admonition&src-at-point input))
(when-not (mobile-util/native-ios?)
(util/stop e)
(paste-text-in-one-block-at-point))

View File

@@ -3,7 +3,6 @@
[frontend.handler.editor.keyboards :as keyboards-handler]
[frontend.state :as state]
[frontend.util :as util]
[frontend.mobile.util :as mobile-util]
[goog.dom :as gdom]))
(defn did-mount!
@@ -21,9 +20,7 @@
(when-let [element (gdom/getElement id)]
(.focus element)
(when (or (mobile-util/is-native-platform?)
(util/mobile?))
(util/make-el-cursor-position-into-center-viewport element))))
(js/setTimeout #(util/scroll-editor-cursor element) 50)))
state)
(defn did-remount!

View File

@@ -137,7 +137,7 @@
[repo]
(when
(and (not (util/electron?))
(not (mobile-util/is-native-platform?)))
(not (mobile-util/native-platform?)))
(fn [close-fn]
[:div
[:p
@@ -288,15 +288,28 @@
(reset! st/*inited? true)
(st/consume-pending-shortcuts!)))
(defmethod handle :mobile/keyboard-will-show [[_ keyboard-height]]
(let [main-node (util/app-scroll-container-node)]
(state/set-state! :mobile/show-tabbar? false)
(state/set-state! :mobile/show-toolbar? true)
(when (mobile-util/native-ios?)
(reset! util/keyboard-height keyboard-height)
(set! (.. main-node -style -marginBottom) (str keyboard-height "px"))
(when-let [card-preview-el (js/document.querySelector ".cards-review")]
(set! (.. card-preview-el -style -marginBottom) (str keyboard-height "px")))
(js/setTimeout (fn []
(let [toolbar (.querySelector main-node "#mobile-editor-toolbar")]
(set! (.. toolbar -style -bottom) (str keyboard-height "px"))))
100))))
(defmethod handle :mobile/keyboard-will-show [[_]]
(when (and (state/get-left-sidebar-open?)
(state/editing?))
(state/set-left-sidebar-open! false)))
(defmethod handle :mobile/keyboard-did-show [[_]]
(when-let [input (state/get-input)]
(util/make-el-cursor-position-into-center-viewport input)))
(defmethod handle :mobile/keyboard-will-hide [[_]]
(let [main-node (util/app-scroll-container-node)]
(state/set-state! :mobile/show-toolbar? false)
(state/set-state! :mobile/show-tabbar? true)
(when (mobile-util/native-ios?)
(when-let [card-preview-el (js/document.querySelector ".cards-review")]
(set! (.. card-preview-el -style -marginBottom) "0px"))
(set! (.. main-node -style -marginBottom) "0px"))))
(defmethod handle :plugin/consume-updates [[_ id pending? updated?]]
(let [downloading? (:plugin/updates-downloading? @state/state)]

View File

@@ -164,7 +164,7 @@
(db/transact! [[:db.fn/retractEntity [:file/path file-path]]])
(->
(p/let [_ (and (config/local-db? repo)
(mobile-util/is-native-platform?)
(mobile-util/native-platform?)
(fs/delete-file! repo file-path file-path {}))
_ (fs/unlink! repo (config/get-repo-path repo file-path) nil)])
(p/catch (fn [err]
@@ -594,7 +594,7 @@
page)
(let [journal? (date/valid-journal-title? page)
ref-file-path (str
(if (or (util/electron?) (mobile-util/is-native-platform?))
(if (or (util/electron?) (mobile-util/native-platform?))
(-> (config/get-repo-dir (state/get-current-repo))
js/decodeURI
(string/replace #"/+$" "")
@@ -728,7 +728,7 @@
(not (state/loading-files? repo)))
(state/set-today! (date/today))
(when (or (config/local-db? repo)
(and (= "local" repo) (not (mobile-util/is-native-platform?))))
(and (= "local" repo) (not (mobile-util/native-platform?))))
(let [title (date/today)
today-page (util/page-name-sanity-lc title)
format (state/get-preferred-format repo)

View File

@@ -135,7 +135,7 @@
(defn exec-js-if-exists-&-allowed!
[t]
(when-not (mobile/is-native-platform?)
(when-not (mobile/native-platform?)
(when-let [href (or
(state/get-custom-js-link)
(config/get-custom-js-path))]

View File

@@ -26,12 +26,12 @@
[frontend.encrypt :as encrypt]))
(defn remove-ignore-files
[files]
[files dir-name nfs?]
(let [files (remove (fn [f]
(let [path (:file/path f)]
(or (string/starts-with? path ".git/")
(string/includes? path ".git/")
(and (util-fs/ignored-path? "" path)
(and (util-fs/ignored-path? (if nfs? "" dir-name) path)
(not= (:file/name f) ".gitignore")))))
files)]
(if-let [ignore-file (some #(when (= (:file/name %) ".gitignore")
@@ -55,7 +55,7 @@
:file/last-modified-at mtime
:file/size size
:file/content content})
result)
result)
electron?
(map (fn [{:keys [path stat content]}]
@@ -64,7 +64,7 @@
:file/last-modified-at mtime
:file/size size
:file/content content}))
result)
result)
:else
(let [result (flatten (bean/->clj result))]
@@ -122,7 +122,7 @@
[ok-handler]
(let [path-handles (atom {})
electron? (util/electron?)
mobile-native? (mobile-util/is-native-platform?)
mobile-native? (mobile-util/native-platform?)
nfs? (and (not electron?)
(not mobile-native?))
*repo (atom nil)]
@@ -147,7 +147,7 @@
(nfs/add-nfs-file-handle! root-handle-path root-handle))
result (nth result 1)
files (-> (->db-files mobile-native? electron? dir-name result)
remove-ignore-files)
(remove-ignore-files dir-name nfs?))
_ (when nfs?
(let [file-paths (set (map :file/path files))]
(swap! path-handles (fn [handles]
@@ -282,7 +282,7 @@
handle-path (str config/local-handle-prefix dir-name)
path-handles (atom {})
electron? (util/electron?)
mobile-native? (mobile-util/is-native-platform?)
mobile-native? (mobile-util/native-platform?)
nfs? (and (not electron?)
(not mobile-native?))]
(when re-index?
@@ -297,7 +297,7 @@
(when nfs?
(swap! path-handles assoc path handle))))
new-files (-> (->db-files mobile-native? electron? dir-name files-result)
remove-ignore-files)
(remove-ignore-files dir-name nfs?))
_ (when nfs?
(let [file-paths (set (map :file/path new-files))]
(swap! path-handles (fn [handles]

View File

@@ -1,5 +1,6 @@
(ns frontend.mobile.core
(:require ["@capacitor/app" :refer [^js App]]
["@capacitor/keyboard" :refer [^js Keyboard]]
[clojure.string :as string]
[frontend.fs.capacitor-fs :as fs]
[frontend.handler.editor :as editor-handler]
@@ -80,6 +81,15 @@
(fn [event]
(state/pub-event! [:file-watcher/changed event])))
(.addListener Keyboard "keyboardWillShow"
(fn [^js info]
(let [keyboard-height (.-keyboardHeight info)]
(state/pub-event! [:mobile/keyboard-will-show keyboard-height]))))
(.addListener Keyboard "keyboardWillHide"
(fn []
(state/pub-event! [:mobile/keyboard-will-hide])))
(.addEventListener js/window "statusTap"
#(util/scroll-to-top true))
@@ -96,6 +106,6 @@
(when (mobile-util/native-ios?)
(ios-init))
(when (mobile-util/is-native-platform?)
(when (mobile-util/native-platform?)
(general-init)))

View File

@@ -1,12 +1,12 @@
(ns frontend.mobile.footer
(:require [frontend.ui :as ui]
[rum.core :as rum]
[frontend.state :as state]
[frontend.mobile.record :as record]
[frontend.util :as util]
(:require [clojure.string :as string]
[frontend.date :as date]
[frontend.handler.editor :as editor-handler]
[clojure.string :as string]
[frontend.date :as date]))
[frontend.mobile.record :as record]
[frontend.state :as state]
[frontend.ui :as ui]
[frontend.util :as util]
[rum.core :as rum]))
(rum/defc mobile-bar-command [command-handler icon]
[:div
@@ -46,9 +46,8 @@
(rum/defc footer < rum/reactive
[]
(when-not (or (state/sub :editor/editing?)
(state/sub :block/component-editing-mode?)
(state/sub :editor/editing-page-title?))
(when (and (state/sub :mobile/show-tabbar?)
(state/get-current-repo))
[:div.cp__footer.w-full.bottom-0.justify-between
(audio-record-cp)
(mobile-bar-command #(state/toggle-document-mode!) "notes")

View File

@@ -1,9 +1,10 @@
.cp__footer {
position: absolute;
bottom: 0px;
left: 0px;
padding: 10px 20px;
background-color: var(--ls-primary-background-color);
z-index: 1000;
z-index: 10;
display: flex;
flex: 0 0 auto;
white-space: nowrap;
@@ -22,6 +23,56 @@
}
}
#mobile-editor-toolbar {
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%;
z-index: 9999;
display: flex;
justify-content: space-between;
button {
padding: 7px 10px;
.submenu {
background-color: red;
z-index: 100;
background-color: var(--ls-secondary-background-color);
border-radius: 5px;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.02);
overflow-x: overlay;
overflow-y: hidden;
left: 0px;
height: 40px;
}
.show-submenu {
display: block;
}
}
.toolbar-commands {
justify-content: space-between;
display: flex;
align-items: center;
overflow-x: overlay;
overflow-y: hidden;
width: 95%;
}
.toolbar-hide-keyboard {
border-left: 1px solid;
border-color: var(--ls-quaternary-background-color);
}
}
html.is-native-ipad {
.cp__footer {
height: 55px;

View File

@@ -1,22 +1,23 @@
(ns frontend.mobile.intent
(:require ["@capacitor/filesystem" :refer [Filesystem]]
["path" :as path]
["send-intent" :refer [^js SendIntent]]
[lambdaisland.glogi :as log]
[promesa.core :as p]
[clojure.pprint :as pprint]
[clojure.set :as set]
[clojure.string :as string]
[frontend.config :as config]
[frontend.date :as date]
[frontend.db :as db]
[frontend.handler.editor :as editor-handler]
[frontend.state :as state]
[frontend.date :as date]
[frontend.util :as util]
[frontend.config :as config]
[logseq.graph-parser.mldoc :as gp-mldoc]
[logseq.graph-parser.config :as gp-config]
["path" :as path]
[frontend.mobile.util :as mobile-util]
[frontend.handler.notification :as notification]
[clojure.pprint :as pprint]
[clojure.set :as set]))
[frontend.mobile.util :as mobile-util]
[frontend.state :as state]
[frontend.util :as util]
[lambdaisland.glogi :as log]
[logseq.graph-parser.config :as gp-config]
[logseq.graph-parser.mldoc :as gp-mldoc]
[logseq.graph-parser.text :as text]
[promesa.core :as p]))
(defn- handle-received-text [result]
(let [{:keys [title url]} result
@@ -33,9 +34,8 @@
(string/split url "\"\n"))
text (some-> text (string/replace #"^\"" ""))
url (and url
(cond (or (string/includes? url "youtube.com")
(string/includes? url "youtu.be"))
(util/format "{{youtube %s}}" url)
(cond (boolean (text/get-matched-video url))
(util/format "{{video %s}}" url)
(and (string/includes? url "twitter.com")
(string/includes? url "status"))

View File

@@ -0,0 +1,141 @@
(ns frontend.mobile.mobile-bar
(:require [dommy.core :as dom]
[frontend.commands :as commands]
[frontend.date :as date]
[frontend.handler.config :as config-handler]
[frontend.handler.editor :as editor-handler]
[frontend.handler.history :as history]
[frontend.handler.page :as page-handler]
[frontend.mobile.camera :as mobile-camera]
[frontend.state :as state]
[frontend.ui :as ui]
[frontend.util :as util]
[goog.dom :as gdom]
[rum.core :as rum]))
(def ^:private icons-keywords
[:checkbox :brackets :parentheses :command :tag :a-b :list :camera
:brand-youtube :link :rotate :rotate-clockwise :code :calendar :bold :italic :strikethrough :paint])
(def ^:private commands-stats
(atom (into {}
(mapv (fn [name] [name {:counts 0}])
icons-keywords))))
(defn set-command-stats [icon]
(let [key (keyword icon)
counts (get-in @commands-stats [key :counts])]
(swap! commands-stats
assoc-in [key :counts] (inc counts))
(config-handler/set-config!
:mobile/toolbar-stats @commands-stats)))
(rum/defc command
[command-handler icon & [count? event?]]
[:div
[:button.bottom-action
{:on-mouse-down (fn [e]
(util/stop e)
(when count?
(set-command-stats icon))
(if event?
(command-handler e)
(command-handler))
(state/set-state! :mobile/toolbar-update-observer (rand-int 1000000)))}
(ui/icon icon {:style {:fontSize ui/icon-size}})]])
(rum/defc indent-outdent [indent? icon]
[:div
[:button.bottom-action
{:on-mouse-down (fn [e]
(util/stop e)
(editor-handler/indent-outdent indent?))}
(ui/icon icon {:style {:fontSize ui/icon-size}})]])
(rum/defc timestamp-submenu
[parent-id]
(let [callback (fn [event]
(util/stop event)
(let [target (.-parentNode (.-target event))]
(dom/remove-class! target "show-submenu")))
command-cp (fn [action description]
[:button
{:on-mouse-down (fn [e]
(action)
(callback e))}
description])]
[:div
[:button.bottom-action
{:on-mouse-down (fn [event]
(util/stop event)
(set-command-stats :calendar)
(state/set-state! :mobile/toolbar-update-observer (rand-int 1000000))
(let [target (gdom/getNextElementSibling (.-target event))]
(dom/add-class! target "show-submenu")))}
(ui/icon "calendar" {:style {:fontSize ui/icon-size}})
[:div.submenu.fixed.hidden.flex.flex-col.w-full.justify-evenly
{:style {:bottom @util/keyboard-height}}
(command-cp #(let [today (page-handler/get-page-ref-text (date/today))]
(commands/simple-insert! parent-id today {}))
"Today")
(command-cp #(let [tomorrow (page-handler/get-page-ref-text (date/tomorrow))]
(commands/simple-insert! parent-id tomorrow {}))
"Tomorrow")
(command-cp #(let [yesterday (page-handler/get-page-ref-text (date/yesterday))]
(commands/simple-insert! parent-id yesterday {}))
"Yesterday")
(command-cp #(let [timestamp (date/get-current-time)]
(commands/simple-insert! parent-id timestamp {}))
"Time")]]]))
(defn commands
[parent-id]
(let [viewport-fn (fn [] (when-let [input (gdom/getElement parent-id)]
(util/scroll-editor-cursor input :to-vw-one-quarter? true)
(.focus input)))]
(zipmap icons-keywords
[(command editor-handler/cycle-todo! "checkbox" true)
(command #(do (viewport-fn) (editor-handler/toggle-page-reference-embed parent-id)) "brackets" true)
(command #(do (viewport-fn) (editor-handler/toggle-block-reference-embed parent-id)) "parentheses" true)
(command #(do (viewport-fn) (commands/simple-insert! parent-id "/" {})) "command" true)
(command #(do (viewport-fn) (commands/simple-insert! parent-id "#" {})) "tag" true)
(command editor-handler/cycle-priority! "a-b" true)
(command editor-handler/toggle-list! "list" true)
(command #(mobile-camera/embed-photo parent-id) "camera" true)
(command commands/insert-youtube-timestamp "brand-youtube" true)
(command editor-handler/html-link-format! "link" true)
(command history/undo! "rotate" true true)
(command history/redo! "rotate-clockwise" true true)
(timestamp-submenu parent-id)
(command #(commands/simple-insert! parent-id "<" {}) "code" true)
(command editor-handler/bold-format! "bold" true)
(command editor-handler/italics-format! "italic" true)
(command editor-handler/strike-through-format! "strikethrough" true)
(command editor-handler/highlight-format! "paint" true)])))
(rum/defc mobile-bar < rum/reactive
[]
(when (and (state/sub :mobile/toolbar-update-observer)
(state/sub :mobile/show-toolbar?))
(when-let [config-toolbar-stats (:mobile/toolbar-stats (state/get-config))]
(prn :config-toolbar-stats config-toolbar-stats)
(reset! commands-stats config-toolbar-stats))
(let [parent-id (state/get-edit-input-id)
commands (commands parent-id)
sorted-commands (sort-by (comp :counts second) > @commands-stats)]
(when (and (state/sub :mobile/show-toolbar?)
(state/sub :editor/editing?))
[:div#mobile-editor-toolbar.bg-base-2
[:div.toolbar-commands
(indent-outdent false "arrow-bar-left")
(indent-outdent true "arrow-bar-right")
(command (editor-handler/move-up-down true) "arrow-bar-to-up")
(command (editor-handler/move-up-down false) "arrow-bar-to-down")
(command #(if (state/sub :document/mode?)
(editor-handler/insert-new-block! nil)
(commands/simple-insert! parent-id "\n" {})) "arrow-back")
(for [command sorted-commands]
((first command) commands))]
[:div.toolbar-hide-keyboard
(command #(state/clear-edit!) "keyboard-show")]]))))

View File

@@ -6,15 +6,15 @@
(defn platform []
(.getPlatform Capacitor))
(defn is-native-platform? []
(defn native-platform? []
(.isNativePlatform Capacitor))
(defn native-ios? []
(and (is-native-platform?)
(and (native-platform?)
(= (platform) "ios")))
(defn native-android? []
(and (is-native-platform?)
(and (native-platform?)
(= (platform) "android")))
(defn convert-file-src [path-str]
@@ -27,7 +27,7 @@
(defonce file-sync (registerPlugin "FileSync")))
;; NOTE: both iOS and android share the same FsWatcher API
(when (is-native-platform?)
(when (native-platform?)
(defonce fs-watcher (registerPlugin "FsWatcher")))
(defn sync-icloud-repo [repo-dir]
@@ -41,45 +41,6 @@
(defn hide-splash []
(.hide SplashScreen))
(def idevice-info
(atom
{:iPadPro12.9 {:width 1024 :height 1366 :statusbar 40}
:iPadPro11 {:width 834 :height 1194 :statusbar 40}
:iPadPro10.5 {:width 834 :height 1112 :statusbar 40}
:iPadAir10.5 {:width 834 :height 1112 :statusbar 40}
:iPadAir10.9 {:width 820 :height 1180 :statusbar 40}
:iPad10.2 {:width 810 :height 1080 :statusbar 40}
:iPadPro9.7 {:width 768 :height 1024 :statusbar 40}
:iPadmini9.7 {:width 768 :height 1024 :statusbar 40}
:iPadAir9.7 {:width 768 :height 1024 :statusbar 40}
:iPad9.7 {:width 768 :height 1024 :statusbar 40}
:iPadmini8.3 {:width 744 :height 1133 :statusbar 40}
:iPhone7Plus {:width 476 :height 847 :statusbar 20}
:iPhone6sPlus {:width 476 :height 847 :statusbar 20}
:iPhone6Plus {:width 476 :height 847 :statusbar 20}
:iPhone13ProMax {:width 428 :height 926 :statusbar 47}
:iPhone12ProMax {:width 428 :height 926 :statusbar 47}
:iPhone11ProMax {:width 414 :height 896 :statusbar 44}
:iPhone11 {:width 414 :height 896 :statusbar 48}
:iPhoneXSMax {:width 414 :height 896 :statusbar 48}
:iPhoneXR {:width 414 :height 896 :statusbar 48}
:iPhone8Plus {:width 414 :height 736 :statusbar 20}
:iPhone13Pro {:width 390 :height 844 :statusbar 47}
:iPhone13 {:width 390 :height 844 :statusbar 47}
:iPhone12 {:width 390 :height 844 :statusbar 47}
:iPhone12Pro {:width 390 :height 844 :statusbar 47}
:iPhone11Pro {:width 375 :height 812 :statusbar 44}
:iPhoneXS {:width 375 :height 812 :statusbar 44}
:iPhoneX {:width 375 :height 812 :statusbar 44}
:iPhone8 {:width 375 :height 667 :statusbar 20}
:iPhone7 {:width 375 :height 667 :statusbar 20}
:iPhone6s {:width 375 :height 667 :statusbar 20}
:iPhone6 {:width 375 :height 667 :statusbar 20}
:iPhone13mini {:width 375 :height 812 :statusbar 44}
:iPhone12mini {:width 375 :height 812 :statusbar 44}
:iPhoneSE4 {:width 320 :height 568 :statusbar 20}
:iPodtouch5 {:width 320 :height 568 :statusbar 20}}))
(defn get-idevice-model
[]
(when (native-ios?)
@@ -121,12 +82,3 @@
[]
(when-let [model (get-idevice-model)]
(string/starts-with? (first model) "iPad")))
(defn get-idevice-statusbar-height
[]
(let [[model landscape?] (get-idevice-model)
model (when-not (= model "Not a known Apple device!")
(keyword model))]
(if (and model landscape?)
20
(:statusbar (model @idevice-info)))))

View File

@@ -18,7 +18,7 @@
:initialScope {:tags
{:platform (cond
(util/electron?) "electron"
(mobile-util/is-native-platform?) "mobile"
(mobile-util/native-platform?) "mobile"
:else "web")
:publishing config/publishing?}}
:integrations [(new posthog/SentryIntegration posthog "logseq" 5311485)

View File

@@ -99,7 +99,7 @@
(-get-parent-id [this]
(-> (get-in this [:data :block/parent])
(outliner-u/->block-id)))
(outliner-u/->block-id)))
(-set-parent-id [this parent-id]
(outliner-u/check-block-id parent-id)
@@ -107,7 +107,7 @@
(-get-left-id [this]
(-> (get-in this [:data :block/left])
(outliner-u/->block-id)))
(outliner-u/->block-id)))
(-set-left-id [this left-id]
(outliner-u/check-block-id left-id)
@@ -170,7 +170,7 @@
(-del [this txs-state children?]
(assert (ds/outliner-txs-state? txs-state)
"db should be satisfied outliner-tx-state?")
"db should be satisfied outliner-tx-state?")
(let [block-id (tree/-get-id this)
ids (set (if children?
(let [children (db/get-block-children (state/get-current-repo) block-id)
@@ -192,7 +192,7 @@
(assoc :block/left parent))))
immediate-children)))
txs))
txs)]
txs)]
(swap! txs-state concat txs)
block-id))
@@ -209,12 +209,7 @@
(defn get-right-sibling
[db-id]
(when db-id
(when-let [block (db/entity db-id)]
(db-model/get-by-parent-&-left (conn/get-db)
(:db/id (:block/parent block))
db-id))))
(db-model/get-right-sibling (conn/get-db) db-id)))
(defn- assoc-level-aux
[tree-vec children-key init-level]
@@ -285,13 +280,13 @@
(loop [node node
limit limit
result []]
(if (zero? limit)
result
(if-let [left (tree/-get-left node)]
(if-not (= left parent)
(recur left (dec limit) (conj result (tree/-get-id left)))
result)
result)))))
(if (zero? limit)
result
(if-let [left (tree/-get-left node)]
(if-not (= left parent)
(recur left (dec limit) (conj result (tree/-get-id left)))
result)
result)))))
(defn- page-first-child?
[block]
@@ -494,6 +489,48 @@
{:tx-data full-tx
:blocks tx}))))
(defn- build-move-blocks-next-tx
[blocks]
(let [id->blocks (zipmap (map :db/id blocks) blocks)
top-level-blocks (get-top-level-blocks blocks)
top-level-blocks-ids (set (map :db/id top-level-blocks))
right-block (get-right-sibling (:db/id (last top-level-blocks)))]
(when (and right-block
(not (contains? top-level-blocks-ids (:db/id right-block))))
{:db/id (:db/id right-block)
:block/left (loop [block (:block/left right-block)]
(if (contains? top-level-blocks-ids (:db/id block))
(recur (:block/left (get id->blocks (:db/id block))))
(:db/id block)))})))
(defn- find-new-left
[block moved-ids target-block current-block sibling?]
(if (= (:db/id target-block) (:db/id (:block/left current-block)))
(if sibling?
(db/entity (last moved-ids))
target-block)
(let [left (db/entity (:db/id (:block/left block)))]
(if (contains? (set moved-ids) (:db/id left))
(find-new-left left moved-ids target-block current-block sibling?)
left))))
(defn- fix-non-consecutive-blocks
[blocks target-block sibling?]
(let [page-blocks (group-by :block/page blocks)]
(->>
(mapcat (fn [[_page blocks]]
(let [blocks (db-model/sort-page-random-blocks blocks)
non-consecutive-blocks (->> (conj (db-model/get-non-consecutive-blocks blocks) (last blocks))
(util/distinct-by :db/id))]
(when (seq non-consecutive-blocks)
(mapv (fn [block]
(when-let [right (get-right-sibling (:db/id block))]
(when-let [new-left (find-new-left right (distinct (map :db/id blocks)) target-block block sibling?)]
{:db/id (:db/id right)
:block/left (:db/id new-left)})))
non-consecutive-blocks)))) page-blocks)
(remove nil?))))
(defn- delete-block
"Delete block from the tree."
[txs-state block' children?]
@@ -556,23 +593,11 @@
(tree/-save new-right-node txs-state))))
(doseq [id block-ids]
(let [node (block (db/pull id))]
(tree/-del node txs-state true)))))
(tree/-del node txs-state true)))
(let [fix-non-consecutive-tx (fix-non-consecutive-blocks blocks nil false)]
(swap! txs-state concat fix-non-consecutive-tx))))
{:tx-data @txs-state}))
(defn- build-move-blocks-next-tx
[blocks]
(let [id->blocks (zipmap (map :db/id blocks) blocks)
top-level-blocks (get-top-level-blocks blocks)
top-level-blocks-ids (set (map :db/id top-level-blocks))
right-block (get-right-sibling (:db/id (last top-level-blocks)))]
(when (and right-block
(not (contains? top-level-blocks-ids (:db/id right-block))))
{:db/id (:db/id right-block)
:block/left (loop [block (:block/left right-block)]
(if (contains? top-level-blocks-ids (:db/id block))
(recur (:block/left (get id->blocks (:db/id block))))
(:db/id block)))})))
(defn move-blocks
"Move `blocks` to `target-block` as siblings or children."
[blocks target-block {:keys [sibling? outliner-op]}]
@@ -598,7 +623,8 @@
(let [children-ids (mapcat #(db/get-block-children-ids (state/get-current-repo) (:block/uuid %)) blocks)]
(map (fn [uuid] {:block/uuid uuid
:block/page target-page}) children-ids)))
full-tx (util/concat-without-nil tx-data move-blocks-next-tx children-page-tx)
fix-non-consecutive-tx (fix-non-consecutive-blocks blocks target-block sibling?)
full-tx (util/concat-without-nil tx-data move-blocks-next-tx children-page-tx fix-non-consecutive-tx)
tx-meta (cond-> {:move-blocks (mapv :db/id blocks)
:target (:db/id target-block)}
not-same-page?

View File

@@ -15,8 +15,7 @@
[]
(try
(comp
(ui/setup-active-keystroke!)
(ui/setup-patch-ios-visual-viewport-state!))
(ui/setup-active-keystroke!))
(catch js/Error _e
nil)))

View File

@@ -58,6 +58,7 @@
:modal/close-btn? nil
:modal/subsets []
;; right sidebar
:ui/fullscreen? false
:ui/settings-open? false
@@ -88,9 +89,6 @@
: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?
:config {}
@@ -114,7 +112,6 @@
:editor/args nil
:editor/on-paste? false
:editor/last-key-code nil
:editor/editing-page-title? false
;; for audio record
:editor/record-status "NONE"
@@ -146,6 +143,13 @@
:electron/updater {}
:electron/user-cfgs nil
;; mobile
:mobile/show-toolbar? false
;;; toolbar icon doesn't update correctly when clicking after separate it from box,
;;; add a random in (<= 1000000) to observer its update
:mobile/toolbar-update-observer 0
:mobile/show-tabbar? false
;; plugin
:plugin/enabled (and (util/electron?)
;; true false :theme-only
@@ -289,7 +293,7 @@
(defn get-current-repo
[]
(or (:git/current-repo @state)
(when-not (mobile-util/is-native-platform?)
(when-not (mobile-util/native-platform?)
"local")))
(defn get-config
@@ -853,10 +857,7 @@
(util/set-change-value input content))
(when move-cursor?
(cursor/move-cursor-to input pos))
(when (or (util/mobile?) (mobile-util/is-native-platform?))
(util/make-el-center-if-near-top input))))))))
(cursor/move-cursor-to input pos))))))))
(defn clear-edit!
[]
@@ -1193,7 +1194,7 @@
(defn enable-tooltip?
[]
(if (or (util/mobile?) (mobile-util/is-native-platform?))
(if (or (util/mobile?) (mobile-util/native-platform?))
false
(get (get (sub-config) (get-current-repo))
:ui/enable-tooltip?
@@ -1547,14 +1548,6 @@
[]
(: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))
(defn get-plugin-by-id
[id]
(when-let [id (and id (keyword id))]

View File

@@ -46,7 +46,7 @@
(util/safari?)
(js/window.scrollTo 0 0)))
(defonce icon-size (if (mobile-util/is-native-platform?) 23 20))
(defonce icon-size (if (mobile-util/native-platform?) 23 20))
(rum/defc ls-textarea
< rum/reactive
@@ -290,40 +290,6 @@
(.appendChild js/document.head node))
style)))
(defn setup-patch-ios-visual-viewport-state!
[]
(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? %)
on-viewport-changed
(fn []
(let [update-vw-state
(debounce
(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))
20)]
(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 vp "resize" on-viewport-changed)
(.removeEventListener vp "scroll" on-viewport-changed)
(state/set-visual-viewport-state nil))))
#())
(defn apply-custom-theme-effect! [theme]
(when plugin-handler/lsp-enabled?
(when-let [custom-theme (state/sub [:ui/custom-theme (keyword theme)])]
@@ -684,7 +650,7 @@
(assoc :on-mouse-down on-mouse-down
:class "cursor"))
[:div.flex.flex-row.items-center
(when-not (mobile-util/is-native-platform?)
(when-not (mobile-util/native-platform?)
[:a.block-control.opacity-50.hover:opacity-100.mr-2
(cond->
{:style {:width 14
@@ -953,7 +919,7 @@
(rum/local true ::active?)
[state content-fn sensor-opts {:keys [reset-height? once?]}]
(let [*active? (::active? state)]
(if (or (util/mobile?) (mobile-util/is-native-platform?))
(if (or (util/mobile?) (mobile-util/native-platform?))
(content-fn)
(let [*visible? (::visible? state)]
(visibility-sensor

View File

@@ -11,7 +11,7 @@
[cljs-time.coerce :as tc]
[cljs-time.core :as t]
[dommy.core :as d]
[frontend.mobile.util :refer [is-native-platform?]]
[frontend.mobile.util :refer [native-platform?]]
[logseq.graph-parser.util :as gp-util]
[goog.dom :as gdom]
[goog.object :as gobj]
@@ -89,7 +89,7 @@
#?(:cljs
(def nfs? (and (not (electron?))
(not (is-native-platform?)))))
(not (native-platform?)))))
#?(:cljs
(defn file-protocol?
@@ -1040,29 +1040,6 @@
(string/replace "&quot;" "\"")
(string/replace "&apos;" "'")))
#?(:cljs
(defn system-locales
[]
(when-not node-test?
(when-let [navigator (and js/window (.-navigator js/window))]
;; https://zzz.buzz/2016/01/13/detect-browser-language-in-javascript/
(when navigator
(let [v (js->clj
(or
(.-languages navigator)
(.-language navigator)
(.-userLanguage navigator)
(.-browserLanguage navigator)
(.-systemLanguage navigator)))]
(if (string? v) [v] v)))))))
#?(:cljs
(defn zh-CN-supported?
[]
(let [system-locales (set (system-locales))]
(or (contains? system-locales "zh-CN")
(contains? system-locales "zh-Hans-CN")))))
(comment
(= (get-relative-path "journals/2020_11_18.org" "pages/grant_ideas.org")
"../pages/grant_ideas.org")
@@ -1216,6 +1193,12 @@
(defn meta-key-name []
(if mac? "Cmd" "Ctrl")))
#?(:cljs
(defn meta-key? [e]
(if mac?
(gobj/get e "metaKey")
(gobj/get e "ctrlKey"))))
#?(:cljs
(defn right-click?
[e]
@@ -1224,42 +1207,53 @@
(or (= which 3)
(= button 2)))))
(def keyboard-height (atom nil))
#?(:cljs
(defn make-el-into-center-viewport
[^js/HTMLElement el]
(when el
(.scrollIntoView el #js {:block "center" :behavior "smooth"}))))
(defn scroll-editor-cursor
[^js/HTMLElement el & {:keys [to-vw-one-quarter?]}]
(when (and el (or (native-platform?) mobile?))
(let [box-rect (.getBoundingClientRect el)
box-top (.-top box-rect)
box-bottom (.-bottom box-rect)
#?(:cljs
(defn make-el-cursor-position-into-center-viewport
[^js/HTMLElement el]
(when el
(let [main-node (gdom/getElement "main-content-container")
pos (get-selection-start el)
cursor-top (some-> (gdom/getElement "mock-text")
gdom/getChildren
array-seq
(nth-safe pos)
.-offsetTop)
box-caret (.getBoundingClientRect el)
box-top (.-top box-caret)
box-bottom (.-bottom box-caret)
vw-height (or (.-height js/window.visualViewport)
(.-clientHeight js/document.documentElement))
scroll-top (.-scrollTop main-node)
cursor-y (if cursor-top (+ cursor-top box-top) box-bottom)
scroll (- cursor-y (/ vw-height 2))]
(when (> scroll 0)
(set! (.-scrollTop main-node) (+ scroll-top scroll)))))))
header-height (-> (gdom/getElementByClass "cp__header")
.-clientHeight)
#?(:cljs
(defn make-el-center-if-near-top
([^js/HTMLElement el]
(make-el-center-if-near-top el 80))
([^js/HTMLElement el offset]
(let [target-top (.-top (.getBoundingClientRect el))]
(when (<= target-top (or (safe-parse-int offset) 0))
(make-el-into-center-viewport el))))))
main-node (app-scroll-container-node)
scroll-top (.-scrollTop main-node)
current-pos (get-selection-start el)
mock-text (some-> (gdom/getElement "mock-text")
gdom/getChildren
array-seq
(nth-safe current-pos))
offset-top (and mock-text (.-offsetTop mock-text))
offset-height (and mock-text (.-offsetHeight mock-text))
cursor-y (if offset-top (+ offset-top box-top offset-height 2) box-bottom)
vw-height (or (.-height js/window.visualViewport)
(.-clientHeight js/document.documentElement))
;; mobile toolbar height: 40px
scroll (- cursor-y (- vw-height (+ @keyboard-height 40)))]
(cond
(and to-vw-one-quarter? (> cursor-y (* vw-height 0.4)))
(set! (.-scrollTop main-node) (+ scroll-top (- cursor-y (/ vw-height 4))))
(and (< cursor-y (+ header-height offset-height 4)) ;; 4 is top+bottom padding for per line
(>= cursor-y header-height))
(.scrollBy main-node (bean/->js {:top (- (+ offset-height 4))}))
(< cursor-y header-height)
(let [_ (.scrollIntoView el true)
main-node (app-scroll-container-node)
scroll-top (.-scrollTop main-node)]
(set! (.-scrollTop main-node) (- scroll-top (/ vw-height 4))))
(> scroll 0)
(set! (.-scrollTop main-node) (+ scroll-top scroll))
:else
nil)))))
#?(:cljs
(defn sm-breakpoint?

View File

@@ -4,17 +4,22 @@
;; TODO: move all file path related util functions to here
;; keep same as ignored-path? in src/electron/electron/utils.cljs
;; TODO: merge them
;; NOTE: This is not the same ignored-path? as src/electron/electron/utils.cljs.
;; The assets directory is ignored.
;;
;; When in nfs-mode, dir is "", path is relative path to graph dir.
;; When in native-mode, dir and path are absolute paths.
(defn ignored-path?
"Ignore path for ls-dir-files-with-handler! and reload-dir!"
[dir path]
(when (string? path)
(or
(some #(string/starts-with? path (str dir "/" %))
["." ".recycle" "assets" "node_modules" "logseq/bak"])
["." ".recycle" "assets" "node_modules" "logseq/bak" "version-files"])
(some #(string/includes? path (str "/" % "/"))
["." ".recycle" "assets" "node_modules" "logseq/bak"])
(string/ends-with? path ".DS_Store")
["." ".recycle" "assets" "node_modules" "logseq/bak" "version-files"])
(some #(string/ends-with? path %)
[".DS_Store" "logseq/graphs-txid.edn" "logseq/broken-config.edn"])
;; hidden directory or file
(let [relpath (path/relative dir path)]
(or (re-find #"/\.[^.]+" relpath)
@@ -24,4 +29,4 @@
(not (string/blank? (path/extname path)))
(not
(some #(string/ends-with? path %)
[".md" ".markdown" ".org" ".js" ".edn" ".css"])))))))
[".md" ".markdown" ".org" ".js" ".edn" ".css"])))))))

View File

@@ -147,7 +147,7 @@
:name name
:end (+ (:end admonition&src) (count name))))))))
(defn- markdown-src-at-point [& [input]]
(defn markdown-src-at-point [& [input]]
(when-let [markdown-src (thing-at-point ["```" "```"] input)]
(let [language (-> (:full-content markdown-src)
string/split-lines

View File

@@ -1,3 +1,3 @@
(ns frontend.version)
(defonce version "0.6.9")
(defonce version "0.6.10")

View File

@@ -122,6 +122,18 @@
[s]
(string/split s #"(\"[^\"]*\")"))
(def bilibili-regex #"^((?:https?:)?//)?((?:www).)?((?:bilibili.com))(/(?:video/)?)([\w-]+)(\S+)?$")
(def loom-regex #"^((?:https?:)?//)?((?:www).)?((?:loom.com))(/(?:share/|embed/))([\w-]+)(\S+)?$")
(def vimeo-regex #"^((?:https?:)?//)?((?:www).)?((?:player.vimeo.com|vimeo.com))(/(?:video/)?)([\w-]+)(\S+)?$")
(def youtube-regex #"^((?:https?:)?//)?((?:www|m).)?((?:youtube.com|youtu.be|y2u.be|youtube-nocookie.com))(/(?:[\w-]+\?v=|embed/|v/)?)([\w-]+)([\S^\?]+)?$")
(defn get-matched-video
[url]
(or (re-find youtube-regex url)
(re-find loom-regex url)
(re-find vimeo-regex url)
(re-find bilibili-regex url)))
(def markdown-link #"\[([^\[]+)\](\(.*\))")
(defn split-page-refs-without-brackets