| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521 |
- (ns frontend.config
- "App config and fns built on top of configuration"
- (:require [clojure.set :as set]
- [clojure.string :as string]
- [frontend.mobile.util :as mobile-util]
- [frontend.state :as state]
- [frontend.util :as util]
- [goog.crypt :as crypt]
- [goog.crypt.Md5]
- [logseq.common.config :as common-config]
- [logseq.common.path :as path]
- [logseq.common.util :as common-util]
- [logseq.db.sqlite.util :as sqlite-util]
- [shadow.resource :as rc]))
- (goog-define DEV-RELEASE false)
- (defonce dev-release? DEV-RELEASE)
- (defonce dev? ^boolean (or dev-release? goog.DEBUG))
- (defonce publishing? common-config/PUBLISHING)
- (goog-define REVISION "unknown")
- (defonce revision REVISION)
- (goog-define ENABLE-FILE-SYNC-PRODUCTION false)
- ;; this is a feature flag to enable the account tab
- ;; when it launches (when pro plan launches) it should be removed
- (def ENABLE-SETTINGS-ACCOUNT-TAB false)
- (if ENABLE-FILE-SYNC-PRODUCTION
- (do (def FILE-SYNC-PROD? true)
- (def LOGIN-URL
- "https://logseq-prod.auth.us-east-1.amazoncognito.com/login?client_id=3c7np6bjtb4r1k1bi9i049ops5&response_type=code&scope=email+openid+phone&redirect_uri=logseq%3A%2F%2Fauth-callback")
- (def API-DOMAIN "api.logseq.com")
- (def WS-URL "wss://ws.logseq.com/file-sync?graphuuid=%s")
- (def COGNITO-IDP "https://cognito-idp.us-east-1.amazonaws.com/")
- (def COGNITO-CLIENT-ID "69cs1lgme7p8kbgld8n5kseii6")
- (def REGION "us-east-1")
- (def USER-POOL-ID "us-east-1_dtagLnju8")
- (def IDENTITY-POOL-ID "us-east-1:d6d3b034-1631-402b-b838-b44513e93ee0")
- (def OAUTH-DOMAIN "logseq-prod.auth.us-east-1.amazoncognito.com")
- (def CONNECTIVITY-TESTING-S3-URL "https://logseq-connectivity-testing-prod.s3.us-east-1.amazonaws.com/logseq-connectivity-testing"))
- (do (def FILE-SYNC-PROD? false)
- (def LOGIN-URL
- "https://logseq-test2.auth.us-east-2.amazoncognito.com/login?client_id=3ji1a0059hspovjq5fhed3uil8&response_type=code&scope=email+openid+phone&redirect_uri=logseq%3A%2F%2Fauth-callback")
- (def API-DOMAIN "api-dev.logseq.com")
- (def WS-URL "wss://ws-dev.logseq.com/file-sync?graphuuid=%s")
- (def COGNITO-IDP "https://cognito-idp.us-east-2.amazonaws.com/")
- (def COGNITO-CLIENT-ID "1qi1uijg8b6ra70nejvbptis0q")
- (def REGION "us-east-2")
- (def USER-POOL-ID "us-east-2_kAqZcxIeM")
- (def IDENTITY-POOL-ID "us-east-2:cc7d2ad3-84d0-4faf-98fe-628f6b52c0a5")
- (def OAUTH-DOMAIN "logseq-test2.auth.us-east-2.amazoncognito.com")
- (def CONNECTIVITY-TESTING-S3-URL "https://logseq-connectivity-testing-prod.s3.us-east-1.amazonaws.com/logseq-connectivity-testing")))
- (goog-define ENABLE-RTC-SYNC-PRODUCTION false)
- (if ENABLE-RTC-SYNC-PRODUCTION
- (def RTC-WS-URL "wss://ws.logseq.com/rtc-sync?token=%s")
- (def RTC-WS-URL "wss://ws-dev.logseq.com/rtc-sync?token=%s"))
- ;; Feature flags
- ;; =============
- (goog-define ENABLE-PLUGINS true)
- (defonce feature-plugin-system-on? ENABLE-PLUGINS)
- ;; Desktop only as other platforms requires better understanding of their
- ;; multi-graph workflows and optimal place for a "global" dir
- (def global-config-enabled? util/electron?)
- ;; User level configuration for whether plugins are enabled
- (defonce lsp-enabled?
- (and util/plugin-platform?
- (not (false? feature-plugin-system-on?))
- (state/lsp-enabled?-or-theme)))
- (defn plugin-config-enabled?
- []
- (and lsp-enabled? (global-config-enabled?)))
- ;; :TODO: How to do this?
- ;; (defonce desktop? ^boolean goog.DESKTOP)
- ;; ============
- (def app-name common-config/app-name)
- (def website
- (if dev?
- "http://localhost:3000"
- (util/format "https://%s.com" app-name)))
- ;; FIXME:
- (def app-website
- (if dev?
- "http://localhost:3001"
- (util/format "https://%s.com" app-name)))
- (def asset-domain (util/format "https://asset.%s.com"
- app-name))
- ;; TODO: Remove this, switch to lazy loader
- (defn asset-uri
- [path]
- (cond
- publishing?
- path
- (util/file-protocol?)
- (string/replace path "/static/" "./")
- :else
- (if dev? path
- (str asset-domain path))))
- (def markup-formats
- #{:org :md :markdown :asciidoc :adoc :rst})
- (def doc-formats
- #{:doc :docx :xls :xlsx :ppt :pptx :one :pdf :epub})
- (def image-formats
- #{:png :jpg :jpeg :bmp :gif :webp :svg :heic})
- (def audio-formats
- #{:mp3 :ogg :mpeg :wav :m4a :flac :wma :aac})
- (def video-formats
- #{:mp4 :webm :mov :flv :avi :mkv})
- (def media-formats (set/union (common-config/img-formats) audio-formats video-formats))
- (defn extname-of-supported?
- ([input] (extname-of-supported?
- input
- [image-formats doc-formats audio-formats
- video-formats markup-formats
- (common-config/text-formats)]))
- ([input formats]
- (when-let [input (some->
- (cond-> input
- (and (string? input)
- (not (string/blank? input)))
- (string/replace-first "." ""))
- (util/safe-lower-case)
- (keyword))]
- (boolean
- (some
- (fn [s]
- (contains? s input))
- formats)))))
- (defn ext-of-video?
- ([s] (ext-of-video? s true))
- ([s html5?]
- (when-let [s (and (string? s) (util/get-file-ext s))]
- (let [video-formats' (cond-> video-formats
- html5? (disj :mkv))]
- (extname-of-supported? s [video-formats'])))))
- (defn ext-of-audio?
- ([s] (ext-of-audio? s true))
- ([s html5?]
- (when-let [s (and (string? s) (util/get-file-ext s))]
- (let [audio-formats' (cond-> audio-formats
- html5? (disj :wma :ogg))]
- (extname-of-supported? s [audio-formats'])))))
- (defn ext-of-image?
- [s]
- (when-let [s (and (string? s) (util/get-file-ext s))]
- (extname-of-supported? s [image-formats])))
- (def mobile?
- "Triggering condition: Mobile phones
- *** Warning!!! ***
- For UX logic only! Don't use for FS logic
- iPad / Android Pad doesn't trigger!
- Same as config/mobile?"
- (when-not util/node-test?
- (util/safe-re-find #"Mobi" js/navigator.userAgent)))
- ;; TODO: protocol design for future formats support
- (defn get-block-pattern
- [format]
- (common-config/get-block-pattern (or format (state/get-preferred-format))))
- (defn get-hr
- [format]
- (let [format (or format (keyword (state/get-preferred-format)))]
- (case format
- :org
- "-----"
- :markdown
- "---"
- "")))
- (defn get-bold
- [format]
- (let [format (or format (keyword (state/get-preferred-format)))]
- (case format
- :org
- "*"
- :markdown
- "**"
- "")))
- (defn get-italic
- [format]
- (let [format (or format (keyword (state/get-preferred-format)))]
- (case format
- :org
- "/"
- :markdown
- "*"
- "")))
- (defn get-underline
- [format]
- (let [format (or format (keyword (state/get-preferred-format)))]
- (case format
- :org
- "_"
- :markdown ;; no underline for markdown
- ""
- "")))
- (defn get-strike-through
- [format]
- (let [format (or format (keyword (state/get-preferred-format)))]
- (case format
- :org
- "+"
- :markdown
- "~~"
- "")))
- (defn get-highlight
- [format]
- (case format
- :org
- "^^"
- :markdown
- "=="
- ""))
- (defn get-code
- [format]
- (let [format (or format (keyword (state/get-preferred-format)))]
- (case format
- :org
- "~"
- :markdown
- "`"
- "")))
- (defn get-empty-link-and-forward-pos
- [format]
- (case format
- :org
- ["[[][]]" 2]
- :markdown
- ["[]()" 1]
- ["" 0]))
- (defn link-format
- [format label link]
- (if (not-empty label)
- (case format
- :org
- (util/format "[[%s][%s]]" link label)
- :markdown
- (util/format "[%s](%s)" label link))
- link))
- (defn with-default-link
- [format link]
- (case format
- :org
- [(util/format "[[%s][]]" link)
- (+ 4 (count link))]
- :markdown
- [(util/format "[](%s)" link)
- 1]
- ["" 0]))
- (defn with-label-link
- [format label link]
- (case format
- :org
- [(util/format "[[%s][%s]]" link label)
- (+ 4 (count link) (count label))]
- :markdown
- [(util/format "[%s](%s)" label link)
- (+ 4 (count link) (count label))]
- ["" 0]))
- (defn with-default-label
- [format label]
- (case format
- :org
- [(util/format "[[][%s]]" label)
- 2]
- :markdown
- [(util/format "[%s]()" label)
- (+ 3 (count label))]
- ["" 0]))
- (defn get-file-extension
- [format]
- (case (keyword format)
- :markdown
- "md"
- (name format)))
- (defonce default-journals-directory "journals")
- (defonce default-pages-directory "pages")
- (defonce default-whiteboards-directory "whiteboards")
- (defn get-pages-directory
- []
- (or (state/get-pages-directory) default-pages-directory))
- (defn get-journals-directory
- []
- (or (state/get-journals-directory) default-journals-directory))
- (defn get-whiteboards-directory
- []
- (or (state/get-whiteboards-directory) default-whiteboards-directory))
- (defonce demo-repo "Demo")
- (defn demo-graph?
- "Demo graph or nil graph?"
- ([]
- (demo-graph? (state/get-current-repo)))
- ([repo-url]
- (or (nil? repo-url) (= repo-url demo-repo)
- (string/ends-with? repo-url demo-repo))))
- (defonce recycle-dir ".recycle")
- (def config-file "config.edn")
- (def custom-css-file "custom.css")
- (def export-css-file "export.css")
- (def custom-js-file "custom.js")
- (def config-default-content (rc/inline "templates/config.edn"))
- (def config-default-content-md5 (let [md5 (new crypt/Md5)]
- (.update md5 (crypt/stringToUtf8ByteArray config-default-content))
- (crypt/byteArrayToHex (.digest md5))))
- ;; NOTE: repo-url is the unique identifier of a repo.
- ;; - `local` => in-memory demo graph
- ;; - `logseq_local_/absolute/path/to/graph` => local graph, native fs backend
- ;; - `logseq_local_x:/absolute/path/to/graph` => local graph, native fs backend, on Windows
- ;; - `logseq_local_GraphName` => local graph, browser fs backend
- ;; - `logseq_db_GraphName` => db based graph, sqlite as backend
- ;; - Use `""` while writing global files
- (defonce idb-db-prefix "logseq-db/")
- (defonce local-db-prefix "logseq_local_")
- (defonce local-handle "handle")
- (defonce db-version-prefix sqlite-util/db-version-prefix)
- (defn local-file-based-graph?
- [s]
- (and (string? s)
- (string/starts-with? s local-db-prefix)))
- (defn db-based-graph?
- ([]
- (db-based-graph? (state/get-current-repo)))
- ([s]
- (boolean
- (and (string? s)
- (sqlite-util/db-based-graph? s)))))
- (defn get-local-asset-absolute-path
- [s]
- (str "/" (string/replace s #"^[./]*" "")))
- (defn get-local-dir
- [repo]
- (if (db-based-graph? repo)
- (path/path-join (get-in @state/state [:system/info :home-dir])
- "logseq"
- "graphs"
- (string/replace repo db-version-prefix ""))
- (string/replace repo local-db-prefix "")))
- ;; FIXME(andelf): this is not the reverse op of get-repo-dir, should be fixed
- (defn get-local-repo
- [dir]
- (str local-db-prefix dir))
- (defn get-repo-dir
- [repo-url]
- (when repo-url
- (let [db-based? (db-based-graph? repo-url)]
- (cond
- (and (util/electron?) db-based-graph?)
- (get-local-dir repo-url)
- db-based?
- (str "memory:///"
- (string/replace-first repo-url db-version-prefix ""))
- (and (util/electron?) (local-file-based-graph? repo-url))
- (get-local-dir repo-url)
- (and (mobile-util/native-platform?) (local-file-based-graph? repo-url))
- (let [dir (get-local-dir repo-url)]
- (if (string/starts-with? dir "file://")
- dir
- (path/path-join "file://" dir)))
- ;; Special handling for demo graph
- (= repo-url demo-repo)
- "memory:///local"
- ;; nfs, browser-fs-access
- ;; Format: logseq_local_{dir-name}
- (local-file-based-graph? repo-url)
- (string/replace-first repo-url local-db-prefix "")
- ;; unit test
- (= repo-url "test-db")
- "/test-db"
- :else
- (do
- (js/console.error "Unknown Repo URL type:" repo-url)
- (str "/"
- (->> (take-last 2 (string/split repo-url #"/"))
- (string/join "_"))))))))
- (defn get-string-repo-dir
- [repo-dir]
- (if (mobile-util/native-ios?)
- (str (if (mobile-util/in-iCloud-container-path? repo-dir)
- "iCloud"
- (cond (mobile-util/native-iphone?)
- "On My iPhone"
- (mobile-util/native-ipad?)
- "On My iPad"
- :else
- "Local"))
- (->> (string/split repo-dir "Documents/")
- last
- common-util/safe-decode-uri-component
- (str "/" (string/capitalize app-name) "/")))
- (get-repo-dir (get-local-repo repo-dir))))
- (defn get-repo-fpath
- [repo-url path]
- (path/path-join (get-repo-dir repo-url) path))
- (defn get-repo-config-path
- []
- (path/path-join app-name config-file))
- (defn get-custom-css-path
- ([]
- (get-custom-css-path (state/get-current-repo)))
- ([repo]
- (if (db-based-graph? repo)
- (path/path-join app-name custom-css-file)
- (when-let [repo-dir (get-repo-dir repo)]
- (path/path-join repo-dir app-name custom-css-file)))))
- (defn get-export-css-path
- ([]
- (get-export-css-path (state/get-current-repo)))
- ([repo]
- (when-let [repo-dir (get-repo-dir repo)]
- (path/path-join repo-dir app-name export-css-file))))
- (defn expand-relative-assets-path
- "Resolve all relative links in custom.css to assets:// URL"
- ;; ../assets/xxx -> {assets|file}://{current-graph-root-path}/xxx
- [source]
- (when-not (string/blank? source)
- (let [protocol (and (string? source)
- (not (string/blank? source))
- (if (util/electron?) "assets://" "file://"))
- ;; BUG: use "assets" as fake current directory
- assets-link-fn (fn [_]
- (let [graph-root (get-repo-dir (state/get-current-repo))
- full-path (if (util/safe-re-find #"^(file|assets):" graph-root)
- (path/path-join graph-root "assets")
- (path/path-join protocol graph-root "assets"))]
- (str (cond-> full-path
- (mobile-util/native-platform?)
- (mobile-util/convert-file-src))
- "/")))]
- (string/replace source #"\.\./assets/" assets-link-fn))))
- (defn get-current-repo-assets-root
- []
- (when-let [repo-dir (get-repo-dir (state/get-current-repo))]
- (path/path-join repo-dir "assets")))
- (defn get-repo-assets-root
- [repo]
- (when-let [repo-dir (get-repo-dir repo)]
- (path/path-join repo-dir "assets")))
- (defn get-custom-js-path
- ([]
- (get-custom-js-path (state/get-current-repo)))
- ([repo]
- (if (db-based-graph? repo)
- (path/path-join app-name custom-js-file)
- (when-let [repo-dir (get-repo-dir repo)]
- (path/path-join repo-dir app-name custom-js-file)))))
- (defn get-block-hidden-properties
- []
- (:block-hidden-properties (state/get-config)))
|