Merge remote-tracking branch 'origin/develop' into response-design

# Conflicts:
#	src/status_im/chat/screen.cljs
#	src/status_im/chat/views/command.cljs
#	src/status_im/chat/views/plain_input.cljs
#	src/status_im/group_settings/screen.cljs
#	src/status_im/models/commands.cljs
#	src/status_im/new_group/screen.cljs


Former-commit-id: 217f0f93d8
This commit is contained in:
virvar 2016-06-03 16:19:59 +03:00
commit 2423dfad15
51 changed files with 602 additions and 304 deletions

9
.gitignore vendored
View File

@ -50,3 +50,12 @@ target/
#
figwheel_server.log
.nrepl-port
# Lein
#
.lein-failures
## Doo
#
out
doo-index.html

View File

@ -10,7 +10,7 @@
(def root-el (r/as-element [reloader]))
(figwheel/watch-and-reload
:websocket-url "ws://10.0.3.2:3449/figwheel-ws"
:websocket-url "ws://localhost:3449/figwheel-ws"
:heads-up-display false
:jsload-callback #(swap! cnt inc))

View File

@ -8,7 +8,7 @@
[reagent "0.5.1" :exclusions [cljsjs/react]]
[re-frame "0.6.0"]
[prismatic/schema "1.0.4"]
^{:voom {:repo "https://github.com/status-im/status-lib.git"
^{:voom {:repo "git@github.com:status-im/status-lib.git"
:branch "master"}}
[status-im/protocol "0.1.1-20160525_083359-g53ab2c2"]
[natal-shell "0.1.6"]
@ -20,9 +20,12 @@
["do" "clean"
["with-profile" "prod" "cljsbuild" "once" "ios"]
["with-profile" "prod" "cljsbuild" "once" "android"]]}
:test-paths ["test/clj"]
:figwheel {:nrepl-port 7888}
:profiles {:dev {:dependencies [[figwheel-sidecar "0.5.0-2"]
[com.cemerick/piggieback "0.2.1"]]
[com.cemerick/piggieback "0.2.1"]
[io.appium/java-client "3.4.1"]]
:plugins [[lein-doo "0.1.6"]]
:source-paths ["src" "env/dev"]
:cljsbuild {:builds {:ios {:source-paths ["src" "env/dev"]
:figwheel true
@ -35,7 +38,13 @@
:compiler {:output-to "target/android/not-used.js"
:main "env.android.main"
:output-dir "target/android"
:optimizations :none}}}}
:optimizations :none}}
:test {:source-paths ["src" "test/cljs"]
:compiler
{:main status-im.test.runner
:output-to "target/test/test.js"
:optimizations :none
:target :nodejs}}}}
:repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}}
:prod {:cljsbuild {:builds {:ios {:source-paths ["src" "env/prod"]
:compiler {:output-to "index.ios.js"
@ -46,5 +55,4 @@
:compiler {:output-to "index.android.js"
:main "env.android.main"
:output-dir "target/android"
:optimizations :simple}}}}
}})
:optimizations :simple}}}}}})

View File

@ -17,14 +17,16 @@ function tab () {
fi
osascript &>/dev/null <<EOF
tell application "iTerm"
tell current terminal
launch session "Default Session"
tell the last session
tell application "iTerm2"
tell current window
set newTab to (create tab with default profile)
tell newTab
tell current session
write text "cd \"$cdto\"$cmd"
end tell
end tell
end tell
end tell
EOF
}
@ -59,3 +61,10 @@ sleep 10s
adb reverse tcp:8081 tcp:8081 && adb reverse tcp:3449 tcp:3449
react-native run-android
if [ ! -z $2 ]
then
tab "appium"
lein test
lein doo node test once
fi

View File

@ -1 +1,4 @@
(ns cljsjs.react)
(when (exists? js/window)
(set! js/window.React (js/require "react-native")))

View File

@ -255,9 +255,9 @@
(sign-up-service/stop-listening-confirmation-code-sms db)))
(register-handler :sign-up-confirm
(fn [db [_ confirmation-code]]
(server/sign-up-confirm confirmation-code sign-up-service/on-send-code-response)
db))
(u/side-effect!
(fn [_ [_ confirmation-code]]
(server/sign-up-confirm confirmation-code sign-up-service/on-send-code-response))))
(register-handler :set-signed-up
(fn [db [_ signed-up]]

View File

@ -21,7 +21,8 @@
[status-im.chat.views.content-suggestions :refer [content-suggestions-view]]
[status-im.chat.views.suggestions :refer [suggestions-view]]
[status-im.chat.views.response :refer [response-view]]
[status-im.chat.views.new-message :refer [chat-message-new]]))
[status-im.chat.views.new-message :refer [chat-message-new]]
[status-im.i18n :refer [label label-pluralize]]))
(defn contacts-by-identity [contacts]
@ -50,7 +51,7 @@
[view st/typing-view
[view st/typing-background
[text {:style st/typing-text}
(str member " is typing")]]])
(str member " " (label :t/is-typing))]]])
(defn typing-all []
[view st/typing-all
@ -104,63 +105,63 @@
[chat-icon-view-menu-item chat-id group-chat name color true])
(defn members-text [members]
(truncate-str (str (s/join ", " (map #(:name %) members)) " and you") 35))
(truncate-str (str (s/join ", " (map #(:name %) members)) " " (label :t/and-you)) 35))
(defn actions-list-view []
(let [{:keys [group-chat chat-id]}
(subscribe [:chat-properties [:group-chat :chat-id]])
members (subscribe [:current-chat-contacts])]
(when-let [actions (if @group-chat
[{:title "Members"
[{:title (label :t/members-title)
:subtitle (members-text @members)
:icon :menu_group
:icon-style {:width 25
:height 19}
;; TODO not implemented: action Members
:handler nil}
{:title "Search chat"
:subtitle "!not implemented"
{:title (label :t/search-chat)
:subtitle (label :t/not-implemented)
:icon :search_gray_copy
:icon-style {:width 17
:height 17}
;; TODO not implemented: action Search chat
:handler nil}
{:title "Notifications and sounds"
:subtitle "!not implemented"
{:title (label :t/notifications-title)
:subtitle (label :t/not-implemented)
;;:subtitle "Chat muted"
:icon :muted
:icon-style {:width 18
:height 21}
;; TODO not implemented: action Notifications
:handler nil}
{:title "Settings"
{:title (label :t/settings)
:icon :settings
:icon-style {:width 20
:height 13}
:handler #(dispatch [:show-group-settings])}]
[{:title "Profile"
[{:title (label :t/profile)
:custom-icon [menu-item-icon-profile]
:icon :menu_group
:icon-style {:width 25
:height 19}
:handler #(dispatch [:show-profile @chat-id])}
{:title "Search chat"
:subtitle "!not implemented"
{:title (label :t/search-chat)
:subtitle (label :t/not-implemented)
:icon :search_gray_copy
:icon-style {:width 17
:height 17}
;; TODO not implemented: action Search chat
:handler nil}
{:title "Notifications and sounds"
:subtitle "!not implemented"
{:title (label :t/notifications-title)
:subtitle (label :t/not-implemented)
;;:subtitle "Notifications on"
:icon :muted
:icon-style {:width 18
:height 21}
;; TODO not implemented: action Notifications
:handler nil}
{:title "Settings"
:subtitle "!not implemented"
{:title (label :t/settings)
:subtitle (label :t/not-implemented)
:icon :settings
:icon-style {:width 20
:height 13}
@ -183,20 +184,15 @@
(fn []
[view (st/chat-name-view @show-actions)
[text {:style st/chat-name-text}
(truncate-str (or @name "Chat name") 30)]
(truncate-str (or @name (label :t/chat-name)) 30)]
(if @group-chat
[view {:flexDirection :row}
[icon :group st/group-icon]
[text {:style st/members}
(let [cnt (inc (count @contacts))]
(str cnt
(if (< 1 cnt)
" members"
" member")
;; TODO stub data: active members
", " cnt " active"))]]
(label-pluralize cnt :t/members))]]
;; TODO stub data: last activity
[text {:style st/last-activity} "Active a minute ago"])])))
[text {:style st/last-activity} (label :t/last-active)])])))
(defn toolbar-action []
(let [show-actions (subscribe [:show-actions])]

View File

@ -13,7 +13,8 @@
[status-im.constants :refer [text-content-type
content-type-command
content-type-command-request
content-type-status]]))
content-type-status]]
[status-im.i18n :refer [label]]))
(defn send-console-msg [text]
{:msg-id (random/id)
@ -32,7 +33,7 @@
(defn on-sync-contacts []
(dispatch [:received-msg
{:msg-id (random/id)
:content (str "Your contacts have been synchronized")
:content (label :t/contacts-syncronized)
:content-type text-content-type
:outgoing false
:from "console"
@ -70,8 +71,7 @@
{:msg-id msg-id
:content (command-content
:confirmation-code
(str "Thanks! We've sent you a text message with a confirmation "
"code. Please provide that code to confirm your phone number"))
(label :t/confirmation-code))
:content-type content-type-command-request
:outgoing false
:from "console"
@ -95,24 +95,21 @@
;; TODO validate and save password
(dispatch [:received-msg
{:msg-id (random/id)
:content (str "OK great! Your password has been saved. Just to let you "
"know you can always change it in the Console by the way "
"it's me the Console nice to meet you!")
:content (label :t/password-saved)
:content-type text-content-type
:outgoing false
:from "console"
:to "me"}])
(dispatch [:received-msg
{:msg-id (random/id)
:content (str "I'll generate a passphrase for you so you can restore your "
"access or log in from another device")
:content (label :t/generate-passphrase)
:content-type text-content-type
:outgoing false
:from "console"
:to "me"}])
(dispatch [:received-msg
{:msg-id (random/id)
:content "Here's your passphrase:"
:content (label :t/passphrase)
:content-type text-content-type
:outgoing false
:from "console"
@ -129,7 +126,7 @@
:to "me"}]))
(dispatch [:received-msg
{:msg-id "8"
:content "Make sure you had securely written it down"
:content (label :t/written-down)
:content-type text-content-type
:outgoing false
:from "console"
@ -140,9 +137,7 @@
{:msg-id msg-id
:content (command-content
:phone
(str "Your phone number is also required to use the app. Type the "
"exclamation mark or hit the icon to open the command list "
"and choose the !phone command"))
(label :t/phone-number-required))
:content-type content-type-command-request
:outgoing false
:from "console"
@ -150,9 +145,7 @@
(def intro-status
{:msg-id "intro-status"
:content (str "The brash businessmans braggadocio "
"and public exchange with candidates "
"in the US presidential election")
:content (label :t/intro-status)
:delivery-status "seen"
:from "console"
:chat-id "console"
@ -164,15 +157,14 @@
(dispatch [:received-msg intro-status])
(dispatch [:received-msg
{:msg-id "intro-message1"
:content "Hello there! It's Status a Dapp browser in your phone."
:content (label :t/intro-message1)
:content-type text-content-type
:outgoing false
:from "console"
:to "me"}])
(dispatch [:received-msg
{:msg-id "intro-message2"
:content (str "Status uses a highly secure key-pair authentication type "
"to provide you a reliable way to access your account")
:content (label :t/intro-message2)
:content-type text-content-type
:outgoing false
:from "console"
@ -182,8 +174,7 @@
{:msg-id msg-id
:content (command-content
:keypair-password
(str "A key pair has been generated and saved to your device. "
"Create a password to secure your key"))
(label :t/keypair-generated))
:content-type content-type-command-request
:outgoing false
:from "console"

View File

@ -72,13 +72,18 @@
(defn set-chat-command [msg-id command]
(dispatch [:set-response-chat-command msg-id (:command command)]))
(defn label [{:keys [command]}]
(->> (name command)
(str "request-")))
(defn message-content-command-request
[{:keys [msg-id content from incoming-group]}]
(let [commands-atom (subscribe [:get-commands])]
(fn [{:keys [msg-id content from incoming-group]}]
(let [commands @commands-atom
{:keys [command content]} (parse-command-request commands content)]
[touchable-highlight {:onPress #(set-chat-command msg-id command)}
[touchable-highlight {:onPress #(set-chat-command msg-id command)
:accessibility-label (label command)}
[view st/comand-request-view
[view st/command-request-message-view
(when incoming-group

View File

@ -90,6 +90,8 @@
input-message
dismiss-keyboard)
(command/try-send input-command validator))}
(when command
{:accessibility-label :command-input})
input-options)
(if message-input?
input-message
@ -102,12 +104,14 @@
[touchable-highlight {:disabled animation?
:on-press #(try-send staged-commands
input-message
dismiss-keyboard)}
dismiss-keyboard)
:accessibility-label :send-message}
[view st/send-container
[icon :send st/send-icon]]])
(if (command/valid? input-command validator)
[touchable-highlight {:disabled animation?
:on-press command/send-command}
:on-press command/send-command
:accessibility-label :stage-command}
[view st/send-container [icon :send st/send-icon]]]
(when-not response?
[touchable-highlight {:disabled animation?

View File

@ -16,13 +16,14 @@
toolbar-background2]]
[status-im.components.toolbar :refer [toolbar]]
[status-im.components.icons.ionicons :refer [icon]]
[status-im.i18n :refer [label]]
[status-im.chats-list.styles :as st]))
(defn chats-list-toolbar []
[toolbar {:nav-action {:image {:source {:uri :icon_hamburger}
:style st/hamburger-icon}
:handler open-drawer}
:title "Chats"
:title (label :t/chats)
:background-color toolbar-background2
;; TODO implement search
:action {:image {:source {:uri :icon_search}
@ -43,13 +44,13 @@
:offsetY 16
:offsetX 16}
[action-button-item
{:title "New Chat"
{:title (label :t/new-chat)
:buttonColor :#9b59b6
:onPress #(dispatch [:navigate-to :contact-list])}
[icon {:name :android-create
:style st/create-icon}]]
[action-button-item
{:title "New Group Chat"
{:title (label :t/new-group-chat)
:buttonColor :#1abc9c
:onPress #(dispatch [:show-group-new])}
[icon {:name :person-stalker

View File

@ -1,7 +1,7 @@
(ns status-im.components.action-button
(:require [reagent.core :as r]))
(set! js/window.ActionButton (js/require "react-native-action-button"))
(def class (js/require "react-native-action-button"))
(def action-button (r/adapt-react-class (.-default js/ActionButton)))
(def action-button-item (r/adapt-react-class (.. js/ActionButton -default -Item)))
(def action-button (r/adapt-react-class (.-default class)))
(def action-button-item (r/adapt-react-class (.. class -default -Item)))

View File

@ -5,11 +5,12 @@
touchable-without-feedback
text]]
[status-im.components.carousel.styles :as st]
[status-im.utils.logging :as log]))
[status-im.utils.logging :as log]
[status-im.components.react :as r]))
(defn window-page-width []
(.-width (.get (.. js/React -Dimensions) "window")))
(.-width (.get (.. r/react -Dimensions) "window")))
(def defaults {:gap 10
:sneak 10

View File

@ -6,7 +6,8 @@
image
icon]]
[status-im.components.chat-icon.styles :as st]
[status-im.components.styles :refer [color-purple]]))
[status-im.components.styles :refer [color-purple]]
[clojure.string :as s]))
(defn default-chat-icon [name styles]
[view (:default-chat-icon styles)
@ -26,10 +27,10 @@
(defview chat-icon-view [chat-id group-chat name online styles]
[photo-path [:chat-photo chat-id]]
[view (:container styles)
(if (and photo-path (not (empty? photo-path)))
(if-not (s/blank? photo-path)
[chat-icon photo-path styles]
[default-chat-icon name styles])
(when (not group-chat)
(when-not group-chat
[contact-online online styles])])
(defn chat-icon-view-chat-list [chat-id group-chat name color online]

View File

@ -2,7 +2,7 @@
(:require [clojure.string :as s]
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
[reagent.core :as r]
[status-im.components.react :refer [android?
[status-im.components.react :refer [react
view
text
image
@ -11,7 +11,8 @@
drawer-layout-android
touchable-opacity]]
[status-im.resources :as res]
[status-im.components.drawer.styles :as st]))
[status-im.components.drawer.styles :as st]
[status-im.i18n :refer [label]]))
(defonce drawer-atom (atom))
@ -45,21 +46,21 @@
[text {:style st/name-text}
@username]]
[view st/menu-items-container
[menu-item {:name "Profile"
[menu-item {:name (label :t/profile)
:handler #(dispatch [:navigate-to :my-profile])}]
[menu-item {:name "Settings"
[menu-item {:name (label :t/settings)
:handler (fn []
;; TODO not implemented
)}]
[menu-item {:name "Discovery"
[menu-item {:name (label :t/discovery)
:handler #(dispatch [:navigate-to :discovery])}]
[menu-item {:name "Contacts"
[menu-item {:name (label :t/contacts)
:handler #(dispatch [:show-contacts navigator])}]
[menu-item {:name "Invite friends"
[menu-item {:name (label :t/invite-friends)
:handler (fn []
;; TODO not implemented
)}]
[menu-item {:name "FAQ"
[menu-item {:name (label :t/faq)
:handler (fn [])}]]
[view st/switch-users-container
[touchable-opacity {:onPress (fn []
@ -67,7 +68,7 @@
;; TODO not implemented
)}
[text {:style st/switch-users-text}
"Switch users"]]]])))
(label :t/switch-users)]]]])))
(defn drawer-view [items]
[drawer-layout-android {:drawerWidth 260

View File

@ -1,6 +1,4 @@
(ns status-im.components.icons.ionicons
(:require [reagent.core :as r]))
(set! js/window.Ionicons (js/require "react-native-vector-icons/Ionicons"))
(def icon (r/adapt-react-class js/Ionicons))
(def icon (r/adapt-react-class (js/require "react-native-vector-icons/Ionicons")))

View File

@ -1,8 +1,8 @@
(ns status-im.components.invertible-scroll-view)
(ns status-im.components.invertible-scroll-view
(:require [reagent.core :as r]))
(set! js/window.InvertibleScrollView (js/require "react-native-invertible-scroll-view"))
(def class (js/require "react-native-invertible-scroll-view"))
(defn invertible-scroll-view [props]
(js/React.createElement js/InvertibleScrollView
(clj->js (merge {:inverted true} props))))
(r/create-element class (clj->js (merge {:inverted true} props))))

View File

@ -1,7 +1,5 @@
(ns status-im.components.item-checkbox
(:require [reagent.core :as r]))
(set! js/window.ItemCheckbox (js/require "react-native-circle-checkbox"))
(def item-checkbox (r/adapt-react-class js/ItemCheckbox))
(def item-checkbox (r/adapt-react-class (js/require "react-native-circle-checkbox")))

View File

@ -12,19 +12,19 @@
[status-im.components.tabs.tabs :refer [tabs]]
[status-im.components.tabs.styles :as st]
[status-im.components.styles :as common-st]
[status-im.utils.logging :as log]))
[status-im.i18n :refer [label]]))
(def tab-list
[{:view-id :chat-list
:title "Chats"
:title (label :t/chats)
:screen chats-list
:icon :icon_tab_chats}
{:view-id :discovery
:title "Discover"
:title (label :t/discovery)
:screen discovery
:icon :icon_tab_discovery}
{:view-id :contact-list
:title "Contacts"
:title (label :t/contacts)
:screen contact-list
:icon :icon_tab_contacts}])

View File

@ -1,26 +1,36 @@
(ns status-im.components.react
(:require [reagent.core :as r]
[status-im.components.styles :as st]))
[status-im.components.styles :as st]
[status-im.utils.utils :as u]))
(set! js/window.React (js/require "react-native"))
(def react (u/require "react-native"))
(def app-registry (.-AppRegistry js/React))
(def navigator (r/adapt-react-class (.-Navigator js/React)))
(def text (r/adapt-react-class (.-Text js/React)))
(def view (r/adapt-react-class (.-View js/React)))
(def image (r/adapt-react-class (.-Image js/React)))
(def touchable-highlight-class (r/adapt-react-class (.-TouchableHighlight js/React)))
(defn get-react-property [name]
(aget react name))
(defn adapt-class [class]
(when class (r/adapt-react-class class)))
(defn get-class [name]
(adapt-class (get-react-property name)))
(def app-registry (get-react-property "AppRegistry"))
(def navigator (get-class "Navigator"))
(def text (get-class "Text"))
(def view (get-class "View"))
(def image (get-class "Image"))
(def touchable-highlight-class (get-class "TouchableHighlight"))
(defn touchable-highlight [props content]
[touchable-highlight-class
(merge {:underlay-color :transparent} props)
content])
(def toolbar-android (r/adapt-react-class (.-ToolbarAndroid js/React)))
(def list-view-class (r/adapt-react-class (.-ListView js/React)))
(def toolbar-android (get-class "ToolbarAndroid"))
(def list-view-class (get-class "ListView"))
(defn list-view [props]
[list-view-class (merge {:enableEmptySections true} props)])
(def scroll-view (r/adapt-react-class (.-ScrollView js/React)))
(def touchable-without-feedback (r/adapt-react-class (.-TouchableWithoutFeedback js/React)))
(def text-input-class (r/adapt-react-class (.-TextInput js/React)))
(def scroll-view (get-class "ScrollView"))
(def touchable-without-feedback (get-class "TouchableWithoutFeedback"))
(def text-input-class (get-class "TextInput"))
(defn text-input [props text]
[text-input-class (merge
{:underlineColorAndroid :transparent
@ -28,11 +38,13 @@
:placeholder "Type"}
props)
text])
(def drawer-layout-android (r/adapt-react-class (.-DrawerLayoutAndroid js/React)))
(def touchable-opacity (r/adapt-react-class (.-TouchableOpacity js/React)))
(def modal (r/adapt-react-class (.-Modal js/React)))
(def picker (r/adapt-react-class (.-Picker js/React)))
(def picker-item (r/adapt-react-class (.-Item (.-Picker js/React))))
(def drawer-layout-android (get-class "DrawerLayoutAndroid"))
(def touchable-opacity (get-class "TouchableOpacity"))
(def modal (get-class "Modal"))
(def picker (get-class "Picker"))
(def picker-item
(when-let [picker (get-react-property "Picker")]
(adapt-class (.-Item picker))))
(def pan-responder (.-PanResponder js/React))
(def animated (.-Animated js/React))
@ -49,20 +61,18 @@
[image {:source {:uri (keyword (str "icon_" (name n)))}
:style style}]))
;(def react-linear-gradient (.-default (js/require "react-native-linear-gradient")))
;(def linear-gradient (r/adapt-react-class react-linear-gradient))
(set! js/window.LinearGradient (js/require "react-native-linear-gradient"))
(def linear-gradient-class (u/require "react-native-linear-gradient"))
(defn linear-gradient [props]
(js/React.createElement js/LinearGradient
(r/create-element linear-gradient-class
(clj->js (merge {:inverted true} props))))
(def platform (.. js/React -Platform -OS))
(def platform
(when-let [pl (.-Platform react)] (.-OS pl)))
(def android? (= platform "android"))
(defn list-item [component]
(r/as-element component))
(def dismiss-keyboard! (js/require "dismissKeyboard"))
(def dismiss-keyboard! (u/require "dismissKeyboard"))

View File

@ -1,9 +0,0 @@
(ns status-im.components.realm
(:require [reagent.core :as r]))
(set! js/window.RealmReactNative (js/require "realm/react-native"))
(def list-view-class (r/adapt-react-class (.-ListView js/RealmReactNative)))
(defn list-view [props]
[list-view-class (merge {:enableEmptySections true} props)])

View File

@ -12,13 +12,11 @@
color-purple
text1-color
text2-color
toolbar-background1]]
[status-im.components.realm :refer [list-view]]
[reagent.core :as r]))
toolbar-background1]]))
(defn toolbar [{:keys [title nav-action hide-nav? action custom-action
background-color custom-content style]}]
(let [style (merge {:flexDirection "row"
(let [style (merge {:flexDirection :row
:backgroundColor (or background-color toolbar-background1)
:height 56
:elevation 2} style)]
@ -28,21 +26,21 @@
[touchable-highlight {:on-press (:handler nav-action)}
[view {:width 56
:height 56
:alignItems "center"
:justifyContent "center"}
:alignItems :center
:justifyContent :center}
[image (:image nav-action)]]]
[touchable-highlight {:on-press #(dispatch [:navigate-back])}
[view {:width 56
:height 56}
[image {:source {:uri "icon_back"}
[image {:source {:uri :icon_back}
:style {:marginTop 21
:marginLeft 23
:width 8
:height 14}}]]]))
(or custom-content
[view {:style {:flex 1
:alignItems "center"
:justifyContent "center"}}
:alignItems :center
:justifyContent :center}}
[text {:style {:marginTop -2.5
:color text1-color
:fontSize 16
@ -54,7 +52,7 @@
[view {:width 56
:height 56
:alignItems "center"
:justifyContent "center"}
:alignItems :center
:justifyContent :center}
[image (:image action)]]])]))

View File

@ -5,7 +5,8 @@
[clojure.string :as s]
[status-im.utils.utils :refer [http-post]]
[status-im.utils.phone-number :refer [format-phone-number]]
[status-im.utils.handlers :as u]))
[status-im.utils.handlers :as u]
[status-im.utils.utils :refer [require]]))
(defn save-contact
[_ [_ contact]]
@ -26,7 +27,7 @@
(register-handler :load-contacts load-contacts!)
;; TODO see https://github.com/rt2zz/react-native-contacts/issues/45
(def react-native-contacts (js/require "react-native-contacts"))
(def react-native-contacts (require "react-native-contacts"))
(defn contact-name [contact]
(->> contact
@ -91,10 +92,14 @@
(defn add-new-contacts
[{:keys [contacts] :as db} [_ new-contacts]]
(let [identities (set (map :whisper-identity contacts))
new-contacts' (remove #(identities (:whisper-identity %)) new-contacts)]
new-contacts' (->> new-contacts
(remove #(identities (:whisper-identity %)))
(map #(vector (:whisper-identity %) %))
(into {}))]
(println new-contacts')
(-> db
(update :contacts concat new-contacts')
(assoc :new-contacts new-contacts'))))
(update :contacts merge new-contacts')
(assoc :new-contacts (vals new-contacts')))))
(register-handler :add-contacts
(after save-contacts!)

View File

@ -10,13 +10,14 @@
[status-im.components.styles :refer [toolbar-background2]]
[status-im.components.toolbar :refer [toolbar]]
[status-im.contacts.styles :as st]
[status-im.utils.listview :as lw]))
[status-im.utils.listview :as lw]
[status-im.i18n :refer [label]]))
(defn render-row [row _ _]
(list-item [contact-view row]))
(defn contact-list-toolbar []
[toolbar {:title "Contacts"
[toolbar {:title (label :t/contacts)
:background-color toolbar-background2
:action {:image {:source {:uri :icon_search}
:style st/search-icon}

View File

@ -2,7 +2,8 @@
(:require [clojure.string :as s]
[status-im.components.react :refer [view image text]]
[status-im.resources :as res]
[status-im.contacts.styles :as st]))
[status-im.contacts.styles :as st]
[status-im.i18n :refer [label]]))
(defn contact-photo [{:keys [photo-path]}]
[view st/contact-photo-container
@ -27,4 +28,4 @@
(if (pos? (count name))
name
;; todo is this correct behaviour?
"Noname")]]])
(label :t/no-name))]]])

View File

@ -9,7 +9,8 @@
[status-im.components.toolbar :refer [toolbar]]
[status-im.discovery.views.popular :refer [popular]]
[status-im.discovery.views.recent :refer [discovery-recent]]
[status-im.discovery.styles :as st]))
[status-im.discovery.styles :as st]
[status-im.i18n :refer [label]]))
(defn get-hashtags [status]
(let [hashtags (map #(subs % 1) (re-seq #"#[^ !?,;:.]+" status))]
@ -20,13 +21,13 @@
(if show-search
[text-input {:style st/discovery-search-input
:autoFocus true
:placeholder "Type your search tags here"
:placeholder (label :t/search-tags)
:onSubmitEditing (fn [e]
(let [search (aget e "nativeEvent" "text")
hashtags (get-hashtags search)]
(dispatch [:broadcast-status search hashtags])))}]
[view
[text {:style st/discovery-title} "Discover"]])])
[text {:style st/discovery-title} (label :t/discovery)]])])
(defn toogle-search [current-value]
(dispatch [:set ::show-search (not current-value)]))
@ -45,8 +46,8 @@
:handler #(toogle-search show-search)}}]
[scroll-view st/scroll-view-container
[view st/section-spacing
[text {:style st/discovery-subtitle} "Popular tags"]]
[text {:style st/discovery-subtitle} (label :t/popular-tags)]]
[popular]
[view st/section-spacing
[text {:style st/discovery-subtitle} "Recent"]]
[text {:style st/discovery-subtitle} (label :t/recent)]]
[discovery-recent]]])

View File

@ -1,7 +1,6 @@
(ns status-im.discovery.tag
(:require
[re-frame.core :refer [subscribe dispatch]]
[status-im.utils.logging :as log]
[status-im.utils.listview :refer [to-datasource]]
[status-im.components.react :refer [view text list-view list-item]]
[status-im.components.toolbar :refer [toolbar]]
@ -23,7 +22,6 @@
(defn discovery-tag []
(let [tag (subscribe [:get :current-tag])
discoveries (subscribe [:get-discoveries-by-tag])]
(log/debug "Got discoveries: " @discoveries)
(fn []
(let [items @discoveries
datasource (to-datasource items)]
@ -31,7 +29,6 @@
[toolbar {:nav-action {:image {:source {:uri :icon_back}
:style st/icon-back}
:handler #(dispatch [:navigate-back])}
:title "Add Participants"
:custom-content (title-content @tag)
:action {:image {:source {:uri :icon_search}
:style st/icon-search}

View File

@ -2,15 +2,16 @@
(:require-macros [status-im.utils.views :refer [defview]])
(:require
[re-frame.core :refer [subscribe]]
[status-im.utils.logging :as log]
[status-im.components.react :refer [android?
text]]
[status-im.components.carousel.carousel :refer [carousel]]
[status-im.discovery.styles :as st]
[status-im.discovery.views.popular-list :refer [discovery-popular-list]]))
[status-im.discovery.views.popular-list :refer [discovery-popular-list]]
[status-im.i18n :refer [label]]
[status-im.components.react :as r]))
(defn page-width []
(.-width (.get (.. js/React -Dimensions) "window")))
(.-width (.get (.. r/react -Dimensions) "window")))
(defview popular []
[popular-tags [:get-popular-tags 3]]
@ -19,4 +20,4 @@
:sneak 20}
(for [{:keys [name count]} popular-tags]
[discovery-popular-list name count])]
[text "None"]))
[text (label :t/none)]))

View File

@ -14,7 +14,8 @@
[status-im.components.toolbar :refer [toolbar]]
[status-im.components.chat-icon.screen :refer [chat-icon-view-action]]
[status-im.group-settings.styles.group-settings :as st]
[status-im.group-settings.views.member :refer [member-view]]))
[status-im.group-settings.views.member :refer [member-view]]
[status-im.i18n :refer [label]]))
(defn remove-member []
(dispatch [:remove-participants]))
@ -35,7 +36,7 @@
[text {:style st/modal-member-name} name]
[touchable-highlight {:on-press remove-member}
[text {:style st/modal-remove-text}
"Remove"]]]]]))
(label :t/remove)]]]]]))
(defview chat-members []
[members [:current-chat-contacts]]
@ -75,13 +76,13 @@
[view st/modal-color-picker-inner-container
[picker {:selectedValue new-color
:onValueChange #(dispatch [:set :new-chat-color %])}
[picker-item {:label "Blue" :value "#7099e6"}]
[picker-item {:label "Purple" :value "#a187d5"}]
[picker-item {:label "Green" :value "green"}]
[picker-item {:label "Red" :value "red"}]]
[picker-item {:label (label :t/blue) :value "#7099e6"}]
[picker-item {:label (label :t/purple) :value "#a187d5"}]
[picker-item {:label (label :t/green) :value "green"}]
[picker-item {:label (label :t/red) :value "red"}]]
[touchable-highlight {:on-press set-chat-color}
[text {:style st/modal-color-picker-save-btn-text}
"Save"]]]]])
(label :t/save)]]]]])
(defview chat-color-icon []
[chat-color [:chat :color]]
@ -92,11 +93,11 @@
(defn settings-view []
(let [settings [{:custom-icon [chat-color-icon]
:title "Change color"
:title (label :t/change-color)
:handler show-chat-color-picker}
;; TODO not implemented: Notifications
(merge {:title "Notifications and sounds"
:subtitle "!not implemented"
(merge {:title (label :t/notifications-title)
:subtitle (label :t/not-implemented)
:handler nil}
(if true
{:icon :notifications-on
@ -108,13 +109,13 @@
{:icon :close-gray
:icon-style {:width 12
:height 12}
:title "Clear history"
:title (label :t/clear-history)
;; TODO show confirmation dialog?
:handler #(dispatch [:clear-history])}
{:icon :bin
:icon-style {:width 12
:height 18}
:title "Delete and leave"
:title (label :t/delete-and-leave)
;; TODO show confirmation dialog?
:handler #(dispatch [:leave-group-chat])}]]
[view st/settings-container
@ -130,7 +131,7 @@
[chat-icon-view-action chat-id group-chat name color false]])
(defn new-group-toolbar []
[toolbar {:title "Chat settings"
[toolbar {:title (label :t/chat-settings)
:custom-action [chat-icon]}])
(defn focus []
@ -149,7 +150,7 @@
focused? [:get ::name-input-focused]
valid? [:new-chat-name-valid?]]
[view
[text {:style st/chat-name-text} "Chat name"]
[text {:style st/chat-name-text} (label :t/chat-name)]
[view (st/chat-name-value-container focused?)
[text-input {:style st/chat-name-value
:ref #(when (and % focused?) (.focus %))
@ -163,7 +164,7 @@
[view [icon :ok-purple st/add-members-icon]]]
[touchable-highlight {:style (st/chat-name-btn-edit-container true)
:on-press focus}
[text {:style st/chat-name-btn-edit-text} "Edit"]])]
[text {:style st/chat-name-btn-edit-text} (label :t/edit)]])]
(when (pos? (count validation-messages))
[text {:style st/chat-name-validation-message} (first validation-messages)])])
@ -173,16 +174,16 @@
[new-group-toolbar]
[scroll-view st/body
[chat-name]
[text {:style st/members-text} "Members"]
[text {:style st/members-text} (label :t/members-title)]
[touchable-highlight {:on-press #(dispatch [:navigate-to :add-participants])}
;; TODO add participants view is not in design
[view st/add-members-container
[icon :add-gray st/add-members-icon]
[text {:style st/add-members-text}
"Add members"]]]
(label :t/add-members)]]]
[chat-members]
[text {:style st/settings-text}
"Settings"]
(label :t/settings)]
[settings-view]]
(when show-color-picker
[chat-color-picker])

View File

@ -7,7 +7,8 @@
icon
touchable-highlight]]
[status-im.resources :as res]
[status-im.group-settings.styles.member :as st]))
[status-im.group-settings.styles.member :as st]
[status-im.i18n :refer [label]]))
(defn contact-photo [{:keys [photo-path]}]
[view st/contact-photo-container
@ -32,7 +33,7 @@
(if (pos? (count name))
name
;; todo is this correct behaviour?
"Noname")]
(label :t/no-name))]
;; TODO implement :role property for group chat contact
(when role
[text {:style st/role-text}

View File

@ -35,15 +35,19 @@
;; -- Common --------------------------------------------------------------
(defn set-el [db [_ k v]]
(assoc db k v))
(register-handler :set
(debug
(fn [db [_ k v]]
(assoc db k v))))
debug
set-el)
(defn set-in [db [_ path v]]
(assoc-in db path v))
(register-handler :set-in
(debug
(fn [db [_ path v]]
(assoc-in db path v))))
debug
set-in)
(register-handler :initialize-db
(fn [_ _]

21
src/status_im/i18n.cljs Normal file
View File

@ -0,0 +1,21 @@
(ns status-im.i18n
(:require
[status-im.translations.en :as en]
[status-im.utils.utils :as u]))
(def i18n (u/require "react-native-i18n"))
(set! (.-fallbacks i18n) true)
(set! (.-defaultSeparator i18n) "/")
(set! (.-translations i18n) (clj->js {:en en/translations}))
(defn label [path & options]
(if (exists? i18n.t)
(.t i18n (name path) (clj->js options))
(name path)))
(defn label-pluralize [count path & options]
(if (exists? i18n.t)
(.p i18n count (name path) (clj->js options))
(name path)))

View File

@ -4,32 +4,33 @@
[re-frame.core :refer [subscribe dispatch]]
[status-im.db :as db]
[status-im.components.animation :as anim]
[status-im.components.styles :refer [color-blue color-dark-mint]]))
[status-im.components.styles :refer [color-blue color-dark-mint]]
[status-im.i18n :refer [label]]))
;; todo delete
(def commands [{:command :money
:text "!money"
:description "Send money"
:description (label :t/money-command-description)
:color color-dark-mint
:request-icon {:uri "icon_lock_white"}
:icon {:uri "icon_lock_gray"}
:suggestion true}
{:command :location
:text "!location"
:description "Send location"
:description (label :t/location-command-description)
:color "#9a5dcf"
:suggestion true}
{:command :phone
:text "!phone"
:description "Send phone number"
:description (label :t/phone-command-description)
:color color-dark-mint
:request-text "Phone number request"
:request-text (label :t/phone-request-text)
:suggestion true
:handler #(dispatch [:sign-up %])}
{:command :confirmation-code
:text "!confirmationCode"
:description "Send confirmation code"
:request-text "Confirmation code request"
:description (label :t/confirmation-code-command-description)
:request-text (label :t/confirmation-code-request-text)
:color color-blue
:request-icon {:uri "icon_lock_white"}
:icon {:uri "icon_lock_gray"}
@ -37,17 +38,17 @@
:handler #(dispatch [:sign-up-confirm %])}
{:command :send
:text "!send"
:description "Send location"
:description (label :t/send-command-description)
:color "#9a5dcf"
:suggestion true}
{:command :request
:text "!request"
:description "Send request"
:description (label :t/request-command-description)
:color "#48ba30"
:suggestion true}
{:command :keypair-password
:text "!keypairPassword"
:description ""
:text "!keypair-password"
:description (label :t/keypair-password-command-description)
:color color-blue
:request-icon {:uri "icon_lock_white"}
:icon {:uri "icon_lock_gray"}
@ -55,7 +56,7 @@
:handler #(dispatch [:save-password %])}
{:command :help
:text "!help"
:description "Help"
:description (label :t/help-command-description)
:color "#9a5dcf"
:suggestion true}])

View File

@ -14,7 +14,8 @@
[status-im.components.toolbar :refer [toolbar]]
[status-im.utils.listview :refer [to-datasource]]
[status-im.new-group.views.contact :refer [new-group-contact]]
[status-im.new-group.styles :as st]))
[status-im.new-group.styles :as st]
[status-im.i18n :refer [label]]))
(defview new-group-toolbar []
@ -23,7 +24,7 @@
valid? [:new-chat-name-valid?]]
(let [create-btn-enabled? (and valid? (not creation-disabled?))]
[toolbar
{:title "New group chat"
{:title (label :t/new-group-chat)
:action {:image {:source res/v ;; {:uri "icon_search"}
:style (st/toolbar-icon create-btn-enabled?)}
:handler (when create-btn-enabled?
@ -37,7 +38,7 @@
{:underlineColorAndroid color-purple
:style st/group-name-input
:autoFocus true
:placeholder "Group Name"
:placeholder (label :t/group-name)
:onChangeText #(dispatch [:set :new-chat-name %])}
group-name]
(when (pos? (count validation-messages))
@ -48,13 +49,13 @@
[view st/new-group-container
[new-group-toolbar]
[view st/chat-name-container
[text {:style st/chat-name-text} "Chat name"]
[text {:style st/chat-name-text} (label :t/chat-name)]
[group-name-input]
[text {:style st/members-text} "Members"]
[text {:style st/members-text} (label :t/members-title)]
[touchable-highlight {:on-press (fn [])}
[view st/add-container
[icon :add_gray st/add-icon]
[text {:style st/add-text} "Add members"]]]
[text {:style st/add-text} (label :t/add-members)]]]
[list-view
{:dataSource (to-datasource contacts)
:renderRow (fn [row _ _]

View File

@ -7,11 +7,12 @@
[status-im.utils.listview :refer [to-datasource]]
[status-im.participants.views.contact :refer [participant-contact]]
[reagent.core :as r]
[status-im.participants.styles :as st]))
[status-im.participants.styles :as st]
[status-im.i18n :refer [label]]))
(defn new-participants-toolbar []
[toolbar
{:title "Add Participants"
{:title (label :t/add-participants)
:action {:image {:source res/v ;; {:uri "icon_search"}
:style st/new-participant-image}
:handler #(do (dispatch [:add-new-participants])

View File

@ -10,11 +10,12 @@
[status-im.participants.views.contact
:refer [participant-contact]]
[reagent.core :as r]
[status-im.participants.styles :as st]))
[status-im.participants.styles :as st]
[status-im.i18n :refer [label]]))
(defn remove-participants-toolbar []
[toolbar
{:title "Remove Participants"
{:title (label :t/remove-participants)
:action {:handler #(do (dispatch [:remove-participants])
(dispatch [:navigate-back]))
:image {:source res/trash-icon ;; {:uri "icon_search"}

View File

@ -2,11 +2,10 @@
(:require [cljs.reader :refer [read-string]]
[status-im.components.styles :refer [default-chat-color]]
[status-im.utils.logging :as log]
[status-im.utils.types :refer [to-string]])
[status-im.utils.types :refer [to-string]]
[status-im.utils.utils :as u])
(:refer-clojure :exclude [exists?]))
(set! js/window.Realm (js/require "realm"))
(def opts {:schema [{:name :contacts
:primaryKey :whisper-identity
:properties {:phone-number {:type "string"
@ -70,7 +69,10 @@
:objectType "tag"}
:last-updated "date"}}]})
(def realm (js/Realm. (clj->js opts)))
(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}]

View File

@ -10,7 +10,8 @@
touchable-opacity]]
[status-im.components.chat-icon.screen :refer [profile-icon
my-profile-icon]]
[status-im.profile.styles :as st]))
[status-im.profile.styles :as st]
[status-im.i18n :refer [label]]))
(defn profile-property-view [{:keys [name value]}]
[view st/profile-property-view-container
@ -34,29 +35,29 @@
[profile-icon]]
[text {:style st/user-name} name]
;; TODO stub data
[text {:style st/status} "!not implemented"]
[text {:style st/status} (label :t/not-implemented)]
[view st/btns-container
[touchable-highlight {:onPress #(message-user whisper-identity)}
[view st/message-btn
[text {:style st/message-btn-text} "Message"]]]
[text {:style st/message-btn-text} (label :t/message)]]]
[touchable-highlight {:onPress (fn []
;; TODO not implemented
)}
[view st/more-btn
[icon :more_vertical_blue st/more-btn-image]]]]]
[view st/profile-properties-container
[profile-property-view {:name "Username"
[profile-property-view {:name (label :t/username)
:value name}]
[profile-property-view {:name "Phone number"
[profile-property-view {:name (label :t/phone-number)
:value phone-number}]
;; TODO stub data
[profile-property-view {:name "Email"
:value "!not implemented"}]
[profile-property-view {:name (label :t/email)
:value (label :t/not-implemented)}]
[view st/report-user-container
[touchable-highlight {:on-press (fn []
;; TODO not implemented
)}
[text {:style st/report-user-text} "REPORT USER"]]]]])
[text {:style st/report-user-text} (label :t/report-user)]]]]])
(defview my-profile []
[username [:get :username]
@ -81,9 +82,9 @@
[text {:style st/user-name} username]
[text {:style st/status} status]]
[view st/profile-properties-container
[profile-property-view {:name "Username"
[profile-property-view {:name (label :t/username)
:value username}]
[profile-property-view {:name "Phone number"
[profile-property-view {:name (label :t/phone-number)
:value phone-number}]
[profile-property-view {:name "Email"
[profile-property-view {:name (label :t/email)
:value email}]]])

View File

@ -12,7 +12,8 @@
set-initialized]]
[status-im.constants :refer [text-content-type]]
[status-im.models.messages :as messages]
[status-im.models.chats :as chats]))
[status-im.models.chats :as chats]
[status-im.i18n :refer [label]]))
(register-handler :initialize-protocol
(u/side-effect!
@ -35,35 +36,35 @@
(let [contact-name (:name (contacts/contact-by-identity from))]
(messages/save-message chat-id {:from "system"
:msg-id (str msg-id "_" from)
:content (str (or contact-name from) " received chat invitation")
:content (str (or contact-name from) " " (label :t/received-invitation))
:content-type text-content-type})))
(defn participant-invited-to-group-msg [chat-id identity from msg-id]
(let [inviter-name (:name (contacts/contact-by-identity from))
invitee-name (if (= identity (api/my-identity))
"You"
(label :t/You)
(:name (contacts/contact-by-identity identity)))]
(messages/save-message chat-id {:from "system"
:msg-id msg-id
:content (str (or inviter-name from) " invited " (or invitee-name identity))
:content (str (or inviter-name from) " " (label :t/invited) " " (or invitee-name identity))
:content-type text-content-type})))
(defn participant-removed-from-group-msg [chat-id identity from msg-id]
(let [remover-name (:name (contacts/contact-by-identity from))
removed-name (:name (contacts/contact-by-identity identity))]
(->> (str (or remover-name from) " removed " (or removed-name identity))
(->> (str (or remover-name from) " " (label :t/removed) " " (or removed-name identity))
(system-message msg-id)
(messages/save-message chat-id))))
(defn you-removed-from-group-msg [chat-id from msg-id]
(let [remover-name (:name (contacts/contact-by-identity from))]
(->> (str (or remover-name from) " removed you from group chat")
(->> (str (or remover-name from) " " (label :t/removed-from-chat))
(system-message msg-id)
(messages/save-message chat-id))))
(defn participant-left-group-msg [chat-id from msg-id]
(let [left-name (:name (contacts/contact-by-identity from))]
(->> (str (or left-name from) " left")
(->> (str (or left-name from) " " (label :t/left))
(system-message msg-id)
(messages/save-message chat-id))))

View File

@ -0,0 +1,122 @@
(ns status-im.translations.en)
(def translations
{
;common
:members-title "Members"
:not-implemented "!not implemented"
:chat-name "Chat name"
:notifications-title "Notifications and sounds"
;drawer
:invite-friends "Invite friends"
:faq "FAQ"
:switch-users "Switch users"
;chat
:is-typing "is typing"
:and-you "and you"
:search-chat "Search chat"
:members {:one "1 member, 1 active"
:other "{{count}} members, {{count}} active"
:zero "no members"}
:last-active "Active a minute ago"
;profile
:profile "Profile"
:report-user "REPORT USER"
:message "Message"
:username "Username"
:phone-number "Phone number"
:email "Email"
;sign-up
:contacts-syncronized "Your contacts have been synchronized"
:confirmation-code (str "Thanks! We've sent you a text message with a confirmation "
"code. Please provide that code to confirm your phone number")
:password-saved (str "OK great! Your password has been saved. Just to let you "
"know you can always change it in the Console by the way "
"it's me the Console nice to meet you!")
:generate-passphrase (str "I'll generate a passphrase for you so you can restore your "
"access or log in from another device")
:passphrase "Here's your passphrase:"
:written-down "Make sure you had securely written it down"
:phone-number-required (str "Your phone number is also required to use the app. Type the "
"exclamation mark or hit the icon to open the command list "
"and choose the !phone command")
:intro-status (str "The brash businessmans braggadocio "
"and public exchange with candidates "
"in the US presidential election")
:intro-message1 "Hello there! It's Status a Dapp browser in your phone."
:intro-message2 (str "Status1 uses a highly secure key-pair authentication type "
"to provide you a reliable way to access your account")
:keypair-generated (str "A key pair has been generated and saved to your device. "
"Create a password to secure your key")
;chats
:chats "Chats"
:new-chat "New Chat"
:new-group-chat "New Group Chat"
;discover
:discovery "Discovery"
:none "None"
:search-tags "Type your search tags here"
:popular-tags "Popular tags"
:recent "Recent"
;settings
:settings "Settings"
;contacts
:contacts "Contacts"
:no-name "Noname"
:new-contact "New Contact"
;group-settings
:remove "Remove"
:save "Save"
:change-color "Change color"
:clear-history "Clear history"
:delete-and-leave "Delete and leave"
:chat-settings "Chat settings"
:edit "Edit"
:add-members "Add Members"
:blue "Blue"
:purple "Purple"
:green "Green"
:red "Red"
;commands
:money-command-description "Send money"
:location-command-description "Send location"
:phone-command-description "Send phone number"
:phone-request-text "Phone number request"
:confirmation-code-command-description "Send confirmation code"
:confirmation-code-request-text "Confirmation code request"
:send-command-description "Send location"
:request-command-description "Send request"
:keypair-password-command-description ""
:help-command-description "Help"
;new-group
:group-name "Group Name"
;participants
:add-participants "Add Participants"
:remove-participants "Remove Participants"
;protocol
:received-invitation "received chat invitation"
:removed-from-chat "removed you from group chat"
:left "left"
:invited "invited"
:removed "removed"
:You "You"
;new-contact
:import-qr "Import from QR"
:contact-name "Contact Name"
:contact-address "Contact Address"
})

View File

@ -1,9 +1,10 @@
(ns status-im.utils.crypt
(:require [goog.crypt :refer [byteArrayToHex]]
[clojure.string :as s])
[clojure.string :as s]
[status-im.utils.utils :as u])
(:import goog.crypt.Sha256))
(set! js/window.RnRandomBytes (js/require "react-native-randombytes"))
(def random-bytes (u/require "react-native-randombytes"))
(def sha-256 (Sha256.))
@ -19,7 +20,7 @@
(byteArrayToHex (.digest sha-256)))
(defn gen-random-bytes [length cb]
(.randomBytes js/window.RnRandomBytes length (fn [& [err buf]]
#_(.randomBytes random-bytes length (fn [& [err buf]]
(if err
(cb {:error err})
(cb {:buffer buf})))))

View File

@ -1,6 +1,5 @@
(ns status-im.utils.listview
(:require-macros [natal-shell.data-source :refer [data-source]])
(:require [status-im.components.realm]))
(:require-macros [natal-shell.data-source :refer [data-source]]))
(defn clone-with-rows [ds rows]
(.cloneWithRows ds (reduce (fn [ac el] (.push ac el) ac)

View File

@ -1,16 +1,17 @@
(ns status-im.utils.phone-number)
(ns status-im.utils.phone-number
(:require [status-im.utils.utils :as u]))
(def i18n (js/require "react-native-i18n"))
(def locale (.-locale i18n))
(def i18n (u/require "react-native-i18n"))
(def locale (or (.-locale i18n) "___en"))
(def country-code (subs locale 3 5))
(set! js/PhoneNumber (js/require "awesome-phonenumber"))
(def awesome-phonenumber (u/require "awesome-phonenumber"))
;; todo check wrong numbers, .getNumber returns empty string
(defn format-phone-number [number]
(str (.getNumber (js/PhoneNumber. number country-code "international"))))
(str (.getNumber (awesome-phonenumber. number country-code "international"))))
(defn valid-mobile-number? [number]
(when (string? number)
(let [number-obj (js/PhoneNumber. number country-code "international")]
(let [number-obj (awesome-phonenumber. number country-code "international")]
(and (.isValid number-obj)
(.isMobile number-obj)))))

View File

@ -1,7 +1,8 @@
(ns status-im.utils.sms-listener
(:require [status-im.components.react :refer [android?]]))
(:require [status-im.components.react :refer [android?]]
[status-im.utils.utils :as u]))
(def sms-listener (.-default (js/require "react-native-android-sms-listener")))
(def sms-listener (.-default (u/require "react-native-android-sms-listener")))
;; Only android is supported!

View File

@ -5,7 +5,6 @@
"Creates subscrition that cheks if collection (map or set) contains element"
[collection]
(fn [db [_ element]]
(println "WWWWWWWWWW" (type db))
(-> (collection @db)
(contains? element)
(reaction))))

View File

@ -5,6 +5,11 @@
[natal-shell.toast-android :as toast])
(:require [status-im.constants :as const]))
(defn require [module]
(if (exists? js/window)
(js/require module)
#js {}))
(defn log [obj]
(.log js/console obj))

View File

@ -0,0 +1,86 @@
(ns status-im.appium
(:require [clojure.java.io :as io]
[clojure.test :refer :all])
(:import (org.openqa.selenium.remote DesiredCapabilities)
(org.openqa.selenium By)
(io.appium.java_client.android AndroidDriver)
(java.net URL)
(java.util.concurrent TimeUnit)))
(defn init []
(let [dir (io/file (str (System/getProperty "user.dir")
"/android/app/build/outputs/apk"))
app (io/file dir "app-debug.apk")
capabilities (doto (DesiredCapabilities.)
(.setCapability "deviceName" "device")
(.setCapability "platformVersion" "6.0.0")
(.setCapability "app" (.getAbsolutePath app))
(.setCapability "appPackage" "com.statusim")
(.setCapability "appActivity" ".MainActivity"))
driver (AndroidDriver. (URL. "http://127.0.0.1:4723/wd/hub") capabilities)]
(-> driver
.manage
.timeouts
(.implicitlyWait 25 TimeUnit/SECONDS))
driver))
(defn by-xpath [driver xpath]
(.findElement driver (By/xpath xpath)))
(defn elements-by-xpath [driver xpath]
(.findElements driver (By/xpath xpath)))
(defn by-id [driver id]
(.findElementByAccessibilityId driver (name id)))
(defn get-element [driver id]
(if (keyword? id)
(by-id driver id)
(by-xpath driver id)))
(defn click [driver id]
(.click (get-element driver id)))
(defn write [driver input-xpath text]
(.sendKeys (get-element driver input-xpath) (into-array [text])))
(defn get-text [driver xpath]
(.getText (by-xpath driver xpath)))
(defn xpath-by-text [text]
(str ".//*[@text='" text "']"))
(defn contains-text [driver text]
(is (= 1 (->> (xpath-by-text text)
(elements-by-xpath driver)
(.size)))))
(defn quit [driver]
(.quit driver))
(defmacro appium-test
"Defines test which will create new appium session and will pass that
session as first argument to each command inside it's body. After execution
of all commands session will be closed.
For instance,
(appium-test my-test
(click :button)
(write :input \"oops\"))
will be expanded to
(deftest my-test
(let [session (init)]
(click session :button)
(write session :input \"oops\")
(quit session)))"
[name & body]
(let [sym (gensym)]
`(deftest ~name
(let [~sym (init)]
~@(for [[f & rest] body]
`(~f ~sym ~@rest))
(quit ~sym)))))

View File

@ -0,0 +1,15 @@
(ns status-im.console
(:require [clojure.test :refer :all]
[status-im.appium :refer :all]))
(def message-text
(str "Your phone number is also required to use the app. Type"
" the exclamation mark or hit the icon to open the command "
"list and choose the !phone command"))
(appium-test console-test
(click :request-keypair-password)
(write :command-input "123")
(click :stage-command)
(click :send-message)
(contains-text message-text))

View File

@ -0,0 +1,6 @@
(ns status-im.test.handlers
(:require [cljs.test :refer-macros [deftest is]]
[status-im.handlers :as h]))
(deftest test-set-val
(is (= {:key :val} (h/set-el {} [nil :key :val]))))

View File

@ -0,0 +1,5 @@
(ns status-im.test.runner
(:require [doo.runner :refer-macros [doo-tests]]
[status-im.test.handlers]))
(doo-tests 'status-im.test.handlers)

View File

@ -1,7 +0,0 @@
(ns status-im.core-test
(:require [clojure.test :refer :all]
[status-im.core :refer :all]))
(deftest a-test
(testing "FIXME, I fail."
(is (= 0 1))))