account database separation try

Former-commit-id: d19b595b9f
This commit is contained in:
Adrian Tiberius 2016-07-18 15:42:48 +03:00
parent f67c252f0a
commit d3b8840893
23 changed files with 509 additions and 365 deletions

View File

@ -23,7 +23,7 @@
"react-native-randombytes": "^2.1.0",
"react-native-vector-icons": "^1.3.4",
"react-native-orientation": "^1.17.0",
"realm": "^0.11.1",
"realm": "^0.14.0",
"react-native-status": "git+ssh://git@github.com/status-im/react-native-status"
}
}

View File

@ -1,6 +1,6 @@
(ns status-im.accounts.handlers
(:require [status-im.models.accounts :as accounts]
[re-frame.core :refer [register-handler after dispatch debug]]
[re-frame.core :refer [register-handler after dispatch dispatch-sync debug]]
[status-im.utils.logging :as log]
[status-im.components.react :refer [geth]]
[status-im.utils.types :refer [json->clj]]
@ -9,6 +9,7 @@
[status-im.utils.identicon :refer [identicon]]
[status-im.db :refer [default-view]]
[status-im.utils.random :as random]
[status-im.persistence.realm.core :as realm]
[status-im.i18n :refer [label]]
[status-im.constants :refer [content-type-command-request]]
[clojure.string :as str]))
@ -32,24 +33,31 @@
account {:public-key public-key
:address address
:name address
:photo-path (identicon address)}]
(log/debug "Created account: " result)
:photo-path (identicon address)}
]
(log/debug "account-created: " account)
(when (not (str/blank? public-key))
(do
(save-password password)
(dispatch [:add-account account])
(when (not (:signed-up db)) (dispatch [:login-account address password]))))))
;(save-password password)
(dispatch-sync [:add-account account])
(dispatch [:login-account address password])))))
(register-handler :create-account
(-> (fn [db [_ password]]
(.createAccount geth password (fn [result] (account-created db result password)))
db)))
(defn login [db address]
(defn logged-in [db address]
(let [account (get-in db [:accounts address])]
(log/debug "Logged in: " address account)
(realm/close-account-realm)
(reset! realm/account-realm (realm/create-account-realm address))
(dispatch [:set :login {}])
(dispatch [:set :current-account account])
(dispatch [:initialize-protocol account])
(dispatch [:set :is-logged-in true])
(dispatch [:set :user-identity account])
(dispatch [:save-console])
(dispatch [:initialize-account account])
(when (:signed-up db) (dispatch [:navigate-to-clean default-view]))))
(register-handler :login-account
@ -60,7 +68,7 @@
success (zero? (count error))]
(log/debug "Logged in account: " address result)
(if success
(login db address)
(logged-in db address)
(dispatch [:set-in [:login :error] error])))))
db)))

View File

@ -40,7 +40,8 @@
:key row-id}]))
(defn create-account [event]
(dispatch [:console-create-account])
;(dispatch [:console-create-account])
(dispatch-sync [:reset-app])
(dispatch [:navigate-to :chat "console"]))
(defview accounts []

View File

@ -16,7 +16,7 @@
(dispatch [:set-in [:login :address] address]))
(defview account-view [{:keys [address photo-path name] :as account}]
[current-account [:get :current-account]]
[current-account [:get :user-identity]]
[touchable-highlight
{:onPress #(on-press address)}
[view st/account-container

View File

@ -43,7 +43,7 @@
(defn app-root []
(let [signed-up (subscribe [:get :signed-up])
view-id (subscribe [:get :view-id])
account (subscribe [:get :current-account])
account (subscribe [:get :user-identity])
keyboard-height (subscribe [:get :keyboard-height])]
(log/debug "Current account: " @account)
(r/create-class
@ -88,16 +88,13 @@
:my-profile [my-profile])))})))
(defn init []
(dispatch-sync [:initialize-db])
(dispatch-sync [:reset-app])
(dispatch [:initialize-crypt])
(dispatch [:initialize-geth])
(dispatch [:load-accounts])
(dispatch [:initialize-chats])
;protocol must be initialized after user enters password and we create account
;(dispatch [:initialize-protocol])
(dispatch [:load-user-phone-number])
(dispatch [:load-contacts])
(dispatch [:init-console-chat])
(dispatch [:init-chat])
;(dispatch [:init-chat])
(init-back-button-handler!)
(.registerComponent app-registry "StatusIm" #(r/reactify-component app-root)))

View File

@ -15,7 +15,7 @@
[status-im.models.chats :as chats]
[status-im.navigation.handlers :as nav]
[status-im.utils.handlers :refer [register-handler] :as u]
[status-im.persistence.realm :as r]
[status-im.persistence.realm.core :as r]
[status-im.handlers.server :as server]
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
[status-im.utils.phone-number :refer [format-phone-number]]
@ -31,9 +31,10 @@
(assoc db :show-actions show-actions)))
(register-handler :load-more-messages
(fn [{:keys [current-chat-id] :as db} _]
(let [all-loaded? (get-in db [:chats current-chat-id :all-loaded?])]
(if all-loaded?
(fn [{:keys [is-logged-in current-chat-id] :as db} _]
(let [all-loaded? (get-in db [:chats current-chat-id :all-loaded?])
account-realm-exists? (or (not= current-chat-id "console") is-logged-in)]
(if (or all-loaded? (not account-realm-exists?))
db
(let [messages-path [:chats current-chat-id :messages]
messages (get-in db messages-path)
@ -291,21 +292,22 @@
:content content})))))
(defn save-message-to-realm!
[{:keys [new-message current-chat-id]} _]
(when new-message
[{:keys [is-logged-in new-message current-chat-id]} _]
(when (and new-message is-logged-in)
(messages/save-message current-chat-id new-message)))
(defn save-commands-to-realm!
[{:keys [new-commands current-chat-id]} _]
[{:keys [is-logged-in new-commands current-chat-id]} _]
(when is-logged-in
(doseq [new-command new-commands]
(messages/save-message
current-chat-id
(dissoc new-command :rendered-preview :to-message))))
(dissoc new-command :rendered-preview :to-message)))))
(defn dispatch-responded-requests!
[{:keys [new-commands current-chat-id]} _]
(doseq [{:keys [to-message]} new-commands]
(when to-message
(doseq [{:keys [is-logged-in to-message]} new-commands]
(when (and to-message is-logged-in)
(dispatch [:request-answered! current-chat-id to-message]))))
(defn invoke-commands-handlers!
@ -409,6 +411,18 @@
((enrich init-chat))
((after load-commands!))))
(register-handler :save-console
(fn [db _]
(when-not (chats/chat-exists? "console")
(let [console-chat (get-in db [:chats "console"])]
(when console-chat
(do
(chats/create-chat console-chat)
(doseq [message (reverse (:messages console-chat))]
(messages/save-message "console" message))))))
db))
(defn initialize-chats
[{:keys [loaded-chats] :as db} _]
(let [chats (->> loaded-chats
@ -429,11 +443,13 @@
((enrich initialize-chats) load-chats!))
(defn store-message!
[{:keys [new-message]} [_ {chat-id :from}]]
(messages/save-message chat-id new-message))
[{:keys [is-logged-in new-message]} [_ {chat-id :from}]]
(if (or (not= chat-id "console") is-logged-in)
(messages/save-message chat-id new-message)))
(defn dispatch-request!
[{:keys [new-message]} [_ {chat-id :from}]]
(log/debug "Dispatching request: " new-message)
(when (= (:content-type new-message) content-type-command-request)
(dispatch [:add-request chat-id new-message])))
@ -455,15 +471,20 @@
(messages/save-message chat-id msg))))
(defmethod nav/preload-data! :chat
[{:keys [current-chat-id] :as db} [_ _ id]]
[{:keys [is-logged-in current-chat-id] :as db} [_ _ id]]
(let [chat-id (or id current-chat-id)
messages (get-in db [:chats chat-id :messages])
db' (assoc db :current-chat-id chat-id)]
(dispatch [:load-requests! chat-id])
db' (assoc db :current-chat-id chat-id)
account-realm-exists? (or (not= chat-id "console") is-logged-in)]
(when account-realm-exists?
(dispatch [:load-requests! chat-id]))
(if (seq messages)
db'
(-> db'
load-messages!
((fn [db]
(if account-realm-exists?
(load-messages! db)
db)))
init-chat))))
(defn prepare-chat
@ -525,17 +546,17 @@
(defn delete-messages!
[{:keys [current-chat-id]} _]
(r/write
(r/write :account
(fn []
(r/delete (r/get-by-field :msgs :chat-id current-chat-id)))))
(r/delete :account (r/get-by-field :account :msgs :chat-id current-chat-id)))))
(defn delete-chat!
[{:keys [current-chat-id]} _]
(r/write
(fn []
(-> (r/get-by-field :chats :chat-id current-chat-id)
(r/write :account
(fn [] :account
(->> (r/get-by-field :account :chats :chat-id current-chat-id)
(r/single)
(r/delete)))))
(r/delete :account)))))
(register-handler :leave-group-chat
;; todo oreder of operations tbd

View File

@ -1,14 +1,15 @@
(ns status-im.chat.handlers.requests
(:require [re-frame.core :refer [after dispatch enrich]]
[status-im.utils.handlers :refer [register-handler]]
[status-im.persistence.realm :as realm]
[status-im.persistence.realm.core :as realm]
[status-im.models.requests :as requests]
[status-im.utils.handlers :as u]))
(defn store-request!
[{:keys [new-request]}]
(realm/write
(fn []
(realm/create :requests new-request))))
[{:keys [is-logged-in new-request] :as db}]
(if (or (not= (:chat-id new-request) "console") is-logged-in)
(requests/save-request new-request)
db))
(defn add-request
[db [_ chat-id {:keys [msg-id content]}]]
@ -24,9 +25,9 @@
(defn load-requests!
[{:keys [current-chat-id] :as db} [_ chat-id]]
(let [chat-id' (or chat-id current-chat-id)
requests (-> :requests
;; todo maybe limit is needed
(realm/get-by-fields {:chat-id chat-id'
requests (-> ;; todo maybe limit is needed
(realm/get-by-fields :account :requests
{:chat-id chat-id'
:status "open"})
(realm/sorted :added :desc)
(realm/collection->map))
@ -35,10 +36,9 @@
(defn mark-request-as-answered!
[_ [_ chat-id message-id]]
(realm/write
(realm/write :account
(fn []
(-> :requests
(realm/get-by-fields
(-> (realm/get-by-fields :account :requests
{:chat-id chat-id
:message-id message-id})
(realm/single)

View File

@ -5,7 +5,8 @@
[status-im.protocol.state.storage :as s]
[status-im.models.chats :as c]
[status-im.components.styles :refer [default-chat-color]]
[status-im.utils.utils :refer [log on-error http-post toast]]
[status-im.utils.utils :refer [on-error http-post toast]]
[status-im.utils.logging :as log]
[status-im.utils.random :as random]
[status-im.utils.sms-listener :refer [add-sms-listener
remove-sms-listener]]
@ -198,14 +199,15 @@
(defn create-chat [handler]
(fn [db]
(let [{:keys [new-chat] :as db'} (handler db)]
(when new-chat
(log/debug new-chat)
(when (and new-chat (not= (:chat-id new-chat) "console"))
(c/create-chat new-chat))
(dissoc db' :new-chat))))
(def init
(create-chat
(fn [{:keys [chats] :as db}]
(if (chats "console")
(fn [{:keys [is-logged-in chats] :as db}]
(if is-logged-in
db
(-> db
(assoc-in [:chats "console"] console-chat)

View File

@ -4,7 +4,7 @@
[status-im.utils.handlers :as u]
[status-im.utils.utils :refer [http-get toast]]
[clojure.string :as s]
[status-im.persistence.realm :as realm]
[status-im.persistence.realm.core :as realm]
[status-im.components.jail :as j]
[status-im.utils.types :refer [json->clj]]
[status-im.commands.utils :refer [reg-handler]]))
@ -13,12 +13,16 @@
(defn load-commands!
[_ [identity]]
(let [is-console? (= identity "console")
schema (if is-console?
:base
:account)]
(dispatch [::fetch-commands! identity])
;; todo uncomment
#_(if-let [{:keys [file]} (realm/get-one-by-field :commands :chat-id
identity)]
#_(if-let [{:keys [file]} (realm/get-one-by-field schema :commands
:chat-id identity)]
(dispatch [::parse-commands! identity file])
(dispatch [::fetch-commands! identity])))
(dispatch [::fetch-commands! identity]))))
(defn fetch-commands!
[db [identity]]
@ -73,7 +77,11 @@
(defn save-commands-js!
[_ [id file]]
(realm/create-object :commands {:chat-id id :file file}))
(let [is-console? (= id "console")
schema (if is-console?
:base
:account)]
(realm/create-object schema :commands {:chat-id id :file file})))
(defn loading-failed!
[db [id reason details]]

View File

@ -1,14 +1,14 @@
(ns status-im.contacts.validations
(:require [cljs.spec :as s]
[cljsjs.web3]
[status-im.persistence.realm :as realm]))
[status-im.persistence.realm.core :as realm]))
(defn is-address? [s]
(.isAddress js/Web3.prototype s))
(defn unique-identity? [identity]
(println identity)
(not (realm/exists? :contacts :whisper-identity identity)))
(not (realm/exists? :account :contacts :whisper-identity identity)))
(defn valid-length? [identity]
(let [length (count identity)]

View File

@ -11,8 +11,9 @@
;; initial state of app-db
(def app-db {:identity-password "replace-me-with-user-entered-password"
:identity "me"
:is-logged-in false
:accounts {}
:current-account false
:user-identity nil
:contacts []
:contacts-ids #{}
:selected-contacts #{}
@ -23,7 +24,7 @@
:chats-updated-signal 0
:show-actions false
:selected-participants #{}
:signed-up true
:signed-up false
:view-id default-view
:navigation-stack (list default-view)
;; TODO fix hardcoded values

View File

@ -1,12 +1,11 @@
(ns status-im.discovery.model
;status-im.models.discoveries
(:require [status-im.utils.logging :as log]
[status-im.persistence.realm :as realm]
[status-im.persistence.realm :as r]))
[status-im.persistence.realm.core :as r]))
(defn get-tag [tag]
(log/debug "Getting tag: " tag)
(-> (r/get-by-field :tag :name tag)
(-> (r/get-by-field :base :tag :name tag)
(r/single-cljs)))
(defn decrease-tag-counter [tag]
@ -15,8 +14,9 @@
(if tag-object
(let [counter (dec (:count tag-object))]
(if (zero? counter)
(realm/delete tag-object)
(realm/create :tag {:name tag
(r/delete :base tag-object)
(r/create :base :tag
{:name tag
:count counter}
true))))))
@ -24,7 +24,8 @@
(let [tag (:name tag)
tag-object (get-tag tag)]
(if tag-object
(realm/create :tag {:name tag
(r/create :base :tag
{:name tag
:count (inc (:count tag-object))}
true))))
@ -37,32 +38,33 @@
(increase-tag-counter tag)))
(defn get-tags [whisper-id]
(:tags (-> (r/get-by-field :discoveries :whisper-id whisper-id)
(:tags (-> (r/get-by-field :base :discoveries :whisper-id whisper-id)
(r/single-cljs))))
(defn- create-discovery [{:keys [tags] :as discovery}]
(log/debug "Creating discovery: " discovery tags)
(realm/create :discoveries discovery true)
(r/create :base :discoveries discovery true)
(increase-tags-counter tags))
(defn- update-discovery [{:keys [whisper-id tags] :as discovery}]
(let [old-tags (get-tags whisper-id)
tags (map :name tags)]
(decrease-tags-counter old-tags)
(realm/create :discoveries discovery true)
(r/create :base :discoveries discovery true)
(increase-tags-counter tags)))
(defn- discovery-exist? [discoveries discovery]
(some #(= (:whisper-id discovery) (:whisper-id %)) discoveries))
(defn discovery-list []
(->> (-> (r/get-all :discoveries)
(->> (-> (r/get-all :base :discoveries)
(r/sorted :last-updated :desc)
r/collection->map)
(map #(update % :tags vals))))
(defn- add-discoveries [discoveries]
(realm/write (fn []
(r/write :base
(fn []
(let [db-discoveries (discovery-list)]
(mapv (fn [discovery]
(if-not (discovery-exist? db-discoveries
@ -75,7 +77,7 @@
(add-discoveries discoveries))
(defn discoveries-by-tag [tag limit]
(let [discoveries (-> (r/get-by-filter :discoveries (str "tags.name = '" tag "'"))
(let [discoveries (-> (r/get-by-filter :base :discoveries (str "tags.name = '" tag "'"))
(r/sorted :last-updated :desc))]
(log/debug "Discoveries by tag: " tag)
(if (pos? limit)
@ -83,7 +85,7 @@
discoveries)))
(defn all-tags []
(-> (r/get-all :tag)
(-> (r/get-all :base :tag)
(r/sorted :count :desc)
r/collection->map))

View File

@ -1,7 +1,7 @@
(ns status-im.group-settings.handlers
(:require [re-frame.core :refer [debug dispatch after enrich]]
[status-im.utils.handlers :refer [register-handler]]
[status-im.persistence.realm :as r]
[status-im.persistence.realm.core :as r]
[status-im.chat.handlers :refer [delete-messages!]]
[status-im.protocol.api :as api]
[status-im.utils.random :as random]
@ -20,8 +20,9 @@
[db-name property-name]
(fn [{:keys [current-chat-id] :as db} _]
(let [property (db-name db)]
(r/write (fn []
(-> (r/get-by-field :chats :chat-id current-chat-id)
(r/write :account
(fn []
(-> (r/get-by-field :account :chats :chat-id current-chat-id)
(r/single)
(aset (name property-name) property)))))))
@ -76,9 +77,9 @@
(defn remove-members-from-realm!
[{:keys [current-chat-id selected-participants] :as db} _]
(let [chat (get-in db [:chats current-chat-id])]
(r/write
(r/write :account
(fn []
(r/create
(r/create :account
:chats
(update chat :contacts remove-identities selected-participants)
true)))))

View File

@ -1,6 +1,6 @@
(ns status-im.handlers
(:require
[re-frame.core :refer [after dispatch debug]]
[re-frame.core :refer [after dispatch dispatch-sync debug]]
[schema.core :as s :include-macros true]
[status-im.db :refer [app-db schema]]
[status-im.persistence.simple-kv-store :as kv]
@ -56,12 +56,34 @@
(assoc-in db [:animations k] v)))
(register-handler :initialize-db
(fn [_ _]
(assoc app-db
:user-identity nil)))
(register-handler :initialize-account-db
(fn [_ _]
(assoc app-db
:signed-up (storage/get kv/kv-store :signed-up)
:user-identity (protocol/stored-identity nil)
:password (storage/get kv/kv-store :password))))
(register-handler :initialize-account
(u/side-effect!
(fn [_ [_ account]]
(dispatch [:initialize-protocol account])
(dispatch [:initialize-chats])
(dispatch [:load-contacts])
; TODO: initialize protocol here
(dispatch [:init-chat]))))
(register-handler :reset-app
(u/side-effect!
(fn [_ _]
(dispatch [:initialize-db])
(dispatch [:load-accounts])
(dispatch [:init-console-chat])
(dispatch [:load-commands! "console"]))))
(register-handler :initialize-crypt
(u/side-effect!
(fn [_ _]

View File

@ -1,22 +1,22 @@
(ns status-im.models.accounts
(:require [status-im.persistence.realm :as r]))
(:require [status-im.persistence.realm.core :as r]))
(defn get-accounts []
(-> (r/get-all :accounts)
(-> (r/get-all :base :accounts)
r/collection->map))
(defn create-account [{:keys [address public-key] :as account}]
(->> account
(r/create :accounts)))
(r/create :base :accounts)))
(defn save-accounts [accounts]
(r/write #(mapv create-account accounts)))
(r/write :base #(mapv create-account accounts)))
;;;;;;;;;;;;;;;;;;;;----------------------------------------------
(defn accounts-list []
(r/get-all :accounts))
(r/get-all :base :accounts))
(defn account-by-address [address]
(r/single-cljs (r/get-by-field :accounts :address address)))
(r/single-cljs (r/get-by-field :base :accounts :address address)))

View File

@ -1,7 +1,7 @@
(ns status-im.models.chats
(:require [clojure.set :refer [difference]]
[re-frame.core :refer [dispatch]]
[status-im.persistence.realm :as r]
[status-im.persistence.realm.core :as r]
[status-im.utils.random :as random :refer [timestamp]]
[clojure.string :refer [join blank?]]
[status-im.utils.logging :as log]
@ -12,7 +12,7 @@
(defn chat-name-from-contacts [identities]
(let [chat-name (->> identities
(map (fn [identity]
(-> (r/get-by-field :contacts :whisper-identity identity)
(-> (r/get-by-field :account :contacts :whisper-identity identity)
(r/single-cljs)
:name)))
(filter identity)
@ -25,7 +25,7 @@
chat-id))
(defn chat-exists? [chat-id]
(r/exists? :chats :chat-id chat-id))
(r/exists? :account :chats :chat-id chat-id))
(defn add-status-message [chat-id]
;; TODO Get real status
@ -42,17 +42,20 @@
(defn create-chat
([{:keys [last-msg-id] :as chat}]
(let [chat (assoc chat :last-msg-id (or last-msg-id ""))]
(r/write #(r/create :chats chat))))
(log/debug "Creating chat" chat)
(r/write :account #(r/create :account :chats chat))))
([db chat-id identities group-chat? chat-name]
(log/debug "Creating chat" chat-id)
(when-not (chat-exists? chat-id)
(let [chat-name (or chat-name
(get-chat-name chat-id identities))
_ (log/debug "creating chat" chat-name)]
(r/write
(r/write :account
(fn []
(let [contacts (mapv (fn [ident]
{:identity ident}) identities)]
(r/create :chats {:chat-id chat-id
(r/create :account :chats
{:chat-id chat-id
:is-active true
:name chat-name
:group-chat group-chat?
@ -62,12 +65,12 @@
(add-status-message chat-id)))))
(defn chat-contacts [chat-id]
(-> (r/get-by-field :chats :chat-id chat-id)
(-> (r/get-by-field :account :chats :chat-id chat-id)
(r/single)
(aget "contacts")))
(defn re-join-group-chat [db group-id identities group-name]
(r/write
(r/write :account
(fn []
(let [new-identities (set identities)
only-old-contacts (->> (chat-contacts group-id)
@ -78,7 +81,8 @@
(mapv (fn [ident]
{:identity ident}))
(concat only-old-contacts))]
(r/create :chats {:chat-id group-id
(r/create :account :chats
{:chat-id group-id
:is-active true
:name group-name
:contacts contacts} true))))
@ -89,23 +93,23 @@
(map #(update % :contacts vals) chats))
(defn chats-list []
(-> (r/get-all :chats)
(-> (r/get-all :account :chats)
(r/sorted :timestamp :desc)
r/collection->map
normalize-contacts))
(defn chat-by-id [chat-id]
(-> (r/get-by-field :chats :chat-id chat-id)
(-> (r/get-by-field :account :chats :chat-id chat-id)
(r/single-cljs)
(r/list-to-array :contacts)))
(defn chat-by-id2 [chat-id]
(-> (r/get-by-field :chats :chat-id chat-id)
(-> (r/get-by-field :account :chats :chat-id chat-id)
r/collection->map
first))
(defn chat-add-participants [chat-id identities]
(r/write
(r/write :account
(fn []
(let [contacts (chat-contacts chat-id)]
(doseq [contact-identity identities]
@ -118,23 +122,24 @@
;; TODO deprecated? (is there need to remove multiple member at once?)
(defn chat-remove-participants [chat-id identities]
(r/write
(r/write :account
(fn []
(let [query (include-query :identity identities)
chat (r/single (r/get-by-field :chats :chat-id chat-id))]
chat (r/single (r/get-by-field :account :chats :chat-id chat-id))]
(-> (aget chat "contacts")
(r/filtered query)
(.forEach (fn [object _ _]
(aset object "is-in-chat" false))))))))
(defn active-group-chats []
(let [results (r/filtered (r/get-all :chats)
(let [results (r/filtered (r/get-all :account :chats)
"group-chat = true && is-active = true")]
(js->clj (.map results (fn [object _ _]
(aget object "chat-id"))))))
(defn set-chat-active [chat-id active?]
(r/write (fn []
(-> (r/get-by-field :chats :chat-id chat-id)
(r/write :account
(fn []
(-> (r/get-by-field :account :chats :chat-id chat-id)
(r/single)
(aset "is-active" active?)))))

View File

@ -1,11 +1,11 @@
(ns status-im.models.contacts
(:require [status-im.persistence.realm :as r]
(:require [status-im.persistence.realm.core :as r]
[status-im.utils.identicon :refer [identicon]]
[status-im.persistence.realm-queries :refer [include-query
exclude-query]]))
(defn get-contacts []
(-> (r/get-all :contacts)
(-> (r/get-all :account :contacts)
(r/sorted :name :asc)
r/collection->map))
@ -13,22 +13,22 @@
(->> {:name (or name "")
:photo-path (or photo-path (identicon whisper-identity))}
(merge contact)
(r/create :contacts)))
(r/create :account :contacts)))
(defn save-contacts [contacts]
(r/write #(mapv create-contact contacts)))
(r/write :account #(mapv create-contact contacts)))
;;;;;;;;;;;;;;;;;;;;----------------------------------------------
(defn contacts-list []
(r/sorted (r/get-all :contacts) :name :asc))
(r/sorted (r/get-all :account :contacts) :name :asc))
(defn contacts-list-exclude [exclude-idents]
(if (empty? exclude-idents)
(contacts-list)
(let [query (exclude-query :whisper-identity exclude-idents)]
(-> (r/get-all :contacts)
(-> (r/get-all :account :contacts)
(r/filtered query)
(r/sorted :name :asc)))))
@ -36,9 +36,9 @@
(if (empty? include-indents)
()
(let [query (include-query :whisper-identity include-indents)]
(-> (r/get-all :contacts)
(-> (r/get-all :account :contacts)
(r/filtered query)
(r/sorted :name :asc)))))
(defn contact-by-identity [identity]
(r/single-cljs (r/get-by-field :contacts :whisper-identity identity)))
(r/single-cljs (r/get-by-field :account :contacts :whisper-identity identity)))

View File

@ -1,5 +1,5 @@
(ns status-im.models.messages
(:require [status-im.persistence.realm :as r]
(:require [status-im.persistence.realm.core :as r]
[re-frame.core :refer [dispatch]]
[cljs.reader :refer [read-string]]
[status-im.utils.random :refer [timestamp]]
@ -28,8 +28,8 @@
;; todo remove chat-id parameter
[chat-id {:keys [msg-id content]
:as message}]
(when-not (r/exists? :msgs :msg-id msg-id)
(r/write
(when-not (r/exists? :account :msgs :msg-id msg-id)
(r/write :account
(fn []
(let [content' (if (string? content)
content
@ -40,7 +40,7 @@
:content content'
:timestamp (timestamp)
:delivery-status nil})]
(r/create :msgs message' true))))))
(r/create :account :msgs message' true))))))
(defn command-type? [type]
(contains?
@ -50,7 +50,7 @@
(defn get-messages
([chat-id] (get-messages chat-id 0))
([chat-id from]
(->> (-> (r/get-by-field :msgs :chat-id chat-id)
(->> (-> (r/get-by-field :account :msgs :chat-id chat-id)
(r/sorted :timestamp :desc)
(r/page from (+ from c/default-number-of-messages))
(r/collection->map))
@ -63,7 +63,7 @@
(defn update-message! [{:keys [msg-id] :as msg}]
(log/debug "update-message!" msg)
(r/write
(r/write :account
(fn []
(when (r/exists? :msgs :msg-id msg-id)
(r/create :msgs msg true)))))
(when (r/exists? :account :msgs :msg-id msg-id)
(r/create :account :msgs msg true)))))

View File

@ -0,0 +1,21 @@
(ns status-im.models.requests
(:require [status-im.persistence.realm.core :as r]))
(defn get-requests []
(-> (r/get-all :account :requests)
r/collection->map))
(defn create-request [request]
(r/create :account :requests request true))
(defn save-request [request}]
(r/write :account
(fn []
(create-request request))))
(defn save-requests [requests]
(r/write :account #(mapv create-request requests)))
(defn requests-list []
(r/get-all :account :requests))

View File

@ -1,200 +0,0 @@
(ns status-im.persistence.realm
(:require [cljs.reader :refer [read-string]]
[status-im.components.styles :refer [default-chat-color]]
[status-im.utils.types :refer [to-string]]
[status-im.utils.utils :as u]
[clojure.string :as str])
(:refer-clojure :exclude [exists?]))
(def opts {:schema [{:name :contacts
:primaryKey :whisper-identity
:properties {:phone-number {:type "string"
:optional true}
:whisper-identity "string"
:name {:type "string"
:optional true}
:photo-path {:type "string"
:optinal true}}}
{:name :accounts
:primaryKey :address
:properties {:address "string"
:public-key "string"
:name "string"
:photo-path "string"}}
{:name :requests
:properties {:message-id :string
:chat-id :string
:type :string
:status {:type :string
:default "open"}
:added :date}}
{:name :kv-store
:primaryKey :key
:properties {:key "string"
:value "string"}}
{:name :msgs
:primaryKey :msg-id
:properties {:msg-id "string"
:from "string"
:to {:type "string"
:optional true}
:content "string" ;; TODO make it ArrayBuffer
:content-type "string"
:timestamp "int"
:chat-id {:type "string"
:indexed true}
:outgoing "bool"
:delivery-status {:type "string"
:optional true}
:same-author "bool"
:same-direction "bool"
:preview {:type :string
:optional true}}}
{:name :chat-contact
:properties {:identity "string"
:is-in-chat {:type "bool"
:default true}}}
{:name :chats
:primaryKey :chat-id
:properties {:chat-id "string"
:name "string"
:color {:type "string"
:default default-chat-color}
:group-chat {:type "bool"
:indexed true}
:is-active "bool"
:timestamp "int"
:contacts {:type "list"
:objectType "chat-contact"}
:dapp-url {:type :string
:optional true}
:dapp-hash {:type :int
:optional true}
:last-msg-id "string"}}
{:name :commands
:primaryKey :chat-id
:properties {:chat-id "string"
:file "string"}}
{:name :tag
:primaryKey :name
:properties {:name "string"
:count {:type "int"
:optional true
:default 0}}}
{:name :discoveries
:primaryKey :whisper-id
:properties {:name "string"
:status "string"
:whisper-id "string"
:photo "string"
:location "string"
:tags {:type "list"
:objectType "tag"}
:last-updated "date"}}]})
(def realm-class (u/require "realm"))
(def realm (when (cljs.core/exists? js/window)
(realm-class. (clj->js opts))))
(def schema-by-name (->> (:schema opts)
(mapv (fn [{:keys [name] :as schema}]
[name schema]))
(into {})))
(defn field-type [schema-name field]
(let [field-def (get-in schema-by-name [schema-name :properties field])]
(if (map? field-def)
(:type field-def)
field-def)))
(defn write [f]
(.write realm f))
(defn create
([schema-name obj]
(create schema-name obj false))
([schema-name obj update?]
(.create realm (to-string schema-name) (clj->js obj) update?)))
(defn create-object
[schema-name obj]
(write (fn [] (create schema-name obj true))))
(defn and-q [queries]
(str/join " and " queries))
(defmulti to-query (fn [schema-name operator field value]
operator))
(defmethod to-query :eq [schema-name operator field value]
(let [value (to-string value)
query (str (name field) "=" (if (= "string" (name (field-type
schema-name field)))
(str "\"" value "\"")
value))]
query))
(defn get-by-filter [schema-name filter]
(-> (.objects realm (name schema-name))
(.filtered filter)))
(defn get-by-field [schema-name field value]
(let [q (to-query schema-name :eq field value)]
(.filtered (.objects realm (name schema-name)) q)))
(defn get-by-fields [schema-name fields]
(let [queries (map (fn [[k v]]
(to-query schema-name :eq k v))
fields)]
(.filtered (.objects realm (name schema-name)) (and-q queries))))
(defn get-all [schema-name]
(.objects realm (to-string schema-name)))
(defn sorted [results field-name order]
(.sorted results (to-string field-name) (if (= order :asc)
false
true)))
(defn filtered [results filter-query]
(.filtered results filter-query))
(defn page [results from to]
(js/Array.prototype.slice.call results from to))
(defn single [result]
(-> (aget result 0)))
(defn single-cljs [result]
(some-> (aget result 0)
(js->clj :keywordize-keys true)))
(defn cljs-list [results]
(-> (js->clj results :keywordize-keys true)
(vals)))
(defn list-to-array [record list-field]
(update-in record [list-field] (comp vec vals)))
(defn decode-value [{:keys [key value]}]
(read-string value))
(defn delete [obj]
(.delete realm obj))
(defn exists? [schema-name field value]
(pos? (.-length (get-by-field schema-name field value))))
(defn get-count [objs]
(.-length objs))
(defn get-list [schema-name]
(vals (js->clj (.objects realm (to-string schema-name)) :keywordize-keys true)))
(defn collection->map [collection]
(-> (.map collection (fn [object _ _] object))
(js->clj :keywordize-keys true)))
(defn get-one-by-field [schema-name field value]
(single-cljs (get-by-field schema-name field value)))

View File

@ -0,0 +1,151 @@
(ns status-im.persistence.realm.core
(:require [cljs.reader :refer [read-string]]
[status-im.components.styles :refer [default-chat-color]]
[status-im.utils.types :refer [to-string]]
[status-im.utils.utils :as u]
[status-im.utils.logging :as log]
[status-im.persistence.realm.schemas :refer [base account]]
[clojure.string :as str])
(:refer-clojure :exclude [exists?]))
(def realm-class (u/require "realm"))
(def base-realm
(when (cljs.core/exists? js/window)
(realm-class. (clj->js base))))
(def account-realm (atom nil))
(defn create-account-realm [address]
(let [opts (merge account {:path (str address ".realm")})]
(when (cljs.core/exists? js/window)
(realm-class. (clj->js opts)))))
(defn realm [schema]
(log/debug "Schema: " schema)
(case schema
:base base-realm
:account @account-realm))
(defn close [schema]
(let [realm-db (realm schema)]
(when realm-db
(.close realm-db))))
(defn close-account-realm []
(close :account)
(reset! account-realm nil))
(defn get-schema-by-name [opts]
(->> (:schema opts)
(mapv (fn [{:keys [name] :as schema}]
[name schema]))
(into {})))
(def schema-by-name
{:base (get-schema-by-name base)
:account (get-schema-by-name account)})
(defn field-type [schema schema-name field]
(let [schema-by-name (get schema-by-name schema)
field-def (get-in schema-by-name [schema-name :properties field])]
(if (map? field-def)
(:type field-def)
field-def)))
(defn write [schema f]
(.write (realm schema) f))
(defn create
([schema schema-name obj]
(create schema schema-name obj false))
([schema schema-name obj update?]
(.create (realm schema) (to-string schema-name) (clj->js obj) update?)))
(defn create-object
[schema schema-name obj]
(write schema (fn [] (create schema schema-name obj true))))
(defn and-q [queries]
(str/join " and " queries))
(defmulti to-query (fn [schema schema-name operator field value]
operator))
(defmethod to-query :eq [schema schema-name operator field value]
(let [value (to-string value)
field-type (field-type schema schema-name field)
query (str (name field) "=" (if (= "string" (name field-type))
(str "\"" value "\"")
value))]
query))
(defn get-by-filter [schema schema-name filter]
(log/debug "Get by filter: " schema schema-name field)
(-> (.objects (realm schema) (name schema-name))
(.filtered filter)))
(defn get-by-field [schema schema-name field value]
(log/debug "Get by field: " schema schema-name field value)
(let [q (to-query schema schema-name :eq field value)]
(.filtered (.objects (realm schema) (name schema-name)) q)))
(defn get-by-fields [schema schema-name fields]
(log/debug "Get by fields: " schema schema-name fields)
(let [queries (map (fn [[k v]]
(to-query schema schema-name :eq k v))
fields)]
(.filtered (.objects (realm schema) (name schema-name)) (and-q queries))))
(defn get-all [schema schema-name]
(log/debug "Get all: " schema schema-name)
(.objects (realm schema) (to-string schema-name)))
(defn sorted [results field-name order]
(.sorted results (to-string field-name) (if (= order :asc)
false
true)))
(defn filtered [results filter-query]
(.filtered results filter-query))
(defn page [results from to]
(js/Array.prototype.slice.call results from to))
(defn single [result]
(-> (aget result 0)))
(defn single-cljs [result]
(some-> (aget result 0)
(js->clj :keywordize-keys true)))
(defn cljs-list [results]
(-> (js->clj results :keywordize-keys true)
(vals)))
(defn list-to-array [record list-field]
(update-in record [list-field] (comp vec vals)))
(defn decode-value [{:keys [key value]}]
(read-string value))
(defn delete [schema obj]
(.delete (realm schema) obj))
(defn exists? [schema schema-name field value]
(pos? (.-length (get-by-field schema schema-name field value))))
(defn get-count [objs]
(.-length objs))
(defn get-list [schema schema-name]
(log/debug "Get list: " schema schema-name)
(vals (js->clj (.objects (realm schema) (to-string schema-name)) :keywordize-keys true)))
(defn collection->map [collection]
(-> (.map collection (fn [object _ _] object))
(js->clj :keywordize-keys true)))
(defn get-one-by-field [schema schema-name field value]
(single-cljs (get-by-field schema schema-name field value)))

View File

@ -0,0 +1,100 @@
(ns status-im.persistence.realm.schemas
(:require [status-im.components.styles :refer [default-chat-color]]))
(def base {:schema [{:name :accounts
:primaryKey :address
:properties {:address "string"
:public-key "string"
:name "string"
:photo-path "string"}}
{:name :tag
:primaryKey :name
:properties {:name "string"
:count {:type "int"
:optional true
:default 0}}}
{:name :discoveries
:primaryKey :whisper-id
:properties {:name "string"
:status "string"
:whisper-id "string"
:photo "string"
:location "string"
:tags {:type "list"
:objectType "tag"}
:last-updated "date"}}
{:name :kv-store
:primaryKey :key
:properties {:key "string"
:value "string"}}
{:name :commands
:primaryKey :chat-id
:properties {:chat-id "string"
:file "string"}}]
:schemaVersion 0})
(def account {:schema [{:name :contacts
:primaryKey :whisper-identity
:properties {:phone-number {:type "string"
:optional true}
:whisper-identity "string"
:name {:type "string"
:optional true}
:photo-path {:type "string"
:optinal true}}}
{:name :requests
:properties {:message-id :string
:chat-id :string
:type :string
:status {:type :string
:default "open"}
:added :date}}
{:name :kv-store
:primaryKey :key
:properties {:key "string"
:value "string"}}
{:name :msgs
:primaryKey :msg-id
:properties {:msg-id "string"
:from "string"
:to {:type "string"
:optional true}
:content "string" ;; TODO make it ArrayBuffer
:content-type "string"
:timestamp "int"
:chat-id {:type "string"
:indexed true}
:outgoing "bool"
:delivery-status {:type "string"
:optional true}
:same-author "bool"
:same-direction "bool"
:preview {:type :string
:optional true}}}
{:name :chat-contact
:properties {:identity "string"
:is-in-chat {:type "bool"
:default true}}}
{:name :chats
:primaryKey :chat-id
:properties {:chat-id "string"
:name "string"
:color {:type "string"
:default default-chat-color}
:group-chat {:type "bool"
:indexed true}
:is-active "bool"
:timestamp "int"
:contacts {:type "list"
:objectType "chat-contact"}
:dapp-url {:type :string
:optional true}
:dapp-hash {:type :int
:optional true}
:last-msg-id "string"}}
{:name :commands
:primaryKey :chat-id
:properties {:chat-id "string"
:file "string"}}]
:schemaVersion 0})

View File

@ -1,25 +1,29 @@
(ns status-im.persistence.simple-kv-store
(:require [status-im.protocol.state.storage :as st]
[status-im.persistence.realm :as r]
[status-im.persistence.realm.core :as r]
[status-im.utils.types :refer [to-edn-string]]))
(defrecord SimpleKvStore []
(defrecord SimpleKvStore [schema]
st/Storage
(put [_ key value]
(r/write
(r/write schema
(fn []
(r/create :kv-store {:key key
(r/create schema :kv-store
{:key key
:value (to-edn-string value)} true))))
(get [_ key]
(some-> (r/get-by-field :kv-store :key key)
(some-> (r/get-by-field schema :kv-store :key key)
(r/single-cljs)
(r/decode-value)))
(contains-key? [_ key]
(r/exists? :kv-store :key key))
(r/exists? schema :kv-store :key key))
(delete [_ key]
(r/write (fn []
(-> (r/get-by-field :kv-store :key key)
(r/write schema
(fn []
(->> (r/get-by-field schema :kv-store :key key)
(r/single)
(r/delete))))))
(r/delete schema))))))
(def kv-store (->SimpleKvStore))
(def kv-store (->SimpleKvStore :account))
(def base-kv-store (->SimpleKvStore :base))