|
@@ -68,9 +68,9 @@
|
|
[:div.sidebar-content-group-inner
|
|
[:div.sidebar-content-group-inner
|
|
[:div.hd.items-center
|
|
[:div.hd.items-center
|
|
(cond-> (merge header-props
|
|
(cond-> (merge header-props
|
|
- {:class (util/classnames [(:class header-props)
|
|
|
|
- {:non-collapsable (false? collapsable?)
|
|
|
|
- :enter-show-more (true? enter-show-more?)}])})
|
|
|
|
|
|
+ {:class (util/classnames [(:class header-props)
|
|
|
|
+ {:non-collapsable (false? collapsable?)
|
|
|
|
+ :enter-show-more (true? enter-show-more?)}])})
|
|
|
|
|
|
(not (false? collapsable?))
|
|
(not (false? collapsable?))
|
|
(assoc :on-click (fn [^js/MouseEvent _e]
|
|
(assoc :on-click (fn [^js/MouseEvent _e]
|
|
@@ -90,54 +90,54 @@
|
|
file-rpath (when (util/electron?) (page-util/get-page-file-rpath name))
|
|
file-rpath (when (util/electron?) (page-util/get-page-file-rpath name))
|
|
ctx-icon #(shui/tabler-icon %1 {:class "scale-90 pr-1 opacity-80"})
|
|
ctx-icon #(shui/tabler-icon %1 {:class "scale-90 pr-1 opacity-80"})
|
|
open-in-sidebar #(state/sidebar-add-block!
|
|
open-in-sidebar #(state/sidebar-add-block!
|
|
- (state/get-current-repo)
|
|
|
|
- (:db/id page)
|
|
|
|
- :page)
|
|
|
|
|
|
+ (state/get-current-repo)
|
|
|
|
+ (:db/id page)
|
|
|
|
+ :page)
|
|
x-menu-content (fn []
|
|
x-menu-content (fn []
|
|
(let [x-menu-item shui/dropdown-menu-item
|
|
(let [x-menu-item shui/dropdown-menu-item
|
|
x-menu-shortcut shui/dropdown-menu-shortcut]
|
|
x-menu-shortcut shui/dropdown-menu-shortcut]
|
|
[:<>
|
|
[:<>
|
|
(when-not recent?
|
|
(when-not recent?
|
|
(x-menu-item
|
|
(x-menu-item
|
|
- {:on-click #(page-handler/<unfavorite-page! (if db-based? (str (:block/uuid page)) title))}
|
|
|
|
- (ctx-icon "star-off")
|
|
|
|
- (t :page/unfavorite)
|
|
|
|
- (x-menu-shortcut (when-let [binding (shortcut-dh/shortcut-binding :command/toggle-favorite)]
|
|
|
|
- (some-> binding
|
|
|
|
- (first)
|
|
|
|
- (shortcut-utils/decorate-binding))))))
|
|
|
|
|
|
+ {:on-click #(page-handler/<unfavorite-page! (if db-based? (str (:block/uuid page)) title))}
|
|
|
|
+ (ctx-icon "star-off")
|
|
|
|
+ (t :page/unfavorite)
|
|
|
|
+ (x-menu-shortcut (when-let [binding (shortcut-dh/shortcut-binding :command/toggle-favorite)]
|
|
|
|
+ (some-> binding
|
|
|
|
+ (first)
|
|
|
|
+ (shortcut-utils/decorate-binding))))))
|
|
(when-let [page-fpath (and (util/electron?) file-rpath
|
|
(when-let [page-fpath (and (util/electron?) file-rpath
|
|
- (config/get-repo-fpath (state/get-current-repo) file-rpath))]
|
|
|
|
|
|
+ (config/get-repo-fpath (state/get-current-repo) file-rpath))]
|
|
[:<>
|
|
[:<>
|
|
(x-menu-item
|
|
(x-menu-item
|
|
- {:on-click #(ipc/ipc :openFileInFolder page-fpath)}
|
|
|
|
- (ctx-icon "folder")
|
|
|
|
- (t :page/open-in-finder))
|
|
|
|
|
|
+ {:on-click #(ipc/ipc :openFileInFolder page-fpath)}
|
|
|
|
+ (ctx-icon "folder")
|
|
|
|
+ (t :page/open-in-finder))
|
|
|
|
|
|
(x-menu-item
|
|
(x-menu-item
|
|
- {:on-click #(js/window.apis.openPath page-fpath)}
|
|
|
|
- (ctx-icon "file")
|
|
|
|
- (t :page/open-with-default-app))])
|
|
|
|
|
|
+ {:on-click #(js/window.apis.openPath page-fpath)}
|
|
|
|
+ (ctx-icon "file")
|
|
|
|
+ (t :page/open-with-default-app))])
|
|
(x-menu-item
|
|
(x-menu-item
|
|
- {:on-click open-in-sidebar}
|
|
|
|
- (ctx-icon "layout-sidebar-right")
|
|
|
|
- (t :content/open-in-sidebar)
|
|
|
|
- (x-menu-shortcut (shortcut-utils/decorate-binding "shift+click")))]))]
|
|
|
|
|
|
+ {:on-click open-in-sidebar}
|
|
|
|
+ (ctx-icon "layout-sidebar-right")
|
|
|
|
+ (t :content/open-in-sidebar)
|
|
|
|
+ (x-menu-shortcut (shortcut-utils/decorate-binding "shift+click")))]))]
|
|
|
|
|
|
;; TODO: move to standalone component
|
|
;; TODO: move to standalone component
|
|
[:a.link-item.group
|
|
[:a.link-item.group
|
|
(cond->
|
|
(cond->
|
|
- {:on-click
|
|
|
|
- (fn [e]
|
|
|
|
- (if (gobj/get e "shiftKey")
|
|
|
|
- (open-in-sidebar)
|
|
|
|
- (route-handler/redirect-to-page! (:block/uuid page) {:click-from-recent? recent?})))
|
|
|
|
- :on-context-menu (fn [^js e]
|
|
|
|
- (shui/popup-show! e (x-menu-content)
|
|
|
|
- {:as-dropdown? true
|
|
|
|
- :content-props {:on-click (fn [] (shui/popup-hide!))
|
|
|
|
- :class "w-60"}})
|
|
|
|
- (util/stop e))}
|
|
|
|
|
|
+ {:on-click
|
|
|
|
+ (fn [e]
|
|
|
|
+ (if (gobj/get e "shiftKey")
|
|
|
|
+ (open-in-sidebar)
|
|
|
|
+ (route-handler/redirect-to-page! (:block/uuid page) {:click-from-recent? recent?})))
|
|
|
|
+ :on-context-menu (fn [^js e]
|
|
|
|
+ (shui/popup-show! e (x-menu-content)
|
|
|
|
+ {:as-dropdown? true
|
|
|
|
+ :content-props {:on-click (fn [] (shui/popup-hide!))
|
|
|
|
+ :class "w-60"}})
|
|
|
|
+ (util/stop e))}
|
|
(ldb/object? page)
|
|
(ldb/object? page)
|
|
(assoc :title (title/block-unique-title page)))
|
|
(assoc :title (title/block-unique-title page)))
|
|
[:span.page-icon icon]
|
|
[:span.page-icon icon]
|
|
@@ -155,22 +155,22 @@
|
|
|
|
|
|
;; dots trigger
|
|
;; dots trigger
|
|
(shui/button
|
|
(shui/button
|
|
- {:size :sm
|
|
|
|
- :variant :ghost
|
|
|
|
- :class "absolute !bg-transparent right-0 top-0 px-1.5 scale-75 opacity-40 hidden group-hover:block hover:opacity-80 active:opacity-100"
|
|
|
|
- :on-click #(do
|
|
|
|
- (shui/popup-show! (.-target %) (x-menu-content)
|
|
|
|
- {:as-dropdown? true
|
|
|
|
- :content-props {:on-click (fn [] (shui/popup-hide!))
|
|
|
|
- :class "w-60"}})
|
|
|
|
- (util/stop %))}
|
|
|
|
- [:i.relative {:style {:top "4px"}} (shui/tabler-icon "dots")])]))
|
|
|
|
|
|
+ {:size :sm
|
|
|
|
+ :variant :ghost
|
|
|
|
+ :class "absolute !bg-transparent right-0 top-0 px-1.5 scale-75 opacity-40 hidden group-hover:block hover:opacity-80 active:opacity-100"
|
|
|
|
+ :on-click #(do
|
|
|
|
+ (shui/popup-show! (.-target %) (x-menu-content)
|
|
|
|
+ {:as-dropdown? true
|
|
|
|
+ :content-props {:on-click (fn [] (shui/popup-hide!))
|
|
|
|
+ :class "w-60"}})
|
|
|
|
+ (util/stop %))}
|
|
|
|
+ [:i.relative {:style {:top "4px"}} (shui/tabler-icon "dots")])]))
|
|
|
|
|
|
(defn sidebar-item
|
|
(defn sidebar-item
|
|
[{:keys [on-click-handler class title icon icon-extension? active href shortcut more]}]
|
|
[{:keys [on-click-handler class title icon icon-extension? active href shortcut more]}]
|
|
[:div
|
|
[:div
|
|
{:class (util/classnames [class {:active active}])}
|
|
{:class (util/classnames [class {:active active}])}
|
|
- [:a.item.group.flex.items-center.text-sm.rounded-md
|
|
|
|
|
|
+ [:a.item.group.flex.items-center.text-sm.rounded-md.font-medium
|
|
{:on-click on-click-handler
|
|
{:on-click on-click-handler
|
|
:class (when active "active")
|
|
:class (when active "active")
|
|
:href href}
|
|
:href href}
|
|
@@ -179,7 +179,7 @@
|
|
(when shortcut
|
|
(when shortcut
|
|
[:span.ml-1
|
|
[:span.ml-1
|
|
(ui/render-keyboard-shortcut
|
|
(ui/render-keyboard-shortcut
|
|
- (ui/keyboard-shortcut-from-config shortcut {:pick-first? true}))])
|
|
|
|
|
|
+ (ui/keyboard-shortcut-from-config shortcut {:pick-first? true}))])
|
|
more]])
|
|
more]])
|
|
|
|
|
|
(rum/defc sidebar-graphs
|
|
(rum/defc sidebar-graphs
|
|
@@ -192,185 +192,184 @@
|
|
(let [[local-navs set-local-navs!] (rum/use-state checked-navs)]
|
|
(let [[local-navs set-local-navs!] (rum/use-state checked-navs)]
|
|
|
|
|
|
(rum/use-effect!
|
|
(rum/use-effect!
|
|
- (fn []
|
|
|
|
- (set-checked-navs! local-navs))
|
|
|
|
- [local-navs])
|
|
|
|
|
|
+ (fn []
|
|
|
|
+ (set-checked-navs! local-navs))
|
|
|
|
+ [local-navs])
|
|
|
|
|
|
(for [nav navs
|
|
(for [nav navs
|
|
:let [name' (name nav)]]
|
|
:let [name' (name nav)]]
|
|
(shui/dropdown-menu-checkbox-item
|
|
(shui/dropdown-menu-checkbox-item
|
|
- {:checked (contains? (set local-navs) nav)
|
|
|
|
- :onCheckedChange (fn [v] (set-local-navs!
|
|
|
|
- (fn []
|
|
|
|
- (if v
|
|
|
|
- (conj local-navs nav)
|
|
|
|
- (filterv #(not= nav %) local-navs)))))}
|
|
|
|
- (tt (keyword "left-side-bar" name')
|
|
|
|
- (keyword "right-side-bar" name'))))))
|
|
|
|
|
|
+ {:checked (contains? (set local-navs) nav)
|
|
|
|
+ :onCheckedChange (fn [v] (set-local-navs!
|
|
|
|
+ (fn []
|
|
|
|
+ (if v
|
|
|
|
+ (conj local-navs nav)
|
|
|
|
+ (filterv #(not= nav %) local-navs)))))}
|
|
|
|
+ (tt (keyword "left-side-bar" name')
|
|
|
|
+ (keyword "right-side-bar" name'))))))
|
|
|
|
|
|
(rum/defc ^:large-vars/cleanup-todo sidebar-navigations
|
|
(rum/defc ^:large-vars/cleanup-todo sidebar-navigations
|
|
[{:keys [default-home route-match route-name srs-open? db-based? enable-whiteboards?]}]
|
|
[{:keys [default-home route-match route-name srs-open? db-based? enable-whiteboards?]}]
|
|
(let [navs [:whiteboards :flashcards :graph-view :all-pages :tag/tasks :tag/assets]
|
|
(let [navs [:whiteboards :flashcards :graph-view :all-pages :tag/tasks :tag/assets]
|
|
[checked-navs set-checked-navs!] (rum/use-state (or (storage/get :ls-sidebar-navigations)
|
|
[checked-navs set-checked-navs!] (rum/use-state (or (storage/get :ls-sidebar-navigations)
|
|
- [:whiteboards :flashcards :graph-view :all-pages :tag/tasks]))]
|
|
|
|
|
|
+ [:whiteboards :flashcards :graph-view :all-pages :tag/tasks]))]
|
|
|
|
|
|
(rum/use-effect!
|
|
(rum/use-effect!
|
|
- (fn []
|
|
|
|
- (when (vector? checked-navs)
|
|
|
|
- (storage/set :ls-sidebar-navigations checked-navs)))
|
|
|
|
- [checked-navs])
|
|
|
|
|
|
+ (fn []
|
|
|
|
+ (when (vector? checked-navs)
|
|
|
|
+ (storage/set :ls-sidebar-navigations checked-navs)))
|
|
|
|
+ [checked-navs])
|
|
|
|
|
|
(sidebar-content-group
|
|
(sidebar-content-group
|
|
- [:a.wrap-th [:strong.flex-1 "Navigations"]]
|
|
|
|
- {:collapsable? false
|
|
|
|
- :enter-show-more? true
|
|
|
|
- :header-props {:on-click (fn [^js e] (when-let [^js _el (some-> (.-target e) (.closest ".as-edit"))]
|
|
|
|
- (shui/popup-show! _el
|
|
|
|
- #(sidebar-navigations-edit-content
|
|
|
|
- {:id (:id %) :navs navs
|
|
|
|
- :checked-navs checked-navs
|
|
|
|
- :set-checked-navs! set-checked-navs!})
|
|
|
|
- {:as-dropdown? false})))}
|
|
|
|
- :more [:a.as-edit {:class "!opacity-60 hover:!opacity-80 relative -top-0.5 right-0"}
|
|
|
|
- (shui/tabler-icon "filter-edit" {:size 15})]}
|
|
|
|
- [:div.sidebar-navigations.flex.flex-col.mt-1
|
|
|
|
|
|
+ [:a.wrap-th [:strong.flex-1 "Navigations"]]
|
|
|
|
+ {:collapsable? false
|
|
|
|
+ :enter-show-more? true
|
|
|
|
+ :header-props {:on-click (fn [^js e] (when-let [^js _el (some-> (.-target e) (.closest ".as-edit"))]
|
|
|
|
+ (shui/popup-show! _el
|
|
|
|
+ #(sidebar-navigations-edit-content
|
|
|
|
+ {:id (:id %) :navs navs
|
|
|
|
+ :checked-navs checked-navs
|
|
|
|
+ :set-checked-navs! set-checked-navs!})
|
|
|
|
+ {:as-dropdown? false})))}
|
|
|
|
+ :more [:a.as-edit {:class "!opacity-60 hover:!opacity-80 relative -top-0.5 right-0"}
|
|
|
|
+ (shui/tabler-icon "filter-edit" {:size 15})]}
|
|
|
|
+ [:div.sidebar-navigations.flex.flex-col.mt-1
|
|
;; required custom home page
|
|
;; required custom home page
|
|
- (let [page (:page default-home)]
|
|
|
|
- (if (and page (not (state/enable-journals? (state/get-current-repo))))
|
|
|
|
- (sidebar-item
|
|
|
|
- {:class "home-nav"
|
|
|
|
- :title page
|
|
|
|
- :on-click-handler route-handler/redirect-to-home!
|
|
|
|
- :active (and (not srs-open?)
|
|
|
|
- (= route-name :page)
|
|
|
|
- (= page (get-in route-match [:path-params :name])))
|
|
|
|
- :icon "home"
|
|
|
|
- :shortcut :go/home})
|
|
|
|
-
|
|
|
|
- (sidebar-item
|
|
|
|
- {:class "journals-nav"
|
|
|
|
- :active (and (not srs-open?)
|
|
|
|
- (or (= route-name :all-journals) (= route-name :home)))
|
|
|
|
- :title (t :left-side-bar/journals)
|
|
|
|
- :on-click-handler (fn [e]
|
|
|
|
- (if (gobj/get e "shiftKey")
|
|
|
|
- (route-handler/sidebar-journals!)
|
|
|
|
- (route-handler/go-to-journals!)))
|
|
|
|
- :icon "calendar"
|
|
|
|
- :shortcut :go/journals})))
|
|
|
|
-
|
|
|
|
- (for [nav checked-navs]
|
|
|
|
- (cond
|
|
|
|
- (= nav :whiteboards)
|
|
|
|
- (when enable-whiteboards?
|
|
|
|
- (when (or config/dev? (not db-based?))
|
|
|
|
- (sidebar-item
|
|
|
|
- {:class "whiteboard"
|
|
|
|
- :title (t :right-side-bar/whiteboards)
|
|
|
|
- :href (rfe/href :whiteboards)
|
|
|
|
- :on-click-handler (fn [_e] (whiteboard-handler/onboarding-show))
|
|
|
|
- :active (and (not srs-open?) (#{:whiteboard :whiteboards} route-name))
|
|
|
|
- :icon "whiteboard"
|
|
|
|
- :icon-extension? true
|
|
|
|
- :shortcut :go/whiteboards})))
|
|
|
|
-
|
|
|
|
- (= nav :flashcards)
|
|
|
|
- (when (state/enable-flashcards? (state/get-current-repo))
|
|
|
|
- (let [num (state/sub :srs/cards-due-count)]
|
|
|
|
- (sidebar-item
|
|
|
|
- {:class "flashcards-nav"
|
|
|
|
- :title (t :right-side-bar/flashcards)
|
|
|
|
- :icon "infinity"
|
|
|
|
- :shortcut :go/flashcards
|
|
|
|
- :active srs-open?
|
|
|
|
- :on-click-handler #(do (fsrs/update-due-cards-count)
|
|
|
|
|
|
+ (let [page (:page default-home)]
|
|
|
|
+ (if (and page (not (state/enable-journals? (state/get-current-repo))))
|
|
|
|
+ (sidebar-item
|
|
|
|
+ {:class "home-nav"
|
|
|
|
+ :title page
|
|
|
|
+ :on-click-handler route-handler/redirect-to-home!
|
|
|
|
+ :active (and (not srs-open?)
|
|
|
|
+ (= route-name :page)
|
|
|
|
+ (= page (get-in route-match [:path-params :name])))
|
|
|
|
+ :icon "home"
|
|
|
|
+ :shortcut :go/home})
|
|
|
|
+
|
|
|
|
+ (sidebar-item
|
|
|
|
+ {:class "journals-nav"
|
|
|
|
+ :active (and (not srs-open?)
|
|
|
|
+ (or (= route-name :all-journals) (= route-name :home)))
|
|
|
|
+ :title (t :left-side-bar/journals)
|
|
|
|
+ :on-click-handler (fn [e]
|
|
|
|
+ (if (gobj/get e "shiftKey")
|
|
|
|
+ (route-handler/sidebar-journals!)
|
|
|
|
+ (route-handler/go-to-journals!)))
|
|
|
|
+ :icon "calendar"
|
|
|
|
+ :shortcut :go/journals})))
|
|
|
|
+
|
|
|
|
+ (for [nav checked-navs]
|
|
|
|
+ (cond
|
|
|
|
+ (= nav :whiteboards)
|
|
|
|
+ (when enable-whiteboards?
|
|
|
|
+ (when (or config/dev? (not db-based?))
|
|
|
|
+ (sidebar-item
|
|
|
|
+ {:class "whiteboard"
|
|
|
|
+ :title (t :right-side-bar/whiteboards)
|
|
|
|
+ :href (rfe/href :whiteboards)
|
|
|
|
+ :on-click-handler (fn [_e] (whiteboard-handler/onboarding-show))
|
|
|
|
+ :active (and (not srs-open?) (#{:whiteboard :whiteboards} route-name))
|
|
|
|
+ :icon "whiteboard"
|
|
|
|
+ :icon-extension? true
|
|
|
|
+ :shortcut :go/whiteboards})))
|
|
|
|
+
|
|
|
|
+ (= nav :flashcards)
|
|
|
|
+ (when (state/enable-flashcards? (state/get-current-repo))
|
|
|
|
+ (let [num (state/sub :srs/cards-due-count)]
|
|
|
|
+ (sidebar-item
|
|
|
|
+ {:class "flashcards-nav"
|
|
|
|
+ :title (t :right-side-bar/flashcards)
|
|
|
|
+ :icon "infinity"
|
|
|
|
+ :shortcut :go/flashcards
|
|
|
|
+ :active srs-open?
|
|
|
|
+ :on-click-handler #(do (fsrs/update-due-cards-count)
|
|
(state/pub-event! [:modal/show-cards]))
|
|
(state/pub-event! [:modal/show-cards]))
|
|
- :more (when (and num (not (zero? num)))
|
|
|
|
- [:span.ml-1.inline-block.py-0.5.px-3.text-xs.font-medium.rounded-full.fade-in num])})))
|
|
|
|
-
|
|
|
|
- (= nav :graph-view)
|
|
|
|
- (sidebar-item
|
|
|
|
- {:class "graph-view-nav"
|
|
|
|
- :title (t :right-side-bar/graph-view)
|
|
|
|
- :href (rfe/href :graph)
|
|
|
|
- :active (and (not srs-open?) (= route-name :graph))
|
|
|
|
- :icon "hierarchy"
|
|
|
|
- :shortcut :go/graph-view})
|
|
|
|
-
|
|
|
|
- (= nav :all-pages)
|
|
|
|
- (sidebar-item
|
|
|
|
- {:class "all-pages-nav"
|
|
|
|
- :title (t :right-side-bar/all-pages)
|
|
|
|
- :href (rfe/href :all-pages)
|
|
|
|
- :active (and (not srs-open?) (= route-name :all-pages))
|
|
|
|
- :icon "files"})
|
|
|
|
-
|
|
|
|
- (= (namespace nav) "tag")
|
|
|
|
- (when db-based?
|
|
|
|
- (let [name'' (name nav)
|
|
|
|
- name' (get {"assets" "Asset" "tasks" "Task"} name'')]
|
|
|
|
- (when-let [tag-uuid (and name' (:block/uuid (db/entity (keyword "logseq.class" name'))))]
|
|
|
|
- (sidebar-item
|
|
|
|
- {:class (str "tag-view-nav " name'')
|
|
|
|
- :title (tt (keyword "left-side-bar" name'')
|
|
|
|
|
|
+ :more (when (and num (not (zero? num)))
|
|
|
|
+ [:span.ml-1.inline-block.py-0.5.px-3.text-xs.font-medium.rounded-full.fade-in num])})))
|
|
|
|
+
|
|
|
|
+ (= nav :graph-view)
|
|
|
|
+ (sidebar-item
|
|
|
|
+ {:class "graph-view-nav"
|
|
|
|
+ :title (t :right-side-bar/graph-view)
|
|
|
|
+ :href (rfe/href :graph)
|
|
|
|
+ :active (and (not srs-open?) (= route-name :graph))
|
|
|
|
+ :icon "hierarchy"
|
|
|
|
+ :shortcut :go/graph-view})
|
|
|
|
+
|
|
|
|
+ (= nav :all-pages)
|
|
|
|
+ (sidebar-item
|
|
|
|
+ {:class "all-pages-nav"
|
|
|
|
+ :title (t :right-side-bar/all-pages)
|
|
|
|
+ :href (rfe/href :all-pages)
|
|
|
|
+ :active (and (not srs-open?) (= route-name :all-pages))
|
|
|
|
+ :icon "files"})
|
|
|
|
+
|
|
|
|
+ (= (namespace nav) "tag")
|
|
|
|
+ (when db-based?
|
|
|
|
+ (let [name'' (name nav)
|
|
|
|
+ name' (get {"assets" "Asset" "tasks" "Task"} name'')]
|
|
|
|
+ (when-let [tag-uuid (and name' (:block/uuid (db/entity (keyword "logseq.class" name'))))]
|
|
|
|
+ (sidebar-item
|
|
|
|
+ {:class (str "tag-view-nav " name'')
|
|
|
|
+ :title (tt (keyword "left-side-bar" name'')
|
|
(keyword "right-side-bar" name''))
|
|
(keyword "right-side-bar" name''))
|
|
- :href (rfe/href :page {:name tag-uuid})
|
|
|
|
- :active (= (str tag-uuid) (get-in route-match [:path-params :name]))
|
|
|
|
- :icon "hash"}))))))
|
|
|
|
- ])))
|
|
|
|
|
|
+ :href (rfe/href :page {:name tag-uuid})
|
|
|
|
+ :active (= (str tag-uuid) (get-in route-match [:path-params :name]))
|
|
|
|
+ :icon "hash"}))))))])))
|
|
|
|
|
|
(rum/defc sidebar-favorites < rum/reactive
|
|
(rum/defc sidebar-favorites < rum/reactive
|
|
[]
|
|
[]
|
|
(let [_favorites-updated? (state/sub :favorites/updated?)
|
|
(let [_favorites-updated? (state/sub :favorites/updated?)
|
|
favorite-entities (page-handler/get-favorites)]
|
|
favorite-entities (page-handler/get-favorites)]
|
|
(sidebar-content-group
|
|
(sidebar-content-group
|
|
- [:a.wrap-th
|
|
|
|
- [:strong.flex-1 (t :left-side-bar/nav-favorites)]]
|
|
|
|
-
|
|
|
|
- {:class "favorites"
|
|
|
|
- :count (count favorite-entities)
|
|
|
|
- :edit-fn
|
|
|
|
- (fn [e]
|
|
|
|
- (rfe/push-state :page {:name "Favorites"})
|
|
|
|
- (util/stop e))}
|
|
|
|
- (when (seq favorite-entities)
|
|
|
|
- (let [favorite-items (map
|
|
|
|
- (fn [e]
|
|
|
|
- (let [icon (icon/get-node-icon-cp e {:size 16})]
|
|
|
|
- {:id (str (:db/id e))
|
|
|
|
- :value (:block/uuid e)
|
|
|
|
- :content [:li.favorite-item (page-name e icon false)]}))
|
|
|
|
- favorite-entities)]
|
|
|
|
- (dnd-component/items favorite-items
|
|
|
|
- {:on-drag-end (fn [favorites']
|
|
|
|
- (page-handler/<reorder-favorites! favorites'))
|
|
|
|
- :parent-node :ul.favorites.text-sm}))))))
|
|
|
|
|
|
+ [:a.wrap-th
|
|
|
|
+ [:strong.flex-1 (t :left-side-bar/nav-favorites)]]
|
|
|
|
+
|
|
|
|
+ {:class "favorites"
|
|
|
|
+ :count (count favorite-entities)
|
|
|
|
+ :edit-fn
|
|
|
|
+ (fn [e]
|
|
|
|
+ (rfe/push-state :page {:name "Favorites"})
|
|
|
|
+ (util/stop e))}
|
|
|
|
+ (when (seq favorite-entities)
|
|
|
|
+ (let [favorite-items (map
|
|
|
|
+ (fn [e]
|
|
|
|
+ (let [icon (icon/get-node-icon-cp e {:size 16})]
|
|
|
|
+ {:id (str (:db/id e))
|
|
|
|
+ :value (:block/uuid e)
|
|
|
|
+ :content [:li.favorite-item.font-medium (page-name e icon false)]}))
|
|
|
|
+ favorite-entities)]
|
|
|
|
+ (dnd-component/items favorite-items
|
|
|
|
+ {:on-drag-end (fn [favorites']
|
|
|
|
+ (page-handler/<reorder-favorites! favorites'))
|
|
|
|
+ :parent-node :ul.favorites.text-sm}))))))
|
|
|
|
|
|
(rum/defc sidebar-recent-pages < rum/reactive db-mixins/query
|
|
(rum/defc sidebar-recent-pages < rum/reactive db-mixins/query
|
|
[]
|
|
[]
|
|
(let [pages (recent-handler/get-recent-pages)]
|
|
(let [pages (recent-handler/get-recent-pages)]
|
|
(sidebar-content-group
|
|
(sidebar-content-group
|
|
- [:a.wrap-th [:strong.flex-1 (t :left-side-bar/nav-recent-pages)]]
|
|
|
|
|
|
+ [:a.wrap-th [:strong.flex-1 (t :left-side-bar/nav-recent-pages)]]
|
|
|
|
|
|
- {:class "recent"
|
|
|
|
- :count (count pages)}
|
|
|
|
|
|
+ {:class "recent"
|
|
|
|
+ :count (count pages)}
|
|
|
|
|
|
- [:ul.text-sm
|
|
|
|
- (for [page pages]
|
|
|
|
- [:li.recent-item.select-none
|
|
|
|
- {:key (str "recent-" (:db/id page))
|
|
|
|
- :title (title/block-unique-title page)
|
|
|
|
- :draggable true
|
|
|
|
- :on-drag-start (fn [event] (editor-handler/block->data-transfer! (:block/name page) event true))
|
|
|
|
- :data-ref name}
|
|
|
|
- (page-name page (icon/get-node-icon-cp page {:size 16}) true)])])))
|
|
|
|
|
|
+ [:ul.text-sm
|
|
|
|
+ (for [page pages]
|
|
|
|
+ [:li.recent-item.select-none.font-medium
|
|
|
|
+ {:key (str "recent-" (:db/id page))
|
|
|
|
+ :title (title/block-unique-title page)
|
|
|
|
+ :draggable true
|
|
|
|
+ :on-drag-start (fn [event] (editor-handler/block->data-transfer! (:block/name page) event true))
|
|
|
|
+ :data-ref name}
|
|
|
|
+ (page-name page (icon/get-node-icon-cp page {:size 16}) true)])])))
|
|
|
|
|
|
(defn get-default-home-if-valid
|
|
(defn get-default-home-if-valid
|
|
[]
|
|
[]
|
|
(when-let [default-home (state/get-default-home)]
|
|
(when-let [default-home (state/get-default-home)]
|
|
(let [page (:page default-home)
|
|
(let [page (:page default-home)
|
|
page (when (and (string? page)
|
|
page (when (and (string? page)
|
|
- (not (string/blank? page)))
|
|
|
|
|
|
+ (not (string/blank? page)))
|
|
(db/get-page page))]
|
|
(db/get-page page))]
|
|
(if page
|
|
(if page
|
|
default-home
|
|
default-home
|
|
@@ -401,43 +400,43 @@
|
|
(when (< touching-x-offset 0)
|
|
(when (< touching-x-offset 0)
|
|
(max touching-x-offset (- 0 (:width el-rect))))))
|
|
(max touching-x-offset (- 0 (:width el-rect))))))
|
|
offset-ratio (and (number? touching-x-offset)
|
|
offset-ratio (and (number? touching-x-offset)
|
|
- (some->> (:width el-rect)
|
|
|
|
- (/ touching-x-offset)))]
|
|
|
|
|
|
+ (some->> (:width el-rect)
|
|
|
|
+ (/ touching-x-offset)))]
|
|
|
|
|
|
(rum/use-effect!
|
|
(rum/use-effect!
|
|
- #(js/setTimeout
|
|
|
|
- (fn [] (some-> (rum/deref ref-el)
|
|
|
|
- (.getBoundingClientRect)
|
|
|
|
- (.toJSON)
|
|
|
|
- (js->clj :keywordize-keys true)
|
|
|
|
- (set-el-rect!)))
|
|
|
|
- 16)
|
|
|
|
- [])
|
|
|
|
|
|
+ #(js/setTimeout
|
|
|
|
+ (fn [] (some-> (rum/deref ref-el)
|
|
|
|
+ (.getBoundingClientRect)
|
|
|
|
+ (.toJSON)
|
|
|
|
+ (js->clj :keywordize-keys true)
|
|
|
|
+ (set-el-rect!)))
|
|
|
|
+ 16)
|
|
|
|
+ [])
|
|
|
|
|
|
(rum/use-layout-effect!
|
|
(rum/use-layout-effect!
|
|
- (fn []
|
|
|
|
- (when (and (rum/deref ref-open?) local-closing?)
|
|
|
|
- (reset! *closing? true))
|
|
|
|
- (rum/set-ref! ref-open? left-sidebar-open?)
|
|
|
|
- #())
|
|
|
|
- [local-closing? left-sidebar-open?])
|
|
|
|
|
|
+ (fn []
|
|
|
|
+ (when (and (rum/deref ref-open?) local-closing?)
|
|
|
|
+ (reset! *closing? true))
|
|
|
|
+ (rum/set-ref! ref-open? left-sidebar-open?)
|
|
|
|
+ #())
|
|
|
|
+ [local-closing? left-sidebar-open?])
|
|
|
|
|
|
(rum/use-effect!
|
|
(rum/use-effect!
|
|
- (fn []
|
|
|
|
- (when-not (neg? close-signal)
|
|
|
|
- (close-fn)))
|
|
|
|
- [close-signal])
|
|
|
|
|
|
+ (fn []
|
|
|
|
+ (when-not (neg? close-signal)
|
|
|
|
+ (close-fn)))
|
|
|
|
+ [close-signal])
|
|
|
|
|
|
[:<>
|
|
[:<>
|
|
[:div.left-sidebar-inner.flex-1.flex.flex-col.min-h-0
|
|
[:div.left-sidebar-inner.flex-1.flex.flex-col.min-h-0
|
|
{:ref ref-el
|
|
{:ref ref-el
|
|
:style (cond-> {}
|
|
:style (cond-> {}
|
|
(and (number? offset-ratio)
|
|
(and (number? offset-ratio)
|
|
- (> touching-x-offset 0))
|
|
|
|
|
|
+ (> touching-x-offset 0))
|
|
(assoc :transform (str "translate3d(calc(" touching-x-offset "px - 100%), 0, 0)"))
|
|
(assoc :transform (str "translate3d(calc(" touching-x-offset "px - 100%), 0, 0)"))
|
|
|
|
|
|
(and (number? offset-ratio)
|
|
(and (number? offset-ratio)
|
|
- (< touching-x-offset 0))
|
|
|
|
|
|
+ (< touching-x-offset 0))
|
|
(assoc :transform (str "translate3d(" (* offset-ratio 100) "%, 0, 0)")))
|
|
(assoc :transform (str "translate3d(" (* offset-ratio 100) "%, 0, 0)")))
|
|
:on-transition-end (fn []
|
|
:on-transition-end (fn []
|
|
(when local-closing?
|
|
(when local-closing?
|
|
@@ -446,7 +445,7 @@
|
|
(close-modal-fn)))
|
|
(close-modal-fn)))
|
|
:on-click #(when-let [^js target (and (util/sm-breakpoint?) (.-target %))]
|
|
:on-click #(when-let [^js target (and (util/sm-breakpoint?) (.-target %))]
|
|
(when (some (fn [sel] (boolean (.closest target sel)))
|
|
(when (some (fn [sel] (boolean (.closest target sel)))
|
|
- [".favorites .bd" ".recent .bd" ".dropdown-wrapper" ".nav-header"])
|
|
|
|
|
|
+ [".favorites .bd" ".recent .bd" ".dropdown-wrapper" ".nav-header"])
|
|
(close-fn)))}
|
|
(close-fn)))}
|
|
|
|
|
|
[:div.wrap
|
|
[:div.wrap
|
|
@@ -456,12 +455,12 @@
|
|
|
|
|
|
;; sidebar sticky navigations
|
|
;; sidebar sticky navigations
|
|
(sidebar-navigations
|
|
(sidebar-navigations
|
|
- {:default-home default-home
|
|
|
|
- :route-match route-match
|
|
|
|
- :db-based? db-based?
|
|
|
|
- :enable-whiteboards? enable-whiteboards?
|
|
|
|
- :route-name route-name
|
|
|
|
- :srs-open? srs-open?})]
|
|
|
|
|
|
+ {:default-home default-home
|
|
|
|
+ :route-match route-match
|
|
|
|
+ :db-based? db-based?
|
|
|
|
+ :enable-whiteboards? enable-whiteboards?
|
|
|
|
+ :route-name route-name
|
|
|
|
+ :srs-open? srs-open?})]
|
|
|
|
|
|
[:div.sidebar-contents-container
|
|
[:div.sidebar-contents-container
|
|
{:on-scroll on-contents-scroll}
|
|
{:on-scroll on-contents-scroll}
|
|
@@ -487,38 +486,38 @@
|
|
|
|
|
|
;; restore size
|
|
;; restore size
|
|
(rum/use-layout-effect!
|
|
(rum/use-layout-effect!
|
|
- (fn []
|
|
|
|
- (when-let [width (storage/get :ls-left-sidebar-width)]
|
|
|
|
- (.setProperty (.-style el-doc) "--ls-left-sidebar-width" width)))
|
|
|
|
- [])
|
|
|
|
|
|
+ (fn []
|
|
|
|
+ (when-let [width (storage/get :ls-left-sidebar-width)]
|
|
|
|
+ (.setProperty (.-style el-doc) "--ls-left-sidebar-width" width)))
|
|
|
|
+ [])
|
|
|
|
|
|
;; draggable handler
|
|
;; draggable handler
|
|
(rum/use-effect!
|
|
(rum/use-effect!
|
|
- (fn []
|
|
|
|
- (when-let [el (and (fn? js/window.interact) (rum/deref *el-ref))]
|
|
|
|
- (let [^js sidebar-el (.querySelector el-doc "#left-sidebar")]
|
|
|
|
- (-> (js/interact el)
|
|
|
|
- (.draggable
|
|
|
|
|
|
+ (fn []
|
|
|
|
+ (when-let [el (and (fn? js/window.interact) (rum/deref *el-ref))]
|
|
|
|
+ (let [^js sidebar-el (.querySelector el-doc "#left-sidebar")]
|
|
|
|
+ (-> (js/interact el)
|
|
|
|
+ (.draggable
|
|
#js {:listeners
|
|
#js {:listeners
|
|
#js {:move (fn [^js/MouseEvent e]
|
|
#js {:move (fn [^js/MouseEvent e]
|
|
(when-let [offset (.-left (.-rect e))]
|
|
(when-let [offset (.-left (.-rect e))]
|
|
(let [width (.toFixed (max (min offset 460) 240) 2)]
|
|
(let [width (.toFixed (max (min offset 460) 240) 2)]
|
|
(adjust-size! (str width "px")))))}})
|
|
(adjust-size! (str width "px")))))}})
|
|
- (.styleCursor false)
|
|
|
|
- (.on "dragstart" (fn []
|
|
|
|
- (.. sidebar-el -classList (add "is-resizing"))
|
|
|
|
- (.. el-doc -classList (add "is-resizing-buf"))))
|
|
|
|
- (.on "dragend" (fn []
|
|
|
|
- (.. sidebar-el -classList (remove "is-resizing"))
|
|
|
|
- (.. el-doc -classList (remove "is-resizing-buf"))))))
|
|
|
|
- #()))
|
|
|
|
- [])
|
|
|
|
|
|
+ (.styleCursor false)
|
|
|
|
+ (.on "dragstart" (fn []
|
|
|
|
+ (.. sidebar-el -classList (add "is-resizing"))
|
|
|
|
+ (.. el-doc -classList (add "is-resizing-buf"))))
|
|
|
|
+ (.on "dragend" (fn []
|
|
|
|
+ (.. sidebar-el -classList (remove "is-resizing"))
|
|
|
|
+ (.. el-doc -classList (remove "is-resizing-buf"))))))
|
|
|
|
+ #()))
|
|
|
|
+ [])
|
|
[:span.left-sidebar-resizer {:ref *el-ref}]))
|
|
[:span.left-sidebar-resizer {:ref *el-ref}]))
|
|
|
|
|
|
(rum/defcs left-sidebar < rum/reactive
|
|
(rum/defcs left-sidebar < rum/reactive
|
|
- (rum/local false ::closing?)
|
|
|
|
- (rum/local -1 ::close-signal)
|
|
|
|
- (rum/local nil ::touch-state)
|
|
|
|
|
|
+ (rum/local false ::closing?)
|
|
|
|
+ (rum/local -1 ::close-signal)
|
|
|
|
+ (rum/local nil ::touch-state)
|
|
[s {:keys [left-sidebar-open? route-match]}]
|
|
[s {:keys [left-sidebar-open? route-match]}]
|
|
(let [close-fn #(state/set-left-sidebar-open! false)
|
|
(let [close-fn #(state/set-left-sidebar-open! false)
|
|
*closing? (::closing? s)
|
|
*closing? (::closing? s)
|
|
@@ -528,9 +527,9 @@
|
|
touch-point-fn (fn [^js e] (some-> (gobj/get e "touches") (aget 0) (#(hash-map :x (.-clientX %) :y (.-clientY %)))))
|
|
touch-point-fn (fn [^js e] (some-> (gobj/get e "touches") (aget 0) (#(hash-map :x (.-clientX %) :y (.-clientY %)))))
|
|
srs-open? (= :srs (state/sub :modal/id))
|
|
srs-open? (= :srs (state/sub :modal/id))
|
|
touching-x-offset (and (some-> @*touch-state :after)
|
|
touching-x-offset (and (some-> @*touch-state :after)
|
|
- (some->> @*touch-state
|
|
|
|
- ((juxt :after :before))
|
|
|
|
- (map :x) (apply -)))
|
|
|
|
|
|
+ (some->> @*touch-state
|
|
|
|
+ ((juxt :after :before))
|
|
|
|
+ (map :x) (apply -)))
|
|
touch-pending? (> (abs touching-x-offset) 20)]
|
|
touch-pending? (> (abs touching-x-offset) 20)]
|
|
|
|
|
|
[:div#left-sidebar.cp__sidebar-left-layout
|
|
[:div#left-sidebar.cp__sidebar-left-layout
|
|
@@ -557,7 +556,7 @@
|
|
|
|
|
|
;; sidebar contents
|
|
;; sidebar contents
|
|
(sidebar-container route-match close-fn left-sidebar-open? enable-whiteboards? srs-open? *closing?
|
|
(sidebar-container route-match close-fn left-sidebar-open? enable-whiteboards? srs-open? *closing?
|
|
- @*close-signal (and touch-pending? touching-x-offset))
|
|
|
|
|
|
+ @*close-signal (and touch-pending? touching-x-offset))
|
|
|
|
|
|
;; resizer
|
|
;; resizer
|
|
(sidebar-resizer)]))
|
|
(sidebar-resizer)]))
|
|
@@ -582,12 +581,12 @@
|
|
{:did-mount (fn [state]
|
|
{:did-mount (fn [state]
|
|
(when-let [element (gdom/getElement "main-content-container")]
|
|
(when-let [element (gdom/getElement "main-content-container")]
|
|
(dnd/subscribe!
|
|
(dnd/subscribe!
|
|
- element
|
|
|
|
- :upload-files
|
|
|
|
- {:drop (fn [_e files]
|
|
|
|
- (when-let [id (state/get-edit-input-id)]
|
|
|
|
- (let [format (:block/format (state/get-edit-block))]
|
|
|
|
- (editor-handler/upload-asset! id files format editor-handler/*asset-uploading? true))))})
|
|
|
|
|
|
+ element
|
|
|
|
+ :upload-files
|
|
|
|
+ {:drop (fn [_e files]
|
|
|
|
+ (when-let [id (state/get-edit-input-id)]
|
|
|
|
+ (let [format (:block/format (state/get-edit-block))]
|
|
|
|
+ (editor-handler/upload-asset! id files format editor-handler/*asset-uploading? true))))})
|
|
(common-handler/listen-to-scroll! element)
|
|
(common-handler/listen-to-scroll! element)
|
|
(when (:margin-less-pages? (first (:rum/args state))) ;; makes sure full screen pages displaying without scrollbar
|
|
(when (:margin-less-pages? (first (:rum/args state))) ;; makes sure full screen pages displaying without scrollbar
|
|
(set! (.. element -scrollTop) 0)))
|
|
(set! (.. element -scrollTop) 0)))
|
|
@@ -599,8 +598,8 @@
|
|
[{:keys [route-match margin-less-pages? route-name indexeddb-support? db-restoring? main-content show-action-bar? show-recording-bar?]}]
|
|
[{:keys [route-match margin-less-pages? route-name indexeddb-support? db-restoring? main-content show-action-bar? show-recording-bar?]}]
|
|
(let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)
|
|
(let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)
|
|
onboarding-and-home? (and (or (nil? (state/get-current-repo)) (config/demo-graph?))
|
|
onboarding-and-home? (and (or (nil? (state/get-current-repo)) (config/demo-graph?))
|
|
- (not config/publishing?)
|
|
|
|
- (= :home route-name))
|
|
|
|
|
|
+ (not config/publishing?)
|
|
|
|
+ (= :home route-name))
|
|
margin-less-pages? (or (and (mobile-util/native-platform?) onboarding-and-home?) margin-less-pages?)]
|
|
margin-less-pages? (or (and (mobile-util/native-platform?) onboarding-and-home?) margin-less-pages?)]
|
|
[:div#main-container.cp__sidebar-main-layout.flex-1.flex
|
|
[:div#main-container.cp__sidebar-main-layout.flex-1.flex
|
|
{:class (util/classnames [{:is-left-sidebar-open left-sidebar-open?}])}
|
|
{:class (util/classnames [{:is-left-sidebar-open left-sidebar-open?}])}
|
|
@@ -620,7 +619,7 @@
|
|
[:div.cp__sidebar-main-content
|
|
[:div.cp__sidebar-main-content
|
|
{:data-is-margin-less-pages margin-less-pages?
|
|
{:data-is-margin-less-pages margin-less-pages?
|
|
:data-is-full-width (or margin-less-pages?
|
|
:data-is-full-width (or margin-less-pages?
|
|
- (contains? #{:all-files :all-pages :my-publishing} route-name))}
|
|
|
|
|
|
+ (contains? #{:all-files :all-pages :my-publishing} route-name))}
|
|
|
|
|
|
(when show-recording-bar?
|
|
(when show-recording-bar?
|
|
(recording-bar))
|
|
(recording-bar))
|
|
@@ -665,8 +664,8 @@
|
|
total (:total state)
|
|
total (:total state)
|
|
width (js/Math.round (* (.toFixed (/ finished total) 2) 100))
|
|
width (js/Math.round (* (.toFixed (/ finished total) 2) 100))
|
|
display-filename (some-> (:current-parsing-file state)
|
|
display-filename (some-> (:current-parsing-file state)
|
|
- not-empty
|
|
|
|
- path/filename)
|
|
|
|
|
|
+ not-empty
|
|
|
|
+ path/filename)
|
|
left-label [:div.flex.flex-row.font-bold
|
|
left-label [:div.flex.flex-row.font-bold
|
|
(t :parsing-files)
|
|
(t :parsing-files)
|
|
[:div.hidden.md:flex.flex-row
|
|
[:div.hidden.md:flex.flex-row
|
|
@@ -676,24 +675,24 @@
|
|
(ui/progress-bar-with-label width left-label (str finished "/" total))))
|
|
(ui/progress-bar-with-label width left-label (str finished "/" total))))
|
|
|
|
|
|
(rum/defc main-content < rum/reactive db-mixins/query
|
|
(rum/defc main-content < rum/reactive db-mixins/query
|
|
- {:init (fn [state]
|
|
|
|
- (when-not @sidebar-inited?
|
|
|
|
- (let [current-repo (state/sub :git/current-repo)
|
|
|
|
- default-home (get-default-home-if-valid)
|
|
|
|
- sidebar (:sidebar default-home)
|
|
|
|
- sidebar (if (string? sidebar) [sidebar] sidebar)]
|
|
|
|
- (when-let [pages (->> (seq sidebar)
|
|
|
|
- (remove string/blank?))]
|
|
|
|
- (doseq [page pages]
|
|
|
|
- (let [page (util/safe-page-name-sanity-lc page)
|
|
|
|
- [db-id block-type] (if (= page "contents")
|
|
|
|
- [(or (:db/id (db/get-page page)) "contents") :contents]
|
|
|
|
- [(:db/id (db/get-page page)) :page])]
|
|
|
|
- (state/sidebar-add-block! current-repo db-id block-type)))
|
|
|
|
- (reset! sidebar-inited? true))))
|
|
|
|
- (when (state/mobile?)
|
|
|
|
- (state/set-state! :mobile/show-tabbar? true))
|
|
|
|
- state)}
|
|
|
|
|
|
+ {:init (fn [state]
|
|
|
|
+ (when-not @sidebar-inited?
|
|
|
|
+ (let [current-repo (state/sub :git/current-repo)
|
|
|
|
+ default-home (get-default-home-if-valid)
|
|
|
|
+ sidebar (:sidebar default-home)
|
|
|
|
+ sidebar (if (string? sidebar) [sidebar] sidebar)]
|
|
|
|
+ (when-let [pages (->> (seq sidebar)
|
|
|
|
+ (remove string/blank?))]
|
|
|
|
+ (doseq [page pages]
|
|
|
|
+ (let [page (util/safe-page-name-sanity-lc page)
|
|
|
|
+ [db-id block-type] (if (= page "contents")
|
|
|
|
+ [(or (:db/id (db/get-page page)) "contents") :contents]
|
|
|
|
+ [(:db/id (db/get-page page)) :page])]
|
|
|
|
+ (state/sidebar-add-block! current-repo db-id block-type)))
|
|
|
|
+ (reset! sidebar-inited? true))))
|
|
|
|
+ (when (state/mobile?)
|
|
|
|
+ (state/set-state! :mobile/show-tabbar? true))
|
|
|
|
+ state)}
|
|
[]
|
|
[]
|
|
(let [default-home (get-default-home-if-valid)
|
|
(let [default-home (get-default-home-if-valid)
|
|
current-repo (state/sub :git/current-repo)
|
|
current-repo (state/sub :git/current-repo)
|
|
@@ -703,8 +702,8 @@
|
|
graph-parsing-state (state/sub [:graph/parsing-state current-repo])]
|
|
graph-parsing-state (state/sub [:graph/parsing-state current-repo])]
|
|
(cond
|
|
(cond
|
|
(or
|
|
(or
|
|
- (:graph-loading? graph-parsing-state)
|
|
|
|
- (not= (:total graph-parsing-state) (:finished graph-parsing-state)))
|
|
|
|
|
|
+ (:graph-loading? graph-parsing-state)
|
|
|
|
+ (not= (:total graph-parsing-state) (:finished graph-parsing-state)))
|
|
[:div.flex.items-center.justify-center.full-height-without-header
|
|
[:div.flex.items-center.justify-center.full-height-without-header
|
|
[:div.flex-1
|
|
[:div.flex-1
|
|
(parsing-progress graph-parsing-state)]]
|
|
(parsing-progress graph-parsing-state)]]
|
|
@@ -713,14 +712,14 @@
|
|
[:div
|
|
[:div
|
|
(cond
|
|
(cond
|
|
(and default-home
|
|
(and default-home
|
|
- (= :home (state/get-current-route))
|
|
|
|
- (not (state/route-has-p?))
|
|
|
|
- (:page default-home))
|
|
|
|
|
|
+ (= :home (state/get-current-route))
|
|
|
|
+ (not (state/route-has-p?))
|
|
|
|
+ (:page default-home))
|
|
(route-handler/redirect-to-page! (:page default-home))
|
|
(route-handler/redirect-to-page! (:page default-home))
|
|
|
|
|
|
(and config/publishing?
|
|
(and config/publishing?
|
|
- (not default-home)
|
|
|
|
- (empty? latest-journals))
|
|
|
|
|
|
+ (not default-home)
|
|
|
|
+ (empty? latest-journals))
|
|
(route-handler/redirect! {:to :all-pages})
|
|
(route-handler/redirect! {:to :all-pages})
|
|
|
|
|
|
loading-files?
|
|
loading-files?
|
|
@@ -737,21 +736,21 @@
|
|
[e]
|
|
[e]
|
|
(state/hide-custom-context-menu!)
|
|
(state/hide-custom-context-menu!)
|
|
(when-not (or (gobj/get e "shiftKey")
|
|
(when-not (or (gobj/get e "shiftKey")
|
|
- (util/meta-key? e)
|
|
|
|
- (state/get-edit-input-id)
|
|
|
|
- (= (shui-dialog/get-last-modal-id) :property-dialog)
|
|
|
|
- (some-> (.-target e) (.closest ".ls-block"))
|
|
|
|
- (some-> (.-target e) (.closest "[data-keep-selection]")))
|
|
|
|
|
|
+ (util/meta-key? e)
|
|
|
|
+ (state/get-edit-input-id)
|
|
|
|
+ (= (shui-dialog/get-last-modal-id) :property-dialog)
|
|
|
|
+ (some-> (.-target e) (.closest ".ls-block"))
|
|
|
|
+ (some-> (.-target e) (.closest "[data-keep-selection]")))
|
|
(editor-handler/clear-selection!)))
|
|
(editor-handler/clear-selection!)))
|
|
|
|
|
|
(rum/defc render-custom-context-menu
|
|
(rum/defc render-custom-context-menu
|
|
[links position]
|
|
[links position]
|
|
(let [ref (rum/use-ref nil)]
|
|
(let [ref (rum/use-ref nil)]
|
|
(rum/use-effect!
|
|
(rum/use-effect!
|
|
- #(let [el (rum/deref ref)
|
|
|
|
- {:keys [x y]} (util/calc-delta-rect-offset el js/document.documentElement)]
|
|
|
|
- (set! (.. el -style -transform)
|
|
|
|
- (str "translate3d(" (if (neg? x) x 0) "px," (if (neg? y) (- y 10) 0) "px" ",0)"))))
|
|
|
|
|
|
+ #(let [el (rum/deref ref)
|
|
|
|
+ {:keys [x y]} (util/calc-delta-rect-offset el js/document.documentElement)]
|
|
|
|
+ (set! (.. el -style -transform)
|
|
|
|
+ (str "translate3d(" (if (neg? x) x 0) "px," (if (neg? y) (- y 10) 0) "px" ",0)"))))
|
|
[:<>
|
|
[:<>
|
|
[:div.menu-backdrop {:on-pointer-down (fn [e] (hide-context-menu-and-clear-selection e))}]
|
|
[:div.menu-backdrop {:on-pointer-down (fn [e] (hide-context-menu-and-clear-selection e))}]
|
|
[:div#custom-context-menu
|
|
[:div#custom-context-menu
|
|
@@ -781,9 +780,9 @@
|
|
[:p.inline-block.mr-1 "Click `D` or type"]
|
|
[:p.inline-block.mr-1 "Click `D` or type"]
|
|
[:div.inline-block.mr-1 (ui/render-keyboard-shortcut (shortcut-dh/gen-shortcut-seq :ui/toggle-document-mode))]
|
|
[:div.inline-block.mr-1 (ui/render-keyboard-shortcut (shortcut-dh/gen-shortcut-seq :ui/toggle-document-mode))]
|
|
[:p.inline-block "to toggle document mode"]]]]}
|
|
[:p.inline-block "to toggle document mode"]]]]}
|
|
- [:a.block.px-1.text-sm.font-medium.bg-base-2.rounded-md.mx-2
|
|
|
|
- {:on-click state/toggle-document-mode!}
|
|
|
|
- "D"])))
|
|
|
|
|
|
+ [:a.block.px-1.text-sm.font-medium.bg-base-2.rounded-md.mx-2
|
|
|
|
+ {:on-click state/toggle-document-mode!}
|
|
|
|
+ "D"])))
|
|
|
|
|
|
(def help-menu-items
|
|
(def help-menu-items
|
|
[{:title "Handbook" :icon "book-2" :on-click #(handbooks/toggle-handbooks)}
|
|
[{:title "Handbook" :icon "book-2" :on-click #(handbooks/toggle-handbooks)}
|
|
@@ -803,16 +802,16 @@
|
|
[]
|
|
[]
|
|
|
|
|
|
(rum/use-effect!
|
|
(rum/use-effect!
|
|
- (fn []
|
|
|
|
- (state/set-state! :ui/handbooks-open? false))
|
|
|
|
- [])
|
|
|
|
|
|
+ (fn []
|
|
|
|
+ (state/set-state! :ui/handbooks-open? false))
|
|
|
|
+ [])
|
|
|
|
|
|
(rum/use-effect!
|
|
(rum/use-effect!
|
|
- (fn []
|
|
|
|
- (let [h #(state/set-state! :ui/help-open? false)]
|
|
|
|
- (.addEventListener js/document.body "click" h)
|
|
|
|
- #(.removeEventListener js/document.body "click" h)))
|
|
|
|
- [])
|
|
|
|
|
|
+ (fn []
|
|
|
|
+ (let [h #(state/set-state! :ui/help-open? false)]
|
|
|
|
+ (.addEventListener js/document.body "click" h)
|
|
|
|
+ #(.removeEventListener js/document.body "click" h)))
|
|
|
|
+ [])
|
|
|
|
|
|
[:div.cp__sidebar-help-menu-popup
|
|
[:div.cp__sidebar-help-menu-popup
|
|
[:div.list-wrap
|
|
[:div.list-wrap
|
|
@@ -856,83 +855,83 @@
|
|
|
|
|
|
(rum/defc app-context-menu-observer
|
|
(rum/defc app-context-menu-observer
|
|
< rum/static
|
|
< rum/static
|
|
- (mixins/event-mixin
|
|
|
|
- (fn [state]
|
|
|
|
|
|
+ (mixins/event-mixin
|
|
|
|
+ (fn [state]
|
|
;; fixme: this mixin will register global event listeners on window
|
|
;; fixme: this mixin will register global event listeners on window
|
|
;; which might cause unexpected issues
|
|
;; which might cause unexpected issues
|
|
- (mixins/listen state js/window "contextmenu"
|
|
|
|
- (fn [^js e]
|
|
|
|
- (let [target (gobj/get e "target")
|
|
|
|
- block-el (.closest target ".bullet-container[blockid]")
|
|
|
|
- block-id (some-> block-el (.getAttribute "blockid"))
|
|
|
|
- {:keys [block block-ref]} (state/sub :block-ref/context)
|
|
|
|
- {:keys [page page-entity]} (state/sub :page-title/context)]
|
|
|
|
-
|
|
|
|
- (let [show!
|
|
|
|
- (fn [content]
|
|
|
|
- (shui/popup-show! e
|
|
|
|
- (fn [{:keys [id]}]
|
|
|
|
- [:div {:on-click #(shui/popup-hide! id)
|
|
|
|
- :data-keep-selection true}
|
|
|
|
- content])
|
|
|
|
- {:on-before-hide state/dom-clear-selection!
|
|
|
|
- :on-after-hide state/state-clear-selection!
|
|
|
|
- :content-props {:class "w-[280px] ls-context-menu-content"}
|
|
|
|
- :as-dropdown? true}))
|
|
|
|
-
|
|
|
|
- handled
|
|
|
|
- (cond
|
|
|
|
- (and page (not block-id))
|
|
|
|
- (do
|
|
|
|
- (show! (cp-content/page-title-custom-context-menu-content page-entity))
|
|
|
|
- (state/set-state! :page-title/context nil))
|
|
|
|
-
|
|
|
|
- block-ref
|
|
|
|
- (do
|
|
|
|
- (show! (cp-content/block-ref-custom-context-menu-content block block-ref))
|
|
|
|
- (state/set-state! :block-ref/context nil))
|
|
|
|
|
|
+ (mixins/listen state js/window "contextmenu"
|
|
|
|
+ (fn [^js e]
|
|
|
|
+ (let [target (gobj/get e "target")
|
|
|
|
+ block-el (.closest target ".bullet-container[blockid]")
|
|
|
|
+ block-id (some-> block-el (.getAttribute "blockid"))
|
|
|
|
+ {:keys [block block-ref]} (state/sub :block-ref/context)
|
|
|
|
+ {:keys [page page-entity]} (state/sub :page-title/context)]
|
|
|
|
+
|
|
|
|
+ (let [show!
|
|
|
|
+ (fn [content]
|
|
|
|
+ (shui/popup-show! e
|
|
|
|
+ (fn [{:keys [id]}]
|
|
|
|
+ [:div {:on-click #(shui/popup-hide! id)
|
|
|
|
+ :data-keep-selection true}
|
|
|
|
+ content])
|
|
|
|
+ {:on-before-hide state/dom-clear-selection!
|
|
|
|
+ :on-after-hide state/state-clear-selection!
|
|
|
|
+ :content-props {:class "w-[280px] ls-context-menu-content"}
|
|
|
|
+ :as-dropdown? true}))
|
|
|
|
+
|
|
|
|
+ handled
|
|
|
|
+ (cond
|
|
|
|
+ (and page (not block-id))
|
|
|
|
+ (do
|
|
|
|
+ (show! (cp-content/page-title-custom-context-menu-content page-entity))
|
|
|
|
+ (state/set-state! :page-title/context nil))
|
|
|
|
+
|
|
|
|
+ block-ref
|
|
|
|
+ (do
|
|
|
|
+ (show! (cp-content/block-ref-custom-context-menu-content block block-ref))
|
|
|
|
+ (state/set-state! :block-ref/context nil))
|
|
|
|
|
|
;; block selection
|
|
;; block selection
|
|
- (and (state/selection?) (not (d/has-class? target "bullet")))
|
|
|
|
- (show! (cp-content/custom-context-menu-content))
|
|
|
|
|
|
+ (and (state/selection?) (not (d/has-class? target "bullet")))
|
|
|
|
+ (show! (cp-content/custom-context-menu-content))
|
|
|
|
|
|
;; block bullet
|
|
;; block bullet
|
|
- (and block-id (parse-uuid block-id))
|
|
|
|
- (let [block (.closest target ".ls-block")
|
|
|
|
- property-default-value? (when block
|
|
|
|
- (= "true" (d/attr block "data-is-property-default-value")))]
|
|
|
|
- (when block
|
|
|
|
- (state/clear-selection!)
|
|
|
|
- (state/conj-selection-block! block :down))
|
|
|
|
- (show! (cp-content/block-context-menu-content target (uuid block-id) property-default-value?)))
|
|
|
|
-
|
|
|
|
- :else
|
|
|
|
- false)]
|
|
|
|
- (when (not (false? handled))
|
|
|
|
- (util/stop e))))))))
|
|
|
|
|
|
+ (and block-id (parse-uuid block-id))
|
|
|
|
+ (let [block (.closest target ".ls-block")
|
|
|
|
+ property-default-value? (when block
|
|
|
|
+ (= "true" (d/attr block "data-is-property-default-value")))]
|
|
|
|
+ (when block
|
|
|
|
+ (state/clear-selection!)
|
|
|
|
+ (state/conj-selection-block! block :down))
|
|
|
|
+ (show! (cp-content/block-context-menu-content target (uuid block-id) property-default-value?)))
|
|
|
|
+
|
|
|
|
+ :else
|
|
|
|
+ false)]
|
|
|
|
+ (when (not (false? handled))
|
|
|
|
+ (util/stop e))))))))
|
|
[]
|
|
[]
|
|
nil)
|
|
nil)
|
|
|
|
|
|
(rum/defcs ^:large-vars/cleanup-todo root-container < rum/reactive
|
|
(rum/defcs ^:large-vars/cleanup-todo root-container < rum/reactive
|
|
- (mixins/event-mixin
|
|
|
|
- (fn [state]
|
|
|
|
- (mixins/listen state js/window "pointerdown" hide-context-menu-and-clear-selection)
|
|
|
|
- (mixins/listen state js/window "keydown"
|
|
|
|
- (fn [e]
|
|
|
|
- (cond
|
|
|
|
- (= 27 (.-keyCode e))
|
|
|
|
- (if (and (state/modal-opened?)
|
|
|
|
- (not
|
|
|
|
- (and
|
|
|
|
|
|
+ (mixins/event-mixin
|
|
|
|
+ (fn [state]
|
|
|
|
+ (mixins/listen state js/window "pointerdown" hide-context-menu-and-clear-selection)
|
|
|
|
+ (mixins/listen state js/window "keydown"
|
|
|
|
+ (fn [e]
|
|
|
|
+ (cond
|
|
|
|
+ (= 27 (.-keyCode e))
|
|
|
|
+ (if (and (state/modal-opened?)
|
|
|
|
+ (not
|
|
|
|
+ (and
|
|
;; FIXME: this does not work on CI tests
|
|
;; FIXME: this does not work on CI tests
|
|
- util/node-test?
|
|
|
|
- (state/editing?))))
|
|
|
|
- (state/close-modal!)
|
|
|
|
- (hide-context-menu-and-clear-selection e)))
|
|
|
|
- (state/set-ui-last-key-code! (.-key e))))
|
|
|
|
- (mixins/listen state js/window "keyup"
|
|
|
|
- (fn [_e]
|
|
|
|
- (state/set-state! :editor/latest-shortcut nil)))))
|
|
|
|
|
|
+ util/node-test?
|
|
|
|
+ (state/editing?))))
|
|
|
|
+ (state/close-modal!)
|
|
|
|
+ (hide-context-menu-and-clear-selection e)))
|
|
|
|
+ (state/set-ui-last-key-code! (.-key e))))
|
|
|
|
+ (mixins/listen state js/window "keyup"
|
|
|
|
+ (fn [_e]
|
|
|
|
+ (state/set-state! :editor/latest-shortcut nil)))))
|
|
[state route-match main-content']
|
|
[state route-match main-content']
|
|
(let [current-repo (state/sub :git/current-repo)
|
|
(let [current-repo (state/sub :git/current-repo)
|
|
granted? (state/sub [:nfs/user-granted? (state/get-current-repo)])
|
|
granted? (state/sub [:nfs/user-granted? (state/get-current-repo)])
|
|
@@ -950,7 +949,7 @@
|
|
right-sidebar-blocks (state/sub-right-sidebar-blocks)
|
|
right-sidebar-blocks (state/sub-right-sidebar-blocks)
|
|
route-name (get-in route-match [:data :name])
|
|
route-name (get-in route-match [:data :name])
|
|
margin-less-pages? (or (boolean (#{:graph} route-name))
|
|
margin-less-pages? (or (boolean (#{:graph} route-name))
|
|
- (db-model/whiteboard-page? (state/get-current-page)))
|
|
|
|
|
|
+ (db-model/whiteboard-page? (state/get-current-page)))
|
|
db-restoring? (state/sub :db/restoring?)
|
|
db-restoring? (state/sub :db/restoring?)
|
|
indexeddb-support? (state/sub :indexeddb/support?)
|
|
indexeddb-support? (state/sub :indexeddb/support?)
|
|
page? (= :page route-name)
|
|
page? (= :page route-name)
|
|
@@ -965,102 +964,102 @@
|
|
show-recording-bar? (state/sub :mobile/show-recording-bar?)
|
|
show-recording-bar? (state/sub :mobile/show-recording-bar?)
|
|
preferred-language (state/sub [:preferred-language])]
|
|
preferred-language (state/sub [:preferred-language])]
|
|
(theme/container
|
|
(theme/container
|
|
- {:t t
|
|
|
|
- :theme theme
|
|
|
|
- :accent-color accent-color
|
|
|
|
- :editor-font editor-font
|
|
|
|
- :route route-match
|
|
|
|
- :current-repo current-repo
|
|
|
|
- :edit? edit?
|
|
|
|
- :nfs-granted? granted?
|
|
|
|
- :db-restoring? db-restoring?
|
|
|
|
- :sidebar-open? sidebar-open?
|
|
|
|
- :settings-open? settings-open?
|
|
|
|
- :sidebar-blocks-len (count right-sidebar-blocks)
|
|
|
|
- :system-theme? system-theme?
|
|
|
|
- :onboarding-state onboarding-state
|
|
|
|
- :preferred-language preferred-language
|
|
|
|
- :on-click (fn [e]
|
|
|
|
- (editor-handler/unhighlight-blocks!)
|
|
|
|
- (util/fix-open-external-with-shift! e))}
|
|
|
|
-
|
|
|
|
- [:main.theme-container-inner#app-container-wrapper
|
|
|
|
- {:class (util/classnames
|
|
|
|
- [{:ls-left-sidebar-open left-sidebar-open?
|
|
|
|
- :ls-right-sidebar-open sidebar-open?
|
|
|
|
- :ls-wide-mode wide-mode?
|
|
|
|
- :ls-window-controls window-controls?
|
|
|
|
- :ls-fold-button-on-right fold-button-on-right?
|
|
|
|
- :ls-hl-colored ls-block-hl-colored?}])
|
|
|
|
- :on-pointer-up (fn []
|
|
|
|
- (when-let [container (gdom/getElement "app-container-wrapper")]
|
|
|
|
- (d/remove-class! container "blocks-selection-mode")
|
|
|
|
- (when (> (count (state/get-selection-blocks)) 1)
|
|
|
|
- (util/clear-selection!))))}
|
|
|
|
-
|
|
|
|
- [:button#skip-to-main
|
|
|
|
- {:on-click #(ui/focus-element (ui/main-node))
|
|
|
|
- :on-key-up (fn [e]
|
|
|
|
- (when (= "Enter" (.-key e))
|
|
|
|
- (ui/focus-element (ui/main-node))))}
|
|
|
|
- (t :accessibility/skip-to-main-content)]
|
|
|
|
- [:div.#app-container
|
|
|
|
- [:div#left-container
|
|
|
|
- {:class (if (state/sub :ui/sidebar-open?) "overflow-hidden" "w-full")}
|
|
|
|
- (header/header {:light? light?
|
|
|
|
- :current-repo current-repo
|
|
|
|
- :logged? logged?
|
|
|
|
- :page? page?
|
|
|
|
- :route-match route-match
|
|
|
|
- :default-home default-home
|
|
|
|
- :new-block-mode new-block-mode})
|
|
|
|
- (when (util/electron?)
|
|
|
|
- (find-in-page/search))
|
|
|
|
-
|
|
|
|
- (main {:route-match route-match
|
|
|
|
- :margin-less-pages? margin-less-pages?
|
|
|
|
- :logged? logged?
|
|
|
|
- :home? home?
|
|
|
|
- :route-name route-name
|
|
|
|
- :indexeddb-support? indexeddb-support?
|
|
|
|
- :light? light?
|
|
|
|
- :db-restoring? db-restoring?
|
|
|
|
- :main-content main-content'
|
|
|
|
- :show-action-bar? show-action-bar?
|
|
|
|
- :show-recording-bar? show-recording-bar?})]
|
|
|
|
-
|
|
|
|
- (when window-controls?
|
|
|
|
- (window-controls/container))
|
|
|
|
-
|
|
|
|
- (right-sidebar/sidebar)
|
|
|
|
-
|
|
|
|
- [:div#app-single-container]]
|
|
|
|
-
|
|
|
|
- (ui/notification)
|
|
|
|
-
|
|
|
|
- (shui-toaster/install-toaster)
|
|
|
|
- (shui-dialog/install-modals)
|
|
|
|
- (shui-popup/install-popups)
|
|
|
|
-
|
|
|
|
- (custom-context-menu)
|
|
|
|
- (plugins/custom-js-installer
|
|
|
|
- {:t t
|
|
|
|
- :current-repo current-repo
|
|
|
|
- :nfs-granted? granted?
|
|
|
|
- :db-restoring? db-restoring?})
|
|
|
|
- (app-context-menu-observer)
|
|
|
|
-
|
|
|
|
- [:a#download.hidden]
|
|
|
|
- [:a#download-as-edn-v2.hidden]
|
|
|
|
- [:a#download-as-json-v2.hidden]
|
|
|
|
- [:a#download-as-json-debug.hidden]
|
|
|
|
- [:a#download-as-sqlite-db.hidden]
|
|
|
|
- [:a#download-as-roam-json.hidden]
|
|
|
|
- [:a#download-as-html.hidden]
|
|
|
|
- [:a#download-as-zip.hidden]
|
|
|
|
- [:a#export-as-markdown.hidden]
|
|
|
|
- [:a#export-as-opml.hidden]
|
|
|
|
- [:a#convert-markdown-to-unordered-list-or-heading.hidden]
|
|
|
|
- (when (and (not config/mobile?)
|
|
|
|
- (not config/publishing?))
|
|
|
|
- (help-button))])))
|
|
|
|
|
|
+ {:t t
|
|
|
|
+ :theme theme
|
|
|
|
+ :accent-color accent-color
|
|
|
|
+ :editor-font editor-font
|
|
|
|
+ :route route-match
|
|
|
|
+ :current-repo current-repo
|
|
|
|
+ :edit? edit?
|
|
|
|
+ :nfs-granted? granted?
|
|
|
|
+ :db-restoring? db-restoring?
|
|
|
|
+ :sidebar-open? sidebar-open?
|
|
|
|
+ :settings-open? settings-open?
|
|
|
|
+ :sidebar-blocks-len (count right-sidebar-blocks)
|
|
|
|
+ :system-theme? system-theme?
|
|
|
|
+ :onboarding-state onboarding-state
|
|
|
|
+ :preferred-language preferred-language
|
|
|
|
+ :on-click (fn [e]
|
|
|
|
+ (editor-handler/unhighlight-blocks!)
|
|
|
|
+ (util/fix-open-external-with-shift! e))}
|
|
|
|
+
|
|
|
|
+ [:main.theme-container-inner#app-container-wrapper
|
|
|
|
+ {:class (util/classnames
|
|
|
|
+ [{:ls-left-sidebar-open left-sidebar-open?
|
|
|
|
+ :ls-right-sidebar-open sidebar-open?
|
|
|
|
+ :ls-wide-mode wide-mode?
|
|
|
|
+ :ls-window-controls window-controls?
|
|
|
|
+ :ls-fold-button-on-right fold-button-on-right?
|
|
|
|
+ :ls-hl-colored ls-block-hl-colored?}])
|
|
|
|
+ :on-pointer-up (fn []
|
|
|
|
+ (when-let [container (gdom/getElement "app-container-wrapper")]
|
|
|
|
+ (d/remove-class! container "blocks-selection-mode")
|
|
|
|
+ (when (> (count (state/get-selection-blocks)) 1)
|
|
|
|
+ (util/clear-selection!))))}
|
|
|
|
+
|
|
|
|
+ [:button#skip-to-main
|
|
|
|
+ {:on-click #(ui/focus-element (ui/main-node))
|
|
|
|
+ :on-key-up (fn [e]
|
|
|
|
+ (when (= "Enter" (.-key e))
|
|
|
|
+ (ui/focus-element (ui/main-node))))}
|
|
|
|
+ (t :accessibility/skip-to-main-content)]
|
|
|
|
+ [:div.#app-container
|
|
|
|
+ [:div#left-container
|
|
|
|
+ {:class (if (state/sub :ui/sidebar-open?) "overflow-hidden" "w-full")}
|
|
|
|
+ (header/header {:light? light?
|
|
|
|
+ :current-repo current-repo
|
|
|
|
+ :logged? logged?
|
|
|
|
+ :page? page?
|
|
|
|
+ :route-match route-match
|
|
|
|
+ :default-home default-home
|
|
|
|
+ :new-block-mode new-block-mode})
|
|
|
|
+ (when (util/electron?)
|
|
|
|
+ (find-in-page/search))
|
|
|
|
+
|
|
|
|
+ (main {:route-match route-match
|
|
|
|
+ :margin-less-pages? margin-less-pages?
|
|
|
|
+ :logged? logged?
|
|
|
|
+ :home? home?
|
|
|
|
+ :route-name route-name
|
|
|
|
+ :indexeddb-support? indexeddb-support?
|
|
|
|
+ :light? light?
|
|
|
|
+ :db-restoring? db-restoring?
|
|
|
|
+ :main-content main-content'
|
|
|
|
+ :show-action-bar? show-action-bar?
|
|
|
|
+ :show-recording-bar? show-recording-bar?})]
|
|
|
|
+
|
|
|
|
+ (when window-controls?
|
|
|
|
+ (window-controls/container))
|
|
|
|
+
|
|
|
|
+ (right-sidebar/sidebar)
|
|
|
|
+
|
|
|
|
+ [:div#app-single-container]]
|
|
|
|
+
|
|
|
|
+ (ui/notification)
|
|
|
|
+
|
|
|
|
+ (shui-toaster/install-toaster)
|
|
|
|
+ (shui-dialog/install-modals)
|
|
|
|
+ (shui-popup/install-popups)
|
|
|
|
+
|
|
|
|
+ (custom-context-menu)
|
|
|
|
+ (plugins/custom-js-installer
|
|
|
|
+ {:t t
|
|
|
|
+ :current-repo current-repo
|
|
|
|
+ :nfs-granted? granted?
|
|
|
|
+ :db-restoring? db-restoring?})
|
|
|
|
+ (app-context-menu-observer)
|
|
|
|
+
|
|
|
|
+ [:a#download.hidden]
|
|
|
|
+ [:a#download-as-edn-v2.hidden]
|
|
|
|
+ [:a#download-as-json-v2.hidden]
|
|
|
|
+ [:a#download-as-json-debug.hidden]
|
|
|
|
+ [:a#download-as-sqlite-db.hidden]
|
|
|
|
+ [:a#download-as-roam-json.hidden]
|
|
|
|
+ [:a#download-as-html.hidden]
|
|
|
|
+ [:a#download-as-zip.hidden]
|
|
|
|
+ [:a#export-as-markdown.hidden]
|
|
|
|
+ [:a#export-as-opml.hidden]
|
|
|
|
+ [:a#convert-markdown-to-unordered-list-or-heading.hidden]
|
|
|
|
+ (when (and (not config/mobile?)
|
|
|
|
+ (not config/publishing?))
|
|
|
|
+ (help-button))])))
|