Browse Source

feat: add support to export to zip

Resolved #779
Tienson Qin 5 years ago
parent
commit
5248444157

+ 1 - 0
package.json

@@ -41,6 +41,7 @@
         "codemirror": "^5.58.1",
         "diff": "^4.0.2",
         "dropbox": "^5.2.0",
+        "jszip": "^3.5.0",
         "localforage": "^1.7.3",
         "mousetrap": "^1.6.5",
         "parinfer-codemirror": "^1.4.2",

+ 1 - 2
src/main/frontend/components/header.cljs

@@ -159,7 +159,6 @@
                        :default-home default-home}))
 
      [:a#download-as-html.hidden]
+     [:a#download-as-zip.hidden]
 
      (right-menu-button)]))
-
-

+ 4 - 0
src/main/frontend/components/repo.cljs

@@ -132,6 +132,10 @@
            :on-click (fn [] (repo-handler/pull-current-repo)))
          (if pulling?
            [:span.lds-dual-ring.mt-1])]
+        [:a.mt-5.text-sm.opacity-50.block
+         {:on-click (fn []
+                      (export-handler/export-repo-as-zip! repo))}
+         (t :repo/download-zip)]
         [:p.pt-2.text-sm.opacity-50
          (t :git/version) (str " " version/version)]]])))]))))
 

+ 12 - 0
src/main/frontend/db.cljs

@@ -926,6 +926,18 @@
       react
       ffirst))))
 
+(defn get-file-contents
+  [repo]
+  (when-let [conn (get-files-conn repo)]
+    (->>
+     (d/q
+       '[:find ?path ?content
+         :where
+         [?file :file/path ?path]
+         [?file :file/content ?content]]
+       @conn)
+     (into {}))))
+
 (defn get-custom-css
   []
   (get-file "logseq/custom.css"))

+ 2 - 0
src/main/frontend/dicts.cljs

@@ -320,6 +320,7 @@ title: How to take dummy notes?
         :go-to "Go to "
         :or "or"
         :download "Download"
+        :repo/download-zip "Download all files as a zip"
         :language "Language"
         :white "Light"
         :dark "Dark"
@@ -767,6 +768,7 @@ title: How to take dummy notes?
            :go-to "转到"
            :or "或"
            :download "下载"
+           :repo/download-zip "下载所有文件"
            :language "语言"
            :white "亮色"
            :dark "暗黑"

+ 20 - 0
src/main/frontend/extensions/zip.cljs

@@ -0,0 +1,20 @@
+(ns frontend.extensions.zip
+  (:require ["jszip" :as JSZip]
+            ["/frontend/utils" :as utils]
+            [promesa.core :as p]
+            [medley.core :as medley]))
+
+(defn make-file [content file-name args]
+  (let [blob-content (clj->js [content])
+        last-modified (or (aget content "lastModified") (js/Date.))
+        args (clj->js args)]
+    (aset args "lastModified" last-modified)
+    (js/File. blob-content file-name args)))
+
+(defn make-zip [repo file-name->content]
+  (let [zip (JSZip.)
+        folder (.folder zip repo)]
+    (doseq [[file-name content] file-name->content]
+      (.file folder file-name content))
+    (p/let [zip-blob (.generateAsync zip #js {:type "blob"})]
+      (make-file zip-blob (str repo ".zip") {:type "application/zip"}))))

+ 2 - 0
src/main/frontend/handler.cljs

@@ -14,6 +14,7 @@
             [frontend.handler.repo :as repo-handler]
             [frontend.handler.file :as file-handler]
             [frontend.handler.ui :as ui-handler]
+            [frontend.handler.export :as export-handler]
             [frontend.ui :as ui]
             [goog.object :as gobj]
             [frontend.helper :as helper]))
@@ -125,6 +126,7 @@
 (defn clear-stores-if-schema-changed!
   [handler]
   (if (not= (storage/get :db-schema) db-schema/schema)
+    ;; TODO: export repo zip
     (p/let [_ (db/clear-local-storage-and-idb!)]
       (handler)
       (store-schema!))

+ 15 - 1
src/main/frontend/handler/export.cljs

@@ -7,7 +7,9 @@
             [goog.dom :as gdom]
             [frontend.publishing.html :as html]
             [frontend.text :as text]
-            [frontend.handler.common :as common-handler]))
+            [frontend.handler.common :as common-handler]
+            [frontend.extensions.zip :as zip]
+            [promesa.core :as p]))
 
 (defn copy-block!
   [block-id]
@@ -75,3 +77,15 @@
         (.setAttribute anchor "href" html-str)
         (.setAttribute anchor "download" "index.html")
         (.click anchor)))))
+
+(defn export-repo-as-zip!
+  [repo]
+  (let [files (db/get-file-contents repo)
+        [owner repo-name] (util/get-git-owner-and-repo repo)
+        repo-name (str owner "-" repo-name)]
+    (when (seq files)
+      (p/let [zipfile (zip/make-zip repo-name files)]
+        (when-let [anchor (gdom/getElement "download-as-zip")]
+          (.setAttribute anchor "href" (js/window.URL.createObjectURL zipfile))
+          (.setAttribute anchor "download" (.-name zipfile))
+          (.click anchor))))))

+ 4 - 5
src/main/frontend/handler/repo.cljs

@@ -563,12 +563,11 @@
   (db/remove-conn! url)
   (db/clear-query-state!)
   (-> (p/let [_ (db/remove-db! url)
-              _ (db/remove-files-db! url)]
-        (fs/rmdir (util/get-repo-dir url)))
+              _ (db/remove-files-db! url)
+              _ (fs/rmdir (util/get-repo-dir url))]
+        (clone-and-pull url))
       (p/catch (fn [error]
-                 (prn "Delete repo failed, error: " error)))
-      (p/finally (fn []
-                   (clone-and-pull url)))))
+                 (prn "Delete repo failed, error: " error)))))
 
 (defn git-commit-and-push!
   [commit-message]

+ 27 - 0
yarn.lock

@@ -2547,6 +2547,16 @@ jsonfile@^4.0.0:
   optionalDependencies:
     graceful-fs "^4.1.6"
 
+jszip@^3.5.0:
+  version "3.5.0"
+  resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.5.0.tgz#b4fd1f368245346658e781fec9675802489e15f6"
+  integrity sha512-WRtu7TPCmYePR1nazfrtuF216cIVon/3GWOvHS9QR5bIwSbnxtdpma6un3jyGGNhHsKCSzn5Ypk+EkDRvTGiFA==
+  dependencies:
+    lie "~3.3.0"
+    pako "~1.0.2"
+    readable-stream "~2.3.6"
+    set-immediate-shim "~1.0.1"
+
 just-debounce@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea"
@@ -2619,6 +2629,13 @@ [email protected]:
   dependencies:
     immediate "~3.0.5"
 
+lie@~3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a"
+  integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==
+  dependencies:
+    immediate "~3.0.5"
+
 liftoff@^3.1.0:
   version "3.1.0"
   resolved "https://registry.yarnpkg.com/liftoff/-/liftoff-3.1.0.tgz#c9ba6081f908670607ee79062d700df062c52ed3"
@@ -3242,6 +3259,11 @@ p-try@^2.0.0:
   resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
   integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
 
+pako@~1.0.2:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
+  integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+
 pako@~1.0.5:
   version "1.0.10"
   resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.10.tgz#4328badb5086a426aa90f541977d4955da5c9732"
@@ -4297,6 +4319,11 @@ set-blocking@^2.0.0:
   resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
   integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
 
+set-immediate-shim@~1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
+  integrity sha1-SysbJ+uAip+NzEgaWOXlb1mfP2E=
+
 set-value@^2.0.0, set-value@^2.0.1:
   version "2.0.1"
   resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"