|
@ -21,7 +21,8 @@
|
|||
"react-native-camera",
|
||||
"react-native-qrcode",
|
||||
"react-native-orientation",
|
||||
"identicon.js"
|
||||
"identicon.js",
|
||||
"react-native-fs"
|
||||
],
|
||||
"imageDirs": [
|
||||
"images"
|
||||
|
|
|
@ -133,6 +133,7 @@ dependencies {
|
|||
compile project(':react-native-camera')
|
||||
compile project(':react-native-status')
|
||||
compile project(':react-native-orientation')
|
||||
compile project(':react-native-fs')
|
||||
//compile(name:'statusgo-android-16', ext:'aar')
|
||||
compile(group: 'status-im', name: 'status-go', version: '0.1.0-201607011545-da53ec', ext: 'aar')
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ import com.lwansbrough.RCTCamera.*;
|
|||
import com.i18n.reactnativei18n.ReactNativeI18n;
|
||||
import android.content.res.Configuration;
|
||||
|
||||
import com.rnfs.RNFSPackage;
|
||||
|
||||
public class MainActivity extends ReactActivity {
|
||||
|
||||
private static final String TAG = "MainActivity";
|
||||
|
@ -112,6 +114,7 @@ public class MainActivity extends ReactActivity {
|
|||
new RCTCameraPackage(),
|
||||
new SmsListener(this),
|
||||
new OrientationPackage(this),
|
||||
new RNFSPackage(),
|
||||
new GethPackage()
|
||||
);
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ public class GethModule extends ReactContextBaseJavaModule implements LifecycleE
|
|||
case GethMessages.MSG_LOGGED_IN:
|
||||
callback = unlockAccountCallbacks.remove(callbackIdentifier);
|
||||
if (callback != null) {
|
||||
callback.invoke(null, "{ \"result\": \"" + data.getString("result") + "\"}");
|
||||
callback.invoke(data.getString("result"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 245 B |
After Width: | Height: | Size: 284 B |
After Width: | Height: | Size: 1017 B |
After Width: | Height: | Size: 158 B |
After Width: | Height: | Size: 188 B |
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 278 B |
After Width: | Height: | Size: 314 B |
After Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 410 B |
After Width: | Height: | Size: 479 B |
After Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 530 B |
After Width: | Height: | Size: 668 B |
|
@ -26,3 +26,6 @@ project(':react-native-camera').projectDir = new File(rootProject.projectDir,
|
|||
|
||||
include ':react-native-orientation', ':app'
|
||||
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')
|
||||
|
|
|
@ -15,15 +15,16 @@
|
|||
"react-native-camera": "github:codyhazelwood/react-native-camera",
|
||||
"react-native-circle-checkbox": "^0.1.3",
|
||||
"react-native-contacts": "^0.2.4",
|
||||
"react-native-fs": "^1.5.1",
|
||||
"react-native-i18n": "0.0.8",
|
||||
"react-native-invertible-scroll-view": "^1.0.0",
|
||||
"react-native-linear-gradient": "1.5.7",
|
||||
"react-native-loading-spinner-overlay": "0.0.8",
|
||||
"react-native-orientation": "^1.17.0",
|
||||
"react-native-qrcode": "^0.2.2",
|
||||
"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-orientation": "^1.17.0",
|
||||
"realm": "^0.11.1",
|
||||
"react-native-status": "git+ssh://git@github.com/status-im/react-native-status"
|
||||
"realm": "^0.14.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
(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]]
|
||||
[status-im.persistence.simple-kv-store :as kv]
|
||||
[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]))
|
||||
|
||||
|
||||
|
@ -20,26 +27,76 @@
|
|||
(defn save-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)
|
||||
public-key (:pubkey data)
|
||||
address (:address data)
|
||||
account {:public-key public-key
|
||||
:address address}]
|
||||
(log/debug "Created account: " result)
|
||||
:address address
|
||||
:name address
|
||||
:photo-path (identicon address)}
|
||||
]
|
||||
(log/debug "account-created: " account)
|
||||
(when (not (str/blank? public-key))
|
||||
(do
|
||||
(save-password password)
|
||||
(dispatch [:login-account address password])
|
||||
(dispatch [:initialize-protocol account])
|
||||
(dispatch [:add-account account])))))
|
||||
;(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 result password)))
|
||||
(.createAccount geth password (fn [result] (account-created db result password)))
|
||||
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
|
||||
(-> (fn [db [_ address password]]
|
||||
(.login geth address password (fn [result] (log/debug "Logged in account: " address result)))
|
||||
db)))
|
||||
(.login geth address password (fn [result]
|
||||
(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)
|
|
@ -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)
|
|
@ -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)]]]]]])
|
|
@ -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
|
||||
{})
|
|
@ -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])
|
|
@ -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})
|
|
@ -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}])]]])
|
|
@ -8,12 +8,14 @@
|
|||
[status-im.components.react :refer [navigator app-registry device-event-emitter
|
||||
orientation]]
|
||||
[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.qr-scanner.screen :refer [qr-scanner]]
|
||||
[status-im.discovery.screen :refer [discovery]]
|
||||
[status-im.discovery.tag :refer [discovery-tag]]
|
||||
[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.new-group.screen :refer [new-group]]
|
||||
[status-im.participants.views.add :refer [new-participants]]
|
||||
|
@ -21,7 +23,9 @@
|
|||
[status-im.group-settings.screen :refer [group-settings]]
|
||||
[status-im.profile.screen :refer [profile my-profile]]
|
||||
[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! []
|
||||
(let [new-listener (fn []
|
||||
|
@ -39,8 +43,11 @@
|
|||
|
||||
(defn app-root []
|
||||
(let [signed-up (subscribe [:get :signed-up])
|
||||
_ (log/debug "signed up: " @signed-up)
|
||||
view-id (subscribe [:get :view-id])
|
||||
account (subscribe [:get :user-identity])
|
||||
keyboard-height (subscribe [:get :keyboard-height])]
|
||||
(log/debug "Current account: " @account)
|
||||
(r/create-class
|
||||
{:component-will-mount
|
||||
(fn []
|
||||
|
@ -62,7 +69,15 @@
|
|||
#(dispatch [:set :keyboard-height 0]))))
|
||||
:render
|
||||
(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-tag [discovery-tag]
|
||||
:add-participants [new-participants]
|
||||
|
@ -76,18 +91,14 @@
|
|||
:qr-scanner [qr-scanner]
|
||||
:chat [chat]
|
||||
:profile [profile]
|
||||
:my-profile [my-profile]))})))
|
||||
:accounts [accounts]
|
||||
:login [login]
|
||||
:my-profile [my-profile])))})))
|
||||
|
||||
(defn init []
|
||||
(dispatch-sync [:initialize-db])
|
||||
(dispatch-sync [:reset-app])
|
||||
(dispatch [:initialize-crypt])
|
||||
(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-contacts])
|
||||
(dispatch [:init-console-chat])
|
||||
(dispatch [:init-chat])
|
||||
(init-back-button-handler!)
|
||||
(.registerComponent app-registry "StatusIm" #(r/reactify-component app-root)))
|
||||
|
|
|
@ -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]]
|
||||
|
@ -343,7 +343,7 @@
|
|||
|
||||
(defn store-message!
|
||||
[{:keys [new-message]} [_ {chat-id :from}]]
|
||||
(messages/save-message chat-id new-message))
|
||||
(messages/save-message chat-id new-message))
|
||||
|
||||
(defn dispatch-request!
|
||||
[{:keys [new-message]} [_ {chat-id :from}]]
|
||||
|
@ -446,17 +446,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/single)
|
||||
(r/delete)))))
|
||||
(r/write :account
|
||||
(fn [] :account
|
||||
(->> (r/get-by-field :account :chats :chat-id current-chat-id)
|
||||
(r/single)
|
||||
(r/delete :account)))))
|
||||
|
||||
(register-handler :leave-group-chat
|
||||
;; todo oreder of operations tbd
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
(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 [new-request] :as db}]
|
||||
(requests/save-request new-request))
|
||||
|
||||
(defn add-request
|
||||
[db [_ chat-id {:keys [msg-id content]}]]
|
||||
|
@ -24,9 +23,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,12 +34,11 @@
|
|||
|
||||
(defn mark-request-as-answered!
|
||||
[_ [_ chat-id message-id]]
|
||||
(realm/write
|
||||
(realm/write :account
|
||||
(fn []
|
||||
(-> :requests
|
||||
(realm/get-by-fields
|
||||
{:chat-id chat-id
|
||||
:message-id message-id})
|
||||
(-> (realm/get-by-fields :account :requests
|
||||
{:chat-id chat-id
|
||||
:message-id message-id})
|
||||
(realm/single)
|
||||
(.-status)
|
||||
(set! "answered")))))
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
(ns status-im.chat.handlers.unviewed-messages
|
||||
(:require [re-frame.core :refer [after enrich path dispatch]]
|
||||
[status-im.utils.handlers :refer [register-handler]]
|
||||
[status-im.persistence.realm :as realm]))
|
||||
[status-im.persistence.realm.core :as realm]))
|
||||
|
||||
(defn delivered-messages []
|
||||
(-> (realm/get-by-fields
|
||||
:msgs
|
||||
:account :msgs
|
||||
{:delivery-status :delivered
|
||||
:outgoing false})
|
||||
(realm/collection->map)))
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
[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.random :as random]
|
||||
[status-im.utils.sms-listener :refer [add-sms-listener
|
||||
remove-sms-listener]]
|
||||
|
|
|
@ -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]]))
|
||||
|
@ -15,8 +15,8 @@
|
|||
[_ [identity]]
|
||||
(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 :account :commands
|
||||
:chat-id identity)]
|
||||
(dispatch [::parse-commands! identity file])
|
||||
(dispatch [::fetch-commands! identity])))
|
||||
|
||||
|
@ -73,7 +73,7 @@
|
|||
|
||||
(defn save-commands-js!
|
||||
[_ [id file]]
|
||||
(realm/create-object :commands {:chat-id id :file file}))
|
||||
(realm/create-object :account :commands {:chat-id id :file file}))
|
||||
|
||||
(defn loading-failed!
|
||||
[db [id reason details]]
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
[view st/switch-users-container
|
||||
[touchable-opacity {:onPress (fn []
|
||||
(close-drawer)
|
||||
(dispatch [:navigate-to :accounts])
|
||||
;; TODO not implemented
|
||||
)}
|
||||
[text {:style st/switch-users-text}
|
||||
|
|
|
@ -18,12 +18,13 @@
|
|||
(def config {:label-top 16
|
||||
:label-bottom 37
|
||||
:label-font-large 16
|
||||
:label-font-small 12
|
||||
:label-font-small 13
|
||||
:label-animation-duration 200})
|
||||
|
||||
(def default-props {:wrapperStyle {}
|
||||
:inputStyle {}
|
||||
:lineStyle {}
|
||||
:editable true
|
||||
:labelColor "#838c93"
|
||||
:lineColor "#0000001f"
|
||||
:focusLineColor "#0000001f"
|
||||
|
@ -68,7 +69,7 @@
|
|||
(:label-font-large config)
|
||||
(:label-font-small config)))
|
||||
:float-label? (if (s/blank? value) false true)}]
|
||||
(log/debug "component-will-mount")
|
||||
;(log/debug "component-will-mount")
|
||||
(r/set-state component data)))
|
||||
|
||||
; Invoked once, only on the client (not on the server), immediately after the
|
||||
|
@ -78,7 +79,8 @@
|
|||
; parent components.
|
||||
(defn component-did-mount [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
|
||||
; 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
|
||||
; this function will not trigger an additional render.
|
||||
(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
|
||||
; 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
|
||||
; componentDidUpdate will not be called.
|
||||
(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)
|
||||
|
||||
; 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
|
||||
; to perform preparation before an update occurs.
|
||||
(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.
|
||||
; 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.
|
||||
(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]}]
|
||||
(do
|
||||
|
@ -141,16 +146,17 @@
|
|||
max-line-width] :as state} (r/state component)
|
||||
{:keys [wrapperStyle inputStyle lineColor focusLineColor
|
||||
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)
|
||||
focusLineColor (if error errorColor focusLineColor)
|
||||
labelColor (if (and error (not float-label?)) errorColor labelColor)
|
||||
label (if error (str label " *") label)]
|
||||
(log/debug "reagent-render: " data state)
|
||||
;(log/debug "reagent-render: " data)
|
||||
[view (merge st/text-field-container wrapperStyle)
|
||||
[animated-text {:style (st/label label-top label-font-size labelColor)} label]
|
||||
[text-input {:style (merge st/text-input inputStyle)
|
||||
:placeholder ""
|
||||
:editable editable
|
||||
:onFocus #(on-focus {:component component
|
||||
:animation {:top label-top
|
||||
:to-top (:label-top config)
|
||||
|
@ -185,5 +191,5 @@
|
|||
:component-did-update component-did-update
|
||||
:display-name "text-field"
|
||||
:reagent-render reagent-render}]
|
||||
(log/debug "Creating text-field component: " data)
|
||||
;(log/debug "Creating text-field component: " data)
|
||||
(r/create-class component-data)))
|
|
@ -1,12 +1,20 @@
|
|||
(ns status-im.contacts.validations
|
||||
(: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]
|
||||
(not (realm/exists? :contacts :whisper-identity identity)))
|
||||
(not (realm/exists? :account :contacts :whisper-identity 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 ::unique-identity unique-identity?)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[status-im.components.text-field.view :refer [text-field]]
|
||||
[status-im.utils.identicon :refer [identicon]]
|
||||
[status-im.components.toolbar :refer [toolbar]]
|
||||
[status-im.utils.utils :refer [log on-error http-post toast]]
|
||||
[status-im.components.styles :refer [color-purple
|
||||
color-white
|
||||
icon-search
|
||||
|
@ -43,12 +44,12 @@
|
|||
:label (label :t/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
|
||||
"Please enter a valid address or scan a QR code")]
|
||||
(label :t/enter-valid-address))]
|
||||
[view button-input-container
|
||||
[text-field
|
||||
{:error error
|
||||
|
@ -56,25 +57,52 @@
|
|||
:value whisper-identity
|
||||
:wrapperStyle (merge button-input)
|
||||
:label (label :t/address)
|
||||
:onChangeText #(dispatch [:set-in [:new-contact :whisper-identity] %])}]
|
||||
[scan-button #(dispatch [:scan-qr-code {:toolbar-title (label :t/new-contact)} :set-new-contact-from-qr])]]))
|
||||
:onChangeText #(do
|
||||
(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 []
|
||||
[{:keys [name whisper-identity phone-number] :as new-contact} [:get :new-contact]]
|
||||
(let [valid-contact? (s/valid? ::v/contact new-contact)]
|
||||
[view st/contact-form-container
|
||||
[toolbar {:background-color :white
|
||||
:nav-action {:image {:source {:uri :icon_back}
|
||||
:style icon-back}
|
||||
:handler #(dispatch [:navigate-back])}
|
||||
:custom-content toolbar-title
|
||||
:action {:image {:source {:uri (if valid-contact?
|
||||
:icon_ok_blue
|
||||
:icon_ok_disabled)}
|
||||
:style icon-search}
|
||||
:handler #(when valid-contact? (dispatch [:add-new-contact (merge {:photo-path (identicon whisper-identity)} new-contact)]))}}]
|
||||
[view st/form-container
|
||||
[contact-name-input name]
|
||||
[contact-whisper-id-input whisper-identity]]
|
||||
[view st/address-explication-container
|
||||
[text {:style st/address-explication} (label :t/address-explication)]]]))
|
||||
[{:keys [name whisper-identity phone-number] :as new-contact} [:get :new-contact]
|
||||
error [:get :new-contact-address-error]]
|
||||
[view st/contact-form-container
|
||||
[toolbar {:background-color :white
|
||||
:nav-action {:image {:source {:uri :icon_back}
|
||||
:style icon-back}
|
||||
:handler #(dispatch [:navigate-back])}
|
||||
:custom-content toolbar-title
|
||||
:action (toolbar-action whisper-identity new-contact error)}]
|
||||
[view st/form-container
|
||||
[contact-name-input name]
|
||||
[contact-whisper-id-input whisper-identity error]]
|
||||
[view st/address-explication-container
|
||||
[text {:style st/address-explication} (label :t/address-explication)]]])
|
||||
|
|
|
@ -11,7 +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 {}
|
||||
:user-identity nil
|
||||
:contacts []
|
||||
:contacts-ids #{}
|
||||
:selected-contacts #{}
|
||||
|
@ -22,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
|
||||
|
|
|
@ -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,18 +14,20 @@
|
|||
(if tag-object
|
||||
(let [counter (dec (:count tag-object))]
|
||||
(if (zero? counter)
|
||||
(realm/delete tag-object)
|
||||
(realm/create :tag {:name tag
|
||||
:count counter}
|
||||
true))))))
|
||||
(r/delete :base tag-object)
|
||||
(r/create :base :tag
|
||||
{:name tag
|
||||
:count counter}
|
||||
true))))))
|
||||
|
||||
(defn increase-tag-counter [tag]
|
||||
(let [tag (:name tag)
|
||||
tag-object (get-tag tag)]
|
||||
(if tag-object
|
||||
(realm/create :tag {:name tag
|
||||
:count (inc (:count tag-object))}
|
||||
true))))
|
||||
(r/create :base :tag
|
||||
{:name tag
|
||||
:count (inc (:count tag-object))}
|
||||
true))))
|
||||
|
||||
(defn decrease-tags-counter [tags]
|
||||
(doseq [tag tags]
|
||||
|
@ -37,45 +38,46 @@
|
|||
(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 []
|
||||
(let [db-discoveries (discovery-list)]
|
||||
(mapv (fn [discovery]
|
||||
(if-not (discovery-exist? db-discoveries
|
||||
discovery)
|
||||
(create-discovery discovery)
|
||||
(update-discovery discovery)))
|
||||
discoveries)))))
|
||||
(r/write :base
|
||||
(fn []
|
||||
(let [db-discoveries (discovery-list)]
|
||||
(mapv (fn [discovery]
|
||||
(if-not (discovery-exist? db-discoveries
|
||||
discovery)
|
||||
(create-discovery discovery)
|
||||
(update-discovery discovery)))
|
||||
discoveries)))))
|
||||
|
||||
(defn save-discoveries [discoveries]
|
||||
(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))
|
||||
|
||||
|
|
|
@ -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)))))
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
(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.realm.core :as realm]
|
||||
[status-im.persistence.simple-kv-store :as kv]
|
||||
[status-im.protocol.state.storage :as storage]
|
||||
[status-im.utils.logging :as log]
|
||||
|
@ -55,11 +56,33 @@
|
|||
|
||||
(register-handler :initialize-db
|
||||
(fn [_ _]
|
||||
(realm/reset-account)
|
||||
(assoc app-db
|
||||
:user-identity nil)))
|
||||
|
||||
(register-handler :initialize-account-db
|
||||
(fn [db _]
|
||||
(assoc 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-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
|
||||
(u/side-effect!
|
||||
(fn [_ _]
|
||||
|
@ -77,12 +100,7 @@
|
|||
(dispatch [:crypt-initialized]))))))))
|
||||
|
||||
(defn node-started [db result]
|
||||
(let [identity (:user-identity db)
|
||||
password (:password db)]
|
||||
(log/debug "Started Node: " result)
|
||||
(when identity (do
|
||||
(dispatch [:login-account (:address identity) password])
|
||||
(dispatch [:initialize-protocol identity])))))
|
||||
(log/debug "Started Node: " result))
|
||||
|
||||
(register-handler :initialize-geth
|
||||
(u/side-effect!
|
||||
|
@ -90,7 +108,7 @@
|
|||
(log/debug "Starting node")
|
||||
(.startNode geth
|
||||
(fn [result] (node-started db result))
|
||||
#(dispatch [:initialize-protocol])))))
|
||||
#(log/debug "Geth already initialized")))))
|
||||
|
||||
(register-handler :crypt-initialized
|
||||
(u/side-effect!
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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,32 +42,33 @@
|
|||
(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))))
|
||||
(r/write :account #(r/create :account :chats chat))))
|
||||
([db chat-id identities group-chat? chat-name]
|
||||
(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
|
||||
:is-active true
|
||||
:name chat-name
|
||||
:group-chat group-chat?
|
||||
:timestamp (timestamp)
|
||||
:contacts contacts
|
||||
:last-msg-id ""}))))
|
||||
(r/create :account :chats
|
||||
{:chat-id chat-id
|
||||
:is-active true
|
||||
:name chat-name
|
||||
:group-chat group-chat?
|
||||
:timestamp (timestamp)
|
||||
:contacts contacts
|
||||
:last-msg-id ""}))))
|
||||
(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,10 +79,11 @@
|
|||
(mapv (fn [ident]
|
||||
{:identity ident}))
|
||||
(concat only-old-contacts))]
|
||||
(r/create :chats {:chat-id group-id
|
||||
:is-active true
|
||||
:name group-name
|
||||
:contacts contacts} true))))
|
||||
(r/create :account :chats
|
||||
{:chat-id group-id
|
||||
:is-active true
|
||||
:name group-name
|
||||
:contacts contacts} true))))
|
||||
db)
|
||||
|
||||
(defn normalize-contacts
|
||||
|
@ -89,23 +91,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 +120,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?)))))
|
||||
|
|
|
@ -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)))
|
||||
|
|
|
@ -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]]
|
||||
|
@ -29,8 +29,8 @@
|
|||
[chat-id {:keys [delivery-status msg-id content]
|
||||
:or {delivery-status :pending}
|
||||
: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
|
||||
|
@ -41,7 +41,7 @@
|
|||
:content content'
|
||||
:delivery-status delivery-status
|
||||
:timestamp (timestamp)})]
|
||||
(r/create :msgs message' true))))))
|
||||
(r/create :account :msgs message' true))))))
|
||||
|
||||
(defn command-type? [type]
|
||||
(contains?
|
||||
|
@ -51,20 +51,20 @@
|
|||
(defn get-messages
|
||||
([chat-id] (get-messages chat-id 0))
|
||||
([chat-id from]
|
||||
(->> (-> (r/get-by-field :msgs :chat-id chat-id)
|
||||
(r/sorted :timestamp :desc)
|
||||
(r/page from (+ from c/default-number-of-messages))
|
||||
(r/collection->map))
|
||||
(into '())
|
||||
reverse
|
||||
(keep (fn [{:keys [content-type] :as message}]
|
||||
(->> (-> (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))
|
||||
(into '())
|
||||
reverse
|
||||
(keep (fn [{:keys [content-type] :as message}]
|
||||
(if (command-type? content-type)
|
||||
(update message :content str-to-map)
|
||||
message))))))
|
||||
|
||||
(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)))))
|
||||
|
|
|
@ -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))
|
||||
|
|
@ -80,3 +80,11 @@
|
|||
(push-view :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)
|
||||
|
|
|
@ -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)))
|
|
@ -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)))
|
|
@ -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})
|
||||
|
|
@ -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
|
||||
:value (to-edn-string value)} true))))
|
||||
(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/single)
|
||||
(r/delete))))))
|
||||
(r/write schema
|
||||
(fn []
|
||||
(->> (r/get-by-field schema :kv-store :key key)
|
||||
(r/single)
|
||||
(r/delete schema))))))
|
||||
|
||||
(def kv-store (->SimpleKvStore))
|
||||
(def kv-store (->SimpleKvStore :account))
|
||||
|
||||
(def base-kv-store (->SimpleKvStore :base))
|
||||
|
|
|
@ -12,12 +12,13 @@
|
|||
[status-im.qr-scanner.styles :as st]))
|
||||
|
||||
|
||||
(defview scan-button [handler]
|
||||
[]
|
||||
[view st/scan-button
|
||||
[touchable-highlight
|
||||
{:on-press handler}
|
||||
[view st/scan-button-content
|
||||
[image {:source {:uri :scan_blue}
|
||||
:style icon-scan}]
|
||||
[text {:style st/scan-text} (label :t/scan-qr)]]]])
|
||||
(defview scan-button [{:keys [showLabel icon labelStyle handler]}]
|
||||
(let [showLabel (if (nil? showLabel) true showLabel)]
|
||||
[view st/scan-button
|
||||
[touchable-highlight
|
||||
{:on-press handler}
|
||||
[view st/scan-button-content
|
||||
[image {:source {:uri (or icon :scan_blue)}
|
||||
:style icon-scan}]
|
||||
(when showLabel [text {:style (merge st/scan-text labelStyle)}
|
||||
(label :t/scan-qr)])]]]))
|
|
@ -125,13 +125,17 @@
|
|||
:name "Name"
|
||||
:whisper-identity "Whisper Identity"
|
||||
: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
|
||||
:recover-from-passphrase "Recover from passphrase"
|
||||
:recover-access "Recover access"
|
||||
:connect "Connect"
|
||||
:address "Address"
|
||||
:password "Password"
|
||||
:login "Login"
|
||||
:wrong-password "Wrong password"
|
||||
|
||||
;users
|
||||
:add-account "Add account"
|
||||
|
|
|
@ -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))
|