Skip to content

Commit

Permalink
feat: multiple windows support
Browse files Browse the repository at this point in the history
  • Loading branch information
tiensonqin committed Dec 21, 2021
1 parent d3e6f16 commit 6fb7121
Show file tree
Hide file tree
Showing 18 changed files with 292 additions and 165 deletions.
80 changes: 9 additions & 71 deletions src/electron/electron/core.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
["path" :as path]
["os" :as os]
["electron" :refer [BrowserWindow app protocol ipcMain dialog Menu MenuItem session] :as electron]
["electron-window-state" :as windowStateKeeper]
[clojure.core.async :as async]
[electron.state :as state]
[electron.git :as git]
[electron.window :as win]
["/electron/utils" :as utils]))

(defonce LSP_SCHEME "lsp")
Expand All @@ -25,10 +25,6 @@
(defonce PLUGINS_ROOT (.join path (.homedir os) ".logseq/plugins"))

(def ROOT_PATH (path/join js/__dirname ".."))
(def MAIN_WINDOW_ENTRY (if dev?
;;"http://localhost:3001"
(str "file://" (path/join js/__dirname "index.html"))
(str "file://" (path/join js/__dirname "electron.html"))))

(defonce *setup-fn (volatile! nil))
(defonce *teardown-fn (volatile! nil))
Expand All @@ -37,53 +33,6 @@
;; Handle creating/removing shortcuts on Windows when installing/uninstalling.
(when (js/require "electron-squirrel-startup") (.quit app))

(defn create-main-window
"Creates main app window"
[]
(let [win-state (windowStateKeeper (clj->js {:defaultWidth 980 :defaultHeight 700}))
win-opts (cond->
{:width (.-width win-state)
:height (.-height win-state)
:frame true
:titleBarStyle "hiddenInset"
:trafficLightPosition {:x 16 :y 16}
:autoHideMenuBar (not mac?)
:webPreferences
{:plugins true ; pdf
:nodeIntegration false
:nodeIntegrationInWorker false
:webSecurity (not dev?)
:contextIsolation true
:spellcheck ((fnil identity true) (cfgs/get-item :spell-check))
;; Remove OverlayScrollbars and transition `.scrollbar-spacing`
;; to use `scollbar-gutter` after the feature is implemented in browsers.
:enableBlinkFeatures 'OverlayScrollbars'
:preload (path/join js/__dirname "js/preload.js")}}
linux?
(assoc :icon (path/join js/__dirname "icons/logseq.png")))
url MAIN_WINDOW_ENTRY
win (BrowserWindow. (clj->js win-opts))]
(.manage win-state win)
(.onBeforeSendHeaders (.. session -defaultSession -webRequest)
(clj->js {:urls (array "*://*.youtube.com/*")})
(fn [^js details callback]
(let [url (.-url details)
urlObj (js/URL. url)
origin (.-origin urlObj)
requestHeaders (.-requestHeaders details)]
(if (and
(.hasOwnProperty requestHeaders "referer")
(not-empty (.-referer requestHeaders)))
(callback #js {:cancel false
:requestHeaders requestHeaders})
(do
(set! (.-referer requestHeaders) origin)
(callback #js {:cancel false
:requestHeaders requestHeaders}))))))
(.loadURL win url)
;;(when dev? (.. win -webContents (openDevTools)))
win))

(defn setup-updater! [^js win]
;; manual/auto updater
(when-not linux?
Expand Down Expand Up @@ -257,10 +206,6 @@
(.removeHandler ipcMain call-app-channel)
(.removeHandler ipcMain call-win-channel))))

(defn- destroy-window!
[^js win]
(.destroy win))

(defn main
[]
(if-not (.requestSingleInstanceLock app)
Expand All @@ -269,18 +214,11 @@
(.quit app))
(do
(.registerSchemesAsPrivileged
protocol (bean/->js [{:scheme LSP_SCHEME
:privileges {:standard true
:secure true
:bypassCSP true
:supportFetchAPI true}}]))
(.on app "second-instance"
(fn [_event _commandLine _workingDirectory]
(when-let [win @*win]
(when (.isMinimized ^object win)
(.restore win))
(.focus win))))

protocol (bean/->js [{:scheme LSP_SCHEME
:privileges {:standard true
:secure true
:bypassCSP true
:supportFetchAPI true}}]))
(.on app "window-all-closed" (fn []
(try
(fs-watcher/close-watcher!)
Expand All @@ -291,7 +229,7 @@
(.on app "ready"
(fn []
(let [t0 (setup-interceptor!)
^js win (create-main-window)
^js win (win/create-main-window)
_ (reset! *win win)
*quitting? (atom false)]
(.. logger (info (str "Logseq App(" (.getVersion app) ") Starting... ")))
Expand Down Expand Up @@ -330,14 +268,14 @@
(let [_ (async/<! state/persistent-dbs-chan)]
(if (or @*quitting? (not mac?))
(when-let [win @*win]
(destroy-window! win)
(win/destroy-window! win)
(reset! *win nil))
(do (.preventDefault ^js/Event e)
(if (and mac? (.isFullScreen win))
(do (.once win "leave-full-screen" #(.hide win))
(.setFullScreen win false))
(.hide win)))))))))
(.on app "before-quit" (fn [_e] (reset! *quitting? true)))

(.on app "activate" #(if @*win (.show win)))))))))

(defn start []
Expand Down
67 changes: 66 additions & 1 deletion src/electron/electron/handler.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
["buffer" :as buffer]
["fs-extra" :as fs-extra]
["path" :as path]
["os" :as os]
[electron.fs-watcher :as watcher]
[electron.configs :as cfgs]
[promesa.core :as p]
Expand All @@ -15,7 +16,8 @@
[clojure.core.async :as async]
[electron.search :as search]
[electron.git :as git]
[electron.plugin :as plugin]))
[electron.plugin :as plugin]
[electron.window :as win]))

(defmulti handle (fn [_window args] (keyword (first args))))

Expand Down Expand Up @@ -153,6 +155,66 @@
(defmethod handle :getFiles [window [_ path]]
(get-files path))

(defn- sanitize-graph-name
[graph-name]
(when graph-name
(string/replace graph-name "/" "++")))

(defn- graph-name->path
[graph-name]
(when graph-name
(string/replace graph-name "++" "/")))

(defn- get-graphs-dir
[]
(let [dir (.join path (.homedir os) ".logseq" "graphs")]
(fs-extra/ensureDirSync dir)
dir))

(defn- get-graphs
[]
(let [dir (get-graphs-dir)
graphs-path (.join path (.homedir os) ".logseq" "graphs")]
(->> (readdir dir)
(remove #{graphs-path})
(map #(path/basename % ".transit"))
(map graph-name->path))))

(defmethod handle :getGraphs [window [_]]
(get-graphs))

(defn- get-graph-path
[graph-name]
(when graph-name
(let [graph-name (sanitize-graph-name graph-name)
dir (get-graphs-dir)]
(.join path dir (str graph-name ".transit")))))

(defn- get-serialized-graph
[graph-name]
(when graph-name
(when-let [file-path (get-graph-path graph-name)]
(utils/read-file file-path))))

(defmethod handle :getSerializedGraph [window [_ graph-name]]
(get-serialized-graph graph-name))

(defmethod handle :saveGraph [window [_ graph-name value-str]]
(when (and graph-name value-str)
(when-let [file-path (get-graph-path graph-name)]
(fs/writeFileSync file-path value-str))))

(defmethod handle :deleteGraph [window [_ graph-name]]
(when graph-name
(when-let [file-path (get-graph-path graph-name)]
(when (fs/existsSync file-path)
(fs-extra/removeSync file-path)))))

(defmethod handle :openNewWindow [window [_]]
(let [win (win/create-main-window)]
(win/on-close-save! win)
nil))

(defmethod handle :persistent-dbs-saved [window _]
(async/put! state/persistent-dbs-chan true)
true)
Expand Down Expand Up @@ -182,6 +244,9 @@

(defn clear-cache!
[]
(let [graphs-dir (get-graphs-dir)]
(fs-extra/removeSync graphs-dir))

(let [path (.getPath ^object app "userData")]
(doseq [dir ["search" "IndexedDB"]]
(let [path (path/join path dir)]
Expand Down
74 changes: 74 additions & 0 deletions src/electron/electron/window.cljs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
(ns electron.window
(:require ["electron-window-state" :as windowStateKeeper]
[electron.utils :refer [*win mac? win32? linux? prod? dev? logger open]]
[electron.configs :as cfgs]
["electron" :refer [BrowserWindow app protocol ipcMain dialog Menu MenuItem session] :as electron]
["path" :as path]
[electron.state :as state]
[clojure.core.async :as async]))

(def MAIN_WINDOW_ENTRY (if dev?
;;"http://localhost:3001"
(str "file://" (path/join js/__dirname "index.html"))
(str "file://" (path/join js/__dirname "electron.html"))))

(defn create-main-window
([]
(create-main-window MAIN_WINDOW_ENTRY))
([url]
(let [win-state (windowStateKeeper (clj->js {:defaultWidth 980 :defaultHeight 700}))
win-opts (cond->
{:width (.-width win-state)
:height (.-height win-state)
:frame true
:titleBarStyle "hiddenInset"
:trafficLightPosition {:x 16 :y 16}
:autoHideMenuBar (not mac?)
:webPreferences
{:plugins true ; pdf
:nodeIntegration false
:nodeIntegrationInWorker false
:webSecurity (not dev?)
:contextIsolation true
:spellcheck ((fnil identity true) (cfgs/get-item :spell-check))
;; Remove OverlayScrollbars and transition `.scrollbar-spacing`
;; to use `scollbar-gutter` after the feature is implemented in browsers.
:enableBlinkFeatures 'OverlayScrollbars'
:preload (path/join js/__dirname "js/preload.js")}}
linux?
(assoc :icon (path/join js/__dirname "icons/logseq.png")))
win (BrowserWindow. (clj->js win-opts))]
(.manage win-state win)
(.onBeforeSendHeaders (.. session -defaultSession -webRequest)
(clj->js {:urls (array "*://*.youtube.com/*")})
(fn [^js details callback]
(let [url (.-url details)
urlObj (js/URL. url)
origin (.-origin urlObj)
requestHeaders (.-requestHeaders details)]
(if (and
(.hasOwnProperty requestHeaders "referer")
(not-empty (.-referer requestHeaders)))
(callback #js {:cancel false
:requestHeaders requestHeaders})
(do
(set! (.-referer requestHeaders) origin)
(callback #js {:cancel false
:requestHeaders requestHeaders}))))))
(.loadURL win url)
;;(when dev? (.. win -webContents (openDevTools)))
win)))

(defn destroy-window!
[^js win]
(.destroy win))

(defn on-close-save!
[^js win]
(.on win "close" (fn [e]
(.preventDefault e)
(let [web-contents (. win -webContents)]
(.send web-contents "persistent-dbs"))
(async/go
(let [_ (async/<! state/persistent-dbs-chan)]
(destroy-window! win))))))
5 changes: 3 additions & 2 deletions src/main/electron/listener.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@
[electron.ipc :as ipc]
[frontend.handler.notification :as notification]
[frontend.handler.metadata :as metadata-handler]
[frontend.ui :as ui]))
[frontend.ui :as ui]
[frontend.db.persist :as db-persist]))

(defn persist-dbs!
[]
(->
(p/let [repos (idb/get-nfs-dbs)
(p/let [repos (db-persist/get-all-graphs)
repos (-> repos
(conj (state/get-current-repo))
(distinct))]
Expand Down
5 changes: 4 additions & 1 deletion src/main/frontend/components/repo.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
[frontend.handler.page :as page-handler]
[frontend.handler.repo :as repo-handler]
[frontend.handler.route :as route-handler]
[frontend.handler.ui :as ui-handler]
[frontend.handler.web.nfs :as nfs-handler]
[frontend.modules.shortcut.core :as shortcut]
[frontend.state :as state]
Expand Down Expand Up @@ -260,7 +261,9 @@
(state/close-modal!)
(repo-handler/re-index!
nfs-handler/rebuild-index!
page-handler/create-today-journal!)))]]))}}])]
page-handler/create-today-journal!)))]]))}}
{:title (t :open-new-window)
:options {:on-click ui-handler/open-new-window!}}])]
(when (seq repos)
(ui/dropdown-with-links
(fn [{:keys [toggle-fn]}]
Expand Down
6 changes: 3 additions & 3 deletions src/main/frontend/db.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
[frontend.db.query-custom]
[frontend.db.query-react]
[frontend.db.react]
[frontend.db.persist :as db-persist]
[frontend.idb :as idb]
[frontend.namespaces :refer [import-vars]]
[frontend.state :as state]
Expand All @@ -20,7 +21,6 @@
conns
get-repo-path
datascript-db
remove-db!
get-conn
me-tx
remove-conn!]
Expand Down Expand Up @@ -72,7 +72,7 @@
(when conn
(let [db (d/db conn)
db-str (if db (db->string db) "")]
(p/let [_ (idb/set-batch! [{:key key :value db-str}])]
(p/let [_ (db-persist/save-graph! key db-str)]
(state/set-last-persist-transact-id! repo false (get-max-tx-id db)))))))

(defonce persistent-jobs (atom {}))
Expand Down Expand Up @@ -142,7 +142,7 @@
db-conn (d/create-conn db-schema/schema)
_ (d/transact! db-conn [{:schema/version db-schema/version}])
_ (swap! conns assoc db-name db-conn)
stored (idb/get-item db-name)
stored (db-persist/get-serialized-graph db-name)
_ (if stored
(let [stored-db (string->db stored)
attached-db (d/db-with stored-db (concat
Expand Down
8 changes: 3 additions & 5 deletions src/main/frontend/db/conn.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,9 @@
(defn datascript-db
[repo]
(when repo
(str config/idb-db-prefix (get-repo-path repo))))

(defn remove-db!
[repo]
(idb/remove-item! (datascript-db repo)))
(let [path (get-repo-path repo)]
(str (if (util/electron?) "" config/idb-db-prefix)
path))))

(defn get-conn
([]
Expand Down
Loading

0 comments on commit 6fb7121

Please sign in to comment.