diff options
| author | Tim <contact@bytim.eu> | 2026-05-14 15:12:49 +0200 |
|---|---|---|
| committer | Tim <contact@bytim.eu> | 2026-05-14 15:12:49 +0200 |
| commit | 607f920d4c880ef548be07c26f6df706bc5f2486 (patch) | |
| tree | 77fd96383a331e589e5be6024a7820b1a4c78c57 /src | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/aome/core.cljs | 40 | ||||
| -rw-r--r-- | src/aome/org_file.cljs | 49 |
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)])))))) + |
