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 figwheel_server.log
.nrepl-port .nrepl-port
# Lein
#
.lein-failures
## Doo
#
out
doo-index.html

View File

@ -10,7 +10,7 @@
(def root-el (r/as-element [reloader])) (def root-el (r/as-element [reloader]))
(figwheel/watch-and-reload (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 :heads-up-display false
:jsload-callback #(swap! cnt inc)) :jsload-callback #(swap! cnt inc))

View File

@ -8,7 +8,7 @@
[reagent "0.5.1" :exclusions [cljsjs/react]] [reagent "0.5.1" :exclusions [cljsjs/react]]
[re-frame "0.6.0"] [re-frame "0.6.0"]
[prismatic/schema "1.0.4"] [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"}} :branch "master"}}
[status-im/protocol "0.1.1-20160525_083359-g53ab2c2"] [status-im/protocol "0.1.1-20160525_083359-g53ab2c2"]
[natal-shell "0.1.6"] [natal-shell "0.1.6"]
@ -20,9 +20,12 @@
["do" "clean" ["do" "clean"
["with-profile" "prod" "cljsbuild" "once" "ios"] ["with-profile" "prod" "cljsbuild" "once" "ios"]
["with-profile" "prod" "cljsbuild" "once" "android"]]} ["with-profile" "prod" "cljsbuild" "once" "android"]]}
:test-paths ["test/clj"]
:figwheel {:nrepl-port 7888} :figwheel {:nrepl-port 7888}
:profiles {:dev {:dependencies [[figwheel-sidecar "0.5.0-2"] :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"] :source-paths ["src" "env/dev"]
:cljsbuild {:builds {:ios {:source-paths ["src" "env/dev"] :cljsbuild {:builds {:ios {:source-paths ["src" "env/dev"]
:figwheel true :figwheel true
@ -35,7 +38,13 @@
:compiler {:output-to "target/android/not-used.js" :compiler {:output-to "target/android/not-used.js"
:main "env.android.main" :main "env.android.main"
:output-dir "target/android" :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]}} :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}}
:prod {:cljsbuild {:builds {:ios {:source-paths ["src" "env/prod"] :prod {:cljsbuild {:builds {:ios {:source-paths ["src" "env/prod"]
:compiler {:output-to "index.ios.js" :compiler {:output-to "index.ios.js"
@ -46,5 +55,4 @@
:compiler {:output-to "index.android.js" :compiler {:output-to "index.android.js"
:main "env.android.main" :main "env.android.main"
:output-dir "target/android" :output-dir "target/android"
:optimizations :simple}}}} :optimizations :simple}}}}}})
}})

View File

@ -17,14 +17,16 @@ function tab () {
fi fi
osascript &>/dev/null <<EOF osascript &>/dev/null <<EOF
tell application "iTerm" tell application "iTerm2"
tell current terminal tell current window
launch session "Default Session" set newTab to (create tab with default profile)
tell the last session tell newTab
tell current session
write text "cd \"$cdto\"$cmd" write text "cd \"$cdto\"$cmd"
end tell end tell
end tell end tell
end tell end tell
end tell
EOF EOF
} }
@ -59,3 +61,10 @@ sleep 10s
adb reverse tcp:8081 tcp:8081 && adb reverse tcp:3449 tcp:3449 adb reverse tcp:8081 tcp:8081 && adb reverse tcp:3449 tcp:3449
react-native run-android 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) (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))) (sign-up-service/stop-listening-confirmation-code-sms db)))
(register-handler :sign-up-confirm (register-handler :sign-up-confirm
(fn [db [_ confirmation-code]] (u/side-effect!
(server/sign-up-confirm confirmation-code sign-up-service/on-send-code-response) (fn [_ [_ confirmation-code]]
db)) (server/sign-up-confirm confirmation-code sign-up-service/on-send-code-response))))
(register-handler :set-signed-up (register-handler :set-signed-up
(fn [db [_ 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.content-suggestions :refer [content-suggestions-view]]
[status-im.chat.views.suggestions :refer [suggestions-view]] [status-im.chat.views.suggestions :refer [suggestions-view]]
[status-im.chat.views.response :refer [response-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] (defn contacts-by-identity [contacts]
@ -50,7 +51,7 @@
[view st/typing-view [view st/typing-view
[view st/typing-background [view st/typing-background
[text {:style st/typing-text} [text {:style st/typing-text}
(str member " is typing")]]]) (str member " " (label :t/is-typing))]]])
(defn typing-all [] (defn typing-all []
[view st/typing-all [view st/typing-all
@ -104,63 +105,63 @@
[chat-icon-view-menu-item chat-id group-chat name color true]) [chat-icon-view-menu-item chat-id group-chat name color true])
(defn members-text [members] (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 [] (defn actions-list-view []
(let [{:keys [group-chat chat-id]} (let [{:keys [group-chat chat-id]}
(subscribe [:chat-properties [:group-chat :chat-id]]) (subscribe [:chat-properties [:group-chat :chat-id]])
members (subscribe [:current-chat-contacts])] members (subscribe [:current-chat-contacts])]
(when-let [actions (if @group-chat (when-let [actions (if @group-chat
[{:title "Members" [{:title (label :t/members-title)
:subtitle (members-text @members) :subtitle (members-text @members)
:icon :menu_group :icon :menu_group
:icon-style {:width 25 :icon-style {:width 25
:height 19} :height 19}
;; TODO not implemented: action Members ;; TODO not implemented: action Members
:handler nil} :handler nil}
{:title "Search chat" {:title (label :t/search-chat)
:subtitle "!not implemented" :subtitle (label :t/not-implemented)
:icon :search_gray_copy :icon :search_gray_copy
:icon-style {:width 17 :icon-style {:width 17
:height 17} :height 17}
;; TODO not implemented: action Search chat ;; TODO not implemented: action Search chat
:handler nil} :handler nil}
{:title "Notifications and sounds" {:title (label :t/notifications-title)
:subtitle "!not implemented" :subtitle (label :t/not-implemented)
;;:subtitle "Chat muted" ;;:subtitle "Chat muted"
:icon :muted :icon :muted
:icon-style {:width 18 :icon-style {:width 18
:height 21} :height 21}
;; TODO not implemented: action Notifications ;; TODO not implemented: action Notifications
:handler nil} :handler nil}
{:title "Settings" {:title (label :t/settings)
:icon :settings :icon :settings
:icon-style {:width 20 :icon-style {:width 20
:height 13} :height 13}
:handler #(dispatch [:show-group-settings])}] :handler #(dispatch [:show-group-settings])}]
[{:title "Profile" [{:title (label :t/profile)
:custom-icon [menu-item-icon-profile] :custom-icon [menu-item-icon-profile]
:icon :menu_group :icon :menu_group
:icon-style {:width 25 :icon-style {:width 25
:height 19} :height 19}
:handler #(dispatch [:show-profile @chat-id])} :handler #(dispatch [:show-profile @chat-id])}
{:title "Search chat" {:title (label :t/search-chat)
:subtitle "!not implemented" :subtitle (label :t/not-implemented)
:icon :search_gray_copy :icon :search_gray_copy
:icon-style {:width 17 :icon-style {:width 17
:height 17} :height 17}
;; TODO not implemented: action Search chat ;; TODO not implemented: action Search chat
:handler nil} :handler nil}
{:title "Notifications and sounds" {:title (label :t/notifications-title)
:subtitle "!not implemented" :subtitle (label :t/not-implemented)
;;:subtitle "Notifications on" ;;:subtitle "Notifications on"
:icon :muted :icon :muted
:icon-style {:width 18 :icon-style {:width 18
:height 21} :height 21}
;; TODO not implemented: action Notifications ;; TODO not implemented: action Notifications
:handler nil} :handler nil}
{:title "Settings" {:title (label :t/settings)
:subtitle "!not implemented" :subtitle (label :t/not-implemented)
:icon :settings :icon :settings
:icon-style {:width 20 :icon-style {:width 20
:height 13} :height 13}
@ -183,20 +184,15 @@
(fn [] (fn []
[view (st/chat-name-view @show-actions) [view (st/chat-name-view @show-actions)
[text {:style st/chat-name-text} [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 (if @group-chat
[view {:flexDirection :row} [view {:flexDirection :row}
[icon :group st/group-icon] [icon :group st/group-icon]
[text {:style st/members} [text {:style st/members}
(let [cnt (inc (count @contacts))] (let [cnt (inc (count @contacts))]
(str cnt (label-pluralize cnt :t/members))]]
(if (< 1 cnt)
" members"
" member")
;; TODO stub data: active members
", " cnt " active"))]]
;; TODO stub data: last activity ;; 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 [] (defn toolbar-action []
(let [show-actions (subscribe [:show-actions])] (let [show-actions (subscribe [:show-actions])]

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,7 @@
(ns status-im.components.action-button (ns status-im.components.action-button
(:require [reagent.core :as r])) (: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 (r/adapt-react-class (.-default class)))
(def action-button-item (r/adapt-react-class (.. js/ActionButton -default -Item))) (def action-button-item (r/adapt-react-class (.. class -default -Item)))

View File

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

View File

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

View File

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

View File

@ -1,6 +1,4 @@
(ns status-im.components.icons.ionicons (ns status-im.components.icons.ionicons
(:require [reagent.core :as r])) (:require [reagent.core :as r]))
(set! js/window.Ionicons (js/require "react-native-vector-icons/Ionicons")) (def icon (r/adapt-react-class (js/require "react-native-vector-icons/Ionicons")))
(def icon (r/adapt-react-class js/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] (defn invertible-scroll-view [props]
(js/React.createElement js/InvertibleScrollView (r/create-element class (clj->js (merge {:inverted true} props))))
(clj->js (merge {:inverted true} props))))

View File

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

View File

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

View File

@ -1,26 +1,36 @@
(ns status-im.components.react (ns status-im.components.react
(:require [reagent.core :as r] (: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)) (defn get-react-property [name]
(def navigator (r/adapt-react-class (.-Navigator js/React))) (aget react name))
(def text (r/adapt-react-class (.-Text js/React)))
(def view (r/adapt-react-class (.-View js/React))) (defn adapt-class [class]
(def image (r/adapt-react-class (.-Image js/React))) (when class (r/adapt-react-class class)))
(def touchable-highlight-class (r/adapt-react-class (.-TouchableHighlight js/React)))
(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] (defn touchable-highlight [props content]
[touchable-highlight-class [touchable-highlight-class
(merge {:underlay-color :transparent} props) (merge {:underlay-color :transparent} props)
content]) content])
(def toolbar-android (r/adapt-react-class (.-ToolbarAndroid js/React))) (def toolbar-android (get-class "ToolbarAndroid"))
(def list-view-class (r/adapt-react-class (.-ListView js/React))) (def list-view-class (get-class "ListView"))
(defn list-view [props] (defn list-view [props]
[list-view-class (merge {:enableEmptySections true} props)]) [list-view-class (merge {:enableEmptySections true} props)])
(def scroll-view (r/adapt-react-class (.-ScrollView js/React))) (def scroll-view (get-class "ScrollView"))
(def touchable-without-feedback (r/adapt-react-class (.-TouchableWithoutFeedback js/React))) (def touchable-without-feedback (get-class "TouchableWithoutFeedback"))
(def text-input-class (r/adapt-react-class (.-TextInput js/React))) (def text-input-class (get-class "TextInput"))
(defn text-input [props text] (defn text-input [props text]
[text-input-class (merge [text-input-class (merge
{:underlineColorAndroid :transparent {:underlineColorAndroid :transparent
@ -28,11 +38,13 @@
:placeholder "Type"} :placeholder "Type"}
props) props)
text]) text])
(def drawer-layout-android (r/adapt-react-class (.-DrawerLayoutAndroid js/React))) (def drawer-layout-android (get-class "DrawerLayoutAndroid"))
(def touchable-opacity (r/adapt-react-class (.-TouchableOpacity js/React))) (def touchable-opacity (get-class "TouchableOpacity"))
(def modal (r/adapt-react-class (.-Modal js/React))) (def modal (get-class "Modal"))
(def picker (r/adapt-react-class (.-Picker js/React))) (def picker (get-class "Picker"))
(def picker-item (r/adapt-react-class (.-Item (.-Picker js/React)))) (def picker-item
(when-let [picker (get-react-property "Picker")]
(adapt-class (.-Item picker))))
(def pan-responder (.-PanResponder js/React)) (def pan-responder (.-PanResponder js/React))
(def animated (.-Animated js/React)) (def animated (.-Animated js/React))
@ -49,20 +61,18 @@
[image {:source {:uri (keyword (str "icon_" (name n)))} [image {:source {:uri (keyword (str "icon_" (name n)))}
:style style}])) :style style}]))
;(def react-linear-gradient (.-default (js/require "react-native-linear-gradient"))) (def linear-gradient-class (u/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"))
(defn linear-gradient [props] (defn linear-gradient [props]
(js/React.createElement js/LinearGradient (r/create-element linear-gradient-class
(clj->js (merge {:inverted true} props)))) (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")) (def android? (= platform "android"))
(defn list-item [component] (defn list-item [component]
(r/as-element 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 color-purple
text1-color text1-color
text2-color text2-color
toolbar-background1]] toolbar-background1]]))
[status-im.components.realm :refer [list-view]]
[reagent.core :as r]))
(defn toolbar [{:keys [title nav-action hide-nav? action custom-action (defn toolbar [{:keys [title nav-action hide-nav? action custom-action
background-color custom-content style]}] background-color custom-content style]}]
(let [style (merge {:flexDirection "row" (let [style (merge {:flexDirection :row
:backgroundColor (or background-color toolbar-background1) :backgroundColor (or background-color toolbar-background1)
:height 56 :height 56
:elevation 2} style)] :elevation 2} style)]
@ -28,21 +26,21 @@
[touchable-highlight {:on-press (:handler nav-action)} [touchable-highlight {:on-press (:handler nav-action)}
[view {:width 56 [view {:width 56
:height 56 :height 56
:alignItems "center" :alignItems :center
:justifyContent "center"} :justifyContent :center}
[image (:image nav-action)]]] [image (:image nav-action)]]]
[touchable-highlight {:on-press #(dispatch [:navigate-back])} [touchable-highlight {:on-press #(dispatch [:navigate-back])}
[view {:width 56 [view {:width 56
:height 56} :height 56}
[image {:source {:uri "icon_back"} [image {:source {:uri :icon_back}
:style {:marginTop 21 :style {:marginTop 21
:marginLeft 23 :marginLeft 23
:width 8 :width 8
:height 14}}]]])) :height 14}}]]]))
(or custom-content (or custom-content
[view {:style {:flex 1 [view {:style {:flex 1
:alignItems "center" :alignItems :center
:justifyContent "center"}} :justifyContent :center}}
[text {:style {:marginTop -2.5 [text {:style {:marginTop -2.5
:color text1-color :color text1-color
:fontSize 16 :fontSize 16
@ -54,7 +52,7 @@
[view {:width 56 [view {:width 56
:height 56 :height 56
:alignItems "center" :alignItems :center
:justifyContent "center"} :justifyContent :center}
[image (:image action)]]])])) [image (:image action)]]])]))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,15 +2,16 @@
(:require-macros [status-im.utils.views :refer [defview]]) (:require-macros [status-im.utils.views :refer [defview]])
(:require (:require
[re-frame.core :refer [subscribe]] [re-frame.core :refer [subscribe]]
[status-im.utils.logging :as log]
[status-im.components.react :refer [android? [status-im.components.react :refer [android?
text]] text]]
[status-im.components.carousel.carousel :refer [carousel]] [status-im.components.carousel.carousel :refer [carousel]]
[status-im.discovery.styles :as st] [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 [] (defn page-width []
(.-width (.get (.. js/React -Dimensions) "window"))) (.-width (.get (.. r/react -Dimensions) "window")))
(defview popular [] (defview popular []
[popular-tags [:get-popular-tags 3]] [popular-tags [:get-popular-tags 3]]
@ -19,4 +20,4 @@
:sneak 20} :sneak 20}
(for [{:keys [name count]} popular-tags] (for [{:keys [name count]} popular-tags]
[discovery-popular-list name count])] [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.toolbar :refer [toolbar]]
[status-im.components.chat-icon.screen :refer [chat-icon-view-action]] [status-im.components.chat-icon.screen :refer [chat-icon-view-action]]
[status-im.group-settings.styles.group-settings :as st] [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 [] (defn remove-member []
(dispatch [:remove-participants])) (dispatch [:remove-participants]))
@ -35,7 +36,7 @@
[text {:style st/modal-member-name} name] [text {:style st/modal-member-name} name]
[touchable-highlight {:on-press remove-member} [touchable-highlight {:on-press remove-member}
[text {:style st/modal-remove-text} [text {:style st/modal-remove-text}
"Remove"]]]]])) (label :t/remove)]]]]]))
(defview chat-members [] (defview chat-members []
[members [:current-chat-contacts]] [members [:current-chat-contacts]]
@ -75,13 +76,13 @@
[view st/modal-color-picker-inner-container [view st/modal-color-picker-inner-container
[picker {:selectedValue new-color [picker {:selectedValue new-color
:onValueChange #(dispatch [:set :new-chat-color %])} :onValueChange #(dispatch [:set :new-chat-color %])}
[picker-item {:label "Blue" :value "#7099e6"}] [picker-item {:label (label :t/blue) :value "#7099e6"}]
[picker-item {:label "Purple" :value "#a187d5"}] [picker-item {:label (label :t/purple) :value "#a187d5"}]
[picker-item {:label "Green" :value "green"}] [picker-item {:label (label :t/green) :value "green"}]
[picker-item {:label "Red" :value "red"}]] [picker-item {:label (label :t/red) :value "red"}]]
[touchable-highlight {:on-press set-chat-color} [touchable-highlight {:on-press set-chat-color}
[text {:style st/modal-color-picker-save-btn-text} [text {:style st/modal-color-picker-save-btn-text}
"Save"]]]]]) (label :t/save)]]]]])
(defview chat-color-icon [] (defview chat-color-icon []
[chat-color [:chat :color]] [chat-color [:chat :color]]
@ -92,11 +93,11 @@
(defn settings-view [] (defn settings-view []
(let [settings [{:custom-icon [chat-color-icon] (let [settings [{:custom-icon [chat-color-icon]
:title "Change color" :title (label :t/change-color)
:handler show-chat-color-picker} :handler show-chat-color-picker}
;; TODO not implemented: Notifications ;; TODO not implemented: Notifications
(merge {:title "Notifications and sounds" (merge {:title (label :t/notifications-title)
:subtitle "!not implemented" :subtitle (label :t/not-implemented)
:handler nil} :handler nil}
(if true (if true
{:icon :notifications-on {:icon :notifications-on
@ -108,13 +109,13 @@
{:icon :close-gray {:icon :close-gray
:icon-style {:width 12 :icon-style {:width 12
:height 12} :height 12}
:title "Clear history" :title (label :t/clear-history)
;; TODO show confirmation dialog? ;; TODO show confirmation dialog?
:handler #(dispatch [:clear-history])} :handler #(dispatch [:clear-history])}
{:icon :bin {:icon :bin
:icon-style {:width 12 :icon-style {:width 12
:height 18} :height 18}
:title "Delete and leave" :title (label :t/delete-and-leave)
;; TODO show confirmation dialog? ;; TODO show confirmation dialog?
:handler #(dispatch [:leave-group-chat])}]] :handler #(dispatch [:leave-group-chat])}]]
[view st/settings-container [view st/settings-container
@ -130,7 +131,7 @@
[chat-icon-view-action chat-id group-chat name color false]]) [chat-icon-view-action chat-id group-chat name color false]])
(defn new-group-toolbar [] (defn new-group-toolbar []
[toolbar {:title "Chat settings" [toolbar {:title (label :t/chat-settings)
:custom-action [chat-icon]}]) :custom-action [chat-icon]}])
(defn focus [] (defn focus []
@ -149,7 +150,7 @@
focused? [:get ::name-input-focused] focused? [:get ::name-input-focused]
valid? [:new-chat-name-valid?]] valid? [:new-chat-name-valid?]]
[view [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?) [view (st/chat-name-value-container focused?)
[text-input {:style st/chat-name-value [text-input {:style st/chat-name-value
:ref #(when (and % focused?) (.focus %)) :ref #(when (and % focused?) (.focus %))
@ -163,7 +164,7 @@
[view [icon :ok-purple st/add-members-icon]]] [view [icon :ok-purple st/add-members-icon]]]
[touchable-highlight {:style (st/chat-name-btn-edit-container true) [touchable-highlight {:style (st/chat-name-btn-edit-container true)
:on-press focus} :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)) (when (pos? (count validation-messages))
[text {:style st/chat-name-validation-message} (first validation-messages)])]) [text {:style st/chat-name-validation-message} (first validation-messages)])])
@ -173,16 +174,16 @@
[new-group-toolbar] [new-group-toolbar]
[scroll-view st/body [scroll-view st/body
[chat-name] [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])} [touchable-highlight {:on-press #(dispatch [:navigate-to :add-participants])}
;; TODO add participants view is not in design ;; TODO add participants view is not in design
[view st/add-members-container [view st/add-members-container
[icon :add-gray st/add-members-icon] [icon :add-gray st/add-members-icon]
[text {:style st/add-members-text} [text {:style st/add-members-text}
"Add members"]]] (label :t/add-members)]]]
[chat-members] [chat-members]
[text {:style st/settings-text} [text {:style st/settings-text}
"Settings"] (label :t/settings)]
[settings-view]] [settings-view]]
(when show-color-picker (when show-color-picker
[chat-color-picker]) [chat-color-picker])

View File

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

View File

@ -35,15 +35,19 @@
;; -- Common -------------------------------------------------------------- ;; -- Common --------------------------------------------------------------
(defn set-el [db [_ k v]]
(assoc db k v))
(register-handler :set (register-handler :set
(debug debug
(fn [db [_ k v]] set-el)
(assoc db k v))))
(defn set-in [db [_ path v]]
(assoc-in db path v))
(register-handler :set-in (register-handler :set-in
(debug debug
(fn [db [_ path v]] set-in)
(assoc-in db path v))))
(register-handler :initialize-db (register-handler :initialize-db
(fn [_ _] (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]] [re-frame.core :refer [subscribe dispatch]]
[status-im.db :as db] [status-im.db :as db]
[status-im.components.animation :as anim] [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 ;; todo delete
(def commands [{:command :money (def commands [{:command :money
:text "!money" :text "!money"
:description "Send money" :description (label :t/money-command-description)
:color color-dark-mint :color color-dark-mint
:request-icon {:uri "icon_lock_white"} :request-icon {:uri "icon_lock_white"}
:icon {:uri "icon_lock_gray"} :icon {:uri "icon_lock_gray"}
:suggestion true} :suggestion true}
{:command :location {:command :location
:text "!location" :text "!location"
:description "Send location" :description (label :t/location-command-description)
:color "#9a5dcf" :color "#9a5dcf"
:suggestion true} :suggestion true}
{:command :phone {:command :phone
:text "!phone" :text "!phone"
:description "Send phone number" :description (label :t/phone-command-description)
:color color-dark-mint :color color-dark-mint
:request-text "Phone number request" :request-text (label :t/phone-request-text)
:suggestion true :suggestion true
:handler #(dispatch [:sign-up %])} :handler #(dispatch [:sign-up %])}
{:command :confirmation-code {:command :confirmation-code
:text "!confirmationCode" :text "!confirmationCode"
:description "Send confirmation code" :description (label :t/confirmation-code-command-description)
:request-text "Confirmation code request" :request-text (label :t/confirmation-code-request-text)
:color color-blue :color color-blue
:request-icon {:uri "icon_lock_white"} :request-icon {:uri "icon_lock_white"}
:icon {:uri "icon_lock_gray"} :icon {:uri "icon_lock_gray"}
@ -37,17 +38,17 @@
:handler #(dispatch [:sign-up-confirm %])} :handler #(dispatch [:sign-up-confirm %])}
{:command :send {:command :send
:text "!send" :text "!send"
:description "Send location" :description (label :t/send-command-description)
:color "#9a5dcf" :color "#9a5dcf"
:suggestion true} :suggestion true}
{:command :request {:command :request
:text "!request" :text "!request"
:description "Send request" :description (label :t/request-command-description)
:color "#48ba30" :color "#48ba30"
:suggestion true} :suggestion true}
{:command :keypair-password {:command :keypair-password
:text "!keypairPassword" :text "!keypair-password"
:description "" :description (label :t/keypair-password-command-description)
:color color-blue :color color-blue
:request-icon {:uri "icon_lock_white"} :request-icon {:uri "icon_lock_white"}
:icon {:uri "icon_lock_gray"} :icon {:uri "icon_lock_gray"}
@ -55,7 +56,7 @@
:handler #(dispatch [:save-password %])} :handler #(dispatch [:save-password %])}
{:command :help {:command :help
:text "!help" :text "!help"
:description "Help" :description (label :t/help-command-description)
:color "#9a5dcf" :color "#9a5dcf"
:suggestion true}]) :suggestion true}])

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,8 @@
set-initialized]] set-initialized]]
[status-im.constants :refer [text-content-type]] [status-im.constants :refer [text-content-type]]
[status-im.models.messages :as messages] [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 (register-handler :initialize-protocol
(u/side-effect! (u/side-effect!
@ -35,35 +36,35 @@
(let [contact-name (:name (contacts/contact-by-identity from))] (let [contact-name (:name (contacts/contact-by-identity from))]
(messages/save-message chat-id {:from "system" (messages/save-message chat-id {:from "system"
:msg-id (str msg-id "_" from) :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}))) :content-type text-content-type})))
(defn participant-invited-to-group-msg [chat-id identity from msg-id] (defn participant-invited-to-group-msg [chat-id identity from msg-id]
(let [inviter-name (:name (contacts/contact-by-identity from)) (let [inviter-name (:name (contacts/contact-by-identity from))
invitee-name (if (= identity (api/my-identity)) invitee-name (if (= identity (api/my-identity))
"You" (label :t/You)
(:name (contacts/contact-by-identity identity)))] (:name (contacts/contact-by-identity identity)))]
(messages/save-message chat-id {:from "system" (messages/save-message chat-id {:from "system"
:msg-id msg-id :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}))) :content-type text-content-type})))
(defn participant-removed-from-group-msg [chat-id identity from msg-id] (defn participant-removed-from-group-msg [chat-id identity from msg-id]
(let [remover-name (:name (contacts/contact-by-identity from)) (let [remover-name (:name (contacts/contact-by-identity from))
removed-name (:name (contacts/contact-by-identity identity))] 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) (system-message msg-id)
(messages/save-message chat-id)))) (messages/save-message chat-id))))
(defn you-removed-from-group-msg [chat-id from msg-id] (defn you-removed-from-group-msg [chat-id from msg-id]
(let [remover-name (:name (contacts/contact-by-identity from))] (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) (system-message msg-id)
(messages/save-message chat-id)))) (messages/save-message chat-id))))
(defn participant-left-group-msg [chat-id from msg-id] (defn participant-left-group-msg [chat-id from msg-id]
(let [left-name (:name (contacts/contact-by-identity from))] (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) (system-message msg-id)
(messages/save-message chat-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 (ns status-im.utils.crypt
(:require [goog.crypt :refer [byteArrayToHex]] (:require [goog.crypt :refer [byteArrayToHex]]
[clojure.string :as s]) [clojure.string :as s]
[status-im.utils.utils :as u])
(:import goog.crypt.Sha256)) (: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.)) (def sha-256 (Sha256.))
@ -19,7 +20,7 @@
(byteArrayToHex (.digest sha-256))) (byteArrayToHex (.digest sha-256)))
(defn gen-random-bytes [length cb] (defn gen-random-bytes [length cb]
(.randomBytes js/window.RnRandomBytes length (fn [& [err buf]] #_(.randomBytes random-bytes length (fn [& [err buf]]
(if err (if err
(cb {:error err}) (cb {:error err})
(cb {:buffer buf}))))) (cb {:buffer buf})))))

View File

@ -1,6 +1,5 @@
(ns status-im.utils.listview (ns status-im.utils.listview
(:require-macros [natal-shell.data-source :refer [data-source]]) (:require-macros [natal-shell.data-source :refer [data-source]]))
(:require [status-im.components.realm]))
(defn clone-with-rows [ds rows] (defn clone-with-rows [ds rows]
(.cloneWithRows ds (reduce (fn [ac el] (.push ac el) ac) (.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 i18n (u/require "react-native-i18n"))
(def locale (.-locale i18n)) (def locale (or (.-locale i18n) "___en"))
(def country-code (subs locale 3 5)) (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 ;; todo check wrong numbers, .getNumber returns empty string
(defn format-phone-number [number] (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] (defn valid-mobile-number? [number]
(when (string? 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) (and (.isValid number-obj)
(.isMobile number-obj))))) (.isMobile number-obj)))))

View File

@ -1,7 +1,8 @@
(ns status-im.utils.sms-listener (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! ;; Only android is supported!

View File

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

View File

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