Merge pull request #155 from status-im/feature/#124

Feature/#124
This commit is contained in:
Jarrad 2016-07-19 16:23:06 +02:00 committed by GitHub
commit 040ce74593
55 changed files with 1074 additions and 406 deletions

View File

@ -21,7 +21,8 @@
"react-native-camera", "react-native-camera",
"react-native-qrcode", "react-native-qrcode",
"react-native-orientation", "react-native-orientation",
"identicon.js" "identicon.js",
"react-native-fs"
], ],
"imageDirs": [ "imageDirs": [
"images" "images"

View File

@ -133,6 +133,7 @@ dependencies {
compile project(':react-native-camera') compile project(':react-native-camera')
compile project(':react-native-status') compile project(':react-native-status')
compile project(':react-native-orientation') compile project(':react-native-orientation')
compile project(':react-native-fs')
//compile(name:'statusgo-android-16', ext:'aar') //compile(name:'statusgo-android-16', ext:'aar')
compile(group: 'status-im', name: 'status-go', version: '0.1.0-201607011545-da53ec', ext: 'aar') compile(group: 'status-im', name: 'status-go', version: '0.1.0-201607011545-da53ec', ext: 'aar')

View File

@ -29,6 +29,8 @@ import com.lwansbrough.RCTCamera.*;
import com.i18n.reactnativei18n.ReactNativeI18n; import com.i18n.reactnativei18n.ReactNativeI18n;
import android.content.res.Configuration; import android.content.res.Configuration;
import com.rnfs.RNFSPackage;
public class MainActivity extends ReactActivity { public class MainActivity extends ReactActivity {
private static final String TAG = "MainActivity"; private static final String TAG = "MainActivity";
@ -112,6 +114,7 @@ public class MainActivity extends ReactActivity {
new RCTCameraPackage(), new RCTCameraPackage(),
new SmsListener(this), new SmsListener(this),
new OrientationPackage(this), new OrientationPackage(this),
new RNFSPackage(),
new GethPackage() new GethPackage()
); );
} }

View File

@ -117,7 +117,7 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE
case GethMessages.MSG_LOGGED_IN: case GethMessages.MSG_LOGGED_IN:
callback = unlockAccountCallbacks.remove(callbackIdentifier); callback = unlockAccountCallbacks.remove(callbackIdentifier);
if (callback != null) { if (callback != null) {
callback.invoke(null, "{ \"result\": \"" + data.getString("result") + "\"}"); callback.invoke(data.getString("result"));
} }
break; break;
default: default:

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 284 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1017 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 188 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 314 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 410 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

View File

@ -26,3 +26,6 @@ project(':react-native-camera').projectDir = new File(rootProject.projectDir,
include ':react-native-orientation', ':app' include ':react-native-orientation', ':app'
project(':react-native-orientation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-orientation/android') project(':react-native-orientation').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-orientation/android')
include ':react-native-fs'
project(':react-native-fs').projectDir = new File(settingsDir, '../node_modules/react-native-fs/android')

View File

@ -15,15 +15,16 @@
"react-native-camera": "github:codyhazelwood/react-native-camera", "react-native-camera": "github:codyhazelwood/react-native-camera",
"react-native-circle-checkbox": "^0.1.3", "react-native-circle-checkbox": "^0.1.3",
"react-native-contacts": "^0.2.4", "react-native-contacts": "^0.2.4",
"react-native-fs": "^1.5.1",
"react-native-i18n": "0.0.8", "react-native-i18n": "0.0.8",
"react-native-invertible-scroll-view": "^1.0.0", "react-native-invertible-scroll-view": "^1.0.0",
"react-native-linear-gradient": "1.5.7", "react-native-linear-gradient": "1.5.7",
"react-native-loading-spinner-overlay": "0.0.8", "react-native-loading-spinner-overlay": "0.0.8",
"react-native-orientation": "^1.17.0",
"react-native-qrcode": "^0.2.2", "react-native-qrcode": "^0.2.2",
"react-native-randombytes": "^2.1.0", "react-native-randombytes": "^2.1.0",
"react-native-status": "git+ssh://git@github.com/status-im/react-native-status",
"react-native-vector-icons": "^1.3.4", "react-native-vector-icons": "^1.3.4",
"react-native-orientation": "^1.17.0", "realm": "^0.14.0"
"realm": "^0.11.1",
"react-native-status": "git+ssh://git@github.com/status-im/react-native-status"
} }
} }

View File

@ -1,11 +1,18 @@
(ns status-im.accounts.handlers (ns status-im.accounts.handlers
(:require [status-im.models.accounts :as accounts] (: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.utils.logging :as log]
[status-im.components.react :refer [geth]] [status-im.components.react :refer [geth]]
[status-im.utils.types :refer [json->clj]] [status-im.utils.types :refer [json->clj]]
[status-im.persistence.simple-kv-store :as kv] [status-im.persistence.simple-kv-store :as kv]
[status-im.protocol.state.storage :as storage] [status-im.protocol.state.storage :as storage]
[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]]
status-im.accounts.login.handlers
[clojure.string :as str])) [clojure.string :as str]))
@ -20,26 +27,76 @@
(defn save-password [password] (defn save-password [password]
(storage/put kv/kv-store :password password)) (storage/put kv/kv-store :password password))
(defn account-created [result password] (defn account-created [db result password]
(let [data (json->clj result) (let [data (json->clj result)
public-key (:pubkey data) public-key (:pubkey data)
address (:address data) address (:address data)
account {:public-key public-key account {:public-key public-key
:address address}] :address address
(log/debug "Created account: " result) :name address
:photo-path (identicon address)}
]
(log/debug "account-created: " account)
(when (not (str/blank? public-key)) (when (not (str/blank? public-key))
(do (do
(save-password password) ;(save-password password)
(dispatch [:login-account address password]) (dispatch-sync [:add-account account])
(dispatch [:initialize-protocol account]) (dispatch [:login-account address password])))))
(dispatch [:add-account account])))))
(register-handler :create-account (register-handler :create-account
(-> (fn [db [_ password]] (-> (fn [db [_ password]]
(.createAccount geth password (fn [result] (account-created result password))) (.createAccount geth password (fn [result] (account-created db result password)))
db))) db)))
(defn initialize-account [db account]
(let [is-login-screen? (= (:view-id db) :login)]
(dispatch [:set :login {}])
(dispatch [:set :is-logged-in true])
(dispatch [:set :user-identity account])
(dispatch [:initialize-account account])
(when is-login-screen? (dispatch [:navigate-to-clean default-view]))))
(defn logged-in [db address]
(let [account (get-in db [:accounts address])
is-login-screen? (= (:view-id db) :login)
new-account? (not is-login-screen?)]
(log/debug "Logged in: " address account)
(realm/change-account-realm address new-account?
#(if (nil? %)
(initialize-account db account)
(log/debug "Error changing acount realm: " %)))))
(register-handler :login-account (register-handler :login-account
(-> (fn [db [_ address password]] (-> (fn [db [_ address password]]
(.login geth address password (fn [result] (log/debug "Logged in account: " address result))) (.login geth address password (fn [result]
db))) (let [data (json->clj result)
error (:error data)
success (zero? (count error))]
(log/debug "Logged in account: " address result)
(if success
(logged-in db address)
(dispatch [:set-in [:login :error] error])))))
db)))
(defn load-accounts! [db _]
(let [accounts (->> (accounts/get-accounts)
(map (fn [{:keys [address] :as account}]
[address account]))
(into {}))]
(assoc db :accounts accounts)))
(register-handler :load-accounts load-accounts!)
(defn console-create-account [db _]
(let [msg-id (random/id)]
(dispatch [:received-msg
{:msg-id msg-id
:content {:command (name :keypair)
:content (label :t/keypair-generated)}
:content-type content-type-command-request
:outgoing false
:from "console"
:to "me"}])
db))
(register-handler :console-create-account console-create-account)

View File

@ -0,0 +1,10 @@
(ns status-im.accounts.login.handlers
(:require [re-frame.core :refer [register-handler after dispatch]]
[status-im.utils.handlers :as u]))
(defn set-login-from-qr
[{:keys [login] :as db} [_ _ login-info]]
(assoc db :login (merge login login-info)))
(register-handler :set-login-from-qr set-login-from-qr)

View File

@ -0,0 +1,91 @@
(ns status-im.accounts.login.screen
(:require-macros [status-im.utils.views :refer [defview]])
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
[status-im.components.react :refer [view
text-class
text-input
image
linear-gradient
touchable-highlight]]
[status-im.components.toolbar :refer [toolbar]]
[status-im.components.text-field.view :refer [text-field]]
[status-im.components.styles :refer [color-purple
color-white
icon-search
icon-back
icon-qr
toolbar-background1
toolbar-title-container
toolbar-title-text
button-input-container
button-input
white-form-text-input]]
[status-im.qr-scanner.views.scan-button :refer [scan-button]]
[status-im.i18n :refer [label]]
[status-im.accounts.login.styles :as st]))
(def toolbar-title
[view toolbar-title-container
[text-class {:style (merge toolbar-title-text {:color color-white})}
(label :t/login)]])
(defview address-input [address]
[view button-input-container
[text-field
{:value address
:editable false
:label (label :t/address)
:labelColor "#ffffff80"
:lineColor :white
:inputStyle st/input-style
:wrapperStyle (merge button-input st/address-input-wrapper)
:onChangeText #(dispatch [:set-in [:login :address] %])}]
;[scan-button {:labelStyle st/scan-label
; :icon :icon_scan_white
; :showLabel (zero? (count address))
; :handler #(dispatch [:scan-qr-code {:toolbar-title (label :t/login)} :set-address-from-qr])}]
])
(defview password-input [error]
[text-field
{:value ""
:error (when (pos? (count error)) (label :t/wrong-password))
:errorColor :white
:label (label :t/password)
:labelColor "#ffffff80"
:lineColor :white
:inputStyle st/input-style
:onChangeText #(do
(dispatch [:set-in [:login :password] %])
(dispatch [:set-in [:login :error] ""]))}])
(defview login []
[{:keys [address password error]} [:get :login]]
[view st/screen-container
[linear-gradient {:colors ["rgba(182, 116, 241, 1)" "rgba(107, 147, 231, 1)" "rgba(43, 171, 238, 1)"]
:start [0, 0]
:end [0.5, 1]
:locations [0, 0.8, 1]
:style st/gradient-background}]
[toolbar {:background-color :transparent
:nav-action {:image {:source {:uri :icon_back_white}
:style icon-back}
:handler #(dispatch [:navigate-back])}
:custom-content toolbar-title
:action {:image {:style icon-search}
:handler #()}}]
[view st/form-container
[address-input (or address "")]
[password-input error]
]
[view st/bottom-actions-container
[view st/recover-text-container
[touchable-highlight
{:on-press #()}
[text-class {:style st/recover-text} (label :t/recover-access)]]]
[view st/connect-button-container
[touchable-highlight
{:on-press #(dispatch [:login-account address password])}
[view st/connect-button
[text-class {:style st/connect-button-text} (label :t/connect)]]]]]])

View File

@ -0,0 +1,64 @@
(ns status-im.accounts.login.styles
(:require [status-im.components.styles :refer [font
title-font
text1-color
color-white
toolbar-background2
online-color]]))
(def screen-container
{:flex 1
:color :white})
(def gradient-background
{:position :absolute
:top 0
:right 0
:bottom 0
:left 0})
(def form-container
{:marginLeft 16
:margin-top 70})
(def bottom-actions-container
{:position :absolute
:left 0
:right 0
:bottom 0})
(def recover-text-container
{:flex 1
:alignItems :center
:padding 16})
(def recover-text
{:flex 1
:color color-white
:fontSize 16})
(def connect-button-container
{:flex 1})
(def connect-button
{:backgroundColor color-white
:flex 1
:alignItems :center
:paddingVertical 16
:paddingHorizontal 28
})
(def connect-button-text
{:color "#7099e6"
:fontSize 16})
(def input-style
{:color :white
:font-size 12})
(def scan-label
{:color :white})
(def address-input-wrapper
{})

View File

@ -0,0 +1,80 @@
(ns status-im.accounts.screen
(:require-macros [status-im.utils.views :refer [defview]])
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
[status-im.components.react :refer [view
text
list-view
list-item
image
linear-gradient
touchable-highlight]]
[status-im.components.toolbar :refer [toolbar]]
[status-im.components.styles :refer [color-purple
color-white
icon-search
icon-back
icon-qr
icon-plus
toolbar-background1
toolbar-title-container
toolbar-title-text
button-input-container
button-input
white-form-text-input]]
[status-im.utils.listview :as lw]
[status-im.accounts.views.account :refer [account-view]]
[status-im.i18n :refer [label]]
[status-im.accounts.styles :as st]
[status-im.utils.logging :as log]))
(def toolbar-title
[view toolbar-title-container
[text {:style (merge toolbar-title-text {:color color-white})}
(label :t/switch-users)]])
(defn render-row [row _ _]
(list-item [account-view row]))
(defn render-separator [_ row-id _]
(list-item [view {:style st/row-separator
:key row-id}]))
(defn create-account [event]
(dispatch-sync [:reset-app])
; add accounts screen to history ( maybe there is a better way ? )
(dispatch [:navigate-to-clean :accounts])
(dispatch [:navigate-to :chat "console"]))
(defview accounts []
[accounts [:get :accounts]
stack [:get :navigation-stack]]
(let [accounts (vals accounts)
show-back? (> (count stack) 1)]
[view st/screen-container
[linear-gradient {:colors ["rgba(182, 116, 241, 1)" "rgba(107, 147, 231, 1)" "rgba(43, 171, 238, 1)"]
:start [0, 0]
:end [0.5, 1]
:locations [0, 0.8, 1]
:style st/gradient-background}]
[toolbar {:background-color :transparent
:nav-action {:image {:source (if show-back? {:uri :icon_back_white} nil)
:style icon-back}
:handler (if show-back? #(dispatch [:navigate-back]) nil)}
:custom-content toolbar-title
:action {:image {:style icon-search}
:handler #()}}]
[view st/accounts-container
[view st/account-list-view-container
[list-view {:dataSource (lw/to-datasource accounts)
:enableEmptySections true
:renderRow render-row
;:renderSeparator render-separator
:style st/account-list}]]]
[view st/add-account-button-container
[touchable-highlight {:on-press create-account}
[view st/add-account-button
[image {:source {:uri :icon_add}
:style st/icon-plus}]
[text {:style st/add-account-text} (label :t/add-account)]]]]]))
;(re-frame.core/dispatch [:set :view-id :users])

View File

@ -0,0 +1,114 @@
(ns status-im.accounts.styles
(:require [status-im.components.styles :refer [font
title-font
text1-color
color-white
toolbar-background2
online-color]]))
(def screen-container
{:flex 1
:color :white})
(def gradient-background
{:position :absolute
:top 0
:right 0
:bottom 0
:left 0})
(def account-list-container1
{:position :absolute
:top 56
:right 0
:bottom 0
:left 0
:justifyContent :center})
(def accounts-container
{:flex 1
:flex-direction :column
:justifyContent :center
:padding-bottom 56})
(def account-list-view-container
{:flexDirection :column
:justifyContent :center})
(def account-list
{})
(def row-separator
{:borderBottomWidth 1
:borderBottomColor "#bababa"})
(def account-container
{:flex 1
:flexDirection :row
:height 69
:backgroundColor "rgba(255, 255, 255, 0.1)"
:alignItems :center
:justifyContent :center})
(def photo-container
{:flex 0.2
:flexDirection :column
:alignItems :center
:justifyContent :center})
(def account-photo-container
{:flex 1
:backgroundColor "rgba(255, 255, 255, 0.2)"
:borderRadius 50
:width 36
:height 36
:alignItems :center
:justifyContent :center})
(def photo-image
{:borderRadius 50
:width 36
:height 36})
(def name-container
{:flex 1
:flexDirection :column})
(def name-text
{:color color-white
:fontSize 16})
(def address-text
{:color color-white
:fontSize 12})
(def online-container
{:flex 0.2
:flexDirection :column
:alignItems :center
:justifyContent :center})
(def add-account-button-container
{:position :absolute
:bottom 16
:height 50
:left 100
:right 100
:justifyContent :center
:alignItems :center})
(def add-account-button
{:flexDirection :row})
(def icon-plus
{:flexDirection :column
:paddingTop 2
:width 20
:height 20})
(def add-account-text
{:flexDirection :column
:color :white
:fontSize 16
:marginLeft 8})

View File

@ -0,0 +1,39 @@
(ns status-im.accounts.views.account
(:require-macros [status-im.utils.views :refer [defview]])
(:require [clojure.string :as s]
[status-im.resources :as res]
[status-im.components.react :refer [view
text
image
touchable-highlight]]
[re-frame.core :refer [dispatch subscribe]]
[status-im.components.styles :refer [icon-ok
icon-plus]]
[status-im.accounts.styles :as st]))
(defn on-press [address]
(dispatch [:navigate-to :login address])
(dispatch [:set-in [:login :address] address]))
(defview account-view [{:keys [address photo-path name] :as account}]
[current-account [:get :user-identity]]
[touchable-highlight
{:onPress #(on-press address)}
[view st/account-container
[view st/photo-container
[view st/account-photo-container
(if (not= address "0x0")
[image {:source {:uri (if (s/blank? photo-path) :avatar photo-path)}
:style st/photo-image}]
[image {:source {:uri :icon_plus}
:style icon-plus}])]]
[view st/name-container
[text {:style st/name-text
:numberOfLines 1} (or name address)]
(when (not= address "0x0")
[text {:style st/address-text
:numberOfLines 1} address])]
[view st/online-container
(when (= address (:address current-account))
[image {:source {:uri :icon_ok}
:style icon-ok}])]]])

View File

@ -8,12 +8,14 @@
[status-im.components.react :refer [navigator app-registry device-event-emitter [status-im.components.react :refer [navigator app-registry device-event-emitter
orientation]] orientation]]
[status-im.components.main-tabs :refer [main-tabs]] [status-im.components.main-tabs :refer [main-tabs]]
[status-im.contacts.views.contact-list :refer [contact-list] ] [status-im.contacts.views.contact-list :refer [contact-list]]
[status-im.contacts.views.new-contact :refer [new-contact]] [status-im.contacts.views.new-contact :refer [new-contact]]
[status-im.qr-scanner.screen :refer [qr-scanner]] [status-im.qr-scanner.screen :refer [qr-scanner]]
[status-im.discovery.screen :refer [discovery]] [status-im.discovery.screen :refer [discovery]]
[status-im.discovery.tag :refer [discovery-tag]] [status-im.discovery.tag :refer [discovery-tag]]
[status-im.chat.screen :refer [chat]] [status-im.chat.screen :refer [chat]]
[status-im.accounts.login.screen :refer [login]]
[status-im.accounts.screen :refer [accounts]]
[status-im.chats-list.screen :refer [chats-list]] [status-im.chats-list.screen :refer [chats-list]]
[status-im.new-group.screen :refer [new-group]] [status-im.new-group.screen :refer [new-group]]
[status-im.participants.views.add :refer [new-participants]] [status-im.participants.views.add :refer [new-participants]]
@ -21,7 +23,9 @@
[status-im.group-settings.screen :refer [group-settings]] [status-im.group-settings.screen :refer [group-settings]]
[status-im.profile.screen :refer [profile my-profile]] [status-im.profile.screen :refer [profile my-profile]]
[status-im.utils.utils :refer [toast]] [status-im.utils.utils :refer [toast]]
[status-im.utils.encryption])) [status-im.utils.encryption]
status-im.persistence.realm.core
[status-im.utils.logging :as log]))
(defn init-back-button-handler! [] (defn init-back-button-handler! []
(let [new-listener (fn [] (let [new-listener (fn []
@ -39,8 +43,11 @@
(defn app-root [] (defn app-root []
(let [signed-up (subscribe [:get :signed-up]) (let [signed-up (subscribe [:get :signed-up])
_ (log/debug "signed up: " @signed-up)
view-id (subscribe [:get :view-id]) view-id (subscribe [:get :view-id])
account (subscribe [:get :user-identity])
keyboard-height (subscribe [:get :keyboard-height])] keyboard-height (subscribe [:get :keyboard-height])]
(log/debug "Current account: " @account)
(r/create-class (r/create-class
{:component-will-mount {:component-will-mount
(fn [] (fn []
@ -62,7 +69,15 @@
#(dispatch [:set :keyboard-height 0])))) #(dispatch [:set :keyboard-height 0]))))
:render :render
(fn [] (fn []
(case (if @signed-up @view-id :chat) (let [startup-view (if @account
(if @signed-up
@view-id
:chat)
(if (contains? #{:login :chat} @view-id)
@view-id
:accounts))]
(log/debug startup-view)
(case (if true startup-view :chat)
:discovery [main-tabs] :discovery [main-tabs]
:discovery-tag [discovery-tag] :discovery-tag [discovery-tag]
:add-participants [new-participants] :add-participants [new-participants]
@ -76,18 +91,14 @@
:qr-scanner [qr-scanner] :qr-scanner [qr-scanner]
:chat [chat] :chat [chat]
:profile [profile] :profile [profile]
:my-profile [my-profile]))}))) :accounts [accounts]
:login [login]
:my-profile [my-profile])))})))
(defn init [] (defn init []
(dispatch-sync [:initialize-db]) (dispatch-sync [:reset-app])
(dispatch [:initialize-crypt]) (dispatch [:initialize-crypt])
(dispatch [:initialize-geth]) (dispatch [:initialize-geth])
(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-user-phone-number])
(dispatch [:load-contacts])
(dispatch [:init-console-chat])
(dispatch [:init-chat])
(init-back-button-handler!) (init-back-button-handler!)
(.registerComponent app-registry "StatusIm" #(r/reactify-component app-root))) (.registerComponent app-registry "StatusIm" #(r/reactify-component app-root)))

View File

@ -15,7 +15,7 @@
[status-im.models.chats :as chats] [status-im.models.chats :as chats]
[status-im.navigation.handlers :as nav] [status-im.navigation.handlers :as nav]
[status-im.utils.handlers :refer [register-handler] :as u] [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.server :as server]
[status-im.handlers.content-suggestions :refer [get-content-suggestions]] [status-im.handlers.content-suggestions :refer [get-content-suggestions]]
[status-im.utils.phone-number :refer [format-phone-number]] [status-im.utils.phone-number :refer [format-phone-number]]
@ -343,7 +343,7 @@
(defn store-message! (defn store-message!
[{:keys [new-message]} [_ {chat-id :from}]] [{:keys [new-message]} [_ {chat-id :from}]]
(messages/save-message chat-id new-message)) (messages/save-message chat-id new-message))
(defn dispatch-request! (defn dispatch-request!
[{:keys [new-message]} [_ {chat-id :from}]] [{:keys [new-message]} [_ {chat-id :from}]]
@ -446,17 +446,17 @@
(defn delete-messages! (defn delete-messages!
[{:keys [current-chat-id]} _] [{:keys [current-chat-id]} _]
(r/write (r/write :account
(fn [] (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! (defn delete-chat!
[{:keys [current-chat-id]} _] [{:keys [current-chat-id]} _]
(r/write (r/write :account
(fn [] (fn [] :account
(-> (r/get-by-field :chats :chat-id current-chat-id) (->> (r/get-by-field :account :chats :chat-id current-chat-id)
(r/single) (r/single)
(r/delete))))) (r/delete :account)))))
(register-handler :leave-group-chat (register-handler :leave-group-chat
;; todo oreder of operations tbd ;; todo oreder of operations tbd

View File

@ -1,14 +1,13 @@
(ns status-im.chat.handlers.requests (ns status-im.chat.handlers.requests
(:require [re-frame.core :refer [after dispatch enrich]] (:require [re-frame.core :refer [after dispatch enrich]]
[status-im.utils.handlers :refer [register-handler]] [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])) [status-im.utils.handlers :as u]))
(defn store-request! (defn store-request!
[{:keys [new-request]}] [{:keys [new-request] :as db}]
(realm/write (requests/save-request new-request))
(fn []
(realm/create :requests new-request))))
(defn add-request (defn add-request
[db [_ chat-id {:keys [msg-id content]}]] [db [_ chat-id {:keys [msg-id content]}]]
@ -24,9 +23,9 @@
(defn load-requests! (defn load-requests!
[{:keys [current-chat-id] :as db} [_ chat-id]] [{:keys [current-chat-id] :as db} [_ chat-id]]
(let [chat-id' (or chat-id current-chat-id) (let [chat-id' (or chat-id current-chat-id)
requests (-> :requests requests (-> ;; todo maybe limit is needed
;; todo maybe limit is needed (realm/get-by-fields :account :requests
(realm/get-by-fields {:chat-id chat-id' {:chat-id chat-id'
:status "open"}) :status "open"})
(realm/sorted :added :desc) (realm/sorted :added :desc)
(realm/collection->map)) (realm/collection->map))
@ -35,12 +34,11 @@
(defn mark-request-as-answered! (defn mark-request-as-answered!
[_ [_ chat-id message-id]] [_ [_ chat-id message-id]]
(realm/write (realm/write :account
(fn [] (fn []
(-> :requests (-> (realm/get-by-fields :account :requests
(realm/get-by-fields {:chat-id chat-id
{:chat-id chat-id :message-id message-id})
:message-id message-id})
(realm/single) (realm/single)
(.-status) (.-status)
(set! "answered"))))) (set! "answered")))))

View File

@ -1,11 +1,11 @@
(ns status-im.chat.handlers.unviewed-messages (ns status-im.chat.handlers.unviewed-messages
(:require [re-frame.core :refer [after enrich path dispatch]] (:require [re-frame.core :refer [after enrich path dispatch]]
[status-im.utils.handlers :refer [register-handler]] [status-im.utils.handlers :refer [register-handler]]
[status-im.persistence.realm :as realm])) [status-im.persistence.realm.core :as realm]))
(defn delivered-messages [] (defn delivered-messages []
(-> (realm/get-by-fields (-> (realm/get-by-fields
:msgs :account :msgs
{:delivery-status :delivered {:delivery-status :delivered
:outgoing false}) :outgoing false})
(realm/collection->map))) (realm/collection->map)))

View File

@ -5,7 +5,7 @@
[status-im.protocol.state.storage :as s] [status-im.protocol.state.storage :as s]
[status-im.models.chats :as c] [status-im.models.chats :as c]
[status-im.components.styles :refer [default-chat-color]] [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.random :as random] [status-im.utils.random :as random]
[status-im.utils.sms-listener :refer [add-sms-listener [status-im.utils.sms-listener :refer [add-sms-listener
remove-sms-listener]] remove-sms-listener]]

View File

@ -4,7 +4,7 @@
[status-im.utils.handlers :as u] [status-im.utils.handlers :as u]
[status-im.utils.utils :refer [http-get toast]] [status-im.utils.utils :refer [http-get toast]]
[clojure.string :as s] [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.components.jail :as j]
[status-im.utils.types :refer [json->clj]] [status-im.utils.types :refer [json->clj]]
[status-im.commands.utils :refer [reg-handler]])) [status-im.commands.utils :refer [reg-handler]]))
@ -15,8 +15,8 @@
[_ [identity]] [_ [identity]]
(dispatch [::fetch-commands! identity]) (dispatch [::fetch-commands! identity])
;; todo uncomment ;; todo uncomment
#_(if-let [{:keys [file]} (realm/get-one-by-field :commands :chat-id #_(if-let [{:keys [file]} (realm/get-one-by-field :account :commands
identity)] :chat-id identity)]
(dispatch [::parse-commands! identity file]) (dispatch [::parse-commands! identity file])
(dispatch [::fetch-commands! identity]))) (dispatch [::fetch-commands! identity])))
@ -73,7 +73,7 @@
(defn save-commands-js! (defn save-commands-js!
[_ [id file]] [_ [id file]]
(realm/create-object :commands {:chat-id id :file file})) (realm/create-object :account :commands {:chat-id id :file file}))
(defn loading-failed! (defn loading-failed!
[db [id reason details]] [db [id reason details]]

View File

@ -65,6 +65,7 @@
[view st/switch-users-container [view st/switch-users-container
[touchable-opacity {:onPress (fn [] [touchable-opacity {:onPress (fn []
(close-drawer) (close-drawer)
(dispatch [:navigate-to :accounts])
;; TODO not implemented ;; TODO not implemented
)} )}
[text {:style st/switch-users-text} [text {:style st/switch-users-text}

View File

@ -18,12 +18,13 @@
(def config {:label-top 16 (def config {:label-top 16
:label-bottom 37 :label-bottom 37
:label-font-large 16 :label-font-large 16
:label-font-small 12 :label-font-small 13
:label-animation-duration 200}) :label-animation-duration 200})
(def default-props {:wrapperStyle {} (def default-props {:wrapperStyle {}
:inputStyle {} :inputStyle {}
:lineStyle {} :lineStyle {}
:editable true
:labelColor "#838c93" :labelColor "#838c93"
:lineColor "#0000001f" :lineColor "#0000001f"
:focusLineColor "#0000001f" :focusLineColor "#0000001f"
@ -68,7 +69,7 @@
(:label-font-large config) (:label-font-large config)
(:label-font-small config))) (:label-font-small config)))
:float-label? (if (s/blank? value) false true)}] :float-label? (if (s/blank? value) false true)}]
(log/debug "component-will-mount") ;(log/debug "component-will-mount")
(r/set-state component data))) (r/set-state component data)))
; Invoked once, only on the client (not on the server), immediately after the ; Invoked once, only on the client (not on the server), immediately after the
@ -78,7 +79,8 @@
; parent components. ; parent components.
(defn component-did-mount [component] (defn component-did-mount [component]
(let [props (r/props component)] (let [props (r/props component)]
(log/debug "component-did-mount:"))) ;(log/debug "component-did-mount:")
))
; Invoked when a component is receiving new props. This method is not called for ; Invoked when a component is receiving new props. This method is not called for
; the initial render. Use this as an opportunity to react to a prop transition ; the initial render. Use this as an opportunity to react to a prop transition
@ -86,7 +88,8 @@
; The old props can be accessed via this.props. Calling this.setState() within ; The old props can be accessed via this.props. Calling this.setState() within
; this function will not trigger an additional render. ; this function will not trigger an additional render.
(defn component-will-receive-props [component new-props] (defn component-will-receive-props [component new-props]
(log/debug "component-will-receive-props: new-props=" new-props)) ;(log/debug "component-will-receive-props: new-props=" new-props)
)
; Invoked before rendering when new props or state are being received. This method ; Invoked before rendering when new props or state are being received. This method
; is not called for the initial render or when forceUpdate is used. Use this as ; is not called for the initial render or when forceUpdate is used. Use this as
@ -96,20 +99,22 @@
; until the next state change. In addition, componentWillUpdate and ; until the next state change. In addition, componentWillUpdate and
; componentDidUpdate will not be called. ; componentDidUpdate will not be called.
(defn should-component-update [component next-props next-state] (defn should-component-update [component next-props next-state]
(log/debug "should-component-update: " next-props next-state) ;(log/debug "should-component-update: " next-props next-state)
true) true)
; Invoked immediately before rendering when new props or state are being received. ; Invoked immediately before rendering when new props or state are being received.
; This method is not called for the initial render. Use this as an opportunity ; This method is not called for the initial render. Use this as an opportunity
; to perform preparation before an update occurs. ; to perform preparation before an update occurs.
(defn component-will-update [component next-props next-state] (defn component-will-update [component next-props next-state]
(log/debug "component-will-update: " next-props next-state)) ;(log/debug "component-will-update: " next-props next-state)
)
; Invoked immediately after the component's updates are flushed to the DOM. ; Invoked immediately after the component's updates are flushed to the DOM.
; This method is not called for the initial render. Use this as an opportunity ; This method is not called for the initial render. Use this as an opportunity
; to operate on the DOM when the component has been updated. ; to operate on the DOM when the component has been updated.
(defn component-did-update [component prev-props prev-state] (defn component-did-update [component prev-props prev-state]
(log/debug "component-did-update: " prev-props prev-state)) ;(log/debug "component-did-update: " prev-props prev-state)
)
(defn on-focus [{:keys [component animation onFocus]}] (defn on-focus [{:keys [component animation onFocus]}]
(do (do
@ -141,16 +146,17 @@
max-line-width] :as state} (r/state component) max-line-width] :as state} (r/state component)
{:keys [wrapperStyle inputStyle lineColor focusLineColor {:keys [wrapperStyle inputStyle lineColor focusLineColor
labelColor errorColor error label value onFocus onBlur labelColor errorColor error label value onFocus onBlur
onChangeText onChange] :as props} (merge default-props (r/props component)) onChangeText onChange editable] :as props} (merge default-props (r/props component))
lineColor (if error errorColor lineColor) lineColor (if error errorColor lineColor)
focusLineColor (if error errorColor focusLineColor) focusLineColor (if error errorColor focusLineColor)
labelColor (if (and error (not float-label?)) errorColor labelColor) labelColor (if (and error (not float-label?)) errorColor labelColor)
label (if error (str label " *") label)] label (if error (str label " *") label)]
(log/debug "reagent-render: " data state) ;(log/debug "reagent-render: " data)
[view (merge st/text-field-container wrapperStyle) [view (merge st/text-field-container wrapperStyle)
[animated-text {:style (st/label label-top label-font-size labelColor)} label] [animated-text {:style (st/label label-top label-font-size labelColor)} label]
[text-input {:style (merge st/text-input inputStyle) [text-input {:style (merge st/text-input inputStyle)
:placeholder "" :placeholder ""
:editable editable
:onFocus #(on-focus {:component component :onFocus #(on-focus {:component component
:animation {:top label-top :animation {:top label-top
:to-top (:label-top config) :to-top (:label-top config)
@ -185,5 +191,5 @@
:component-did-update component-did-update :component-did-update component-did-update
:display-name "text-field" :display-name "text-field"
:reagent-render reagent-render}] :reagent-render reagent-render}]
(log/debug "Creating text-field component: " data) ;(log/debug "Creating text-field component: " data)
(r/create-class component-data))) (r/create-class component-data)))

View File

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

View File

@ -11,6 +11,7 @@
[status-im.components.text-field.view :refer [text-field]] [status-im.components.text-field.view :refer [text-field]]
[status-im.utils.identicon :refer [identicon]] [status-im.utils.identicon :refer [identicon]]
[status-im.components.toolbar :refer [toolbar]] [status-im.components.toolbar :refer [toolbar]]
[status-im.utils.utils :refer [log on-error http-post toast]]
[status-im.components.styles :refer [color-purple [status-im.components.styles :refer [color-purple
color-white color-white
icon-search icon-search
@ -43,12 +44,12 @@
:label (label :t/name) :label (label :t/name)
:onChangeText #(dispatch [:set-in [:new-contact :name] %])}]) :onChangeText #(dispatch [:set-in [:new-contact :name] %])}])
(defview contact-whisper-id-input [whisper-identity] (defview contact-whisper-id-input [whisper-identity error]
[] []
(let [error (if (str/blank? whisper-identity) "" nil) (let [error (if (str/blank? whisper-identity) "" error)
error (if (s/valid? ::v/whisper-identity whisper-identity) error (if (s/valid? ::v/whisper-identity whisper-identity)
error error
"Please enter a valid address or scan a QR code")] (label :t/enter-valid-address))]
[view button-input-container [view button-input-container
[text-field [text-field
{:error error {:error error
@ -56,25 +57,52 @@
:value whisper-identity :value whisper-identity
:wrapperStyle (merge button-input) :wrapperStyle (merge button-input)
:label (label :t/address) :label (label :t/address)
:onChangeText #(dispatch [:set-in [:new-contact :whisper-identity] %])}] :onChangeText #(do
[scan-button #(dispatch [:scan-qr-code {:toolbar-title (label :t/new-contact)} :set-new-contact-from-qr])]])) (dispatch [:set-in [:new-contact :whisper-identity] %])
(dispatch [:set :new-contact-address-error nil]))}]
[scan-button {:showLabel (zero? (count whisper-identity))
:handler #(dispatch [:scan-qr-code {:toolbar-title (label :t/new-contact)} :set-new-contact-from-qr])}]]))
(defn on-add-contact [whisper-identity new-contact]
(if (v/is-address? whisper-identity)
(http-post "get-contacts-by-address" {:addresses [whisper-identity]}
(fn [{:keys [contacts]}]
(if (> (count contacts) 0)
(let [contact (first contacts)
new-contact (merge
new-contact
{:address whisper-identity
:whisper-identity (:whisper-identity contact)})]
(dispatch [:add-new-contact new-contact]))
(dispatch [:set :new-contact-address-error (label :t/unknown-address)]))))
(dispatch [:add-new-contact new-contact])))
(defn toolbar-action [whisper-identity new-contact error]
(let [valid-contact? (and
(s/valid? ::v/contact new-contact)
(nil? error))]
{:image {:source {:uri (if valid-contact?
:icon_ok_blue
:icon_ok_disabled)}
:style icon-search}
:handler #(when valid-contact?
(let [contact (merge
{:photo-path (identicon whisper-identity)}
new-contact)]
(on-add-contact whisper-identity contact)))}))
(defview new-contact [] (defview new-contact []
[{:keys [name whisper-identity phone-number] :as new-contact} [:get :new-contact]] [{:keys [name whisper-identity phone-number] :as new-contact} [:get :new-contact]
(let [valid-contact? (s/valid? ::v/contact new-contact)] error [:get :new-contact-address-error]]
[view st/contact-form-container [view st/contact-form-container
[toolbar {:background-color :white [toolbar {:background-color :white
:nav-action {:image {:source {:uri :icon_back} :nav-action {:image {:source {:uri :icon_back}
:style icon-back} :style icon-back}
:handler #(dispatch [:navigate-back])} :handler #(dispatch [:navigate-back])}
:custom-content toolbar-title :custom-content toolbar-title
:action {:image {:source {:uri (if valid-contact? :action (toolbar-action whisper-identity new-contact error)}]
:icon_ok_blue [view st/form-container
:icon_ok_disabled)} [contact-name-input name]
:style icon-search} [contact-whisper-id-input whisper-identity error]]
:handler #(when valid-contact? (dispatch [:add-new-contact (merge {:photo-path (identicon whisper-identity)} new-contact)]))}}] [view st/address-explication-container
[view st/form-container [text {:style st/address-explication} (label :t/address-explication)]]])
[contact-name-input name]
[contact-whisper-id-input whisper-identity]]
[view st/address-explication-container
[text {:style st/address-explication} (label :t/address-explication)]]]))

View File

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

View File

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

View File

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

View File

@ -1,8 +1,9 @@
(ns status-im.handlers (ns status-im.handlers
(:require (:require
[re-frame.core :refer [after dispatch debug]] [re-frame.core :refer [after dispatch dispatch-sync debug]]
[schema.core :as s :include-macros true] [schema.core :as s :include-macros true]
[status-im.db :refer [app-db schema]] [status-im.db :refer [app-db schema]]
[status-im.persistence.realm.core :as realm]
[status-im.persistence.simple-kv-store :as kv] [status-im.persistence.simple-kv-store :as kv]
[status-im.protocol.state.storage :as storage] [status-im.protocol.state.storage :as storage]
[status-im.utils.logging :as log] [status-im.utils.logging :as log]
@ -55,11 +56,33 @@
(register-handler :initialize-db (register-handler :initialize-db
(fn [_ _] (fn [_ _]
(realm/reset-account)
(assoc app-db (assoc app-db
:user-identity nil)))
(register-handler :initialize-account-db
(fn [db _]
(assoc db
:signed-up (storage/get kv/kv-store :signed-up) :signed-up (storage/get kv/kv-store :signed-up)
:user-identity (protocol/stored-identity nil)
:password (storage/get kv/kv-store :password)))) :password (storage/get kv/kv-store :password))))
(register-handler :initialize-account
(u/side-effect!
(fn [_ [_ account]]
(dispatch [:initialize-protocol account])
(dispatch [:initialize-account-db])
(dispatch [:initialize-chats])
(dispatch [:load-contacts])
(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 (register-handler :initialize-crypt
(u/side-effect! (u/side-effect!
(fn [_ _] (fn [_ _]
@ -77,12 +100,7 @@
(dispatch [:crypt-initialized])))))))) (dispatch [:crypt-initialized]))))))))
(defn node-started [db result] (defn node-started [db result]
(let [identity (:user-identity db) (log/debug "Started Node: " result))
password (:password db)]
(log/debug "Started Node: " result)
(when identity (do
(dispatch [:login-account (:address identity) password])
(dispatch [:initialize-protocol identity])))))
(register-handler :initialize-geth (register-handler :initialize-geth
(u/side-effect! (u/side-effect!
@ -90,7 +108,7 @@
(log/debug "Starting node") (log/debug "Starting node")
(.startNode geth (.startNode geth
(fn [result] (node-started db result)) (fn [result] (node-started db result))
#(dispatch [:initialize-protocol]))))) #(log/debug "Geth already initialized")))))
(register-handler :crypt-initialized (register-handler :crypt-initialized
(u/side-effect! (u/side-effect!

View File

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

View File

@ -1,11 +1,11 @@
(ns status-im.models.contacts (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.utils.identicon :refer [identicon]]
[status-im.persistence.realm-queries :refer [include-query [status-im.persistence.realm-queries :refer [include-query
exclude-query]])) exclude-query]]))
(defn get-contacts [] (defn get-contacts []
(-> (r/get-all :contacts) (-> (r/get-all :account :contacts)
(r/sorted :name :asc) (r/sorted :name :asc)
r/collection->map)) r/collection->map))
@ -13,22 +13,22 @@
(->> {:name (or name "") (->> {:name (or name "")
:photo-path (or photo-path (identicon whisper-identity))} :photo-path (or photo-path (identicon whisper-identity))}
(merge contact) (merge contact)
(r/create :contacts))) (r/create :account :contacts)))
(defn save-contacts [contacts] (defn save-contacts [contacts]
(r/write #(mapv create-contact contacts))) (r/write :account #(mapv create-contact contacts)))
;;;;;;;;;;;;;;;;;;;;---------------------------------------------- ;;;;;;;;;;;;;;;;;;;;----------------------------------------------
(defn contacts-list [] (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] (defn contacts-list-exclude [exclude-idents]
(if (empty? exclude-idents) (if (empty? exclude-idents)
(contacts-list) (contacts-list)
(let [query (exclude-query :whisper-identity exclude-idents)] (let [query (exclude-query :whisper-identity exclude-idents)]
(-> (r/get-all :contacts) (-> (r/get-all :account :contacts)
(r/filtered query) (r/filtered query)
(r/sorted :name :asc))))) (r/sorted :name :asc)))))
@ -36,9 +36,9 @@
(if (empty? include-indents) (if (empty? include-indents)
() ()
(let [query (include-query :whisper-identity include-indents)] (let [query (include-query :whisper-identity include-indents)]
(-> (r/get-all :contacts) (-> (r/get-all :account :contacts)
(r/filtered query) (r/filtered query)
(r/sorted :name :asc))))) (r/sorted :name :asc)))))
(defn contact-by-identity [identity] (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 (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]] [re-frame.core :refer [dispatch]]
[cljs.reader :refer [read-string]] [cljs.reader :refer [read-string]]
[status-im.utils.random :refer [timestamp]] [status-im.utils.random :refer [timestamp]]
@ -29,8 +29,8 @@
[chat-id {:keys [delivery-status msg-id content] [chat-id {:keys [delivery-status msg-id content]
:or {delivery-status :pending} :or {delivery-status :pending}
:as message}] :as message}]
(when-not (r/exists? :msgs :msg-id msg-id) (when-not (r/exists? :account :msgs :msg-id msg-id)
(r/write (r/write :account
(fn [] (fn []
(let [content' (if (string? content) (let [content' (if (string? content)
content content
@ -41,7 +41,7 @@
:content content' :content content'
:delivery-status delivery-status :delivery-status delivery-status
:timestamp (timestamp)})] :timestamp (timestamp)})]
(r/create :msgs message' true)))))) (r/create :account :msgs message' true))))))
(defn command-type? [type] (defn command-type? [type]
(contains? (contains?
@ -51,20 +51,20 @@
(defn get-messages (defn get-messages
([chat-id] (get-messages chat-id 0)) ([chat-id] (get-messages chat-id 0))
([chat-id from] ([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/sorted :timestamp :desc)
(r/page from (+ from c/default-number-of-messages)) (r/page from (+ from c/default-number-of-messages))
(r/collection->map)) (r/collection->map))
(into '()) (into '())
reverse reverse
(keep (fn [{:keys [content-type] :as message}] (keep (fn [{:keys [content-type] :as message}]
(if (command-type? content-type) (if (command-type? content-type)
(update message :content str-to-map) (update message :content str-to-map)
message)))))) message))))))
(defn update-message! [{:keys [msg-id] :as msg}] (defn update-message! [{:keys [msg-id] :as msg}]
(log/debug "update-message!" msg) (log/debug "update-message!" msg)
(r/write (r/write :account
(fn [] (fn []
(when (r/exists? :msgs :msg-id msg-id) (when (r/exists? :account :msgs :msg-id msg-id)
(r/create :msgs msg true))))) (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

@ -80,3 +80,11 @@
(push-view :profile))) (push-view :profile)))
(register-handler :show-profile show-profile) (register-handler :show-profile show-profile)
(defn navigate-to-clean
[db [_ view-id]]
(-> db
(assoc :navigation-stack (list))
(push-view view-id)))
(register-handler :navigate-to-clean navigate-to-clean)

View File

@ -1,198 +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 :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,179 @@
(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.fs :as fs]
[status-im.utils.logging :as log]
[status-im.persistence.realm.schemas :refer [base account]]
[clojure.string :as str])
(:refer-clojure :exclude [exists?]))
(def new-account-filename "new-account")
(def realm-class (u/require "realm"))
(defn create-account-realm [address]
(let [opts (merge account {:path (str address ".realm")})]
(when (cljs.core/exists? js/window)
(realm-class. (clj->js opts)))))
(def base-realm
(when (cljs.core/exists? js/window)
(realm-class. (clj->js base))))
(def account-realm (atom (create-account-realm new-account-filename)))
(defn is-new-account? []
(let [path (.-path @account-realm)
realm_file (str new-account-filename ".realm")]
(str/ends-with? path realm_file)))
(defn realm [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 reset-account []
(when @account-realm
(close-account-realm))
(reset! account-realm (create-account-realm new-account-filename))
(.write @account-realm #(.deleteAll @account-realm)))
(defn move-file-handler [address err handler]
(log/debug "Moved file with error: " err address)
(if err
(log/error "Error moving account realm: " (.-message err))
(reset! account-realm (create-account-realm address)))
(handler err))
(defn change-account-realm [address new-account? handler]
(let [path (.-path @account-realm)
realm-file (str new-account-filename ".realm")]
(log/debug "closing account realm: " path)
(close-account-realm)
(log/debug "is new account? " new-account?)
(if new-account?
(let [new-path (str/replace path realm-file (str address ".realm"))]
(log/debug "Moving file to " new-path)
(fs/move-file path new-path #(move-file-handler address % handler)))
(do
(reset! account-realm (create-account-realm address))
(handler 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]
(-> (.objects (realm schema) (name schema-name))
(.filtered filter)))
(defn 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]
(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]
(.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]
(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,96 @@
(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"}}]
: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 (ns status-im.persistence.simple-kv-store
(:require [status-im.protocol.state.storage :as st] (: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]])) [status-im.utils.types :refer [to-edn-string]]))
(defrecord SimpleKvStore [] (defrecord SimpleKvStore [schema]
st/Storage st/Storage
(put [_ key value] (put [_ key value]
(r/write (r/write schema
(fn [] (fn []
(r/create :kv-store {:key key (r/create schema :kv-store
:value (to-edn-string value)} true)))) {:key key
:value (to-edn-string value)} true))))
(get [_ key] (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/single-cljs)
(r/decode-value))) (r/decode-value)))
(contains-key? [_ key] (contains-key? [_ key]
(r/exists? :kv-store :key key)) (r/exists? schema :kv-store :key key))
(delete [_ key] (delete [_ key]
(r/write (fn [] (r/write schema
(-> (r/get-by-field :kv-store :key key) (fn []
(r/single) (->> (r/get-by-field schema :kv-store :key key)
(r/delete)))))) (r/single)
(r/delete schema))))))
(def kv-store (->SimpleKvStore)) (def kv-store (->SimpleKvStore :account))
(def base-kv-store (->SimpleKvStore :base))

View File

@ -12,12 +12,13 @@
[status-im.qr-scanner.styles :as st])) [status-im.qr-scanner.styles :as st]))
(defview scan-button [handler] (defview scan-button [{:keys [showLabel icon labelStyle handler]}]
[] (let [showLabel (if (nil? showLabel) true showLabel)]
[view st/scan-button [view st/scan-button
[touchable-highlight [touchable-highlight
{:on-press handler} {:on-press handler}
[view st/scan-button-content [view st/scan-button-content
[image {:source {:uri :scan_blue} [image {:source {:uri (or icon :scan_blue)}
:style icon-scan}] :style icon-scan}]
[text {:style st/scan-text} (label :t/scan-qr)]]]]) (when showLabel [text {:style (merge st/scan-text labelStyle)}
(label :t/scan-qr)])]]]))

View File

@ -125,13 +125,17 @@
:name "Name" :name "Name"
:whisper-identity "Whisper Identity" :whisper-identity "Whisper Identity"
:address-explication "Maybe here should be some text explaining what an address is and where to look for it" :address-explication "Maybe here should be some text explaining what an address is and where to look for it"
:enter-valid-address "Please enter a valid address or scan a QR code"
:unknown-address "Unknown address"
;login ;login
:recover-from-passphrase "Recover from passphrase" :recover-access "Recover access"
:connect "Connect" :connect "Connect"
:address "Address" :address "Address"
:password "Password" :password "Password"
:login "Login" :login "Login"
:wrong-password "Wrong password"
;users ;users
:add-account "Add account" :add-account "Add account"

View File

@ -0,0 +1,11 @@
(ns status-im.utils.fs
(:require [clojure.string :as s]
[status-im.utils.utils :as u]))
(def fs (u/require "react-native-fs"))
(defn move-file [src dst handler]
(let [result (.moveFile fs src dst)
result (.then result #(handler nil %))
result (.catch result #(handler % nil))]
result))