summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/aome/core.cljs40
-rw-r--r--src/aome/org_file.cljs49
2 files changed, 89 insertions, 0 deletions
diff --git a/src/aome/core.cljs b/src/aome/core.cljs
new file mode 100644
index 0000000..a4cb41f
--- /dev/null
+++ b/src/aome/core.cljs
@@ -0,0 +1,40 @@
+(ns aome.core
+ (:require [reagent.core :as r]
+ [reagent.dom.client :as rdclient]
+ [aome.org-file :as aorg-file]))
+
+(defn header []
+ [:fieldset
+ [:div {:class ["field" "label" "border" "small"] :style {:display :inline-block :margin-top :auto}}
+ [:input {:type :text :placeholder " " :value @aorg-file/current-file-name
+ :on-change #(reset! aorg-file/current-file-name (.. % -target -value))}]
+ [:label "File name"]]
+ [:div {:class ["field" "label" "suffix" "border" "small"] :style {:width :fit-content :display :inline-block :margin-top :auto}}
+ [:select {:on-change #(reset! aorg-file/current-file-extension (.. % -target -value))}
+ [:option {:selected (= @aorg-file/current-file-extension ".org")} ".org"]
+ [:option {:selected (= @aorg-file/current-file-extension ".org.gpg")} ".org.gpg"]]
+ [:label "File extension"]
+ [:i "arrow_drop_down"]]
+ [:button {:class ["responsive" "border"] :style {:display :inline-block :width :fit-content} :on-click aorg-file/save-to-file-picker!}
+ [:i "save"]
+ [:span "Save"]]
+ [:button {:class ["responsive" "border"] :style {:width :fit-content} :on-click aorg-file/load-from-file-picker!}
+ [:i "file_open"]
+ [:span "Read file"]]])
+
+(defn editor []
+ [:textarea {:style {:resize :none :width "100%" :height "50em"}
+ :on-change #(reset! aorg-file/content (.. % -target -value))
+ :value @aorg-file/content}])
+
+(defn render []
+ [:div
+ [header]
+ [editor]])
+
+(defn init! []
+ (-> js/document
+ (.getElementById "app")
+ rdclient/create-root
+ (rdclient/render [render])))
+
diff --git a/src/aome/org_file.cljs b/src/aome/org_file.cljs
new file mode 100644
index 0000000..9fa6c4a
--- /dev/null
+++ b/src/aome/org_file.cljs
@@ -0,0 +1,49 @@
+(ns aome.org-file
+ (:require [shadow.cljs.modern :as scmodern]
+ [reagent.core :as r]
+ ["openpgp" :as pgp]))
+
+(def current-file-name (r/atom ""))
+(def current-file-extension (r/atom ".org"))
+(def content (r/atom ""))
+
+(defn- decrypt-string [bytes callback]
+ (scmodern/js-await [pgp-message (pgp/readMessage #js {"binaryMessage" bytes})]
+ (scmodern/js-await [decrypted (pgp/decrypt #js {"message" pgp-message
+ "passwords" (.prompt js/window "Passphrase:" "")})]
+ (callback (-> decrypted
+ js->clj
+ (get "data"))))))
+
+(defn load-from-file-picker! []
+ (scmodern/js-await [fileHandles (.showOpenFilePicker js/window (clj->js opts))]
+ (let [fileHandle (first fileHandles)]
+ (scmodern/js-await [file (.getFile fileHandle)]
+ (if-let [split-name (->> (.-name file)
+ (re-seq #"([A-z0-9-_]*)((\.[A-z]*){1,2})$")
+ first)]
+ (do (reset! current-file-name (nth split-name 1))
+ (reset! current-file-extension (nth split-name 2))))
+ (if (= @current-file-extension ".org.gpg")
+ (scmodern/js-await [file-content-bytes (.bytes file)]
+ (decrypt-string file-content-bytes #(reset! content %)))
+ (scmodern/js-await [file-content (.text file)]
+ (reset! content file-content)))))))
+
+(defn- encrypt-string [s callback]
+ (scmodern/js-await [pgp-message (pgp/createMessage #js {"text" s})]
+ (scmodern/js-await [encrypted (pgp/encrypt #js {"message" pgp-message
+ "passwords" (.prompt js/window "Passphrase:" "")
+ "format" "binary"})]
+ (callback encrypted))))
+
+(defn save-to-file-picker! []
+ (scmodern/js-await [fileHandle (.showSaveFilePicker js/window #js {"suggestedName" (str @current-file-name @current-file-extension)})]
+ (scmodern/js-await [writable (.createWritable fileHandle)]
+ (if (= @current-file-extension ".org.gpg")
+ (encrypt-string @content
+ #(scmodern/js-await [_ (.write writable %)]
+ (scmodern/js-await [_ (.close writable)])))
+ (scmodern/js-await [_ (.write writable @content)]
+ (scmodern/js-await [_ (.close writable)]))))))
+