|
|
@@ -8,11 +8,14 @@
|
|
|
[frontend.util.drawer :as drawer]
|
|
|
[frontend.util.persist-var :as persist-var]
|
|
|
[frontend.db :as db]
|
|
|
+ [frontend.db.model :as db-model]
|
|
|
[frontend.db-mixins :as db-mixins]
|
|
|
[frontend.state :as state]
|
|
|
[frontend.handler.editor :as editor-handler]
|
|
|
[frontend.components.block :as component-block]
|
|
|
[frontend.components.macro :as component-macro]
|
|
|
+ [frontend.components.select :as component-select]
|
|
|
+ [frontend.components.svg :as svg]
|
|
|
[frontend.ui :as ui]
|
|
|
[frontend.date :as date]
|
|
|
[frontend.commands :as commands]
|
|
|
@@ -21,7 +24,6 @@
|
|
|
[cljs-time.local :as tl]
|
|
|
[cljs-time.coerce :as tc]
|
|
|
[clojure.string :as string]
|
|
|
- [goog.object :as gobj]
|
|
|
[rum.core :as rum]
|
|
|
[frontend.modules.shortcut.core :as shortcut]
|
|
|
[medley.core :as medley]))
|
|
|
@@ -215,16 +217,18 @@
|
|
|
|
|
|
(deftype Sided-Cloze-Card [block]
|
|
|
ICard
|
|
|
- (get-root-block [_this] (db/pull [:block/uuid (:block/uuid block)]))
|
|
|
+ (get-root-block [_this] (db/pull [:block/uuid block]))
|
|
|
ICardShow
|
|
|
(show-cycle [_this phase]
|
|
|
- (let [blocks (-> (db/get-block-and-children (state/get-current-repo) (:block/uuid block))
|
|
|
+ (let [block-id (:db/id block)
|
|
|
+ blocks (-> (db/get-paginated-blocks (state/get-current-repo) block-id
|
|
|
+ {:scoped-block-id block-id})
|
|
|
clear-collapsed-property)
|
|
|
cloze? (has-cloze? blocks)]
|
|
|
(case phase
|
|
|
1
|
|
|
(let [blocks-count (count blocks)]
|
|
|
- {:value [block] :next-phase (if (or (> blocks-count 1) (nil? cloze?)) 2 3)})
|
|
|
+ {:value [(first blocks)] :next-phase (if (or (> blocks-count 1) (nil? cloze?)) 2 3)})
|
|
|
2
|
|
|
{:value blocks :next-phase (if cloze? 3 1)}
|
|
|
3
|
|
|
@@ -240,8 +244,8 @@
|
|
|
{:show-cloze? true})))
|
|
|
|
|
|
(defn- ->card [block]
|
|
|
- {:pre [(map? block)]}
|
|
|
- (->Sided-Cloze-Card block))
|
|
|
+ (let [block' (db/pull (:db/id block))]
|
|
|
+ (->Sided-Cloze-Card block')))
|
|
|
|
|
|
;;; ================================================================
|
|
|
;;;
|
|
|
@@ -251,37 +255,38 @@
|
|
|
Add an extra condition: block's :block/refs contains `#card or [[card]]'"
|
|
|
([repo query-string]
|
|
|
(query repo query-string {}))
|
|
|
- ([repo query-string {:keys [disable-reactive? use-cache?]
|
|
|
+ ([repo query-string {:keys [use-cache?]
|
|
|
:or {use-cache? true}}]
|
|
|
(when (string? query-string)
|
|
|
- (let [query-string (template/resolve-dynamic-template! query-string)
|
|
|
- query-string (if-not (or (string/blank? query-string)
|
|
|
- (string/starts-with? query-string "(")
|
|
|
- (string/starts-with? query-string "["))
|
|
|
- (util/format "[[%s]]" (string/trim query-string))
|
|
|
- query-string)
|
|
|
- {:keys [query sort-by rules]} (query-dsl/parse query-string)
|
|
|
- query* (concat [['?b :block/refs '?bp] ['?bp :block/name card-hash-tag]]
|
|
|
- (if (coll? (first query))
|
|
|
- query
|
|
|
- [query]))]
|
|
|
- (when-let [query (query-dsl/query-wrapper query* true)]
|
|
|
- (let [result (query-react/react-query repo
|
|
|
- {:query (with-meta query {:cards-query? true})
|
|
|
- :rules (or rules [])}
|
|
|
- (merge
|
|
|
- {:use-cache? use-cache?}
|
|
|
- (cond->
|
|
|
- (when sort-by
|
|
|
- {:transform-fn sort-by})
|
|
|
- disable-reactive?
|
|
|
- (assoc :disable-reactive? true))))]
|
|
|
- (when result
|
|
|
- (flatten (util/react result)))))))))
|
|
|
+ (let [result (if (string/blank? query-string)
|
|
|
+ (:block/_refs (db/entity [:block/name card-hash-tag]))
|
|
|
+ (let [query-string (template/resolve-dynamic-template! query-string)
|
|
|
+ query-string (if-not (or (string/blank? query-string)
|
|
|
+ (string/starts-with? query-string "(")
|
|
|
+ (string/starts-with? query-string "["))
|
|
|
+ (util/format "[[%s]]" (string/trim query-string))
|
|
|
+ query-string)
|
|
|
+ {:keys [query sort-by rules]} (query-dsl/parse query-string)
|
|
|
+ query* (util/concat-without-nil
|
|
|
+ [['?b :block/refs '?br] ['?br :block/name card-hash-tag]]
|
|
|
+ (if (coll? (first query)) query [query]))]
|
|
|
+ (when-let [query (query-dsl/query-wrapper query*
|
|
|
+ {:blocks? true
|
|
|
+ :block-attrs [:db/id :block/properties]})]
|
|
|
+ (let [result (query-react/react-query repo
|
|
|
+ {:query (with-meta query {:cards-query? true})
|
|
|
+ :rules (or rules [])}
|
|
|
+ (merge
|
|
|
+ {:use-cache? use-cache?}
|
|
|
+ (when sort-by
|
|
|
+ {:transform-fn sort-by})))]
|
|
|
+ (when result
|
|
|
+ (flatten (util/react result)))))))]
|
|
|
+ (vec result)))))
|
|
|
|
|
|
(defn- query-scheduled
|
|
|
"Return blocks scheduled to 'time' or before"
|
|
|
- [_repo blocks time]
|
|
|
+ [blocks time]
|
|
|
(let [filtered-result (filterv (fn [b]
|
|
|
(let [props (:block/properties b)
|
|
|
next-sched (get props card-next-schedule-property)
|
|
|
@@ -333,7 +338,7 @@
|
|
|
result (get-next-interval card score)
|
|
|
next-of-matrix (:next-of-matrix result)]
|
|
|
(reset! of-matrix next-of-matrix)
|
|
|
- (save-block-card-properties! (db/pull [:block/uuid (:block/uuid block)])
|
|
|
+ (save-block-card-properties! (db/pull (:db/id block))
|
|
|
(select-keys result
|
|
|
[card-last-interval-property
|
|
|
card-repeats-property
|
|
|
@@ -346,23 +351,24 @@
|
|
|
[card]
|
|
|
{:pre [(satisfies? ICard card)]}
|
|
|
(let [block (.-block card)]
|
|
|
- (reset-block-card-properties! (db/pull [:block/uuid (:block/uuid block)]))))
|
|
|
+ (reset-block-card-properties! (db/pull (:db/id block)))))
|
|
|
|
|
|
(defn- operation-card-info-summary!
|
|
|
[review-records review-cards card-query-block]
|
|
|
(when card-query-block
|
|
|
(let [review-count (count (flatten (vals review-records)))
|
|
|
review-cards-count (count review-cards)
|
|
|
- score-5-count (count (get review-records 5))
|
|
|
- score-1-count (count (get review-records 1))]
|
|
|
+ score-remembered-count (+ (count (get review-records 5))
|
|
|
+ (count (get review-records 3)))
|
|
|
+ score-forgotten-count (count (get review-records 1))]
|
|
|
(editor-handler/insert-block-tree-after-target
|
|
|
(:db/id card-query-block) false
|
|
|
[{:content (util/format "Summary: %d items, %d review counts [[%s]]"
|
|
|
review-cards-count review-count (date/today))
|
|
|
:children [{:content
|
|
|
- (util/format "Remembered: %d (%d%%)" score-5-count (* 100 (/ score-5-count review-count)))}
|
|
|
+ (util/format "Remembered: %d (%d%%)" score-remembered-count (* 100 (/ score-remembered-count review-count)))}
|
|
|
{:content
|
|
|
- (util/format "Forgotten : %d (%d%%)" score-1-count (* 100 (/ score-1-count review-count)))}]}]
|
|
|
+ (util/format "Forgotten : %d (%d%%)" score-forgotten-count (* 100 (/ score-forgotten-count review-count)))}]}]
|
|
|
(:block/format card-query-block)))))
|
|
|
|
|
|
;;; ================================================================
|
|
|
@@ -376,24 +382,20 @@
|
|
|
(dec n)
|
|
|
n))))
|
|
|
|
|
|
-(defn- review-finished?
|
|
|
- [cards]
|
|
|
- (<= (count cards) 1))
|
|
|
-
|
|
|
-(defn- score-and-next-card [score card *card-index cards *phase *review-records cb]
|
|
|
+(defn- score-and-next-card [score card *card-index finished? *phase *review-records cb]
|
|
|
(operation-score! card score)
|
|
|
(swap! *review-records #(update % score (fn [ov] (conj ov card))))
|
|
|
- (if (review-finished? cards)
|
|
|
+ (if finished?
|
|
|
(when cb (cb @*review-records))
|
|
|
(reset! *phase 1))
|
|
|
(swap! *card-index inc)
|
|
|
(when @global-cards-mode?
|
|
|
(dec-cards-due-count!)))
|
|
|
|
|
|
-(defn- skip-card [card *card-index cards *phase *review-records cb]
|
|
|
+(defn- skip-card [card *card-index finished? *phase *review-records cb]
|
|
|
(swap! *review-records #(update % "skip" (fn [ov] (conj ov card))))
|
|
|
(swap! *card-index inc)
|
|
|
- (if (review-finished? cards)
|
|
|
+ (if finished?
|
|
|
(when cb (cb @*review-records))
|
|
|
(reset! *phase 1)))
|
|
|
|
|
|
@@ -402,42 +404,31 @@
|
|
|
|
|
|
(defn- btn-with-shortcut [{:keys [shortcut id btn-text background on-click class]}]
|
|
|
(ui/button
|
|
|
- [:span btn-text (when-not (util/sm-breakpoint?)
|
|
|
- [" " (ui/render-keyboard-shortcut shortcut)])]
|
|
|
- :id id
|
|
|
- :class (str id " " class)
|
|
|
- :background background
|
|
|
- :on-click (fn [e]
|
|
|
- (when-let [elem (gobj/get e "target")]
|
|
|
- (.add (.-classList elem) "opacity-25"))
|
|
|
- (js/setTimeout #(on-click) 10))))
|
|
|
-
|
|
|
-(rum/defcs view
|
|
|
- < rum/reactive
|
|
|
- db-mixins/query
|
|
|
+ [:span btn-text (when-not (util/sm-breakpoint?)
|
|
|
+ [" " (ui/render-keyboard-shortcut shortcut)])]
|
|
|
+ :id id
|
|
|
+ :class (str id " " class)
|
|
|
+ :background background
|
|
|
+ :on-mouse-down (fn [e] (util/stop-propagation e))
|
|
|
+ :on-click (fn [_e]
|
|
|
+ (js/setTimeout #(on-click) 10))))
|
|
|
+
|
|
|
+(rum/defcs view < rum/reactive db-mixins/query
|
|
|
(rum/local 1 ::phase)
|
|
|
(rum/local {} ::review-records)
|
|
|
- {:will-mount (fn [state]
|
|
|
- (state/set-state! :srs/mode? true)
|
|
|
- state)
|
|
|
- :will-unmount (fn [state]
|
|
|
- (state/set-state! :srs/mode? false)
|
|
|
- state)}
|
|
|
[state blocks {preview? :preview?
|
|
|
+ cards? :cards?
|
|
|
modal? :modal?
|
|
|
cb :callback}
|
|
|
card-index]
|
|
|
- (let [blocks (if (fn? blocks) (blocks) blocks)
|
|
|
- cards (map ->card blocks)
|
|
|
- review-records (::review-records state)
|
|
|
- ;; TODO: needs refactor
|
|
|
- card (if preview?
|
|
|
- (when card-index (util/nth-safe cards @card-index))
|
|
|
- (first cards))]
|
|
|
- (if-not card
|
|
|
+ (let [review-records (::review-records state)
|
|
|
+ current-block (util/nth-safe blocks @card-index)
|
|
|
+ card (when current-block (->card current-block))
|
|
|
+ finished? (= (inc @card-index) (count blocks))]
|
|
|
+ (if (nil? card)
|
|
|
review-finished
|
|
|
(let [phase (::phase state)
|
|
|
- {blocks :value next-phase :next-phase} (show-cycle card @phase)
|
|
|
+ {current-blocks :value next-phase :next-phase} (show-cycle card @phase)
|
|
|
root-block (.-block card)
|
|
|
root-block-id (:block/uuid root-block)]
|
|
|
[:div.ls-card.content
|
|
|
@@ -448,7 +439,7 @@
|
|
|
[:div {:style {:margin-top 20}}
|
|
|
(component-block/breadcrumb {} repo root-block-id {})])
|
|
|
(component-block/blocks-container
|
|
|
- blocks
|
|
|
+ current-blocks
|
|
|
(merge (show-cycle-config card @phase)
|
|
|
{:id (str root-block-id)
|
|
|
:editor-box editor/box
|
|
|
@@ -464,14 +455,16 @@
|
|
|
:id "card-answers"
|
|
|
:class "mr-2"
|
|
|
:on-click #(reset! phase next-phase)}))
|
|
|
- (when (and (> (count cards) 1) preview?)
|
|
|
+ (when (and (not= @card-index (count blocks))
|
|
|
+ cards?
|
|
|
+ preview?)
|
|
|
(btn-with-shortcut {:btn-text "Next"
|
|
|
:shortcut "n"
|
|
|
:id "card-next"
|
|
|
:class "mr-2"
|
|
|
:on-click (fn [e]
|
|
|
(util/stop e)
|
|
|
- (skip-card card card-index cards phase review-records cb))}))
|
|
|
+ (skip-card card card-index finished? phase review-records cb))}))
|
|
|
|
|
|
(when (and (not preview?) (= 1 next-phase))
|
|
|
[:<>
|
|
|
@@ -480,20 +473,20 @@
|
|
|
:id "card-forgotten"
|
|
|
:background "red"
|
|
|
:on-click (fn []
|
|
|
- (score-and-next-card 1 card card-index cards phase review-records cb)
|
|
|
+ (score-and-next-card 1 card card-index finished? phase review-records cb)
|
|
|
(let [tomorrow (tc/to-string (t/plus (t/today) (t/days 1)))]
|
|
|
(editor-handler/set-block-property! root-block-id card-next-schedule-property tomorrow)))})
|
|
|
|
|
|
(btn-with-shortcut {:btn-text (if (util/mobile?) "Hard" "Took a while to recall")
|
|
|
:shortcut "t"
|
|
|
:id "card-recall"
|
|
|
- :on-click #(score-and-next-card 3 card card-index cards phase review-records cb)})
|
|
|
+ :on-click #(score-and-next-card 3 card card-index finished? phase review-records cb)})
|
|
|
|
|
|
(btn-with-shortcut {:btn-text "Remembered"
|
|
|
:shortcut "r"
|
|
|
:id "card-remembered"
|
|
|
:background "green"
|
|
|
- :on-click #(score-and-next-card 5 card card-index cards phase review-records cb)})])
|
|
|
+ :on-click #(score-and-next-card 5 card card-index finished? phase review-records cb)})])
|
|
|
|
|
|
(when preview?
|
|
|
(ui/tippy {:html [:div.text-sm
|
|
|
@@ -510,24 +503,19 @@
|
|
|
|
|
|
(rum/defc view-modal <
|
|
|
(shortcut/mixin :shortcut.handler/cards)
|
|
|
- rum/reactive
|
|
|
- db-mixins/query
|
|
|
[blocks option card-index]
|
|
|
- (let [option (update option :random-mode? (fn [v] (if (util/atom? v) @v v)))
|
|
|
- blocks (if (fn? blocks) (blocks) blocks)
|
|
|
- blocks (if (:random-mode? option)
|
|
|
- (shuffle blocks)
|
|
|
- blocks)]
|
|
|
- [:div#cards-modal
|
|
|
- (if (seq blocks)
|
|
|
+ [:div#cards-modal
|
|
|
+ (if (seq blocks)
|
|
|
+ (rum/with-key
|
|
|
(view blocks option card-index)
|
|
|
- review-finished)]))
|
|
|
+ (str "ls-card-" (:db/id (first blocks))))
|
|
|
+ review-finished)])
|
|
|
|
|
|
-(rum/defc preview-cp
|
|
|
+(rum/defc preview-cp < rum/reactive db-mixins/query
|
|
|
[block-id]
|
|
|
- (let [blocks-f (fn [] (db/get-paginated-blocks (state/get-current-repo) block-id
|
|
|
- {:scoped-block-id block-id}))]
|
|
|
- (view-modal blocks-f {:preview? true} (atom 0))))
|
|
|
+ (let [blocks (db/get-paginated-blocks (state/get-current-repo) block-id
|
|
|
+ {:scoped-block-id block-id})]
|
|
|
+ (view-modal blocks {:preview? true} (atom 0))))
|
|
|
|
|
|
(defn preview
|
|
|
[block-id]
|
|
|
@@ -563,49 +551,69 @@
|
|
|
(try
|
|
|
(let [repo (state/get-current-repo)
|
|
|
query-string ""
|
|
|
- blocks (query repo query-string {:use-cache? false
|
|
|
- :disable-reactive? true})]
|
|
|
+ blocks (query repo query-string {:use-cache? false})]
|
|
|
(when (seq blocks)
|
|
|
- (let [{:keys [result]} (query-scheduled repo blocks (tl/local-now))
|
|
|
+ (let [{:keys [result]} (query-scheduled blocks (tl/local-now))
|
|
|
count (count result)]
|
|
|
(reset! cards-total count)
|
|
|
count)))
|
|
|
(catch js/Error e
|
|
|
(js/console.error e) 0)))
|
|
|
|
|
|
+(declare cards)
|
|
|
+
|
|
|
+(rum/defc cards-select
|
|
|
+ [{:keys [on-chosen]}]
|
|
|
+ (let [cards (db-model/get-macro-blocks (state/get-current-repo) "cards")
|
|
|
+ items (->> (map (comp :logseq.macro-arguments :block/properties) cards)
|
|
|
+ (map (fn [col] (string/join " " col))))
|
|
|
+ items (concat items ["All"])]
|
|
|
+ (component-select/select {:items items
|
|
|
+ :on-chosen on-chosen
|
|
|
+ :close-modal? false
|
|
|
+ :input-default-placeholder "Switch to"
|
|
|
+ :extract-fn nil})))
|
|
|
+
|
|
|
;;; register cards macro
|
|
|
-(rum/defcs ^:large-vars/cleanup-todo cards < rum/reactive db-mixins/query
|
|
|
+(rum/defcs ^:large-vars/cleanup-todo cards-inner < rum/reactive db-mixins/query
|
|
|
(rum/local 0 ::card-index)
|
|
|
(rum/local false ::random-mode?)
|
|
|
(rum/local false ::preview-mode?)
|
|
|
- [state config options]
|
|
|
+ [state config options {:keys [query-atom query-string query-result due-result]}]
|
|
|
(let [*random-mode? (::random-mode? state)
|
|
|
*preview-mode? (::preview-mode? state)
|
|
|
- repo (state/get-current-repo)
|
|
|
- query-string (string/join ", " (:arguments options))
|
|
|
- query-result (query repo query-string)
|
|
|
- *card-index (::card-index state)
|
|
|
- global? (:global? config)]
|
|
|
+ *card-index (::card-index state)]
|
|
|
(if (seq query-result)
|
|
|
- (let [{:keys [total result]} (query-scheduled repo query-result (tl/local-now))
|
|
|
- review-cards result
|
|
|
+ (let [{:keys [total result]} due-result
|
|
|
+ review-cards (if @*preview-mode? query-result result)
|
|
|
card-query-block (db/entity [:block/uuid (:block/uuid config)])
|
|
|
filtered-total (count result)
|
|
|
- ;; FIXME: It seems that model? is always true?
|
|
|
modal? (:modal? config)
|
|
|
callback-fn (fn [review-records]
|
|
|
(when-not @*preview-mode?
|
|
|
(operation-card-info-summary!
|
|
|
review-records review-cards card-query-block)
|
|
|
(persist-var/persist-save of-matrix)))]
|
|
|
- [:div.flex-1.cards-review {:style (when modal? {:height "100%"})
|
|
|
- :class (if global? "" "shadow-xl")}
|
|
|
+ [:div.flex-1.cards-review {:style (when modal? {:height "100%"})}
|
|
|
[:div.flex.flex-row.items-center.justify-between.cards-title
|
|
|
[:div.flex.flex-row.items-center
|
|
|
- (if @*preview-mode?
|
|
|
- (ui/icon "book" {:style {:font-size 20}})
|
|
|
- (ui/icon "infinity" {:style {:font-size 20}}))
|
|
|
- [:div.ml-1.text-sm.font-medium (if (string/blank? query-string) "All" query-string)]]
|
|
|
+ (ui/icon "infinity" {:style {:font-size 20}})
|
|
|
+ (ui/dropdown
|
|
|
+ (fn [{:keys [toggle-fn]}]
|
|
|
+ [:div.ml-1.text-sm.font-medium.cursor
|
|
|
+ {:on-mouse-down (fn [e]
|
|
|
+ (util/stop e)
|
|
|
+ (toggle-fn))}
|
|
|
+ [:span.flex (if (string/blank? query-string) "All" query-string)
|
|
|
+ [:span {:style {:margin-top 2}}
|
|
|
+ (svg/caret-down)]]])
|
|
|
+ (fn [{:keys [toggle-fn]}]
|
|
|
+ (cards-select {:on-chosen (fn [query]
|
|
|
+ (let [query' (if (= query "All") "" query)]
|
|
|
+ (reset! query-atom query')
|
|
|
+ (toggle-fn)))}))
|
|
|
+ {:modal-class (util/hiccup->class
|
|
|
+ "origin-top-right.absolute.left-0.mt-2.ml-2.rounded-md.shadow-lg")})]
|
|
|
|
|
|
[:div.flex.flex-row.items-center
|
|
|
|
|
|
@@ -618,10 +626,10 @@
|
|
|
[:span "/"]
|
|
|
total])
|
|
|
(ui/tippy {:html [:div.text-sm "overdue/total"]
|
|
|
- ;; :class "tippy-hover"
|
|
|
+ ;; :class "tippy-hover"
|
|
|
:interactive true}
|
|
|
[:div.opacity-60.text-sm.mr-3
|
|
|
- filtered-total
|
|
|
+ (max 0 (- filtered-total @*card-index))
|
|
|
[:span "/"]
|
|
|
total]))
|
|
|
|
|
|
@@ -654,34 +662,22 @@
|
|
|
:font-weight 600}
|
|
|
@*random-mode?
|
|
|
(assoc :color "orange"))})])]]
|
|
|
- (if (or @*preview-mode? (seq review-cards))
|
|
|
- [:div.px-1
|
|
|
- (when (and (not modal?) (not @*preview-mode?))
|
|
|
- {:on-click (fn []
|
|
|
- (let [blocks-f (fn []
|
|
|
- (let [query-result (query repo query-string)]
|
|
|
- (:result (query-scheduled repo query-result (tl/local-now)))))]
|
|
|
- (state/set-modal! #(view-modal
|
|
|
- blocks-f
|
|
|
- {:modal? true
|
|
|
- :random-mode? *random-mode?
|
|
|
- :preview? false
|
|
|
- :callback callback-fn}
|
|
|
- *card-index)
|
|
|
- {:id :srs})))})
|
|
|
- (let [view-fn (if modal? view-modal view)
|
|
|
- blocks (if @*preview-mode?
|
|
|
- (query repo query-string)
|
|
|
- review-cards)]
|
|
|
- (view-fn blocks
|
|
|
- (merge config
|
|
|
- {:global? global?
|
|
|
- :random-mode? @*random-mode?
|
|
|
- :preview? @*preview-mode?
|
|
|
- :callback callback-fn})
|
|
|
- *card-index))]
|
|
|
- review-finished)])
|
|
|
- (if global?
|
|
|
+ [:div.px-1
|
|
|
+ (when (and (not modal?) (not @*preview-mode?))
|
|
|
+ {:on-click (fn []
|
|
|
+ (state/set-modal! #(cards (assoc config :modal? true) {:query-string query-string})
|
|
|
+ {:id :srs}))})
|
|
|
+ (let [view-fn (if modal? view-modal view)
|
|
|
+ blocks (if @*preview-mode? query-result review-cards)
|
|
|
+ blocks (if @*random-mode? (shuffle blocks) blocks)]
|
|
|
+ (view-fn blocks
|
|
|
+ (merge config
|
|
|
+ (merge options
|
|
|
+ {:random-mode? @*random-mode?
|
|
|
+ :preview? @*preview-mode?
|
|
|
+ :callback callback-fn}))
|
|
|
+ *card-index))]])
|
|
|
+ (if (:global? config)
|
|
|
[:div.ls-card.content
|
|
|
[:h1.title "Time to create a card!"]
|
|
|
|
|
|
@@ -697,6 +693,28 @@
|
|
|
[:code.p-1 (str "Cards: " query-string)]]
|
|
|
[:div.mt-2.ml-2.font-medium "No matched cards"]]))))
|
|
|
|
|
|
+(rum/defcs cards <
|
|
|
+ (rum/local nil ::query)
|
|
|
+ {:will-mount (fn [state]
|
|
|
+ (state/set-state! :srs/mode? true)
|
|
|
+ state)
|
|
|
+ :will-unmount (fn [state]
|
|
|
+ (state/set-state! :srs/mode? false)
|
|
|
+ state)}
|
|
|
+ [state config options]
|
|
|
+ (let [*query (::query state)
|
|
|
+ repo (state/get-current-repo)
|
|
|
+ query-string (or @*query
|
|
|
+ (:query-string options)
|
|
|
+ (string/join ", " (:arguments options)))
|
|
|
+ query-result (query repo query-string)
|
|
|
+ due-result (query-scheduled query-result (tl/local-now))]
|
|
|
+ (cards-inner config (assoc options :cards? true)
|
|
|
+ {:query-atom *query
|
|
|
+ :query-string query-string
|
|
|
+ :query-result query-result
|
|
|
+ :due-result due-result})))
|
|
|
+
|
|
|
(rum/defc global-cards <
|
|
|
{:will-mount (fn [state]
|
|
|
(reset! global-cards-mode? true)
|
|
|
@@ -739,10 +757,16 @@
|
|
|
block-id
|
|
|
(str (string/trim content) " #" card-hash-tag))))))
|
|
|
|
|
|
+(defonce *due-cards-interval (atom nil))
|
|
|
+
|
|
|
(defn update-cards-due-count!
|
|
|
[]
|
|
|
- (js/setTimeout
|
|
|
- (fn []
|
|
|
- (let [total (get-srs-cards-total)]
|
|
|
- (state/set-state! :srs/cards-due-count total)))
|
|
|
- 200))
|
|
|
+ (when (state/enable-flashcards?)
|
|
|
+ (let [f (fn []
|
|
|
+ (let [total (get-srs-cards-total)]
|
|
|
+ (state/set-state! :srs/cards-due-count total)))]
|
|
|
+ (js/setTimeout f 1000)
|
|
|
+ (when (nil? @*due-cards-interval)
|
|
|
+ ;; refresh every hour
|
|
|
+ (let [interval (js/setInterval f (* 3600 1000))]
|
|
|
+ (reset! *due-cards-interval interval))))))
|