mirror of
https://github.com/logseq/logseq.git
synced 2026-02-01 22:47:36 +00:00
feat(ui): enhance left sidebar (#2899)
* feat(ui): enhance left sidebar Co-authored-by: Tienson Qin <tiensonqin@gmail.com>
This commit is contained in:
@@ -4,10 +4,12 @@
|
||||
--ls-page-text-size: 1em;
|
||||
--ls-page-title-size: 36px;
|
||||
--ls-font-family: 'Inter';
|
||||
--ls-main-content-max-width: 740px;
|
||||
--ls-main-content-max-width: 820px;
|
||||
--ls-main-content-max-width-wide: 100%;
|
||||
--ls-border-radius-low: 4px;
|
||||
--ls-border-radius-medium: 8px;
|
||||
--ls-left-sidebar-width: 240px;
|
||||
--ls-left-sidebar-nav-btn-size: 38px;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
|
||||
4
resources/css/tabler-icons.min.css
vendored
Normal file
4
resources/css/tabler-icons.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -3,6 +3,7 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" name="viewport">
|
||||
<link type="text/css" rel="stylesheet" href="./css/tabler-icons.min.css">
|
||||
<link href="./css/style.css" rel="stylesheet" type="text/css">
|
||||
<link href="./img/logo.png" rel="shortcut icon" type="image/png">
|
||||
<link href="./img/logo.png" rel="shortcut icon" sizes="192x192">
|
||||
|
||||
BIN
resources/fonts/tabler-icons.eot
Normal file
BIN
resources/fonts/tabler-icons.eot
Normal file
Binary file not shown.
BIN
resources/fonts/tabler-icons.woff
Normal file
BIN
resources/fonts/tabler-icons.woff
Normal file
Binary file not shown.
BIN
resources/fonts/tabler-icons.woff2
Normal file
BIN
resources/fonts/tabler-icons.woff2
Normal file
Binary file not shown.
@@ -3,8 +3,8 @@
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no" name="viewport">
|
||||
<link rel="stylesheet" type="text/css" href="./css/tabler-icons.min.css">
|
||||
<link href="./css/style.css" rel="stylesheet" type="text/css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/@tabler/icons@latest/iconfont/tabler-icons.min.css">
|
||||
<link href="./img/logo.png" rel="shortcut icon" type="image/png">
|
||||
<link href="./img/logo.png" rel="shortcut icon" sizes="192x192">
|
||||
<link href="./img/logo.png" rel="apple-touch-icon">
|
||||
|
||||
@@ -113,7 +113,7 @@
|
||||
(defn- new-version-downloaded-cb
|
||||
[_ & args]
|
||||
(.info logger "[update-downloaded]" args)
|
||||
(when-let [web-contents (and @*win (. @*win -webContents))]
|
||||
(when-let [web-contents (and @*win (. ^js @*win -webContents))]
|
||||
(.send web-contents "auto-updater-downloaded" (bean/->js args))))
|
||||
|
||||
(defn init-auto-updater
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
[frontend.components.plugins :as plugins]
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.handler.block :as block-handler]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.handler.dnd :as dnd]
|
||||
[frontend.handler.editor :as editor-handler]
|
||||
[frontend.handler.repeated :as repeated]
|
||||
@@ -373,6 +374,9 @@
|
||||
:on-mouse-down
|
||||
(fn [e]
|
||||
(util/stop e)
|
||||
(when redirect-page-name
|
||||
(page-handler/add-page-to-recent! (state/get-current-repo) redirect-page-name)
|
||||
(js/setTimeout #(model/refresh-recent-pages) 300))
|
||||
(let [create-first-block! (fn []
|
||||
(when-not (editor-handler/add-default-title-property-if-needed! redirect-page-name)
|
||||
(editor-handler/insert-first-page-block-if-not-exists! redirect-page-name)))]
|
||||
@@ -389,7 +393,9 @@
|
||||
(create-first-block!)
|
||||
(route-handler/redirect! {:to :page
|
||||
:path-params {:name redirect-page-name}}))))
|
||||
(when (and contents-page? (state/get-left-sidebar-open?))
|
||||
(when (and contents-page?
|
||||
(util/mobile?)
|
||||
(state/get-left-sidebar-open?))
|
||||
(ui-handler/close-left-sidebar!)))}
|
||||
|
||||
(if (and (coll? children) (seq children))
|
||||
|
||||
@@ -35,6 +35,9 @@
|
||||
(.readAsText reader file)))
|
||||
(notification/show! "Please choose a JSON file."
|
||||
:error))))}]
|
||||
|
||||
[:hr]
|
||||
|
||||
[:div.mt-4
|
||||
(case roam-importing?
|
||||
true (ui/loading "Loading")
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require [frontend.components.export :as export]
|
||||
[frontend.components.plugins :as plugins]
|
||||
[frontend.components.repo :as repo]
|
||||
[frontend.components.page :as page]
|
||||
[frontend.components.right-sidebar :as sidebar]
|
||||
[frontend.components.search :as search]
|
||||
[frontend.components.svg :as svg]
|
||||
@@ -22,20 +23,14 @@
|
||||
[rum.core :as rum]
|
||||
[frontend.mobile.util :as mobile-util]))
|
||||
|
||||
(rum/defc home-btn < rum/reactive
|
||||
[{:keys [white? electron-mac?]}]
|
||||
[:a.cp__header-logo
|
||||
{:class (when electron-mac? "button")
|
||||
:href (rfe/href :home)
|
||||
(rum/defc home-button
|
||||
[]
|
||||
[:a.button
|
||||
{:href (rfe/href :home)
|
||||
:on-click (fn []
|
||||
(util/scroll-to-top)
|
||||
(state/set-journals-length! 2))}
|
||||
(if electron-mac?
|
||||
svg/home
|
||||
(if-let [logo (and config/publishing?
|
||||
(get-in (state/get-config) [:project :logo]))]
|
||||
[:img.cp__header-logo-img {:src logo}]
|
||||
(svg/logo (not white?))))])
|
||||
(ui/icon "home" {:style {:fontSize 20}})])
|
||||
|
||||
(rum/defc login
|
||||
[logged?]
|
||||
@@ -62,54 +57,38 @@
|
||||
|
||||
(rum/defc left-menu-button < rum/reactive
|
||||
[{:keys [on-click]}]
|
||||
[:button#left-menu.cp__header-left-menu
|
||||
{:on-click on-click}
|
||||
[:svg.h-6.w-6
|
||||
{:viewBox "0 0 24 24", :fill "none", :stroke "currentColor"}
|
||||
[:path
|
||||
{:d "M4 6h16M4 12h16M4 18h7"
|
||||
:stroke-width "2"
|
||||
:stroke-linejoin "round"
|
||||
:stroke-linecap "round"}]]])
|
||||
(let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)]
|
||||
|
||||
(ui/tippy
|
||||
{:html [:div.text-sm.font-medium
|
||||
"Shortcut: "
|
||||
[:code (util/->platform-shortcut "t l")]]
|
||||
:delay 2000
|
||||
:hideDelay 1
|
||||
:position "right"
|
||||
:interactive true
|
||||
:arrow true}
|
||||
|
||||
[:a#left-menu.cp__header-left-menu.button
|
||||
{:on-click on-click
|
||||
:style {:margin-left 10}}
|
||||
(ui/icon "menu-2" {:style {:fontSize 20}})])))
|
||||
|
||||
(rum/defc dropdown-menu < rum/reactive
|
||||
[{:keys [me current-repo t default-home]}]
|
||||
(let [projects (state/sub [:me :projects])
|
||||
developer-mode? (state/sub [:ui/developer-mode?])
|
||||
logged? (state/logged?)]
|
||||
logged? (state/logged?)
|
||||
page-menu (page/page-menu t)
|
||||
page-menu-and-hr (when (seq page-menu)
|
||||
(concat page-menu [{:hr true}]))]
|
||||
(ui/dropdown-with-links
|
||||
(fn [{:keys [toggle-fn]}]
|
||||
[:a.cp__right-menu-button.button
|
||||
[:a.button
|
||||
{:on-click toggle-fn}
|
||||
(svg/horizontal-dots nil)])
|
||||
(ui/icon "dots" {:style {:fontSize 20}})])
|
||||
(->>
|
||||
[(when current-repo
|
||||
{:title (t :cards-view)
|
||||
:options {:on-click #(state/pub-event! [:modal/show-cards])}})
|
||||
|
||||
(when current-repo
|
||||
{:title (t :graph-view)
|
||||
:options {:href (rfe/href :graph)}
|
||||
:icon svg/graph-sm})
|
||||
|
||||
(when current-repo
|
||||
{:title (t :all-pages)
|
||||
:options {:href (rfe/href :all-pages)}
|
||||
:icon svg/pages-sm})
|
||||
|
||||
(when (and current-repo (not config/publishing?))
|
||||
{:title (t :all-files)
|
||||
:options {:href (rfe/href :all-files)}
|
||||
:icon svg/folder-sm})
|
||||
|
||||
(when (and default-home current-repo)
|
||||
{:title (t :all-journals)
|
||||
:options {:href (rfe/href :all-journals)}
|
||||
:icon svg/calendar-sm})
|
||||
|
||||
{:hr true}
|
||||
|
||||
(when-not (state/publishing-enable-editing?)
|
||||
[(when-not (state/publishing-enable-editing?)
|
||||
{:title (t :settings)
|
||||
:options {:on-click state/open-settings!}
|
||||
:icon svg/settings-sm})
|
||||
@@ -123,7 +102,7 @@
|
||||
:options {:on-click #(plugins/open-select-theme!)}})
|
||||
|
||||
(when current-repo
|
||||
{:title (t :export)
|
||||
{:title (t :export-graph)
|
||||
:options {:on-click #(state/set-modal! export/export)}
|
||||
:icon nil})
|
||||
|
||||
@@ -142,6 +121,7 @@
|
||||
{:title (t :sign-out)
|
||||
:options {:on-click user-handler/sign-out!}
|
||||
:icon svg/logout-sm})]
|
||||
(concat page-menu-and-hr)
|
||||
(remove nil?))
|
||||
;; {:links-footer (when (and (util/electron?) (not logged?))
|
||||
;; [:div.px-2.py-2 (login logged?)])}
|
||||
@@ -202,12 +182,10 @@
|
||||
(js/window.apis.toggleMaxOrMinActiveWindow))))}
|
||||
(left-menu-button {:on-click (fn []
|
||||
(open-fn)
|
||||
(state/set-left-sidebar-open! true))})
|
||||
(state/set-left-sidebar-open!
|
||||
(not (:ui/left-sidebar-open? @state/state))))})
|
||||
|
||||
|
||||
(home-btn {:white? white? :electron-mac? electron-mac?})
|
||||
(when electron-mac? (back-and-forward true))
|
||||
|
||||
(when current-repo
|
||||
(ui/tippy
|
||||
{:html [:div.text-sm.font-medium
|
||||
@@ -215,21 +193,26 @@
|
||||
;; TODO: Pull from config so it displays custom shortcut, not just the default
|
||||
[:code (util/->platform-shortcut "Ctrl + k")]]
|
||||
:interactive true
|
||||
:delay [2000, 0]
|
||||
:arrow true}
|
||||
[:a.button#search-button
|
||||
{:on-click #(state/pub-event! [:go/search])}
|
||||
svg/search]))
|
||||
|
||||
(when electron-not-mac? (back-and-forward))
|
||||
(ui/icon "search" {:style {:fontSize 20}})]))
|
||||
|
||||
[:div.flex-1.flex] ;; Spacer in the middle ------------------------------
|
||||
|
||||
(when (and
|
||||
(not (mobile-util/is-native-platform?))
|
||||
(not (util/electron?)))
|
||||
(login logged?))
|
||||
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(plugins/hook-ui-items :toolbar))
|
||||
|
||||
[:a (when refreshing?
|
||||
[:div {:class "animate-spin-reverse"}
|
||||
svg/refresh])]
|
||||
(when (not= (state/get-current-route) :home)
|
||||
(home-button))
|
||||
|
||||
(when electron-mac? (back-and-forward electron-mac?))
|
||||
|
||||
(new-block-mode)
|
||||
|
||||
@@ -237,17 +220,8 @@
|
||||
[:div {:class "animate-spin-reverse"}
|
||||
svg/refresh])
|
||||
|
||||
(when (and
|
||||
(not (mobile-util/is-native-platform?))
|
||||
(not (util/electron?)))
|
||||
(login logged?))
|
||||
|
||||
(repo/sync-status current-repo)
|
||||
|
||||
(when-not (util/mobile?)
|
||||
[:div.repos
|
||||
(repo/repos-dropdown nil nil)])
|
||||
|
||||
(when show-open-folder?
|
||||
[:a.text-sm.font-medium.button
|
||||
{:on-click #(page-handler/ls-dir-files! shortcut/refresh!)}
|
||||
@@ -261,17 +235,12 @@
|
||||
[:a.text-sm.font-medium.button {:href (rfe/href :graph)}
|
||||
(t :graph)])
|
||||
|
||||
;; Go to Keyboard Shortcuts page
|
||||
[:a.button
|
||||
{:title "Keyboard shortcuts"
|
||||
:on-click (fn [] (route-handler/redirect! {:to :shortcut-setting}))}
|
||||
(svg/icon-cmd 20)]
|
||||
|
||||
(dropdown-menu {:me me
|
||||
:t t
|
||||
:current-repo current-repo
|
||||
:default-home default-home})
|
||||
|
||||
(when (not (state/sub :ui/sidebar-open?)) (sidebar/toggle))
|
||||
(when (not (state/sub :ui/sidebar-open?))
|
||||
(sidebar/toggle))
|
||||
|
||||
(updater-tips-new-version t)])))
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
left: 0;
|
||||
right: 0;
|
||||
user-select: none;
|
||||
transition: width 0.3s;
|
||||
line-height: 1;
|
||||
|
||||
.it svg {
|
||||
@@ -80,10 +79,6 @@
|
||||
|
||||
.is-electron.is-mac .cp__header {
|
||||
padding-left: 78px;
|
||||
-moz-transition: padding-left .3s ease-in;
|
||||
-o-transition: padding-left .3s ease-in;
|
||||
-webkit-transition: padding-left .3s ease-in;
|
||||
transition: padding-left .3s ease-in;
|
||||
}
|
||||
|
||||
.cp__header .navigation svg {
|
||||
@@ -98,19 +93,6 @@
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
|
||||
.cp__header-left-menu {
|
||||
@apply px-4 mr-4;
|
||||
border-right: 1px solid var(--ls-secondary-background-color);
|
||||
color: var(--ls-link-text-color);
|
||||
display: block;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cp__header-left-menu:focus {
|
||||
@apply outline-none;
|
||||
background: var(--ls-menu-hover-color);
|
||||
}
|
||||
|
||||
.cp__header-logo {
|
||||
@apply p-2;
|
||||
}
|
||||
@@ -133,10 +115,6 @@
|
||||
@apply shadow-none;
|
||||
}
|
||||
|
||||
.cp__header-left-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.cp__header-logo {
|
||||
display: block;
|
||||
}
|
||||
@@ -147,13 +125,11 @@
|
||||
}
|
||||
|
||||
#repo-name {
|
||||
vertical-align: middle;
|
||||
display: inline;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
max-width: 7ch;
|
||||
color: var(--ls-icon-color, #045591);
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
|
||||
38
src/main/frontend/components/modals.cljs
Normal file
38
src/main/frontend/components/modals.cljs
Normal file
@@ -0,0 +1,38 @@
|
||||
(ns frontend.components.modals
|
||||
(:require [frontend.db.model :as db-model]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.ui :as ui]
|
||||
[clojure.string :as string]
|
||||
[rum.core :as rum]
|
||||
[frontend.state :as state]
|
||||
[frontend.mixins :as mixins]
|
||||
[frontend.context.i18n :as i18n]
|
||||
[goog.dom :as gdom]))
|
||||
|
||||
(rum/defcs new-page-modal <
|
||||
(mixins/event-mixin
|
||||
(fn [state]
|
||||
(mixins/on-enter
|
||||
state
|
||||
:node (gdom/getElement "input-new-page-title")
|
||||
:on-enter (fn [^js e]
|
||||
(let [^js target (.-target e)
|
||||
value (.-value target)]
|
||||
(when-let [title (and (not (string/blank? (string/trim value))) value)]
|
||||
(if (db-model/page-empty? (state/get-current-repo) title)
|
||||
(page-handler/create! title {:redirect? true})
|
||||
(route-handler/redirect! {:to :page
|
||||
:path-params {:name title}}))))))))
|
||||
[state]
|
||||
(rum/with-context
|
||||
[[t] i18n/*tongue-context*]
|
||||
[:div
|
||||
[:h2.text-xl.pb-4 (t :new-page)]
|
||||
[:input#input-new-page-title.form-input
|
||||
{:autoFocus true
|
||||
:placeholder "page title"}]
|
||||
[:p.py-2.flex (ui/button (t :submit))]]))
|
||||
|
||||
(defn show-new-page-modal! []
|
||||
(state/set-modal! new-page-modal))
|
||||
@@ -48,9 +48,7 @@
|
||||
(when page-name
|
||||
(if block?
|
||||
(db/get-block-and-children repo block-id)
|
||||
(do
|
||||
(page-handler/add-page-to-recent! repo page-original-name)
|
||||
(db/get-page-blocks repo page-name)))))
|
||||
(db/get-page-blocks repo page-name))))
|
||||
|
||||
(defn- open-first-block!
|
||||
[state]
|
||||
@@ -270,87 +268,97 @@
|
||||
{:default-collapsed? false})]])))
|
||||
|
||||
(defn page-menu
|
||||
[repo t page page-name page-original-name title journal? public? developer-mode?]
|
||||
(let [contents? (= (string/lower-case (str page-name)) "contents")
|
||||
links (fn [] (->>
|
||||
[(when-not contents?
|
||||
{:title (t :page/add-to-favorites)
|
||||
:options {:on-click (fn [] (page-handler/handle-add-page-to-contents! page-original-name))}})
|
||||
[t]
|
||||
(when-let [page-name (and (state/get-current-page)
|
||||
(string/lower-case (state/get-current-page)))]
|
||||
(let [repo (state/sub :git/current-repo)
|
||||
page (and page-name (db/entity repo [:block/name page-name]))
|
||||
page-original-name (:block/original-name page)
|
||||
journal? (db/journal-page? page-name)
|
||||
block? (and page (util/uuid-string? page-name))
|
||||
contents? (= (string/lower-case (str page-name)) "contents")
|
||||
{:keys [title] :as properties} (:block/properties page)
|
||||
title (or title page-original-name page-name)
|
||||
public? (true? (:public properties))
|
||||
favorites (:favorites (state/sub-graph-config))
|
||||
favorited? (contains? (set (map string/lower-case favorites))
|
||||
(string/lower-case page-name))
|
||||
developer-mode? (state/sub [:ui/developer-mode?])]
|
||||
(when (and page (not block?))
|
||||
(->>
|
||||
[{:title (if favorited?
|
||||
(t :page/unfavorite)
|
||||
(t :page/add-to-favorites))
|
||||
:options {:on-click
|
||||
(fn []
|
||||
(if favorited?
|
||||
(page-handler/unfavorite-page! page-original-name)
|
||||
(page-handler/favorite-page! page-original-name)))}}
|
||||
|
||||
{:title "Go to presentation mode"
|
||||
:options {:on-click (fn []
|
||||
(state/sidebar-add-block!
|
||||
repo
|
||||
(:db/id page)
|
||||
:page-presentation
|
||||
{:page page}))}}
|
||||
(when (and (not contents?)
|
||||
(not journal?))
|
||||
{:title (t :page/rename)
|
||||
:options {:on-click #(state/set-modal! (rename-page-dialog title page-name))}})
|
||||
{:title (t :page/presentation-mode)
|
||||
:options {:on-click (fn []
|
||||
(state/sidebar-add-block!
|
||||
repo
|
||||
(:db/id page)
|
||||
:page-presentation
|
||||
{:page page}))}}
|
||||
(when (and (not contents?)
|
||||
(not journal?))
|
||||
{:title (t :page/rename)
|
||||
:options {:on-click #(state/set-modal! (rename-page-dialog title page-name))}})
|
||||
|
||||
(when-let [file-path (and (util/electron?) (page-handler/get-page-file-path))]
|
||||
[{:title (t :page/open-in-finder)
|
||||
:options {:on-click #(js/window.apis.showItemInFolder file-path)}}
|
||||
{:title (t :page/open-with-default-app)
|
||||
:options {:on-click #(js/window.apis.openPath file-path)}}])
|
||||
(when-let [file-path (and (util/electron?) (page-handler/get-page-file-path))]
|
||||
[{:title (t :page/open-in-finder)
|
||||
:options {:on-click #(js/window.apis.showItemInFolder file-path)}}
|
||||
{:title (t :page/open-with-default-app)
|
||||
:options {:on-click #(js/window.apis.openPath file-path)}}])
|
||||
|
||||
(when-not contents?
|
||||
{:title (t :page/delete)
|
||||
:options {:on-click #(state/set-modal! (delete-page-dialog page-name))}})
|
||||
(when-not contents?
|
||||
{:title (t :page/delete)
|
||||
:options {:on-click #(state/set-modal! (delete-page-dialog page-name))}})
|
||||
|
||||
(when (state/get-current-page)
|
||||
{:title (t :export)
|
||||
:options {:on-click #(state/set-modal!
|
||||
(fn []
|
||||
(export/export-blocks [(:block/uuid page)])))}})
|
||||
|
||||
(when (util/electron?)
|
||||
{:title (t (if public? :page/make-private :page/make-public))
|
||||
:options {:on-click
|
||||
(when (state/get-current-page)
|
||||
{:title (t :export-page)
|
||||
:options {:on-click #(state/set-modal!
|
||||
(fn []
|
||||
(page-handler/update-public-attribute!
|
||||
page-name
|
||||
(if public? false true))
|
||||
(state/close-modal!))}})
|
||||
(export/export-blocks [(:block/uuid page)])))}})
|
||||
|
||||
(when (util/electron?)
|
||||
{:title (t :page/version-history)
|
||||
:options {:on-click
|
||||
(fn []
|
||||
(shell/get-file-latest-git-log page 100))}})
|
||||
(when (util/electron?)
|
||||
{:title (t (if public? :page/make-private :page/make-public))
|
||||
:options {:on-click
|
||||
(fn []
|
||||
(page-handler/update-public-attribute!
|
||||
page-name
|
||||
(if public? false true))
|
||||
(state/close-modal!))}})
|
||||
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(for [[_ {:keys [key label] :as cmd} action pid] (state/get-plugins-commands-with-type :page-menu-item)]
|
||||
{:title label
|
||||
:options {:on-click #(commands/exec-plugin-simple-command!
|
||||
pid (assoc cmd :page (state/get-current-page)) action)}}))
|
||||
(when (util/electron?)
|
||||
{:title (t :page/version-history)
|
||||
:options {:on-click
|
||||
(fn []
|
||||
(shell/get-file-latest-git-log page 100))}})
|
||||
|
||||
(when developer-mode?
|
||||
{:title "(Dev) Show page data"
|
||||
:options {:on-click (fn []
|
||||
(let [page-data (with-out-str (pprint/pprint (db/pull (:db/id page))))]
|
||||
(println page-data)
|
||||
(notification/show!
|
||||
[:div
|
||||
[:pre.code page-data]
|
||||
[:br]
|
||||
(ui/button "Copy to clipboard"
|
||||
:on-click #(.writeText js/navigator.clipboard page-data))]
|
||||
:success
|
||||
false)))}})]
|
||||
(flatten)
|
||||
(remove nil?)))]
|
||||
(ui/dropdown-with-links
|
||||
(fn [{:keys [toggle-fn]}]
|
||||
[:a.cp__vertical-menu-button
|
||||
{:title "More options"
|
||||
:on-click toggle-fn}
|
||||
(svg/vertical-dots nil)])
|
||||
links
|
||||
{:modal-class (util/hiccup->class
|
||||
"origin-top-right.absolute.right-0.top-10.mt-2.rounded-md.shadow-lg.whitespace-nowrap.dropdown-overflow-auto.page-drop-options")
|
||||
:z-index 1})))
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(for [[_ {:keys [key label] :as cmd} action pid] (state/get-plugins-commands-with-type :page-menu-item)]
|
||||
{:title label
|
||||
:options {:on-click #(commands/exec-plugin-simple-command!
|
||||
pid (assoc cmd :page (state/get-current-page)) action)}}))
|
||||
|
||||
(when developer-mode?
|
||||
{:title "(Dev) Show page data"
|
||||
:options {:on-click (fn []
|
||||
(let [page-data (with-out-str (pprint/pprint (db/pull (:db/id page))))]
|
||||
(println page-data)
|
||||
(notification/show!
|
||||
[:div
|
||||
[:pre.code page-data]
|
||||
[:br]
|
||||
(ui/button "Copy to clipboard"
|
||||
:on-click #(.writeText js/navigator.clipboard page-data))]
|
||||
:success
|
||||
false)))}})]
|
||||
(flatten)
|
||||
(remove nil?))))))
|
||||
|
||||
;; A page is just a logical block
|
||||
(rum/defcs page < rum/reactive
|
||||
@@ -429,10 +437,7 @@
|
||||
[:div.flex.flex-row
|
||||
(when plugin-handler/lsp-enabled?
|
||||
(plugins/hook-ui-slot :page-head-actions-slotted nil)
|
||||
(plugins/hook-ui-items :pagebar))
|
||||
|
||||
(page-menu repo t page page-name page-original-name title
|
||||
journal? public? developer-mode?)])])
|
||||
(plugins/hook-ui-items :pagebar))])])
|
||||
[:div
|
||||
(when (and block? (not sidebar?))
|
||||
(let [config {:id "block-parent"
|
||||
@@ -750,6 +755,10 @@
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
[:div.flex-1
|
||||
[:h1.title (t :all-pages)]
|
||||
[:a.ml-1.opacity-70.hover:opacity-100 {:href (rfe/href :all-files)}
|
||||
[:span
|
||||
(ui/icon "files")
|
||||
[:span.ml-1 (t :all-files)]]]
|
||||
(when current-repo
|
||||
(let [pages (->> (page-handler/get-all-pages current-repo)
|
||||
(map (fn [page] (assoc page :block/backlinks (count (:block/_refs (db/entity (:db/id page)))))))
|
||||
|
||||
@@ -189,9 +189,7 @@
|
||||
(when (seq repos)
|
||||
(ui/dropdown-with-links
|
||||
(fn [{:keys [toggle-fn]}]
|
||||
[:a#repo-switch.block.pr-2.whitespace-nowrap {:on-click toggle-fn
|
||||
:class (when-not (util/mobile?)
|
||||
"fade-link")}
|
||||
[:a#repo-switch.block.pr-2.whitespace-nowrap {:on-click toggle-fn}
|
||||
[:span
|
||||
(let [repo-name (get-repo-name current-repo)
|
||||
repo-name (if (or (util/electron?)
|
||||
@@ -199,8 +197,8 @@
|
||||
(last
|
||||
(string/split repo-name #"/"))
|
||||
repo-name)]
|
||||
[:span#repo-name {:title repo-name} repo-name])
|
||||
[:span.dropdown-caret.ml-1 {:style {:border-top-color "#6b7280"}}]]])
|
||||
[:span#repo-name.font-medium {:title repo-name} repo-name])
|
||||
[:span.dropdown-caret.ml-2 {:style {:border-top-color "#6b7280"}}]]])
|
||||
(mapv
|
||||
(fn [{:keys [id url]}]
|
||||
{:title (get-repo-name url)
|
||||
@@ -219,7 +217,7 @@
|
||||
switch-repos)
|
||||
(cond->
|
||||
{:modal-class (util/hiccup->class
|
||||
"origin-top-right.absolute.left-0.mt-2.w-48.rounded-md.shadow-lg")
|
||||
"origin-top-right.absolute.left-0.mt-2.rounded-md.shadow-lg")
|
||||
:links-footer [:div
|
||||
(when (seq switch-repos) [:hr.my-4])
|
||||
[:a {:class "block px-4 py-2 text-sm transition ease-in-out duration-150 cursor menu-link"
|
||||
|
||||
@@ -22,8 +22,19 @@
|
||||
(rum/defc toggle
|
||||
[]
|
||||
(when-not (util/mobile?)
|
||||
[:a.button {:on-click state/toggle-sidebar-open?!}
|
||||
(svg/menu)]))
|
||||
(ui/tippy
|
||||
{:html [:div.text-sm.font-medium
|
||||
"Shortcut: "
|
||||
[:code (util/->platform-shortcut "t r")]]
|
||||
:delay 2000
|
||||
:hideDelay 1
|
||||
:position "left"
|
||||
:interactive true
|
||||
:arrow true}
|
||||
|
||||
[:a.button.fade-link.toggle
|
||||
{:on-click state/toggle-sidebar-open?!}
|
||||
(ui/icon "layout-sidebar-right" {:style {:fontSize "20px"}})])))
|
||||
|
||||
(rum/defc block-cp < rum/reactive
|
||||
[repo idx block]
|
||||
@@ -49,8 +60,7 @@
|
||||
[repo idx db-id block-type block-data t]
|
||||
(case block-type
|
||||
:contents
|
||||
[(or (state/get-favorites-name)
|
||||
(t :right-side-bar/favorites))
|
||||
[(t :right-side-bar/contents)
|
||||
(contents)]
|
||||
|
||||
:help
|
||||
@@ -215,8 +225,7 @@
|
||||
[:div.ml-4.text-sm
|
||||
[:a.cp__right-sidebar-settings-btn {:on-click (fn [e]
|
||||
(state/sidebar-add-block! repo "contents" :contents nil))}
|
||||
(or (state/get-favorites-name)
|
||||
(t :right-side-bar/favorites))]]
|
||||
(t :right-side-bar/contents)]]
|
||||
|
||||
[:div.ml-4.text-sm
|
||||
[:a.cp__right-sidebar-settings-btn {:on-click (fn []
|
||||
|
||||
@@ -14,3 +14,8 @@ html[data-theme=light] {
|
||||
.sidebar-item-list {
|
||||
padding-bottom: 150px;
|
||||
}
|
||||
|
||||
|
||||
html[data-theme='light'] a.toggle:hover {
|
||||
color: var(--ls-primary-text-color);
|
||||
}
|
||||
|
||||
@@ -284,11 +284,10 @@
|
||||
"Tip: " [:code (util/->platform-shortcut "Ctrl+Shift+p")] " to open the commands palette"]
|
||||
:interactive true
|
||||
:arrow true}
|
||||
[:a.inline-block
|
||||
{:style {:margin-top 1
|
||||
:margin-left 12}
|
||||
[:a.inline-block.fade-link
|
||||
{:style {:margin-left 12}
|
||||
:on-click #(state/toggle! :ui/command-palette-open?)}
|
||||
(svg/icon-cmd 20)])])]
|
||||
(ui/icon "command" {:style {:font-size 20}})])])]
|
||||
(let [recent-search (mapv (fn [q] {:type :search :data q}) (db/get-key-value :recent/search))
|
||||
pages (->> (db/get-key-value :recent/pages)
|
||||
(remove nil?)
|
||||
|
||||
@@ -584,18 +584,19 @@
|
||||
|
||||
[:aside.md:w-64
|
||||
[:ul
|
||||
(for [[label text icon] [[:general (t :settings-page/tab-general) (svg/adjustments 16)]
|
||||
[:editor (t :settings-page/tab-editor) (svg/icon-editor 16)]
|
||||
[:shortcuts (t :settings-page/tab-shortcuts) (svg/icon-cmd 18)]
|
||||
[:git (t :settings-page/tab-version-control) svg/git]
|
||||
[:advanced (t :settings-page/tab-advanced) (svg/icon-cli 16)]]]
|
||||
(for [[label text icon] [[:general (t :settings-page/tab-general) (ui/icon "adjustments" {:style {:font-size 20}})]
|
||||
[:editor (t :settings-page/tab-editor) (ui/icon "writing" {:style {:font-size 20}})]
|
||||
[:shortcuts (t :settings-page/tab-shortcuts) (ui/icon "command" {:style {:font-size 20}})]
|
||||
[:git (t :settings-page/tab-version-control) (ui/icon "history" {:style {:font-size 20}})]
|
||||
[:advanced (t :settings-page/tab-advanced) (ui/icon "bulb" {:style {:font-size 20}})]]]
|
||||
|
||||
[:li
|
||||
{:class (util/classnames [{:active (= label @*active)}])
|
||||
:on-click #(reset! *active label)}
|
||||
|
||||
[:a.flex.items-center
|
||||
[[:i.flex.items-center icon] [:strong text]]]])]]
|
||||
icon
|
||||
[:strong text]]])]]
|
||||
|
||||
[:article
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
font-size: 14px;
|
||||
font-weight: normal;
|
||||
padding-left: 5px;
|
||||
margin-top: 2px;
|
||||
opacity: .9;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,19 +9,25 @@
|
||||
[frontend.components.settings :as settings]
|
||||
[frontend.components.theme :as theme]
|
||||
[frontend.components.widgets :as widgets]
|
||||
[frontend.components.modals :refer [show-new-page-modal!]]
|
||||
[frontend.config :as config]
|
||||
[frontend.context.i18n :as i18n]
|
||||
[frontend.db :as db]
|
||||
[frontend.db.model :as db-model]
|
||||
[frontend.components.svg :as svg]
|
||||
[frontend.db-mixins :as db-mixins]
|
||||
[frontend.handler.editor :as editor-handler]
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.page :as page-handler]
|
||||
[frontend.mixins :as mixins]
|
||||
[frontend.modules.shortcut.data-helper :as shortcut-dh]
|
||||
[frontend.state :as state]
|
||||
[frontend.ui :as ui]
|
||||
[frontend.util :as util]
|
||||
[reitit.frontend.easy :as rfe]
|
||||
[goog.dom :as gdom]
|
||||
[rum.core :as rum]))
|
||||
[rum.core :as rum]
|
||||
[frontend.extensions.srs :as srs]))
|
||||
|
||||
(defn nav-item
|
||||
[title href svg-d active? close-modal-fn]
|
||||
@@ -37,34 +43,155 @@
|
||||
:stroke-linecap "round"}]]
|
||||
title])
|
||||
|
||||
(rum/defc nav-content-item
|
||||
[name {:keys [edit-fn class] :as opts} child]
|
||||
|
||||
[:div.nav-content-item.is-expand
|
||||
{:class class}
|
||||
[:div.hd.items-center.mb-2
|
||||
{:on-click (fn [^js/MouseEvent e]
|
||||
(let [^js target (.-target e)
|
||||
^js parent (.closest target ".nav-content-item")]
|
||||
(.toggle (.-classList parent) "is-expand")))}
|
||||
|
||||
[:a.font-medium.fade-link name]
|
||||
[:span
|
||||
[:a.more svg/arrow-down-v2]]]
|
||||
[:div.bd child]])
|
||||
|
||||
;; TODO: enhance
|
||||
(defn- pick-one-ast-page-ref
|
||||
[block]
|
||||
(when-let [title-ast (and block (:block/title block))]
|
||||
(when-let [link-ref (and (= (ffirst title-ast) "Link")
|
||||
(:url (second (first title-ast))))]
|
||||
(when (= "Page_ref" (first link-ref))
|
||||
(second link-ref)))))
|
||||
|
||||
(defn- delta-y
|
||||
[e]
|
||||
(let [rect (.. (.. e -target) getBoundingClientRect)]
|
||||
(- (.. e -pageY) (.. rect -top))))
|
||||
|
||||
(defn- move-up?
|
||||
[e]
|
||||
(let [delta (delta-y e)]
|
||||
(< delta 14)))
|
||||
|
||||
(rum/defcs favorite-item <
|
||||
(rum/local nil ::up?)
|
||||
(rum/local nil ::dragging-over)
|
||||
[state t name]
|
||||
(let [up? (get state ::up?)
|
||||
dragging-over (get state ::dragging-over)
|
||||
target (state/sub :favorites/dragging)]
|
||||
[:li.favorite-item
|
||||
{:key name
|
||||
:class (if (and target @dragging-over (not= target @dragging-over))
|
||||
"dragging-target"
|
||||
"")
|
||||
:draggable true
|
||||
:on-drag-start (fn [event]
|
||||
(state/set-state! :favorites/dragging name))
|
||||
:on-drag-over (fn [e]
|
||||
(util/stop e)
|
||||
(reset! dragging-over name)
|
||||
(when-not (= name (get @state/state :favorites/dragging))
|
||||
(reset! up? (move-up? e))))
|
||||
:on-drag-leave (fn [e]
|
||||
(reset! dragging-over nil))
|
||||
:on-drop (fn [e]
|
||||
(page-handler/reorder-favorites! {:to name
|
||||
:up? (move-up? e)})
|
||||
(reset! up? nil)
|
||||
(reset! dragging-over nil))}
|
||||
[:a {:href (rfe/href :page {:name name})}
|
||||
name]]))
|
||||
|
||||
(rum/defc favorites < rum/reactive
|
||||
[t]
|
||||
(nav-content-item
|
||||
[:a.flex.items-center.text-sm.font-medium.rounded-md
|
||||
(ui/icon "star mr-1" {:style {:font-size 18}})
|
||||
[:span.flex-1.uppercase {:style {:padding-top 2}}
|
||||
(t :left-side-bar/nav-favorites)]]
|
||||
|
||||
{:class "favorites"
|
||||
:edit-fn
|
||||
(fn [e]
|
||||
(rfe/push-state :page {:name "Favorites"})
|
||||
(util/stop e))}
|
||||
|
||||
(let [favorites (:favorites (state/sub-graph-config))]
|
||||
(when (seq favorites)
|
||||
[:ul.favorites
|
||||
(for [name favorites]
|
||||
(when-not (string/blank? name)
|
||||
(favorite-item t name)))]))))
|
||||
|
||||
(rum/defc recent-pages
|
||||
< rum/reactive db-mixins/query
|
||||
[t]
|
||||
|
||||
(nav-content-item
|
||||
[:a.flex.items-center.text-sm.font-medium.rounded-md
|
||||
(ui/icon "history mr-1" {:style {:font-size 18}})
|
||||
[:span.flex-1.uppercase {:style {:padding-top 2}}
|
||||
(t :left-side-bar/nav-recent-pages)]]
|
||||
|
||||
{:class "recent"}
|
||||
|
||||
(let [pages (state/sub :editor/recent-pages)]
|
||||
|
||||
[:ul
|
||||
(for [name pages]
|
||||
[:li {:key name}
|
||||
[:a {:href (rfe/href :page {:name name})} name]])])))
|
||||
|
||||
(rum/defc flashcards < rum/reactive
|
||||
[]
|
||||
(let [num (srs/get-srs-cards-total)]
|
||||
[:a.item.group.flex.items-center.px-2.py-2.text-sm.font-medium.rounded-md {:on-click #(state/pub-event! [:modal/show-cards])}
|
||||
(ui/icon "infinity mr-3" {:style {:font-size 20}})
|
||||
[:span.flex-1 "Flashcards"]
|
||||
(when (and num (not (zero? num)))
|
||||
[:span.ml-3.inline-block.py-0.5.px-3.text-xs.font-medium.rounded-full num])]))
|
||||
|
||||
(rum/defc sidebar-nav < rum/reactive
|
||||
[route-match close-modal-fn]
|
||||
(let [white? (= "white" (state/sub :ui/theme))
|
||||
active? (fn [route] (= route (get-in route-match [:data :name])))
|
||||
page-active? (fn [page]
|
||||
(= page (get-in route-match [:parameters :path :name])))
|
||||
right-sidebar? (state/sub :ui/sidebar-open?)
|
||||
left-sidebar? (state/sub :ui/left-sidebar-open?)]
|
||||
(when left-sidebar?
|
||||
[:nav.flex-1.left-sidebar-inner
|
||||
(nav-item "Journals" "#/"
|
||||
"M3 12l9-9 9 9M5 10v10a1 1 0 001 1h3a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1h3a1 1 0 001-1V10M9 21h6"
|
||||
(active? :home)
|
||||
close-modal-fn)
|
||||
(nav-item "All Pages" "#/all-pages"
|
||||
"M6 2h9a1 1 0 0 1 .7.3l4 4a1 1 0 0 1 .3.7v13a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V4c0-1.1.9-2 2-2zm9 2.41V7h2.59L15 4.41zM18 9h-3a2 2 0 0 1-2-2V4H6v16h12V9zm-2 7a1 1 0 0 1-1 1H9a1 1 0 0 1 0-2h6a1 1 0 0 1 1 1zm0-4a1 1 0 0 1-1 1H9a1 1 0 0 1 0-2h6a1 1 0 0 1 1 1zm-5-4a1 1 0 0 1-1 1H9a1 1 0 1 1 0-2h1a1 1 0 0 1 1 1z"
|
||||
(active? :all-pages)
|
||||
close-modal-fn)
|
||||
(when-not config/publishing?
|
||||
(nav-item "All Files" "#/all-files"
|
||||
"M3 7V17C3 18.1046 3.89543 19 5 19H19C20.1046 19 21 18.1046 21 17V9C21 7.89543 20.1046 7 19 7H13L11 5H5C3.89543 5 3 5.89543 3 7Z"
|
||||
(active? :all-files)
|
||||
close-modal-fn))
|
||||
(when-not right-sidebar?
|
||||
[:div.pl-4.pr-4 {:style {:height 1
|
||||
:background-color (if white? "#f0f8ff" "#073642")
|
||||
:margin 12}}])
|
||||
(right-sidebar/contents)])))
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
(let [active? (fn [route] (= route (get-in route-match [:data :name])))
|
||||
page-active? (fn [page]
|
||||
(= page (get-in route-match [:parameters :path :name])))
|
||||
left-sidebar? (state/sub :ui/left-sidebar-open?)
|
||||
white? (= "white" (state/sub :ui/theme))]
|
||||
(when left-sidebar?
|
||||
[:div.left-sidebar-inner.flex-1.flex.flex-col.min-h-0
|
||||
[:div.flex.flex-col.pt-5.pb-4.overflow-y-auto
|
||||
(when-not (util/mobile?)
|
||||
[:div.flex.items-center.flex-shrink-0.px-4.mb-5
|
||||
[:a {:href (rfe/href :home)}
|
||||
(svg/logo (not white?))]
|
||||
[:div.repos.ml-2
|
||||
(repo/repos-dropdown nil nil)]])
|
||||
[:nav.flex-1.px-2.space-y-1 {:aria-label "Sidebar"}
|
||||
[:a.item.group.flex.items-center.px-2.py-2.text-sm.font-medium.rounded-md {:href (rfe/href :all-journals)}
|
||||
(ui/icon "calendar mr-3" {:style {:font-size 20}})
|
||||
[:span.flex-1 "Journals"]]
|
||||
|
||||
(flashcards)
|
||||
|
||||
[:a.item.group.flex.items-center.px-2.py-2.text-sm.font-medium.rounded-md {:href (rfe/href :graph)}
|
||||
(ui/icon "hierarchy mr-3" {:style {:font-size 20}})
|
||||
[:span.flex-1 "Graph view"]]
|
||||
|
||||
[:a.item.group.flex.items-center.px-2.py-2.text-sm.font-medium.rounded-md {:href (rfe/href :all-pages)}
|
||||
(ui/icon "files mr-3" {:style {:font-size 20}})
|
||||
[:span.flex-1 "All pages"]]]
|
||||
|
||||
(favorites t)
|
||||
|
||||
(recent-pages t)]]))))
|
||||
|
||||
(rum/defc sidebar-mobile-sidebar < rum/reactive
|
||||
[{:keys [open? close-fn route-match]}]
|
||||
@@ -99,41 +226,47 @@
|
||||
{:did-mount (fn [state]
|
||||
(when-let [element (gdom/getElement "main-content")]
|
||||
(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))))}))
|
||||
state)}
|
||||
[{:keys [route-match global-graph-pages? logged? home? route-name indexeddb-support? white? db-restoring? main-content]}]
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
[:div#main-content.cp__sidebar-main-layout.flex-1.flex
|
||||
[:div#sidebar-nav-wrapper.flex-col.pt-4.hidden.sm:block
|
||||
{:style {:flex (if (state/get-left-sidebar-open?)
|
||||
"0 1 20%"
|
||||
"0 0 0px")}}
|
||||
(when (state/sub :ui/left-sidebar-open?)
|
||||
(sidebar-nav route-match nil))]
|
||||
[:div#main-content-container.w-full.flex.justify-center
|
||||
{:style {:margin-top (if global-graph-pages? 0 "2rem")}}
|
||||
[:div.cp__sidebar-main-content
|
||||
{:data-is-global-graph-pages global-graph-pages?
|
||||
:data-is-full-width (or global-graph-pages?
|
||||
(contains? #{:all-files :all-pages :my-publishing} route-name))}
|
||||
(cond
|
||||
(not indexeddb-support?)
|
||||
nil
|
||||
|
||||
db-restoring?
|
||||
[:div.mt-20
|
||||
[:div.ls-center
|
||||
(ui/loading (t :loading))]]
|
||||
(let [left-sidebar-open? (state/sub :ui/left-sidebar-open?)
|
||||
mobile? (util/mobile?)]
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
[:div#main-content.cp__sidebar-main-layout.flex-1.flex
|
||||
{:class (util/classnames [{:is-left-sidebar-open left-sidebar-open?}])}
|
||||
|
||||
:else
|
||||
[:div.pb-24 {:class (if global-graph-pages? "" (util/hiccup->class "max-w-7xl.mx-auto"))
|
||||
:style {:margin-bottom (if global-graph-pages? 0 120)}}
|
||||
main-content])]]]))
|
||||
;; desktop left sidebar layout
|
||||
(when-not mobile?
|
||||
[:div#sidebar-nav-wrapper.cp__sidebar-left-layout
|
||||
{:class (util/classnames [{:is-open left-sidebar-open?}])}
|
||||
|
||||
;; sidebar contents
|
||||
(sidebar-nav route-match nil)])
|
||||
|
||||
[:div#main-content-container.w-full.flex.justify-center
|
||||
[:div.cp__sidebar-main-content
|
||||
{:data-is-global-graph-pages global-graph-pages?
|
||||
:data-is-full-width (or global-graph-pages?
|
||||
(contains? #{:all-files :all-pages :my-publishing} route-name))}
|
||||
(cond
|
||||
(not indexeddb-support?)
|
||||
nil
|
||||
|
||||
db-restoring?
|
||||
[:div.mt-20
|
||||
[:div.ls-center
|
||||
(ui/loading (t :loading))]]
|
||||
|
||||
:else
|
||||
[:div.pb-24 {:class (if global-graph-pages? "" (util/hiccup->class "max-w-7xl.mx-auto"))
|
||||
:style {:margin-bottom (if global-graph-pages? 0 120)}}
|
||||
main-content])]]])))
|
||||
|
||||
(rum/defc footer
|
||||
[]
|
||||
@@ -155,22 +288,22 @@
|
||||
;; TODO: simplify logic
|
||||
|
||||
(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 (string/lower-case page)
|
||||
[db-id block-type] (if (= page "contents")
|
||||
["contents" :contents]
|
||||
[page :page])]
|
||||
(state/sidebar-add-block! current-repo db-id block-type nil)))
|
||||
(reset! sidebar-inited? 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 (string/lower-case page)
|
||||
[db-id block-type] (if (= page "contents")
|
||||
["contents" :contents]
|
||||
[page :page])]
|
||||
(state/sidebar-add-block! current-repo db-id block-type nil)))
|
||||
(reset! sidebar-inited? true))))
|
||||
state)}
|
||||
[]
|
||||
(let [today (state/sub :today)
|
||||
cloning? (state/sub :repo/cloning?)
|
||||
@@ -184,60 +317,60 @@
|
||||
preferred-format (state/sub [:me :preferred_format])
|
||||
logged? (:name me)]
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
[:div
|
||||
(cond
|
||||
(and default-home
|
||||
(= :home (state/get-current-route))
|
||||
(not (state/route-has-p?))
|
||||
(:page default-home))
|
||||
(route-handler/redirect! {:to :page
|
||||
:path-params {:name (:page default-home)}})
|
||||
[:div
|
||||
(cond
|
||||
(and default-home
|
||||
(= :home (state/get-current-route))
|
||||
(not (state/route-has-p?))
|
||||
(:page default-home))
|
||||
(route-handler/redirect! {:to :page
|
||||
:path-params {:name (:page default-home)}})
|
||||
|
||||
(and config/publishing?
|
||||
(not default-home)
|
||||
(empty? latest-journals))
|
||||
(route-handler/redirect! {:to :all-pages})
|
||||
(and config/publishing?
|
||||
(not default-home)
|
||||
(empty? latest-journals))
|
||||
(route-handler/redirect! {:to :all-pages})
|
||||
|
||||
importing-to-db?
|
||||
(ui/loading (t :parsing-files))
|
||||
importing-to-db?
|
||||
(ui/loading (t :parsing-files))
|
||||
|
||||
loading-files?
|
||||
(ui/loading (t :loading-files))
|
||||
loading-files?
|
||||
(ui/loading (t :loading-files))
|
||||
|
||||
(and (not logged?) (seq latest-journals))
|
||||
(journal/journals latest-journals)
|
||||
(and (not logged?) (seq latest-journals))
|
||||
(journal/journals latest-journals)
|
||||
|
||||
(and logged? (not preferred-format))
|
||||
(widgets/choose-preferred-format)
|
||||
(and logged? (not preferred-format))
|
||||
(widgets/choose-preferred-format)
|
||||
|
||||
;; TODO: delay this
|
||||
(and logged? (nil? (:email me)))
|
||||
(settings/set-email)
|
||||
(and logged? (nil? (:email me)))
|
||||
(settings/set-email)
|
||||
|
||||
cloning?
|
||||
(ui/loading (t :cloning))
|
||||
cloning?
|
||||
(ui/loading (t :cloning))
|
||||
|
||||
(seq latest-journals)
|
||||
(journal/journals latest-journals)
|
||||
(seq latest-journals)
|
||||
(journal/journals latest-journals)
|
||||
|
||||
(and logged? (empty? (:repos me)))
|
||||
(widgets/add-graph)
|
||||
(and logged? (empty? (:repos me)))
|
||||
(widgets/add-graph)
|
||||
|
||||
;; FIXME: why will this happen?
|
||||
:else
|
||||
[:div])])))
|
||||
:else
|
||||
[:div])])))
|
||||
|
||||
(rum/defc custom-context-menu < rum/reactive
|
||||
[]
|
||||
(when (state/sub :custom-context-menu/show?)
|
||||
(when-let [links (state/sub :custom-context-menu/links)]
|
||||
(ui/css-transition
|
||||
{:class-names "fade"
|
||||
:timeout {:enter 500
|
||||
:exit 300}}
|
||||
links
|
||||
{:class-names "fade"
|
||||
:timeout {:enter 500
|
||||
:exit 300}}
|
||||
links
|
||||
;; (custom-context-menu-content)
|
||||
))))
|
||||
))))
|
||||
|
||||
(rum/defc new-block-mode < rum/reactive
|
||||
[]
|
||||
@@ -261,11 +394,11 @@
|
||||
(when-not (state/sub :ui/sidebar-open?)
|
||||
;; TODO: remove with-context usage
|
||||
(rum/with-context [[t] i18n/*tongue-context*]
|
||||
[:div.cp__sidebar-help-btn
|
||||
{:title (t :help-shortcut-title)
|
||||
:on-click (fn []
|
||||
(state/sidebar-add-block! (state/get-current-repo) "help" :help nil))}
|
||||
"?"])))
|
||||
[:div.cp__sidebar-help-btn
|
||||
{:title (t :help-shortcut-title)
|
||||
:on-click (fn []
|
||||
(state/sidebar-add-block! (state/get-current-repo) "help" :help nil))}
|
||||
"?"])))
|
||||
|
||||
(rum/defc settings-modal < rum/reactive
|
||||
[]
|
||||
@@ -273,7 +406,7 @@
|
||||
(if settings-open?
|
||||
(do
|
||||
(state/set-modal!
|
||||
(fn [] [:div.settings-modal (settings/settings)]))
|
||||
(fn [] [:div.settings-modal (settings/settings)]))
|
||||
(util/lock-global-scroll settings-open?))
|
||||
(state/set-modal! nil))
|
||||
nil))
|
||||
@@ -307,6 +440,7 @@
|
||||
system-theme? (state/sub :ui/system-theme?)
|
||||
white? (= "white" (state/sub :ui/theme))
|
||||
sidebar-open? (state/sub :ui/sidebar-open?)
|
||||
left-sidebar-open? (state/sub :ui/left-sidebar-open?)
|
||||
route-name (get-in route-match [:data :name])
|
||||
global-graph-pages? (= :graph route-name)
|
||||
logged? (:name me)
|
||||
@@ -329,47 +463,50 @@
|
||||
(editor-handler/unhighlight-blocks!)
|
||||
(util/fix-open-external-with-shift! e))}
|
||||
|
||||
[:div.theme-inner
|
||||
(sidebar-mobile-sidebar
|
||||
{:open? open?
|
||||
:close-fn close-fn
|
||||
:route-match route-match})
|
||||
[:div.#app-container.h-screen.flex
|
||||
[:div.flex-1.h-full.flex.flex-col#left-container.relative
|
||||
{:class (if (state/sub :ui/sidebar-open?) "overflow-hidden" "w-full")}
|
||||
(header/header {:open-fn open-fn
|
||||
:white? white?
|
||||
:current-repo current-repo
|
||||
:logged? logged?
|
||||
:page? page?
|
||||
:route-match route-match
|
||||
:me me
|
||||
:default-home default-home
|
||||
:new-block-mode new-block-mode})
|
||||
[:div.theme-inner
|
||||
{:class (util/classnames [{:ls-left-sidebar-open left-sidebar-open?}])}
|
||||
|
||||
[:div#main-container.scrollbar-spacing
|
||||
(main {:route-match route-match
|
||||
:global-graph-pages? global-graph-pages?
|
||||
:logged? logged?
|
||||
:home? home?
|
||||
:route-name route-name
|
||||
:indexeddb-support? indexeddb-support?
|
||||
:white? white?
|
||||
:db-restoring? db-restoring?
|
||||
:main-content main-content})]
|
||||
(sidebar-mobile-sidebar
|
||||
{:open? open?
|
||||
:close-fn close-fn
|
||||
:route-match route-match})
|
||||
|
||||
(footer)]
|
||||
(right-sidebar/sidebar)
|
||||
[:div.#app-container.h-screen.flex
|
||||
[:div.flex-1.h-full.flex.flex-col#left-container.relative
|
||||
{:class (if (state/sub :ui/sidebar-open?) "overflow-hidden" "w-full")}
|
||||
(header/header {:open-fn open-fn
|
||||
:white? white?
|
||||
:current-repo current-repo
|
||||
:logged? logged?
|
||||
:page? page?
|
||||
:route-match route-match
|
||||
:me me
|
||||
:default-home default-home
|
||||
:new-block-mode new-block-mode})
|
||||
|
||||
[:div#app-single-container]]
|
||||
[:div#main-container.scrollbar-spacing
|
||||
(main {:route-match route-match
|
||||
:global-graph-pages? global-graph-pages?
|
||||
:logged? logged?
|
||||
:home? home?
|
||||
:route-name route-name
|
||||
:indexeddb-support? indexeddb-support?
|
||||
:white? white?
|
||||
:db-restoring? db-restoring?
|
||||
:main-content main-content})]
|
||||
|
||||
(ui/notification)
|
||||
(ui/modal)
|
||||
(settings-modal)
|
||||
(command-palette/command-palette-modal)
|
||||
(custom-context-menu)
|
||||
[:a#download.hidden]
|
||||
(when
|
||||
(and (not config/mobile?)
|
||||
(not config/publishing?))
|
||||
(help-button))]))))
|
||||
(footer)]
|
||||
(right-sidebar/sidebar)
|
||||
|
||||
[:div#app-single-container]]
|
||||
|
||||
(ui/notification)
|
||||
(ui/modal)
|
||||
(settings-modal)
|
||||
(command-palette/command-palette-modal)
|
||||
(custom-context-menu)
|
||||
[:a#download.hidden]
|
||||
(when
|
||||
(and (not config/mobile?)
|
||||
(not config/publishing?))
|
||||
(help-button))]))))
|
||||
|
||||
@@ -10,14 +10,41 @@
|
||||
}
|
||||
}
|
||||
|
||||
#app-container {
|
||||
flex: 0 0 100%;
|
||||
transition: all 200ms ease-in 0s;
|
||||
.is-electron.is-mac .cp__sidebar-left-layout {
|
||||
padding-top: 30px;
|
||||
transition: all 0.25s;
|
||||
-webkit-transition: all 0.25s;
|
||||
}
|
||||
|
||||
#main-content-container {
|
||||
.is-electron.is-mac.is-fullscreen .cp__sidebar-left-layout {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.ls-left-sidebar-open {
|
||||
.cp__header {
|
||||
padding-left: 0 !important;
|
||||
margin-left: var(--ls-left-sidebar-width);
|
||||
}
|
||||
}
|
||||
|
||||
#app-container {
|
||||
flex: 0 0 100%;
|
||||
transition: all 200ms ease-in 0s;
|
||||
}
|
||||
|
||||
#main-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#main-content {
|
||||
&.is-left-sidebar-open {
|
||||
padding-left: var(--ls-left-sidebar-width);
|
||||
}
|
||||
|
||||
&-container {
|
||||
font-size: 1em;
|
||||
padding: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
#left-sidebar {
|
||||
@@ -49,15 +76,130 @@
|
||||
color: var(--ls-active-primary-color);
|
||||
}
|
||||
|
||||
.left-sidebar-inner {
|
||||
padding-right: 15px;
|
||||
}
|
||||
|
||||
nav > a {
|
||||
color: var(--ls-icon-color);
|
||||
}
|
||||
}
|
||||
|
||||
.left-sidebar-inner {
|
||||
height: 100%;
|
||||
|
||||
.dropdown-wrapper {
|
||||
min-width: 180px;
|
||||
}
|
||||
|
||||
.nav-content-item {
|
||||
padding: 32px 0 0 0;
|
||||
|
||||
> .hd {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 5px;
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
padding: 0 18px;
|
||||
|
||||
> span {
|
||||
> a {
|
||||
opacity: .4;
|
||||
padding-left: 12px;
|
||||
display: none;
|
||||
transition: none;
|
||||
|
||||
&:hover {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
transform: translateY(-6px) translateX(2px) rotate(90deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
> span {
|
||||
> a {
|
||||
display: block;
|
||||
|
||||
&:last-child {
|
||||
display: block;
|
||||
opacity: .6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
> .bd {
|
||||
display: none;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
|
||||
a {
|
||||
width: 100%;
|
||||
padding: 2px 20px;
|
||||
display: flex;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
color: var(--ls-primary-text-color);
|
||||
|
||||
&:hover {
|
||||
background-color: var(--ls-quaternary-background-color);
|
||||
}
|
||||
|
||||
&:active {
|
||||
opacity: .7;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-expand {
|
||||
> .hd > span > a {
|
||||
&:last-child {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
}
|
||||
|
||||
> .bd {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.item:hover {
|
||||
background-color: var(--ls-quaternary-background-color);
|
||||
}
|
||||
}
|
||||
|
||||
.white-theme .left-sidebar-inner a{
|
||||
color: var(--ls-primary-text-color);
|
||||
}
|
||||
|
||||
.cp__sidebar-left-layout {
|
||||
@apply flex-col sm:block;
|
||||
|
||||
background-color: var(--ls-secondary-background-color);
|
||||
width: var(--ls-left-sidebar-width);
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 9;
|
||||
|
||||
transition: transform .25s;
|
||||
transform: translateX(-100%);
|
||||
|
||||
&.is-open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
}
|
||||
|
||||
.settings-modal {
|
||||
margin: -15px;
|
||||
}
|
||||
@@ -148,19 +290,19 @@
|
||||
}
|
||||
|
||||
&-topbar {
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: var(--ls-secondary-background-color, #d8e1e8);
|
||||
z-index: 999;
|
||||
user-select: none;
|
||||
-webkit-app-region: drag;
|
||||
position: sticky;
|
||||
position: -webkit-sticky;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: var(--ls-secondary-background-color, #d8e1e8);
|
||||
z-index: 999;
|
||||
user-select: none;
|
||||
-webkit-app-region: drag;
|
||||
|
||||
a, svg {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
a, svg {
|
||||
-webkit-app-region: no-drag;
|
||||
}
|
||||
}
|
||||
|
||||
.page {
|
||||
@@ -219,3 +361,7 @@
|
||||
overflow-y: overlay;
|
||||
}
|
||||
}
|
||||
|
||||
.favorites li.dragging-target {
|
||||
border-left: 5px solid green;
|
||||
}
|
||||
|
||||
@@ -399,7 +399,7 @@
|
||||
(rum/defc logo
|
||||
[dark?]
|
||||
[:svg
|
||||
{:fill (if dark? "currentColor" "#002B36"), :view-box "0 0 21 21", :height "21", :width "21"}
|
||||
{:fill "currentColor", :view-box "0 0 21 21", :height "21", :width "21"}
|
||||
[:ellipse
|
||||
{:transform
|
||||
"matrix(0.987073 0.160274 -0.239143 0.970984 11.7346 2.59206)"
|
||||
|
||||
@@ -1357,3 +1357,8 @@
|
||||
(filter :block/file)
|
||||
(sort-by :block/updated-at >)
|
||||
(take 200)))
|
||||
|
||||
(defn refresh-recent-pages
|
||||
[]
|
||||
(let [results (db-utils/get-key-value :recent/pages)]
|
||||
(state/set-state! :editor/recent-pages results)))
|
||||
|
||||
@@ -101,6 +101,10 @@
|
||||
:right-side-bar/favorites "Favorites"
|
||||
:right-side-bar/page-graph "Page graph"
|
||||
:right-side-bar/block-ref "Block reference"
|
||||
:left-side-bar/new-page "New page"
|
||||
:left-side-bar/nav-favorites "Favorites"
|
||||
:left-side-bar/nav-shortcuts "Shortcuts"
|
||||
:left-side-bar/nav-recent-pages "Recent"
|
||||
:git/set-access-token "Set GitHub personal access token"
|
||||
:git/token-is-encrypted "The token will be encrypted and stored in the browser local storage"
|
||||
:git/token-server "The server will never store it"
|
||||
@@ -136,7 +140,7 @@
|
||||
:project/setup "Setup a public project on Logseq"
|
||||
:project/location "All published pages will be located under"
|
||||
:project/sync-settings "Sync project settings"
|
||||
:page/presentation-mode "Presentation mode (powered by Reveal.js)"
|
||||
:page/presentation-mode "Presentation"
|
||||
:page/edit-properties-placeholder "Properties"
|
||||
:page/delete-success "Page {1} was deleted successfully!"
|
||||
:page/delete-confirmation "Are you sure you want to delete this page and its file?"
|
||||
@@ -156,6 +160,7 @@
|
||||
:page/publish-as-slide "Publish this page as a slide on Logseq"
|
||||
:page/unpublish "Un-publish this page on Logseq"
|
||||
:page/add-to-favorites "Add to Favorites"
|
||||
:page/unfavorite "Unfavorite page"
|
||||
:page/show-journals "Show journals"
|
||||
:page/show-name "Show page name"
|
||||
:page/hide-name "Hide page name"
|
||||
@@ -266,6 +271,8 @@
|
||||
:cards-view "View cards"
|
||||
:publishing "Publishing"
|
||||
:export "Export"
|
||||
:export-graph "Export graph"
|
||||
:export-page "Export page"
|
||||
:export-markdown "Export as standard Markdown (no block properties)"
|
||||
:export-opml "Export as OPML"
|
||||
:export-public-pages "Export public pages"
|
||||
@@ -415,7 +422,7 @@
|
||||
:project/setup "Einrichten eines öffentlichen Projekts auf Logseq"
|
||||
:project/location "Alle veröffentlichten Seiten befinden sich unter"
|
||||
:project/sync-settings "Projekteinstellungen synchronisieren"
|
||||
:page/presentation-mode "Präsentationsmodus (angetrieben von Reveal.js)"
|
||||
:page/presentation-mode "Präsentationsmodus"
|
||||
:page/edit-properties-placeholder "Klicken Sie hier, um die Eigenschaften dieser Seite zu bearbeiten"
|
||||
:page/delete-success "Die Seite {1} wurde erfolgreich gelöscht!"
|
||||
:page/delete-confirmation "Diese Seite und die zugehörige Datei löschen?"
|
||||
@@ -616,7 +623,7 @@
|
||||
:project/setup "Paramétrer un projet public sur Logseq"
|
||||
:project/location "Toutes les pages publiées seront joignables sous"
|
||||
:project/sync-settings "Synchroniser les paramètres du projet"
|
||||
:page/presentation-mode "Mode présentation (avec Reveal.js)"
|
||||
:page/presentation-mode "Mode présentation"
|
||||
:page/delete-success "Page {1} supprimée !"
|
||||
:page/delete-confirmation "Etes-vous sûr de vouloir supprimer la page ?"
|
||||
:page/rename-to "Renommer \"{1}\" en:"
|
||||
@@ -820,6 +827,10 @@
|
||||
:right-side-bar/favorites "收藏"
|
||||
:right-side-bar/page-graph "页面图谱:"
|
||||
:right-side-bar/block-ref "块引用"
|
||||
:left-side-bar/new-page "新页面"
|
||||
:left-side-bar/nav-favorites "收藏页面"
|
||||
:left-side-bar/nav-shortcuts "快捷导航"
|
||||
:left-side-bar/nav-recent-pages "最近使用"
|
||||
:git/set-access-token "设定 GitHub 个人访问令牌"
|
||||
:git/token-is-encrypted "令牌将被加密并存储在浏览器本地存储"
|
||||
:git/token-server "服务器将永远不会存储它"
|
||||
@@ -856,7 +867,7 @@
|
||||
:project/location "一切发布的页面将会被放到 "
|
||||
:project/sync-settings "同步项目设置"
|
||||
:page/edit-properties-placeholder "点击这里编辑当前页面的属性 (标签,别名等)"
|
||||
:page/presentation-mode "演讲模式 (由 Reveal.js 驱动)"
|
||||
:page/presentation-mode "打开幻灯片"
|
||||
:page/delete-success "页面 {1} 删除成功!"
|
||||
:page/delete-confirmation "您确定要删除此页面和文件吗?"
|
||||
:page/rename-to "重命名 \"{1}\" 至:"
|
||||
@@ -875,6 +886,7 @@
|
||||
:page/publish-as-slide "将本页作为幻灯片发布至 Logseq"
|
||||
:page/unpublish "取消将本页发布至 Logseq"
|
||||
:page/add-to-favorites "添加收藏"
|
||||
:page/unfavorite "取消收藏"
|
||||
:page/show-journals "显示日志"
|
||||
:page/show-name "显示页面名"
|
||||
:page/hide-name "隐藏页面名"
|
||||
@@ -957,6 +969,8 @@
|
||||
:new-graph "添加图谱"
|
||||
:re-index "重新建立索引"
|
||||
:sync-from-local-files "刷新(读取本地最新文件)"
|
||||
:export-graph "导出图谱"
|
||||
:export-page "导出当前页面"
|
||||
:export-json "以 JSON 格式导出"
|
||||
:export-roam-json "以 Roam JSON 格式导出"
|
||||
:export-markdown "以 Markdown 格式导出"
|
||||
@@ -1161,7 +1175,7 @@
|
||||
:project/setup "在 Logseq 上發布新的項目"
|
||||
:project/location "一切發布的頁面將會被放到 "
|
||||
:project/sync-settings "同步項目設置"
|
||||
:page/presentation-mode "演講模式 (由 Reveal.js 驅動)"
|
||||
:page/presentation-mode "演講模式"
|
||||
:page/delete-success "頁面 {1} 刪除成功!"
|
||||
:page/delete-confirmation "您確定要刪除此頁面嗎?"
|
||||
:page/rename-to "重命名 \"{1}\" 至:"
|
||||
@@ -1397,7 +1411,7 @@
|
||||
:project/setup "Stel 'n publieke projek op by Logseq"
|
||||
:project/location "Alle gepubliseerde blaai sal voorkom onder"
|
||||
:project/sync-settings "Sinkroniseer projek instellings"
|
||||
:page/presentation-mode "Aanbiedings modus (gedryf deur Reveal.js)"
|
||||
:page/presentation-mode "Aanbiedings modus"
|
||||
:page/delete-success "Bladsy {1} is suksesvol uitgevee!"
|
||||
:page/delete-confirmation "Is jy seker jy wil die bladsy uitvee?"
|
||||
:page/rename-to "Hernoem \"{1}\" na:"
|
||||
@@ -1618,7 +1632,7 @@
|
||||
:project/setup "Configurar un proyecto público en Logseq"
|
||||
:project/location "Todas las páginas publicadas se encontrarán en"
|
||||
:project/sync-settings "Opciones de sincronización del proyecto"
|
||||
:page/presentation-mode "Modo presentación (usando Reveal.js)"
|
||||
:page/presentation-mode "Modo presentación"
|
||||
:page/edit-properties-placeholder "Propiedades"
|
||||
:page/delete-success "¡Página {1} eliminada con éxito!"
|
||||
:page/delete-confirmation "¿Está seguro que desea eliminar esta página y su archivo?"
|
||||
@@ -1905,7 +1919,7 @@
|
||||
:project/setup "Sett opp et offentlig prosjekt på Logseq"
|
||||
:project/location "Alle publiserte sider vil bli lokalisert under"
|
||||
:project/sync-settings "Synkroniser prosjektinnstillinger"
|
||||
:page/presentation-mode "Presentasjonsmodus (Drevet av Reveal.js)"
|
||||
:page/presentation-mode "Presentasjonsmodus"
|
||||
:page/edit-properties-placeholder "Egenskaper"
|
||||
:page/delete-success "Side {1} ble vellykket slettet!"
|
||||
:page/delete-confirmation "Er du sikker på at du vil slette denne siden og filen dens?"
|
||||
@@ -2205,7 +2219,7 @@
|
||||
:project/setup "Configurar um projeto público em Logseq"
|
||||
:project/location "Todas as páginas publicadas ficarão localizadas em"
|
||||
:project/sync-settings "Definições de sincronização do projeto"
|
||||
:page/presentation-mode "Modo de apresentação (usando Reveal.js)"
|
||||
:page/presentation-mode "Modo de apresentação"
|
||||
:page/edit-properties-placeholder "Propriedades"
|
||||
:page/delete-success "Página {1} apagada com sucesso!"
|
||||
:page/delete-confirmation "Tem a certeza de que quer apagar esta página e o respetivo ficheiro?"
|
||||
|
||||
@@ -1084,8 +1084,8 @@
|
||||
(if (or (= status-doc :loading)
|
||||
(nil? initial-hls))
|
||||
|
||||
[:div.flex.justify-center.items-center.h-screen.text-gray-500.text-md
|
||||
"Downloading PDF file " url]
|
||||
[:div.flex.justify-center.items-center.h-screen.text-gray-500.text-lg
|
||||
svg/loading]
|
||||
|
||||
[(rum/with-key (pdf-viewer
|
||||
url initial-hls
|
||||
|
||||
@@ -678,6 +678,14 @@ body.is-pdf-active {
|
||||
#head {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
#main-content.is-left-sidebar-open {
|
||||
padding-left: unset;
|
||||
}
|
||||
|
||||
.ls-left-sidebar-open .cp__header {
|
||||
margin-left: unset;
|
||||
}
|
||||
}
|
||||
|
||||
/* overrides for pdf_viewer.css from PDF.JS web viewer */
|
||||
|
||||
@@ -515,6 +515,16 @@
|
||||
|
||||
(component-macro/register cloze-macro-name cloze-macro-show)
|
||||
|
||||
(defn get-srs-cards-total
|
||||
[]
|
||||
(let [repo (state/get-current-repo)
|
||||
query-string ""
|
||||
*query-result (query repo query-string)]
|
||||
(when *query-result
|
||||
(let [blocks (rum/react *query-result)
|
||||
{:keys [result]} (query-scheduled repo blocks (tl/local-now))]
|
||||
(count result)))))
|
||||
|
||||
;;; register cards macro
|
||||
(rum/defcs cards
|
||||
< rum/reactive
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
[frontend.components.diff :as diff]
|
||||
[frontend.components.plugins :as plugin]
|
||||
[frontend.components.encryption :as encryption]
|
||||
[frontend.components.modals :as modals]
|
||||
[frontend.components.git :as git-component]
|
||||
[frontend.components.shell :as shell]
|
||||
[frontend.components.search :as search]
|
||||
@@ -53,6 +54,9 @@
|
||||
(defmethod handle :repo/install-error [[_ repo-url title]]
|
||||
(show-install-error! repo-url title))
|
||||
|
||||
(defmethod handle :modal/show-new-page-modal []
|
||||
(modals/show-new-page-modal!))
|
||||
|
||||
(defmethod handle :modal/encryption-setup-dialog [[_ repo-url close-fn]]
|
||||
(state/set-modal!
|
||||
(encryption/encryption-setup-dialog repo-url close-fn)))
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
[frontend.handler.route :as route-handler]
|
||||
[frontend.handler.ui :as ui-handler]
|
||||
[frontend.handler.web.nfs :as web-nfs]
|
||||
[frontend.handler.config :as config-handler]
|
||||
[frontend.modules.outliner.core :as outliner-core]
|
||||
[frontend.modules.outliner.file :as outliner-file]
|
||||
[frontend.modules.outliner.tree :as outliner-tree]
|
||||
@@ -204,32 +205,6 @@
|
||||
(p/catch (fn [err]
|
||||
(js/console.error "error: " err)))))))
|
||||
|
||||
(defn delete!
|
||||
[page-name ok-handler]
|
||||
(when page-name
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(let [page-name (string/lower-case page-name)
|
||||
blocks (db/get-page-blocks page-name)
|
||||
tx-data (mapv
|
||||
(fn [block]
|
||||
[:db.fn/retractEntity [:block/uuid (:block/uuid block)]])
|
||||
blocks)]
|
||||
(db/transact! tx-data)
|
||||
|
||||
(delete-file! repo page-name)
|
||||
|
||||
;; if other page alias this pagename,
|
||||
;; then just remove some attrs of this entity instead of retractEntity
|
||||
(if (model/get-alias-source-page (state/get-current-repo) page-name)
|
||||
(when-let [id (:db/id (db/entity [:block/name page-name]))]
|
||||
(let [txs (mapv (fn [attribute]
|
||||
[:db/retract id attribute])
|
||||
db-schema/retract-page-attributes)]
|
||||
(db/transact! txs)))
|
||||
(db/transact! [[:db.fn/retractEntity [:block/name page-name]]]))
|
||||
|
||||
(ok-handler)))))
|
||||
|
||||
(defn- compute-new-file-path
|
||||
[old-path new-page-name]
|
||||
(let [result (string/split old-path "/")
|
||||
@@ -344,6 +319,53 @@
|
||||
(p/let [_ (rename-file-aux! repo old-path new-path)]
|
||||
(println "Renamed " old-path " to " new-path)))))))
|
||||
|
||||
(defn favorite-page!
|
||||
[page-name]
|
||||
(when-not (string/blank? page-name)
|
||||
(let [favorites (->
|
||||
(cons
|
||||
page-name
|
||||
(or (:favorites (state/get-config)) []))
|
||||
(distinct)
|
||||
(vec))]
|
||||
(config-handler/set-config! :favorites favorites))))
|
||||
|
||||
(defn unfavorite-page!
|
||||
[page-name]
|
||||
(when-not (string/blank? page-name)
|
||||
(let [favorites (->> (:favorites (state/get-config))
|
||||
(remove #(= (string/lower-case %) (string/lower-case page-name)))
|
||||
(vec))]
|
||||
(config-handler/set-config! :favorites favorites))))
|
||||
|
||||
(defn delete!
|
||||
[page-name ok-handler]
|
||||
(when page-name
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(let [page-name (string/lower-case page-name)
|
||||
blocks (db/get-page-blocks page-name)
|
||||
tx-data (mapv
|
||||
(fn [block]
|
||||
[:db.fn/retractEntity [:block/uuid (:block/uuid block)]])
|
||||
blocks)]
|
||||
(db/transact! tx-data)
|
||||
|
||||
(delete-file! repo page-name)
|
||||
|
||||
;; if other page alias this pagename,
|
||||
;; then just remove some attrs of this entity instead of retractEntity
|
||||
(if (model/get-alias-source-page (state/get-current-repo) page-name)
|
||||
(when-let [id (:db/id (db/entity [:block/name page-name]))]
|
||||
(let [txs (mapv (fn [attribute]
|
||||
[:db/retract id attribute])
|
||||
db-schema/retract-page-attributes)]
|
||||
(db/transact! txs)))
|
||||
(db/transact! [[:db.fn/retractEntity [:block/name page-name]]]))
|
||||
|
||||
(unfavorite-page! page-name)
|
||||
|
||||
(ok-handler)))))
|
||||
|
||||
(defn- rename-page-aux [old-name new-name]
|
||||
(when-let [repo (state/get-current-repo)]
|
||||
(when-let [page (db/pull [:block/name (string/lower-case old-name)])]
|
||||
@@ -417,6 +439,9 @@
|
||||
|
||||
(repo-handler/push-if-auto-enabled! repo)
|
||||
|
||||
(p/let [_ (unfavorite-page! old-name)]
|
||||
(favorite-page! new-name))
|
||||
|
||||
(ui-handler/re-render-root!))))
|
||||
|
||||
(defn rename!
|
||||
@@ -438,14 +463,27 @@
|
||||
:else
|
||||
(rename-page-aux old-name new-name)))))
|
||||
|
||||
(defn handle-add-page-to-contents!
|
||||
[page-name]
|
||||
(let [content (str "[[" page-name "]]")]
|
||||
(editor-handler/api-insert-new-block!
|
||||
content
|
||||
{:page "Contents"})
|
||||
(notification/show! (util/format "Added to %s!" (state/get-favorites-name)) :success)
|
||||
(editor-handler/clear-when-saved!)))
|
||||
(defn- split-col-by-element
|
||||
[col element]
|
||||
(let [col (vec col)
|
||||
idx (.indexOf col element)]
|
||||
[(subvec col 0 (inc idx))
|
||||
(subvec col (inc idx))]))
|
||||
|
||||
(defn reorder-favorites!
|
||||
[{:keys [to up?]}]
|
||||
(let [favorites (:favorites (state/get-config))
|
||||
from (get @state/state :favorites/dragging)]
|
||||
(when (and from to (not= from to))
|
||||
(let [[prev next] (split-col-by-element favorites to)
|
||||
[prev next] (mapv #(remove (fn [e] (= from e)) %) [prev next])
|
||||
favorites (->>
|
||||
(if up?
|
||||
(concat (drop-last prev) [from (last prev)] next)
|
||||
(concat prev [from] next))
|
||||
(remove nil?)
|
||||
(distinct))]
|
||||
(config-handler/set-config! :favorites favorites)))))
|
||||
|
||||
(defn has-more-journals?
|
||||
[]
|
||||
|
||||
@@ -66,6 +66,24 @@
|
||||
(when-not file-exists?
|
||||
(file-handler/reset-file! repo-url path default-content)))))
|
||||
|
||||
(defn create-favorites-file
|
||||
[repo-url]
|
||||
(spec/validate :repos/url repo-url)
|
||||
(let [repo-dir (config/get-repo-dir repo-url)
|
||||
format (state/get-preferred-format)
|
||||
path (str (state/get-pages-directory)
|
||||
"/favorites."
|
||||
(config/get-file-extension format))
|
||||
file-path (str "/" path)
|
||||
default-content (case (name format)
|
||||
"org" (rc/inline "favorites.org")
|
||||
"markdown" (rc/inline "favorites.md")
|
||||
"")]
|
||||
(p/let [_ (fs/mkdir-if-not-exists (str repo-dir "/" (state/get-pages-directory)))
|
||||
file-exists? (fs/create-if-not-exists repo-url repo-dir file-path default-content)]
|
||||
(when-not file-exists?
|
||||
(file-handler/reset-file! repo-url path default-content)))))
|
||||
|
||||
(defn create-custom-theme
|
||||
[repo-url]
|
||||
(spec/validate :repos/url repo-url)
|
||||
@@ -145,6 +163,7 @@
|
||||
;; TODO: move to frontend.handler.file
|
||||
(create-config-file-if-not-exists repo-url)
|
||||
(create-contents-file repo-url)
|
||||
(create-favorites-file repo-url)
|
||||
(create-custom-theme repo-url)
|
||||
(state/pub-event! [:page/create-today-journal repo-url])))))
|
||||
|
||||
@@ -554,6 +573,7 @@
|
||||
(create-today-journal-if-not-exists repo {:content tutorial})))
|
||||
(create-config-file-if-not-exists repo)
|
||||
(create-contents-file repo)
|
||||
(create-favorites-file repo)
|
||||
(create-custom-theme repo)
|
||||
(state/set-db-restoring! false)
|
||||
(ui-handler/re-render-root!)))
|
||||
|
||||
@@ -15,6 +15,11 @@
|
||||
(when-let [elem (gdom/getElement "close-left-bar")]
|
||||
(.click elem)))
|
||||
|
||||
(defn toggle-left-sidebar!
|
||||
[]
|
||||
(state/set-left-sidebar-open!
|
||||
(not (@state/state :ui/left-sidebar-open?))))
|
||||
|
||||
(defn hide-right-sidebar
|
||||
[]
|
||||
(state/hide-right-sidebar!))
|
||||
|
||||
@@ -43,11 +43,11 @@
|
||||
^{:before m/prevent-default-behavior}
|
||||
{:pdf/previous-page
|
||||
{:desc "Previous page of current pdf doc"
|
||||
:binding "ctrl+p"
|
||||
:binding "alt+p"
|
||||
:fn pdf-utils/prev-page}
|
||||
:pdf/next-page
|
||||
{:desc "Next page of current pdf doc"
|
||||
:binding "ctrl+n"
|
||||
:binding "alt+n"
|
||||
:fn pdf-utils/next-page}}
|
||||
|
||||
:shortcut.handler/auto-complete
|
||||
@@ -142,7 +142,7 @@
|
||||
:fn editor-handler/strike-through-format!}
|
||||
:editor/move-block-up
|
||||
{:desc "Move block up"
|
||||
:binding (if mac? "mod+shift+up" "alt+shift+up")
|
||||
:binding (if mac? "mod+shift+up" "alt+shift+up")
|
||||
:fn (editor-handler/move-up-down true)}
|
||||
:editor/move-block-down
|
||||
{:desc "Move block down"
|
||||
@@ -185,13 +185,13 @@
|
||||
:binding (if mac? false "alt+w")
|
||||
:fn editor-handler/backward-kill-word}
|
||||
:editor/replace-block-reference-at-point
|
||||
{:desc "Replace block reference with its content at point"
|
||||
{:desc "Replace block reference with its content at point"
|
||||
:binding "mod+shift+r"
|
||||
:fn editor-handler/replace-block-reference-with-content-at-point}
|
||||
:fn editor-handler/replace-block-reference-with-content-at-point}
|
||||
:editor/paste-text-in-one-block-at-point
|
||||
{:desc "Paste text into one block at point"
|
||||
{:desc "Paste text into one block at point"
|
||||
:binding "mod+shift+v"
|
||||
:fn editor-handler/paste-text-in-one-block-at-point}
|
||||
:fn editor-handler/paste-text-in-one-block-at-point}
|
||||
:editor/insert-youtube-timestamp
|
||||
{:desc "Insert youtube timestamp"
|
||||
:binding "mod+shift+y"
|
||||
@@ -264,7 +264,11 @@
|
||||
:editor/redo
|
||||
{:desc "Redo"
|
||||
:binding ["shift+mod+z" "mod+y"]
|
||||
:fn history/redo!}}
|
||||
:fn history/redo!}
|
||||
:editor/new-page
|
||||
{:desc "New page"
|
||||
:binding "mod+n"
|
||||
:fn #(state/pub-event! [:modal/show-new-page-modal])}}
|
||||
|
||||
:shortcut.handler/global-prevent-default
|
||||
^{:before m/prevent-default-behavior}
|
||||
@@ -327,12 +331,12 @@
|
||||
;; always overrides the copy due to "mod+c mod+s"
|
||||
{:misc/copy
|
||||
{:binding "mod+c"
|
||||
:fn (fn [] (js/document.execCommand "copy"))}
|
||||
:fn (fn [] (js/document.execCommand "copy"))}
|
||||
|
||||
:command-palette/toggle
|
||||
{:desc "Toggle command palette"
|
||||
{:desc "Toggle command palette"
|
||||
:binding "mod+shift+p"
|
||||
:fn (fn [] (state/toggle! :ui/command-palette-open?))}}
|
||||
:fn (fn [] (state/toggle! :ui/command-palette-open?))}}
|
||||
|
||||
:shortcut.handler/global-non-editing-only
|
||||
^{:before m/enable-when-not-editing-mode!}
|
||||
@@ -360,6 +364,10 @@
|
||||
{:desc "Toggle right sidebar"
|
||||
:binding "t r"
|
||||
:fn ui-handler/toggle-right-sidebar!}
|
||||
:ui/toggle-left-sidebar
|
||||
{:desc "Toggle left sidebar"
|
||||
:binding "t l"
|
||||
:fn ui-handler/toggle-left-sidebar!}
|
||||
:ui/toggle-help
|
||||
{:desc "Toggle help"
|
||||
:binding "shift+/"
|
||||
@@ -378,11 +386,11 @@
|
||||
:fn ui-handler/toggle-wide-mode!}
|
||||
:ui/select-theme-color
|
||||
{:desc "Select available theme colors"
|
||||
:binding "t i"
|
||||
:binding "t i"
|
||||
:fn plugin-handler/show-themes-modal!}
|
||||
:ui/goto-plugins
|
||||
{:desc "Go to plugins dashboard"
|
||||
:binding "t p"
|
||||
:binding "t p"
|
||||
:fn plugin-handler/goto-plugins-dashboard!}
|
||||
:editor/toggle-open-blocks
|
||||
{:desc "Toggle open blocks (collapse or expand all blocks)"
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
:ui/fullscreen? false
|
||||
:ui/settings-open? false
|
||||
:ui/sidebar-open? false
|
||||
:ui/left-sidebar-open? false
|
||||
:ui/left-sidebar-open? (boolean (storage/get "ls-left-sidebar-open?"))
|
||||
:ui/theme (or (storage/get :ui/theme) "dark")
|
||||
:ui/system-theme? ((fnil identity (or util/mac? util/win32? false)) (storage/get :ui/system-theme?))
|
||||
:ui/wide-mode? false
|
||||
@@ -103,6 +103,8 @@
|
||||
:editor/document-mode? document-mode?
|
||||
:editor/args nil
|
||||
:editor/on-paste? false
|
||||
:editor/recent-pages nil
|
||||
|
||||
:db/last-transact-time {}
|
||||
:db/last-persist-transact-ids {}
|
||||
;; whether database is persisted
|
||||
@@ -171,7 +173,9 @@
|
||||
|
||||
:debug/write-acks {}
|
||||
|
||||
:encryption/graph-parsing? false})))
|
||||
:encryption/graph-parsing? false
|
||||
|
||||
:favorites/dragging nil})))
|
||||
|
||||
|
||||
(defn sub
|
||||
@@ -1117,6 +1121,7 @@
|
||||
|
||||
(defn set-left-sidebar-open!
|
||||
[value]
|
||||
(storage/set "ls-left-sidebar-open?" (boolean value))
|
||||
(set-state! :ui/left-sidebar-open? value))
|
||||
|
||||
(defn set-developer-mode!
|
||||
|
||||
@@ -99,13 +99,15 @@
|
||||
(on-click-fn e))
|
||||
(close-fn)))
|
||||
child (if hr
|
||||
[:hr.my-1]
|
||||
nil
|
||||
[:div
|
||||
{:style {:display "flex" :flex-direction "row"}}
|
||||
[:div {:style {:margin-right "8px"}} title]])]
|
||||
(rum/with-key
|
||||
(menu-link new-options child)
|
||||
title)))
|
||||
(if hr
|
||||
[:hr.my-1]
|
||||
(rum/with-key
|
||||
(menu-link new-options child)
|
||||
title))))
|
||||
(when links-footer links-footer)])
|
||||
opts))
|
||||
|
||||
@@ -710,6 +712,7 @@
|
||||
:options {:theme (when (= (state/sub :ui/theme) "dark") "dark")}
|
||||
:on-tweet-load-success #(reset! *loading? false)})]]))
|
||||
|
||||
(rum/defc icon
|
||||
[class]
|
||||
[:i {:class (str "ti ti-" class)}])
|
||||
(defn icon
|
||||
([class] (icon class nil))
|
||||
([class opts]
|
||||
[:i (merge {:class (str "ti ti-" class)} opts)]))
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
[frontend.db.query-dsl :as query-dsl]
|
||||
[frontend.db.utils :as db-utils]
|
||||
[frontend.fs :as fs]
|
||||
[frontend.handler :as handler]
|
||||
[frontend.handler.dnd :as editor-dnd-handler]
|
||||
[frontend.handler.editor :as editor-handler]
|
||||
[frontend.handler.export :as export-handler]
|
||||
@@ -22,6 +23,7 @@
|
||||
[frontend.handler.plugin :as plugin-handler]
|
||||
[frontend.modules.outliner.core :as outliner]
|
||||
[frontend.modules.outliner.tree :as outliner-tree]
|
||||
[electron.listener :as el]
|
||||
[frontend.state :as state]
|
||||
[frontend.util :as util]
|
||||
[frontend.util.cursor :as cursor]
|
||||
@@ -520,3 +522,8 @@
|
||||
([content status] (let [hiccup? (and (string? content) (string/starts-with? (string/triml content) "[:"))
|
||||
content (if hiccup? (parse-hiccup-ui content) content)]
|
||||
(notification/show! content (keyword status)))))
|
||||
|
||||
(defn ^:export force_save_graph
|
||||
[]
|
||||
(p/let [_ (el/persist-dbs!)
|
||||
_ (reset! handler/triggered? true)]))
|
||||
@@ -40,12 +40,12 @@
|
||||
;; If not specified, Logseq default opens journals page on startup
|
||||
;; value for `:page` is name of page
|
||||
;; Possible options for `:sidebar` are
|
||||
;; 1. `"Contents"` to open up `Favorites` in sidebar by default
|
||||
;; 1. `"Contents"` to open up `Contents` in sidebar by default
|
||||
;; 2. `page name` to open up some page in sidebar
|
||||
;; 3. Or multiple pages in an array ["Contents" "Page A" "Page B"]
|
||||
;; If `:sidebar` is not set, sidebar will be hidden
|
||||
;; Example:
|
||||
;; 1. Setup page "Changelog" as home page and "Favorites" in sidebar
|
||||
;; 1. Setup page "Changelog" as home page and "Contents" in sidebar
|
||||
;; :default-home {:page "Changelog", :sidebar "Contents"}
|
||||
;; 2. Setup page "Jun 3rd, 2021" as home page without sidebar
|
||||
;; :default-home {:page "Jun 3rd, 2021"}
|
||||
|
||||
1
templates/favorites.md
Normal file
1
templates/favorites.md
Normal file
@@ -0,0 +1 @@
|
||||
-
|
||||
1
templates/favorites.org
Normal file
1
templates/favorites.org
Normal file
@@ -0,0 +1 @@
|
||||
*
|
||||
@@ -7862,11 +7862,6 @@ react-grid-layout@^0.16.6:
|
||||
react-draggable "3.x"
|
||||
react-resizable "1.x"
|
||||
|
||||
react-icon-base@2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-icon-base/-/react-icon-base-2.1.0.tgz#a196e33fdf1e7aaa1fda3aefbb68bdad9e82a79d"
|
||||
integrity sha1-oZbjP98eeqof2jrvu2i9rZ6Cp50=
|
||||
|
||||
react-icons@^2.2.7:
|
||||
version "2.2.7"
|
||||
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-2.2.7.tgz#d7860826b258557510dac10680abea5ca23cf650"
|
||||
|
||||
Reference in New Issue
Block a user