mirror of
https://github.com/logseq/logseq.git
synced 2026-05-23 12:14:06 +00:00
Merge branch 'feat/db' into feat/capacitor-new
This commit is contained in:
4
deps/db/src/logseq/db/common/sqlite.cljs
vendored
4
deps/db/src/logseq/db/common/sqlite.cljs
vendored
@@ -330,9 +330,7 @@
|
||||
views
|
||||
all-files
|
||||
pages-datoms))]
|
||||
(prn :debug "db-graph?" db-graph?)
|
||||
(prn :debug "block/journal-day schema" (str (:block/journal-day (:schema db))))
|
||||
{:schema (assoc schema :block/journal-day {:db/index true})
|
||||
{:schema schema
|
||||
:initial-data data}))
|
||||
|
||||
(defn restore-initial-data
|
||||
|
||||
3
deps/db/src/logseq/db/file_based/schema.cljs
vendored
3
deps/db/src/logseq/db/file_based/schema.cljs
vendored
@@ -45,7 +45,8 @@
|
||||
|
||||
;; for pages
|
||||
:block/alias {:db/valueType :db.type/ref
|
||||
:db/cardinality :db.cardinality/many}
|
||||
:db/cardinality :db.cardinality/many
|
||||
:db/index true}
|
||||
|
||||
;; todo keywords, e.g. "TODO", "DOING", "DONE"
|
||||
:block/marker {}
|
||||
|
||||
@@ -241,19 +241,16 @@
|
||||
(if db-based?
|
||||
(db-based-statuses)
|
||||
(file-based-statuses))
|
||||
(mapv (fn [m]
|
||||
(let [command (if db-based?
|
||||
[:div.flex.flex-row.items-center.gap-2 m [:div.text-xs.opacity-50 "Status"]]
|
||||
m)
|
||||
icon (if db-based?
|
||||
(case m
|
||||
(mapv (fn [command]
|
||||
(let [icon (if db-based?
|
||||
(case command
|
||||
"Canceled" "Cancelled"
|
||||
"Doing" "InProgress50"
|
||||
m)
|
||||
command)
|
||||
"square-asterisk")]
|
||||
[command (->marker m) (str "Set status to " m) icon]))))]
|
||||
[command (->marker command) (str "Set status to " command) icon]))))]
|
||||
(when (seq result)
|
||||
(map (fn [v] (conj v "TASK")) result))))
|
||||
(map (fn [v] (conj v "TASK STATUS")) result))))
|
||||
|
||||
(defn file-based-priorities
|
||||
[]
|
||||
@@ -273,17 +270,17 @@
|
||||
(db-based-priorities)
|
||||
(file-based-priorities))
|
||||
(mapv (fn [item]
|
||||
(let [command (if db-based?
|
||||
[:div.flex.flex-row.items-center.gap-2 item [:div.text-xs.opacity-50 "Priority"]]
|
||||
item)]
|
||||
[command (->priority item) (str "Set priority to " item)
|
||||
(let [command item]
|
||||
[command
|
||||
(->priority item)
|
||||
(str "Set priority to " item)
|
||||
(if db-based?
|
||||
(str "priorityLvl" item)
|
||||
(str "circle-letter-" (util/safe-lower-case item)))])))
|
||||
(with-no-priority)
|
||||
(vec))]
|
||||
(when (seq result)
|
||||
(map (fn [v] (conj v "PRIORITY")) result))))
|
||||
(map (fn [v] (into v ["PRIORITY"])) result))))
|
||||
|
||||
;; Credits to roamresearch.com
|
||||
|
||||
@@ -297,8 +294,9 @@
|
||||
[]
|
||||
(mapv (fn [level]
|
||||
(let [heading (str "Heading " level)]
|
||||
[heading (->heading level) heading (str "h-" level)])) (range 1 7)))
|
||||
[heading (->heading level) heading (str "h-" level) "Heading"])) (range 1 7)))
|
||||
|
||||
(defonce *latest-matched-command (atom ""))
|
||||
(defonce *matched-commands (atom nil))
|
||||
(defonce *initial-commands (atom nil))
|
||||
|
||||
@@ -474,12 +472,18 @@
|
||||
(defn init-commands!
|
||||
[get-page-ref-text]
|
||||
(let [commands (commands-map get-page-ref-text)]
|
||||
(reset! *latest-matched-command "")
|
||||
(reset! *initial-commands commands)
|
||||
(reset! *matched-commands commands)))
|
||||
|
||||
(defn set-matched-commands!
|
||||
[command matched-commands]
|
||||
(reset! *latest-matched-command command)
|
||||
(reset! *matched-commands matched-commands))
|
||||
|
||||
(defn reinit-matched-commands!
|
||||
[]
|
||||
(reset! *matched-commands @*initial-commands))
|
||||
(set-matched-commands! "" @*initial-commands))
|
||||
|
||||
(defn restore-state
|
||||
[]
|
||||
|
||||
@@ -1068,7 +1068,7 @@
|
||||
(contains? config/video-formats asset-type))))
|
||||
|
||||
(declare block-positioned-properties)
|
||||
(rum/defc page-reference < rum/reactive
|
||||
(rum/defc page-reference < rum/reactive db-mixins/query
|
||||
"Component for page reference"
|
||||
[html-export? uuid-or-title* {:keys [nested-link? show-brackets? id] :as config} label]
|
||||
(when uuid-or-title*
|
||||
@@ -1077,7 +1077,8 @@
|
||||
uuid-or-title*)
|
||||
show-brackets? (if (some? show-brackets?) show-brackets? (state/show-brackets?))
|
||||
contents-page? (= "contents" (string/lower-case (str id)))
|
||||
block (db/get-page uuid-or-title)
|
||||
block* (db/get-page uuid-or-title)
|
||||
block (or (some-> (:db/id block*) db/sub-block) block*)
|
||||
config' (assoc config
|
||||
:label (mldoc/plain->text label)
|
||||
:contents-page? contents-page?
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
[react-draggable]
|
||||
[rum.core :as rum]))
|
||||
|
||||
(defonce no-matched-commands [["No matched commands" [[:editor/move-cursor-to-end]]]])
|
||||
|
||||
(defn filter-commands
|
||||
[page? commands]
|
||||
(if page?
|
||||
@@ -45,7 +47,7 @@
|
||||
(or
|
||||
(= "Add new property" (first item))
|
||||
(when (= (count item) 5)
|
||||
(contains? #{"TASK" "PRIORITY"} (last item))))) commands)
|
||||
(contains? #{"TASK STATUS" "PRIORITY"} (last item))))) commands)
|
||||
commands))
|
||||
|
||||
(rum/defcs commands < rum/reactive
|
||||
@@ -56,57 +58,59 @@
|
||||
_ (when (state/get-editor-action)
|
||||
(reset! *matched matched'))
|
||||
page? (db/page? (db/entity (:db/id (state/get-edit-block))))
|
||||
matched (filter-commands page? @*matched)]
|
||||
matched (or (filter-commands page? @*matched) no-matched-commands)
|
||||
filtered? (not= matched @commands/*initial-commands)]
|
||||
(ui/auto-complete
|
||||
matched
|
||||
{:get-group-name
|
||||
(fn [item]
|
||||
(when (= (count item) 5) (last item)))
|
||||
(cond->
|
||||
{:item-render
|
||||
(fn [item]
|
||||
(let [command-name (first item)
|
||||
command-doc (get item 2)
|
||||
plugin-id (get-in item [1 1 1 :pid])
|
||||
doc (when (state/show-command-doc?) command-doc)
|
||||
options (some-> item (get 3))
|
||||
icon-name (some-> (if (map? options) (:icon options) options) (name))
|
||||
command-name (if icon-name
|
||||
[:span.flex.items-center.gap-1
|
||||
(shui/tabler-icon icon-name)
|
||||
[:strong.font-normal command-name]]
|
||||
command-name)]
|
||||
(cond
|
||||
(or plugin-id (vector? doc))
|
||||
[:div.has-help
|
||||
{:title plugin-id}
|
||||
command-name
|
||||
(when doc (ui/tooltip [:small (svg/help-circle)] doc))]
|
||||
|
||||
:item-render
|
||||
(fn [item]
|
||||
(let [command-name (first item)
|
||||
command-doc (get item 2)
|
||||
plugin-id (get-in item [1 1 1 :pid])
|
||||
doc (when (state/show-command-doc?) command-doc)
|
||||
options (some-> item (get 3))
|
||||
icon-name (some-> (if (map? options) (:icon options) options) (name))
|
||||
command-name (if icon-name
|
||||
[:span.flex.items-center.gap-1
|
||||
(shui/tabler-icon icon-name)
|
||||
[:strong.font-normal command-name]]
|
||||
command-name)]
|
||||
(cond
|
||||
(or plugin-id (vector? doc))
|
||||
[:div.has-help
|
||||
{:title plugin-id}
|
||||
command-name
|
||||
(when doc (ui/tooltip [:small (svg/help-circle)] doc))]
|
||||
(string? doc)
|
||||
[:div {:title doc}
|
||||
command-name]
|
||||
|
||||
(string? doc)
|
||||
[:div {:title doc}
|
||||
command-name]
|
||||
:else
|
||||
[:div command-name])))
|
||||
|
||||
:else
|
||||
[:div command-name])))
|
||||
|
||||
:on-chosen
|
||||
(fn [chosen-item]
|
||||
(let [command (first chosen-item)]
|
||||
(reset! commands/*current-command command)
|
||||
(let [command-steps (get (into {} matched) command)
|
||||
restore-slash? (or
|
||||
(contains? #{"Today" "Yesterday" "Tomorrow" "Current time"} command)
|
||||
(and
|
||||
(not (fn? command-steps))
|
||||
(not (contains? (set (map first command-steps)) :editor/input))
|
||||
(not (contains? #{"Date picker" "Template" "Deadline" "Scheduled" "Upload an image"} command))))]
|
||||
(editor-handler/insert-command! id command-steps
|
||||
format
|
||||
{:restore? restore-slash?
|
||||
:command command}))))
|
||||
:class
|
||||
"cp__commands-slash"})))
|
||||
:on-chosen
|
||||
(fn [chosen-item]
|
||||
(let [command (first chosen-item)]
|
||||
(reset! commands/*current-command command)
|
||||
(let [command-steps (get (into {} matched) command)
|
||||
restore-slash? (or
|
||||
(contains? #{"Today" "Yesterday" "Tomorrow" "Current time"} command)
|
||||
(and
|
||||
(not (fn? command-steps))
|
||||
(not (contains? (set (map first command-steps)) :editor/input))
|
||||
(not (contains? #{"Date picker" "Template" "Deadline" "Scheduled" "Upload an image"} command))))]
|
||||
(editor-handler/insert-command! id command-steps
|
||||
format
|
||||
{:restore? restore-slash?
|
||||
:command command}))))
|
||||
:class
|
||||
"cp__commands-slash"}
|
||||
(not filtered?)
|
||||
(assoc :get-group-name
|
||||
(fn [item]
|
||||
(when (= (count item) 5) (last item))))))))
|
||||
|
||||
(defn- page-on-chosen-handler
|
||||
[embed? input id q pos format]
|
||||
|
||||
@@ -818,7 +818,7 @@
|
||||
concat-prev-block?
|
||||
(let [children (:block/_parent (db/entity (:db/id block)))
|
||||
db-based? (config/db-based-graph? repo)
|
||||
prev-block-is-not-parent? (not= (:block/uuid (:block/parent block)) (:block/uuid prev-block))
|
||||
prev-block-is-not-parent? (empty? (:block/_parent prev-block))
|
||||
delete-prev-block? (and db-based?
|
||||
prev-block-is-not-parent?
|
||||
(empty? (:block/tags block))
|
||||
@@ -1773,23 +1773,25 @@
|
||||
[property q]
|
||||
(search/property-value-search property q))
|
||||
|
||||
(defn get-matched-commands
|
||||
(defn get-last-command
|
||||
[input]
|
||||
(try
|
||||
(let [edit-content (or (gobj/get input "value") "")
|
||||
pos (cursor/pos input)
|
||||
last-slash-caret-pos (:pos (:pos (state/get-editor-action-data)))
|
||||
last-command (and last-slash-caret-pos (subs edit-content last-slash-caret-pos pos))]
|
||||
(when (> pos 0)
|
||||
(or
|
||||
(and (= commands/command-trigger (util/nth-safe edit-content (dec pos)))
|
||||
@commands/*initial-commands)
|
||||
(and last-command
|
||||
(commands/get-matched-commands last-command)))))
|
||||
(when (> pos 0) last-command))
|
||||
(catch :default e
|
||||
(js/console.error e)
|
||||
nil)))
|
||||
|
||||
(defn get-matched-commands
|
||||
[command]
|
||||
(condp = command
|
||||
nil nil
|
||||
"" @commands/*initial-commands
|
||||
(commands/get-matched-commands command)))
|
||||
|
||||
(defn auto-complete?
|
||||
[]
|
||||
(or @*asset-uploading?
|
||||
@@ -1929,9 +1931,9 @@
|
||||
(defn resize-image!
|
||||
[config block-id metadata full_text size]
|
||||
(let [asset (:asset-block config)]
|
||||
(if (and asset (config/db-based-graph?))
|
||||
(if (config/db-based-graph?)
|
||||
(property-handler/set-block-property! (state/get-current-repo)
|
||||
(:db/id asset)
|
||||
(if asset (:db/id asset) block-id)
|
||||
:logseq.property.asset/resize-metadata
|
||||
size)
|
||||
(let [new-meta (merge metadata size)
|
||||
@@ -3206,10 +3208,13 @@
|
||||
(and (= :commands (state/get-editor-action)) (not= k commands/command-trigger))
|
||||
(if (= commands/command-trigger (second (re-find #"(\S+)\s+$" value)))
|
||||
(state/clear-editor-action!)
|
||||
(let [matched-commands (get-matched-commands input)]
|
||||
(let [command (get-last-command input)
|
||||
matched-commands (get-matched-commands command)]
|
||||
(if (seq matched-commands)
|
||||
(reset! commands/*matched-commands matched-commands)
|
||||
(state/clear-editor-action!))))
|
||||
(commands/set-matched-commands! command matched-commands)
|
||||
(if (> (- (count command) (count @commands/*latest-matched-command)) 2)
|
||||
(state/clear-editor-action!)
|
||||
(reset! commands/*matched-commands nil)))))
|
||||
|
||||
:else
|
||||
(default-case-for-keyup-handler input current-pos k code is-processed?))
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
(ns frontend.handler.events.ui
|
||||
"UI events"
|
||||
(:require [frontend.components.block :as block]
|
||||
(:require [clojure.core.async :as async]
|
||||
[clojure.core.async.interop :refer [p->c]]
|
||||
[frontend.components.block :as block]
|
||||
[frontend.components.cmdk.core :as cmdk]
|
||||
[frontend.components.file-sync :as file-sync]
|
||||
[frontend.components.page :as component-page]
|
||||
[frontend.components.plugins :as plugin]
|
||||
[frontend.components.property.dialog :as property-dialog]
|
||||
@@ -20,6 +23,7 @@
|
||||
[frontend.fs.capacitor-fs :as capacitor-fs]
|
||||
[frontend.fs.nfs :as nfs]
|
||||
[frontend.fs.sync :as sync]
|
||||
[frontend.handler.db-based.rtc :as rtc-handler]
|
||||
[frontend.handler.editor :as editor-handler]
|
||||
[frontend.handler.events :as events]
|
||||
[frontend.handler.file-based.nfs :as nfs-handler]
|
||||
@@ -27,8 +31,11 @@
|
||||
[frontend.handler.notification :as notification]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.handler.repo :as repo-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.user :as user-handler]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[frontend.modules.instrumentation.sentry :as sentry-event]
|
||||
[frontend.state :as state]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
@@ -352,3 +359,44 @@
|
||||
(merge {:close-btn? false
|
||||
:center? true
|
||||
:close-backdrop? false} opts)))
|
||||
|
||||
(defn- enable-beta-features!
|
||||
[]
|
||||
(when-not (false? (state/enable-sync?)) ; user turns it off
|
||||
(file-sync-handler/set-sync-enabled! true)))
|
||||
|
||||
;; TODO: separate rtc and file-based implementation
|
||||
(defmethod events/handle :user/fetch-info-and-graphs [[_]]
|
||||
(state/set-state! [:ui/loading? :login] false)
|
||||
(async/go
|
||||
(let [result (async/<! (sync/<user-info sync/remoteapi))]
|
||||
(cond
|
||||
(instance? ExceptionInfo result)
|
||||
nil
|
||||
(map? result)
|
||||
(do
|
||||
(state/set-user-info! result)
|
||||
(when-let [uid (user-handler/user-uuid)]
|
||||
(sentry-event/set-user! uid))
|
||||
(let [status (if (user-handler/alpha-or-beta-user?) :welcome :unavailable)]
|
||||
(when (and (= status :welcome) (user-handler/logged-in?))
|
||||
(enable-beta-features!)
|
||||
(async/<! (p->c (rtc-handler/<get-remote-graphs)))
|
||||
(async/<! (file-sync-handler/load-session-graphs))
|
||||
(p/let [repos (repo-handler/refresh-repos!)]
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(when (some #(and (= (:url %) repo)
|
||||
(vector? (:sync-meta %))
|
||||
(util/uuid-string? (first (:sync-meta %)))
|
||||
(util/uuid-string? (second (:sync-meta %)))) repos)
|
||||
(sync/<sync-start)))))
|
||||
(file-sync/maybe-onboarding-show status)))))))
|
||||
|
||||
(defmethod events/handle :file-sync/onboarding-tip [[_ type opts]]
|
||||
(let [type (keyword type)]
|
||||
(when-not (config/db-based-graph? (state/get-current-repo))
|
||||
(shui/dialog-open!
|
||||
(file-sync/make-onboarding-panel type)
|
||||
(merge {:close-btn? false
|
||||
:center? true
|
||||
:close-backdrop? (not= type :welcome)} opts)))))
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns frontend.handler.file-based.events
|
||||
"Events that are only for file graphs"
|
||||
(:require [clojure.core.async :as async]
|
||||
[clojure.core.async.interop :refer [p->c]]
|
||||
[clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[frontend.components.diff :as diff]
|
||||
@@ -14,7 +13,6 @@
|
||||
[frontend.fs :as fs]
|
||||
[frontend.fs.sync :as sync]
|
||||
[frontend.handler.common :as common-handler]
|
||||
[frontend.handler.db-based.rtc :as rtc-handler]
|
||||
[frontend.handler.events :as events]
|
||||
[frontend.handler.file-based.file :as file-handler]
|
||||
[frontend.handler.file-based.nfs :as nfs-handler]
|
||||
@@ -28,7 +26,6 @@
|
||||
[frontend.handler.user :as user-handler]
|
||||
[frontend.mobile.graph-picker :as graph-picker]
|
||||
[frontend.mobile.util :as mobile-util]
|
||||
[frontend.modules.instrumentation.sentry :as sentry-event]
|
||||
[frontend.modules.shortcut.core :as st]
|
||||
[frontend.state :as state]
|
||||
[frontend.ui :as ui]
|
||||
@@ -164,37 +161,6 @@
|
||||
opts))
|
||||
{:center? true :close-btn? false :close-backdrop? false}))
|
||||
|
||||
(defn- enable-beta-features!
|
||||
[]
|
||||
(when-not (false? (state/enable-sync?)) ; user turns it off
|
||||
(file-sync-handler/set-sync-enabled! true)))
|
||||
|
||||
(defmethod events/handle :user/fetch-info-and-graphs [[_]]
|
||||
(state/set-state! [:ui/loading? :login] false)
|
||||
(async/go
|
||||
(let [result (async/<! (sync/<user-info sync/remoteapi))]
|
||||
(cond
|
||||
(instance? ExceptionInfo result)
|
||||
nil
|
||||
(map? result)
|
||||
(do
|
||||
(state/set-user-info! result)
|
||||
(when-let [uid (user-handler/user-uuid)]
|
||||
(sentry-event/set-user! uid))
|
||||
(let [status (if (user-handler/alpha-or-beta-user?) :welcome :unavailable)]
|
||||
(when (and (= status :welcome) (user-handler/logged-in?))
|
||||
(enable-beta-features!)
|
||||
(async/<! (p->c (rtc-handler/<get-remote-graphs)))
|
||||
(async/<! (file-sync-handler/load-session-graphs))
|
||||
(p/let [repos (repo-handler/refresh-repos!)]
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(when (some #(and (= (:url %) repo)
|
||||
(vector? (:sync-meta %))
|
||||
(util/uuid-string? (first (:sync-meta %)))
|
||||
(util/uuid-string? (second (:sync-meta %)))) repos)
|
||||
(sync/<sync-start)))))
|
||||
(file-sync/maybe-onboarding-show status)))))))
|
||||
|
||||
(defmethod events/handle :graph/pull-down-remote-graph [[_ graph dir-name]]
|
||||
(if (mobile-util/native-ios?)
|
||||
(when-let [graph-name (or dir-name (:GraphName graph))]
|
||||
@@ -234,15 +200,6 @@
|
||||
(file-sync/pick-page-histories-panel graph-uuid page-name)
|
||||
{:id :page-histories :label "modal-page-histories"}))
|
||||
|
||||
(defmethod events/handle :file-sync/onboarding-tip [[_ type opts]]
|
||||
(let [type (keyword type)]
|
||||
(when-not (config/db-based-graph? (state/get-current-repo))
|
||||
(shui/dialog-open!
|
||||
(file-sync/make-onboarding-panel type)
|
||||
(merge {:close-btn? false
|
||||
:center? true
|
||||
:close-backdrop? (not= type :welcome)} opts)))))
|
||||
|
||||
(defmethod events/handle :file-sync/maybe-onboarding-show [[_ type]]
|
||||
(file-sync/maybe-onboarding-show type))
|
||||
|
||||
|
||||
23
src/main/frontend/worker/db/fix.cljs
Normal file
23
src/main/frontend/worker/db/fix.cljs
Normal file
@@ -0,0 +1,23 @@
|
||||
(ns frontend.worker.db.fix
|
||||
"fix db"
|
||||
(:require [datascript.core :as d]
|
||||
[logseq.db.sqlite.util :as sqlite-util]))
|
||||
|
||||
(defn check-and-fix-schema!
|
||||
[repo conn]
|
||||
(let [schema (sqlite-util/get-schema repo)
|
||||
db-schema (:schema @conn)
|
||||
diffs (->> (keep (fn [[k v]]
|
||||
(let [schema-v (-> (get db-schema k)
|
||||
(dissoc :db/ident))
|
||||
schema-v' (cond-> schema-v
|
||||
(= (:db/cardinality schema-v) :db.cardinality/one)
|
||||
(dissoc :db/cardinality)
|
||||
(and (:db/index schema-v)
|
||||
(nil? (:db/index v)))
|
||||
(dissoc :db/index))]
|
||||
(when-not (or (= v schema-v') (= k :db/ident))
|
||||
(assoc v :db/ident k))))
|
||||
schema))]
|
||||
(when (seq diffs)
|
||||
(d/transact! conn diffs))))
|
||||
@@ -13,6 +13,7 @@
|
||||
[frontend.common.graph-view :as graph-view]
|
||||
[frontend.common.thread-api :as thread-api :refer [def-thread-api]]
|
||||
[frontend.worker.db-listener :as db-listener]
|
||||
[frontend.worker.db.fix :as db-fix]
|
||||
[frontend.worker.db.migrate :as db-migrate]
|
||||
[frontend.worker.db.validate :as worker-db-validate]
|
||||
[frontend.worker.export :as worker-export]
|
||||
@@ -333,6 +334,7 @@
|
||||
(search/create-tables-and-triggers! search-db)
|
||||
(let [schema (sqlite-util/get-schema repo)
|
||||
conn (sqlite-common-db/get-storage-conn storage schema)
|
||||
_ (db-fix/check-and-fix-schema! repo conn)
|
||||
_ (when datoms
|
||||
(let [data (map (fn [datom]
|
||||
[:db/add (:e datom) (:a datom) (:v datom)]) datoms)]
|
||||
|
||||
@@ -82,8 +82,10 @@
|
||||
(state/set-editor-action! action)
|
||||
;; Default cursor pos to end of line
|
||||
(let [pos (or cursor-pos (count value))
|
||||
input #js {:value value}]
|
||||
(with-redefs [editor/get-matched-commands (constantly commands)
|
||||
input #js {:value value}
|
||||
command (subs value 1)]
|
||||
(with-redefs [editor/get-last-command (constantly command)
|
||||
editor/get-matched-commands (constantly commands)
|
||||
;; Ignore as none of its behaviors are tested
|
||||
editor/default-case-for-keyup-handler (constantly nil)
|
||||
cursor/pos (constantly pos)]
|
||||
@@ -93,18 +95,31 @@
|
||||
|
||||
(deftest keyup-handler-test
|
||||
(testing "Command autocompletion"
|
||||
;; default last matching command is ""
|
||||
(keyup-handler {:value "/z"
|
||||
:action :commands
|
||||
:commands []})
|
||||
(is (= :commands (state/get-editor-action))
|
||||
"Completion stays open if no matches but differs from last success by <= 2 chars")
|
||||
|
||||
(keyup-handler {:value "/zz"
|
||||
:action :commands
|
||||
:commands []})
|
||||
(is (= :commands (state/get-editor-action))
|
||||
"Completion stays open if no matches but differs from last success by <= 2 chars")
|
||||
|
||||
(keyup-handler {:value "/zzz"
|
||||
:action :commands
|
||||
:commands []})
|
||||
(is (= nil (state/get-editor-action))
|
||||
"Completion closed if no matches and > 2 chars form last success")
|
||||
|
||||
(keyup-handler {:value "/b"
|
||||
:action :commands
|
||||
:commands [:fake-command]})
|
||||
(is (= :commands (state/get-editor-action))
|
||||
"Completion stays open if there is a matching command")
|
||||
|
||||
(keyup-handler {:value "/zz"
|
||||
:action :commands
|
||||
:commands []})
|
||||
(is (= nil (state/get-editor-action))
|
||||
"Completion closed if there no matching commands")
|
||||
|
||||
(keyup-handler {:value "/ " :action :commands})
|
||||
(is (= nil (state/get-editor-action))
|
||||
"Completion closed after a space follows /")
|
||||
|
||||
Reference in New Issue
Block a user