Merge branch 'develop' into structure
Conflicts: src/syng_im/android/core.cljs src/syng_im/chat/screen.cljs src/syng_im/chat/styles/suggestions.cljs src/syng_im/chat/suggestions.cljs src/syng_im/chat/views/command.cljs src/syng_im/chat/views/phone.cljs src/syng_im/chat/views/suggestions.cljs src/syng_im/components/chat/input/money.cljs src/syng_im/components/chats/chats_list.cljs src/syng_im/components/contact_list/contact.cljs src/syng_im/components/contact_list/contact_list.cljs src/syng_im/components/discovery/discovery.cljs src/syng_im/components/toolbar.cljs src/syng_im/db.cljs src/syng_im/discovery/styles.cljs src/syng_im/handlers.cljs src/syng_im/models/chat.cljs src/syng_im/models/contacts.cljs src/syng_im/subs.cljs
After Width: | Height: | Size: 347 B |
After Width: | Height: | Size: 181 B |
After Width: | Height: | Size: 366 B |
After Width: | Height: | Size: 162 B |
After Width: | Height: | Size: 274 B |
After Width: | Height: | Size: 130 B |
After Width: | Height: | Size: 242 B |
After Width: | Height: | Size: 129 B |
After Width: | Height: | Size: 444 B |
After Width: | Height: | Size: 210 B |
After Width: | Height: | Size: 500 B |
After Width: | Height: | Size: 219 B |
After Width: | Height: | Size: 624 B |
After Width: | Height: | Size: 301 B |
After Width: | Height: | Size: 775 B |
After Width: | Height: | Size: 291 B |
After Width: | Height: | Size: 892 B |
After Width: | Height: | Size: 437 B |
After Width: | Height: | Size: 960 B |
After Width: | Height: | Size: 413 B |
|
@ -2,7 +2,6 @@
|
|||
(:require-macros
|
||||
[natal-shell.back-android :refer [add-event-listener remove-event-listener]])
|
||||
(:require [reagent.core :as r :refer [atom]]
|
||||
[cljs.core :as cljs]
|
||||
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[syng-im.handlers]
|
||||
[syng-im.subs]
|
||||
|
@ -15,12 +14,10 @@
|
|||
[syng-im.new-group.screen :refer [new-group]]
|
||||
[syng-im.participants.views.create :refer [new-participants]]
|
||||
[syng-im.participants.views.remove :refer [remove-participants]]
|
||||
[syng-im.components.profile :refer [profile my-profile]]
|
||||
[syng-im.utils.utils :refer [toast]]
|
||||
[syng-im.utils.encryption]))
|
||||
|
||||
(def back-button-handler (cljs/atom {:nav nil
|
||||
:handler nil}))
|
||||
|
||||
(defn init-back-button-handler! []
|
||||
(let [new-listener (fn []
|
||||
;; todo: it might be better always return false from
|
||||
|
@ -44,7 +41,9 @@
|
|||
:chat-list [chats-list]
|
||||
:new-group [new-group]
|
||||
:contact-list [contact-list]
|
||||
:chat [chat]))))
|
||||
:chat [chat]
|
||||
:profile [profile]
|
||||
:my-profile [my-profile]))))
|
||||
|
||||
(defn init []
|
||||
(dispatch-sync [:initialize-db])
|
||||
|
|
|
@ -340,3 +340,7 @@
|
|||
((after save-chat!))
|
||||
((after open-chat!))
|
||||
debug))
|
||||
|
||||
(register-handler :switch-command-suggestions
|
||||
(fn [db [_]]
|
||||
(suggestions/switch-command-suggestions db)))
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
[syng-im.resources :as res]
|
||||
[syng-im.utils.listview :refer [to-datasource]]
|
||||
[syng-im.components.invertible-scroll-view :refer [invertible-scroll-view]]
|
||||
[syng-im.components.toolbar :refer [toolbar]]
|
||||
[syng-im.chat.views.message :refer [chat-message]]
|
||||
[syng-im.chat.views.new-message :refer [chat-message-new]]))
|
||||
|
||||
|
||||
(defn contacts-by-identity [contacts]
|
||||
(->> contacts
|
||||
(map (fn [{:keys [identity] :as contact}]
|
||||
|
@ -76,24 +78,43 @@
|
|||
[view nil]]
|
||||
items])
|
||||
|
||||
(defn action-view [{:keys [icon-style handler title subtitle]
|
||||
(defn action-view [{:keys [icon-style custom-icon handler title subtitle]
|
||||
icon-name :icon}]
|
||||
[touchable-highlight {:on-press (fn []
|
||||
(dispatch [:set-show-actions false])
|
||||
(handler))}
|
||||
(when handler
|
||||
(handler)))}
|
||||
[view st/action-icon-row
|
||||
[view st/action-icon-view
|
||||
[icon icon-name icon-style]]
|
||||
(or custom-icon
|
||||
[icon icon-name icon-style])]
|
||||
[view st/action-view
|
||||
[text {:style st/action-title} title]
|
||||
(when-let [subtitle subtitle]
|
||||
[text {:style st/action-subtitle}
|
||||
subtitle])]]])
|
||||
|
||||
(defn menu-item-contact-photo [{:keys [photo-path]}]
|
||||
[image {:source (if (s/blank? photo-path)
|
||||
res/user-no-photo
|
||||
{:uri photo-path})
|
||||
:style st/menu-item-profile-contact-photo}])
|
||||
|
||||
(defn menu-item-contact-online [{:keys [online]}]
|
||||
(when online
|
||||
[view st/menu-item-profile-online-view
|
||||
[view st/menu-item-profile-online-dot-left]
|
||||
[view st/menu-item-profile-online-dot-right]]))
|
||||
|
||||
(defn menu-item-icon-profile []
|
||||
[view st/icon-view
|
||||
[menu-item-contact-photo {}]
|
||||
[menu-item-contact-online {:online true}]])
|
||||
|
||||
(defn actions-list-view []
|
||||
(let [{:keys [group-chat active]}
|
||||
(subscribe [:chat-properties [:group-chat :active]])]
|
||||
(when-let [actions (when (and @group-chat @active)
|
||||
(let [{:keys [group-chat chat-id]}
|
||||
(subscribe [:chat-properties [:group-chat :chat-id]])]
|
||||
(when-let [actions (if @group-chat
|
||||
[{:title "Add Contact to chat"
|
||||
:icon :menu_group
|
||||
:icon-style {:width 25
|
||||
|
@ -113,6 +134,32 @@
|
|||
{:title "Settings"
|
||||
:subtitle "Not implemented"
|
||||
:icon :settings
|
||||
:icon-style {:width 20
|
||||
:height 13}
|
||||
:handler (fn [])}]
|
||||
[{:title "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"
|
||||
:icon :search_gray_copy
|
||||
:icon-style {:width 17
|
||||
:height 17}
|
||||
:handler nil #_#(dispatch
|
||||
[:show-remove-participants navigator])}
|
||||
{:title "Notifications and sounds"
|
||||
:subtitle "!not implemented"
|
||||
:icon :muted
|
||||
:icon-style {:width 18
|
||||
:height 21}
|
||||
:handler nil #_#(dispatch [:leave-group-chat
|
||||
navigator])}
|
||||
{:title "Settings"
|
||||
:subtitle "!not implemented"
|
||||
:icon :settings
|
||||
:icon-style {:width 20
|
||||
:height 13}
|
||||
:handler (fn [])}])]
|
||||
|
@ -126,40 +173,48 @@
|
|||
[overlay {:on-click-outside #(dispatch [:set-show-actions false])}
|
||||
[actions-list-view]])
|
||||
|
||||
(defn toolbar []
|
||||
(defn toolbar-content []
|
||||
(let [{:keys [group-chat name contacts]}
|
||||
(subscribe [:chat-properties [:group-chat :name :contacts]])
|
||||
show-actions (subscribe [:show-actions])]
|
||||
(fn []
|
||||
[view st/toolbar-view
|
||||
(when (not @show-actions)
|
||||
[touchable-highlight {:on-press #(dispatch [:navigate-back])}
|
||||
[view st/icon-view
|
||||
[icon :back st/back-icon]]])
|
||||
[view (st/chat-name-view @show-actions)
|
||||
[text {:style st/chat-name-text}
|
||||
(or @name "Chat name")]
|
||||
(if @group-chat
|
||||
[view {:flexDirection :row}
|
||||
[icon :group st/group-icon]
|
||||
[text {:style st/members}
|
||||
(let [cnt (count @contacts)]
|
||||
(str cnt
|
||||
(if (< 1 cnt)
|
||||
" members"
|
||||
" member")
|
||||
", " cnt " active"))]]
|
||||
[text {:style st/last-activity} "Active a minute ago"])]
|
||||
(if @show-actions
|
||||
[touchable-highlight
|
||||
{:on-press #(dispatch [:set-show-actions false])}
|
||||
[view st/icon-view
|
||||
[icon :up st/up-icon]]]
|
||||
[touchable-highlight
|
||||
{:on-press #(dispatch [:set-show-actions true])}
|
||||
[view st/icon-view
|
||||
[chat-photo {}]
|
||||
[contact-online {:online true}]]])])))
|
||||
[view (st/chat-name-view @show-actions)
|
||||
[text {:style st/chat-name-text}
|
||||
(or @name "Chat name")]
|
||||
(if @group-chat
|
||||
[view {:flexDirection :row}
|
||||
[icon :group st/group-icon]
|
||||
[text {:style st/members}
|
||||
(let [cnt (count @contacts)]
|
||||
(str cnt
|
||||
(if (< 1 cnt)
|
||||
" members"
|
||||
" member")
|
||||
", " cnt " active"))]]
|
||||
[text {:style st/last-activity} "Active a minute ago"])])))
|
||||
|
||||
(defn toolbar-action []
|
||||
(let [show-actions (subscribe [:show-actions])]
|
||||
(fn []
|
||||
(if @show-actions
|
||||
[touchable-highlight
|
||||
{:on-press #(dispatch [:set-show-actions false])}
|
||||
[view st/icon-view
|
||||
[icon :up st/up-icon]]]
|
||||
[touchable-highlight
|
||||
{:on-press #(dispatch [:set-show-actions true])}
|
||||
[view st/icon-view
|
||||
[chat-photo {}]
|
||||
[contact-online {:online true}]]]))))
|
||||
|
||||
(defn chat-toolbar []
|
||||
(let [{:keys [group-chat name contacts]}
|
||||
(subscribe [:chat-properties [:group-chat :name :contacts]])
|
||||
show-actions (subscribe [:show-actions])]
|
||||
(fn []
|
||||
[toolbar {:hide-nav? @show-actions
|
||||
:custom-content [toolbar-content]
|
||||
:custom-action [toolbar-action]}])))
|
||||
|
||||
(defview messages-view [group-chat]
|
||||
[messages [:chat :messages]
|
||||
|
@ -176,7 +231,7 @@
|
|||
group-chat [:chat :group-chat]
|
||||
show-actions-atom [:show-actions]]
|
||||
[view st/chat-view
|
||||
[toolbar]
|
||||
[chat-toolbar]
|
||||
[messages-view group-chat]
|
||||
(when group-chat [typing-all])
|
||||
(when is-active [chat-message-new])
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
text2-color
|
||||
chat-background
|
||||
color-black]]))
|
||||
|
||||
(def money-input
|
||||
{:flex 1
|
||||
:marginLeft 8
|
||||
|
@ -15,6 +14,9 @@
|
|||
:fontFamily font
|
||||
:color :black})
|
||||
|
||||
(def command-input-and-suggestions-container
|
||||
{:flexDirection :column})
|
||||
|
||||
(def command-input-container
|
||||
{:flexDirection :row
|
||||
:height 56
|
||||
|
|
|
@ -12,17 +12,22 @@
|
|||
:height 56
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def switch-commands-touchable
|
||||
{:width 56
|
||||
:height 56
|
||||
:alignItems :center
|
||||
:justifyContent :center})
|
||||
|
||||
(def list-icon
|
||||
{:marginTop 22
|
||||
:marginRight 6
|
||||
:marginBottom 6
|
||||
:marginLeft 21
|
||||
:width 13
|
||||
:height 12})
|
||||
{:width 13
|
||||
:height 12})
|
||||
|
||||
(def close-icon
|
||||
{:width 12
|
||||
:height 12})
|
||||
|
||||
(def message-input
|
||||
{:flex 1
|
||||
:marginLeft 16
|
||||
:marginTop -2
|
||||
:padding 0
|
||||
:fontSize 14
|
||||
|
|
|
@ -167,3 +167,34 @@
|
|||
|
||||
(def overlay-highlight
|
||||
{:flex 1})
|
||||
|
||||
;;----- Menu item Profile ----------------
|
||||
|
||||
(def menu-item-profile-contact-photo
|
||||
{:marginTop 13
|
||||
:marginLeft 16
|
||||
:borderRadius 50
|
||||
:width 24
|
||||
:height 24})
|
||||
|
||||
(def menu-item-profile-online-view
|
||||
{:position :absolute
|
||||
:top 26
|
||||
:left 29
|
||||
:width 15
|
||||
:height 15
|
||||
:borderRadius 50
|
||||
:backgroundColor online-color
|
||||
:borderWidth 2
|
||||
:borderColor color-white})
|
||||
|
||||
(def menu-item-profile-online-dot
|
||||
{:position :absolute
|
||||
:top 4
|
||||
:width 3
|
||||
:height 3
|
||||
:borderRadius 50
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def menu-item-profile-online-dot-left (merge menu-item-profile-online-dot {:left 1.7}))
|
||||
(def menu-item-profile-online-dot-right (merge menu-item-profile-online-dot {:left 6.3}))
|
||||
|
|
|
@ -1,44 +1,69 @@
|
|||
(ns syng-im.chat.styles.suggestions
|
||||
(:require [syng-im.components.styles :refer [font color-white]]))
|
||||
(:require [syng-im.components.styles :refer [font
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
color-blue-transparent
|
||||
selected-message-color
|
||||
online-color
|
||||
separator-color
|
||||
text1-color
|
||||
text2-color
|
||||
text3-color]]))
|
||||
|
||||
(def suggestion-item-container
|
||||
{:flexDirection :row
|
||||
:marginVertical 1
|
||||
:marginHorizontal 0
|
||||
:height 40
|
||||
:backgroundColor color-white})
|
||||
(def suggestion-height 88)
|
||||
|
||||
(def suggestion-container
|
||||
{:flexDirection :column
|
||||
:paddingLeft 16
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def suggestion-sub-container
|
||||
{:height suggestion-height
|
||||
:borderBottomWidth 1
|
||||
:borderBottomColor separator-color})
|
||||
|
||||
(defn suggestion-background
|
||||
[{:keys [color]}]
|
||||
{:flexDirection :column
|
||||
:position :absolute
|
||||
:top 10
|
||||
:left 60
|
||||
{:alignSelf :flex-start
|
||||
:marginTop 10
|
||||
:height 24
|
||||
:backgroundColor color
|
||||
:borderRadius 10})
|
||||
:borderRadius 50})
|
||||
|
||||
(def suggestion-text
|
||||
{:marginTop -2
|
||||
:marginHorizontal 10
|
||||
:fontSize 14
|
||||
{:marginTop 2.5
|
||||
:marginHorizontal 12
|
||||
:fontSize 12
|
||||
:fontFamily font
|
||||
:color color-white})
|
||||
|
||||
(def suggestion-description
|
||||
{:flex 1
|
||||
:position :absolute
|
||||
:top 7
|
||||
:left 190
|
||||
:lineHeight 18
|
||||
(def value-text
|
||||
{:marginTop 6
|
||||
:fontSize 14
|
||||
:fontFamily font
|
||||
:color :black})
|
||||
:color text1-color})
|
||||
|
||||
(defn suggestions-container
|
||||
[suggestions]
|
||||
(def description-text
|
||||
{:marginTop 2
|
||||
:fontSize 12
|
||||
:fontFamily font
|
||||
:color text2-color})
|
||||
|
||||
(defn suggestions-container [suggestions-count]
|
||||
{:flexDirection :row
|
||||
:marginVertical 1
|
||||
:marginHorizontal 0
|
||||
:height (min 105 (* 42 (count suggestions)))
|
||||
:height (min 168 (* suggestion-height suggestions-count))
|
||||
:backgroundColor color-white
|
||||
:borderRadius 5})
|
||||
|
||||
(def drag-down-touchable
|
||||
{:height 22
|
||||
:alignItems :center
|
||||
:justifyContent :center})
|
||||
|
||||
(def drag-down-icon
|
||||
{:width 16
|
||||
:height 16})
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
(:require [re-frame.core :refer [register-sub]]
|
||||
[syng-im.db :as db]
|
||||
;todo handlers in subs?...
|
||||
[syng-im.chat.suggestions :refer [get-suggestions]]
|
||||
[syng-im.models.commands :as commands]))
|
||||
[syng-im.chat.suggestions :refer
|
||||
[get-suggestions typing-command? get-content-suggestions]]
|
||||
[syng-im.models.commands :as commands]
|
||||
[syng-im.handlers.content-suggestions :refer [get-content-suggestions]]))
|
||||
|
||||
(register-sub :chat-properties
|
||||
(fn [db [_ properties]]
|
||||
|
@ -80,3 +82,13 @@
|
|||
(register-sub :get-chat
|
||||
(fn [db [_ chat-id]]
|
||||
(reaction (get-in @db [:chats chat-id]))))
|
||||
|
||||
(register-sub :typing-command?
|
||||
(fn [db _]
|
||||
(reaction (typing-command? @db))))
|
||||
|
||||
(register-sub :get-content-suggestions
|
||||
(fn [db _]
|
||||
(let [command (reaction (commands/get-chat-command @db))
|
||||
text (reaction (commands/get-chat-command-content @db))]
|
||||
(reaction (get-content-suggestions @db @command @text)))))
|
||||
|
|
|
@ -61,3 +61,12 @@
|
|||
[suggestion] (filter #(= suggestion-text' (:text %))
|
||||
(get-commands db))]
|
||||
suggestion)))
|
||||
|
||||
(defn typing-command? [db]
|
||||
(-> db
|
||||
(get-in [:chats (:current-chat-id db) :input-text])
|
||||
suggestion?))
|
||||
|
||||
(defn switch-command-suggestions [db]
|
||||
(let [text (if (typing-command? db) nil "!")]
|
||||
(assoc-in db [:chats (:current-chat-id db) :input-text] text)))
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
(ns syng-im.chat.views.command
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[syng-im.components.react :refer [view
|
||||
image
|
||||
icon
|
||||
text
|
||||
text-input
|
||||
touchable-highlight]]
|
||||
[syng-im.resources :as res]
|
||||
[syng-im.components.chat.content-suggestions :refer [content-suggestions-view]]
|
||||
[syng-im.chat.styles.input :as st]))
|
||||
|
||||
(defn cancel-command-input []
|
||||
|
@ -19,23 +18,31 @@
|
|||
(dispatch [:stage-command])
|
||||
(cancel-command-input))
|
||||
|
||||
(defn simple-command-input-view [command input-options]
|
||||
(defn valid? [message validator]
|
||||
(if validator
|
||||
(validator message)
|
||||
(pos? (count message))))
|
||||
|
||||
(defn simple-command-input-view [command input-options & {:keys [validator]}]
|
||||
(let [message-atom (subscribe [:get-chat-command-content])]
|
||||
(fn [command input-options]
|
||||
(fn [command input-options & {:keys [validator]}]
|
||||
(let [message @message-atom]
|
||||
[view st/command-input-container
|
||||
[view (st/command-text-container command)
|
||||
[text {:style st/command-text} (:text command)]]
|
||||
[text-input (merge {:style st/command-input
|
||||
:autoFocus true
|
||||
:onChangeText set-input-message
|
||||
:onSubmitEditing send-command}
|
||||
input-options)
|
||||
message]
|
||||
(if (pos? (count message))
|
||||
[touchable-highlight {:on-press send-command}
|
||||
[view st/send-container [icon :send st/send-icon]]]
|
||||
[touchable-highlight {:on-press cancel-command-input}
|
||||
[view st/cancel-container
|
||||
[image {:source res/icon-close-gray
|
||||
:style st/cancel-icon}]]])]))))
|
||||
[view st/command-input-and-suggestions-container
|
||||
[content-suggestions-view]
|
||||
[view st/command-input-container
|
||||
[view (st/command-text-container command)
|
||||
[text {:style st/command-text} (:text command)]]
|
||||
[text-input (merge {:style st/command-input
|
||||
:autoFocus true
|
||||
:onChangeText set-input-message
|
||||
:onSubmitEditing (fn []
|
||||
(when (valid? message validator)
|
||||
(send-command)))}
|
||||
input-options)
|
||||
message]
|
||||
(if (valid? message validator)
|
||||
[touchable-highlight {:on-press send-command}
|
||||
[view st/send-container [icon :send st/send-icon]]]
|
||||
[touchable-highlight {:on-press cancel-command-input}
|
||||
[view st/cancel-container
|
||||
[icon :close-gray st/cancel-icon]]])]]))))
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
(ns syng-im.chat.views.phone
|
||||
(:require
|
||||
[syng-im.chat.views.command
|
||||
:refer [simple-command-input-view]]))
|
||||
:refer [simple-command-input-view]]
|
||||
[syng-im.utils.phone-number :refer [valid-mobile-number?]]))
|
||||
|
||||
(defn phone-input-view [command]
|
||||
[simple-command-input-view command {:keyboardType :phone-pad}])
|
||||
[simple-command-input-view command {:keyboardType :phone-pad}
|
||||
:validator valid-mobile-number?])
|
||||
|
|
|
@ -18,24 +18,39 @@
|
|||
(dispatch [:send-group-chat-msg chat-id input-message])
|
||||
(dispatch [:send-chat-msg]))))
|
||||
|
||||
(defn message-valid? [staged-commands message]
|
||||
(or (and (pos? (count message))
|
||||
(not= "!" message))
|
||||
(pos? (count staged-commands))))
|
||||
|
||||
(defn try-send [chat staged-commands message]
|
||||
(when (message-valid? staged-commands message)
|
||||
(send chat message)))
|
||||
|
||||
(defn plain-message-input-view []
|
||||
(let [chat (subscribe [:get-current-chat])
|
||||
input-message-atom (subscribe [:get-chat-input-text])
|
||||
staged-commands-atom (subscribe [:get-chat-staged-commands])]
|
||||
staged-commands-atom (subscribe [:get-chat-staged-commands])
|
||||
typing-command? (subscribe [:typing-command?])]
|
||||
(fn []
|
||||
(let [input-message @input-message-atom]
|
||||
[view st/input-container
|
||||
[suggestions-view]
|
||||
[view st/input-view
|
||||
[icon :list st/list-icon]
|
||||
[touchable-highlight {:on-press #(dispatch [:switch-command-suggestions])
|
||||
:style st/switch-commands-touchable}
|
||||
[view nil
|
||||
(if @typing-command?
|
||||
[icon :close-gray st/close-icon]
|
||||
[icon :list st/list-icon])]]
|
||||
[text-input {:style st/message-input
|
||||
:autoFocus (pos? (count @staged-commands-atom))
|
||||
:onChangeText set-input-message
|
||||
:onSubmitEditing #(send @chat input-message)}
|
||||
:onSubmitEditing #(try-send @chat @staged-commands-atom
|
||||
input-message)}
|
||||
input-message]
|
||||
[icon :smile st/smile-icon]
|
||||
(when (or (pos? (count input-message))
|
||||
(pos? (count @staged-commands-atom)))
|
||||
(when (message-valid? @staged-commands-atom input-message)
|
||||
[touchable-highlight {:on-press #(send @chat input-message)}
|
||||
[view st/send-container
|
||||
[icon :send st/send-icon]]])]]))))
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[syng-im.components.react :refer [view
|
||||
text
|
||||
icon
|
||||
touchable-highlight
|
||||
list-view
|
||||
list-item]]
|
||||
|
@ -17,10 +18,12 @@
|
|||
:as suggestion}]
|
||||
[touchable-highlight
|
||||
{:onPress #(set-command-input (keyword command))}
|
||||
[view st/suggestion-item-container
|
||||
[view (st/suggestion-background suggestion)
|
||||
[text {:style st/suggestion-text} label]]
|
||||
[text {:style st/suggestion-description} description]]])
|
||||
[view st/suggestion-container
|
||||
[view st/suggestion-sub-container
|
||||
[view (st/suggestion-background suggestion)
|
||||
[text {:style st/suggestion-text} label]]
|
||||
[text {:style st/value-text} label]
|
||||
[text {:style st/description-text} description]]]])
|
||||
|
||||
(defn render-row [row _ _]
|
||||
(list-item [suggestion-list-item row]))
|
||||
|
@ -30,8 +33,14 @@
|
|||
(fn []
|
||||
(let [suggestions @suggestions-atom]
|
||||
(when (seq suggestions)
|
||||
[view (st/suggestions-container suggestions)
|
||||
[list-view {:dataSource (to-datasource suggestions)
|
||||
:enableEmptySections true
|
||||
:renderRow render-row
|
||||
:style {}}]])))))
|
||||
[view
|
||||
[touchable-highlight {:style st/drag-down-touchable
|
||||
:onPress (fn []
|
||||
;; TODO hide suggestions?
|
||||
)}
|
||||
[view
|
||||
[icon :drag_down st/drag-down-icon]]]
|
||||
[view (st/suggestions-container (count suggestions))
|
||||
[list-view {:dataSource (to-datasource suggestions)
|
||||
:enableEmptySections true
|
||||
:renderRow render-row}]]])))))
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
(ns syng-im.components.chat.content-suggestions
|
||||
(:require-macros
|
||||
[natal-shell.core :refer [with-error-view]])
|
||||
(:require [clojure.string :as cstr]
|
||||
[reagent.core :as r]
|
||||
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[syng-im.components.react :refer [view
|
||||
icon
|
||||
text
|
||||
touchable-highlight
|
||||
list-view
|
||||
list-item]]
|
||||
[syng-im.components.chat.content-suggestions-styles :as st]
|
||||
[syng-im.utils.listview :refer [to-datasource]]
|
||||
[syng-im.utils.utils :refer [log toast http-post]]
|
||||
[syng-im.utils.logging :as log]))
|
||||
|
||||
(defn set-command-content [content]
|
||||
(dispatch [:set-chat-command-content content]))
|
||||
|
||||
(defn suggestion-list-item [suggestion]
|
||||
[touchable-highlight {:onPress (fn []
|
||||
(set-command-content (:value suggestion)))
|
||||
:underlay-color :transparent}
|
||||
[view st/suggestion-container
|
||||
[view st/suggestion-sub-container
|
||||
[text {:style st/value-text}
|
||||
(:value suggestion)]
|
||||
[text {:style st/description-text}
|
||||
(:description suggestion)]]]])
|
||||
|
||||
(defn render-row [row section-id row-id]
|
||||
(list-item [suggestion-list-item (js->clj row :keywordize-keys true)]))
|
||||
|
||||
(defn content-suggestions-view []
|
||||
(let [suggestions-atom (subscribe [:get-content-suggestions])]
|
||||
(fn []
|
||||
(let [suggestions @suggestions-atom]
|
||||
(when (seq suggestions)
|
||||
[view nil
|
||||
[touchable-highlight {:style st/drag-down-touchable
|
||||
:onPress (fn []
|
||||
;; TODO hide suggestions?
|
||||
)
|
||||
:underlay-color :transparent}
|
||||
[view nil
|
||||
[icon :drag_down st/drag-down-icon]]]
|
||||
[view (st/suggestions-container (count suggestions))
|
||||
[list-view {:dataSource (to-datasource suggestions)
|
||||
:renderRow render-row}]]])))))
|
|
@ -0,0 +1,54 @@
|
|||
(ns syng-im.components.chat.content-suggestions-styles
|
||||
(:require [syng-im.components.styles :refer [font
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
color-blue-transparent
|
||||
selected-message-color
|
||||
online-color
|
||||
separator-color
|
||||
text1-color
|
||||
text2-color
|
||||
text3-color]]))
|
||||
|
||||
(def suggestion-height 56)
|
||||
|
||||
(def suggestion-container
|
||||
{:flexDirection :column
|
||||
:paddingLeft 16
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def suggestion-sub-container
|
||||
{:height suggestion-height
|
||||
:borderBottomWidth 1
|
||||
:borderBottomColor separator-color})
|
||||
|
||||
(def value-text
|
||||
{:marginTop 9
|
||||
:fontSize 14
|
||||
:fontFamily font
|
||||
:color text1-color})
|
||||
|
||||
(def description-text
|
||||
{:marginTop 1.5
|
||||
:fontSize 14
|
||||
:fontFamily font
|
||||
:color text2-color})
|
||||
|
||||
(defn suggestions-container [suggestions-count]
|
||||
{:flexDirection :row
|
||||
:marginVertical 1
|
||||
:marginHorizontal 0
|
||||
:height (min 150 (* suggestion-height suggestions-count))
|
||||
:backgroundColor color-white
|
||||
:borderRadius 5})
|
||||
|
||||
(def drag-down-touchable
|
||||
{:height 22
|
||||
:alignItems :center
|
||||
:justifyContent :center})
|
||||
|
||||
(def drag-down-icon
|
||||
{:width 16
|
||||
:height 16})
|
|
@ -0,0 +1,81 @@
|
|||
(ns syng-im.components.drawer
|
||||
(:require [clojure.string :as s]
|
||||
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[reagent.core :as r]
|
||||
[syng-im.components.react :refer [android?
|
||||
view
|
||||
text
|
||||
image
|
||||
navigator
|
||||
toolbar-android
|
||||
drawer-layout-android
|
||||
touchable-opacity]]
|
||||
[syng-im.resources :as res]
|
||||
[syng-im.components.drawer-styles :as st]))
|
||||
|
||||
(defonce drawer-atom (atom))
|
||||
|
||||
(defn open-drawer []
|
||||
(.openDrawer @drawer-atom))
|
||||
|
||||
(defn close-drawer []
|
||||
(.closeDrawer @drawer-atom))
|
||||
|
||||
(defn user-photo [{:keys [photo-path]}]
|
||||
[image {:source (if (s/blank? photo-path)
|
||||
res/user-no-photo
|
||||
{:uri photo-path})
|
||||
:style st/user-photo}])
|
||||
|
||||
(defn menu-item [{:keys [name handler]}]
|
||||
[touchable-opacity {:style st/menu-item-touchable
|
||||
:onPress (fn []
|
||||
(close-drawer)
|
||||
(handler))}
|
||||
[text {:style st/menu-item-text}
|
||||
name]])
|
||||
|
||||
(defn drawer-menu [navigator]
|
||||
(let [username (subscribe [:get :username])]
|
||||
(fn [navigator]
|
||||
[view st/drawer-menu
|
||||
[view st/user-photo-container
|
||||
[user-photo {}]]
|
||||
[view st/name-container
|
||||
[text {:style st/name-text}
|
||||
@username]]
|
||||
[view st/menu-items-container
|
||||
[menu-item {:name "Profile"
|
||||
:handler (fn []
|
||||
(dispatch [:show-my-profile]))}]
|
||||
[menu-item {:name "Settings"
|
||||
:handler (fn []
|
||||
;; TODO not implemented
|
||||
)}]
|
||||
[menu-item {:name "Discovery"
|
||||
:handler (fn []
|
||||
(dispatch [:navigate-to :discovery]))}]
|
||||
[menu-item {:name "Contacts"
|
||||
:handler (fn []
|
||||
(dispatch [:show-contacts navigator]))}]
|
||||
[menu-item {:name "Invite friends"
|
||||
:handler (fn []
|
||||
;; TODO not implemented
|
||||
)}]
|
||||
[menu-item {:name "FAQ"
|
||||
:handler (fn [])}]]
|
||||
[view st/switch-users-container
|
||||
[touchable-opacity {:onPress (fn []
|
||||
(close-drawer)
|
||||
;; TODO not implemented
|
||||
)}
|
||||
[text {:style st/switch-users-text}
|
||||
"Switch users"]]]])))
|
||||
|
||||
(defn drawer-view [{:keys [navigator]} items]
|
||||
[drawer-layout-android {:drawerWidth 260
|
||||
:drawerPosition js/React.DrawerLayoutAndroid.positions.Left
|
||||
:render-navigation-view #(r/as-element [drawer-menu navigator])
|
||||
:ref (fn [drawer]
|
||||
(reset! drawer-atom drawer))}
|
||||
items])
|
|
@ -0,0 +1,64 @@
|
|||
(ns syng-im.components.drawer-styles
|
||||
(:require [syng-im.components.styles :refer [font
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
color-blue-transparent
|
||||
selected-message-color
|
||||
online-color
|
||||
separator-color
|
||||
text1-color
|
||||
text2-color
|
||||
text3-color]]))
|
||||
|
||||
(def user-photo
|
||||
{:borderRadius 50
|
||||
:width 64
|
||||
:height 64})
|
||||
|
||||
(def menu-item-touchable
|
||||
{:height 48
|
||||
:paddingLeft 16
|
||||
:paddingTop 14})
|
||||
|
||||
(def menu-item-text
|
||||
{:fontSize 14
|
||||
:fontFamily font
|
||||
:lineHeight 21
|
||||
:color text1-color})
|
||||
|
||||
(def drawer-menu
|
||||
{:flex 1
|
||||
:backgroundColor color-white
|
||||
:flexDirection :column})
|
||||
|
||||
(def user-photo-container
|
||||
{:marginTop 40
|
||||
:alignItems :center
|
||||
:justifyContent :center})
|
||||
|
||||
(def name-container
|
||||
{:marginTop 20
|
||||
:alignItems :center})
|
||||
|
||||
(def name-text
|
||||
{:marginTop -2.5
|
||||
:color text1-color
|
||||
:fontSize 16})
|
||||
|
||||
(def menu-items-container
|
||||
{:flex 1
|
||||
:marginTop 80
|
||||
:alignItems :stretch
|
||||
:flexDirection :column})
|
||||
|
||||
(def switch-users-container
|
||||
{:paddingVertical 36
|
||||
:alignItems :center})
|
||||
|
||||
(def switch-users-text
|
||||
{:fontSize 14
|
||||
:fontFamily font
|
||||
:lineHeight 21
|
||||
:color text3-color})
|
|
@ -0,0 +1,109 @@
|
|||
(ns syng-im.components.profile
|
||||
(:require [clojure.string :as s]
|
||||
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[syng-im.components.react :refer [android?
|
||||
view
|
||||
text
|
||||
text-input
|
||||
image
|
||||
icon
|
||||
scroll-view
|
||||
touchable-highlight
|
||||
touchable-opacity]]
|
||||
[syng-im.resources :as res]
|
||||
[syng-im.components.profile-styles :as st]))
|
||||
|
||||
(defn user-photo [{:keys [photo-path]}]
|
||||
[image {:source (if (s/blank? photo-path)
|
||||
res/user-no-photo
|
||||
{:uri photo-path})
|
||||
:style st/user-photo}])
|
||||
|
||||
(defn user-online [{:keys [online]}]
|
||||
(when online
|
||||
[view st/user-online-container
|
||||
[view st/user-online-dot-left]
|
||||
[view st/user-online-dot-right]]))
|
||||
|
||||
(defn profile-property-view [{:keys [name value]}]
|
||||
[view st/profile-property-view-container
|
||||
[view st/profile-property-view-sub-container
|
||||
[text {:style st/profile-property-view-label}
|
||||
name]
|
||||
[text {:style st/profile-property-view-value}
|
||||
value]]])
|
||||
|
||||
(defn message-user [identity]
|
||||
(when identity
|
||||
(dispatch [:show-chat identity nil :push])))
|
||||
|
||||
(defn profile []
|
||||
(let [contact (subscribe [:contact])]
|
||||
(fn []
|
||||
[scroll-view {:style st/profile}
|
||||
[touchable-highlight {:style st/back-btn-touchable
|
||||
:on-press #(dispatch [:navigate-back])}
|
||||
[view st/back-btn-container
|
||||
[icon :back st/back-btn-icon]]]
|
||||
[view st/status-block
|
||||
[view st/user-photo-container
|
||||
[user-photo {}]
|
||||
[user-online {:online true}]]
|
||||
[text {:style st/user-name}
|
||||
(:name @contact)]
|
||||
[text {:style st/status}
|
||||
"!not implemented"]
|
||||
[view st/btns-container
|
||||
[touchable-highlight {:onPress #(message-user (:whisper-identity @contact))}
|
||||
[view st/message-btn
|
||||
[text {:style st/message-btn-text}
|
||||
"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"
|
||||
:value (:name @contact)}]
|
||||
[profile-property-view {:name "Phone number"
|
||||
:value (:phone-number @contact)}]
|
||||
[profile-property-view {:name "Email"
|
||||
:value "!not implemented"}]
|
||||
[view st/report-user-container
|
||||
[touchable-opacity {}
|
||||
[text {:style st/report-user-text}
|
||||
"REPORT USER"]]]]])))
|
||||
|
||||
(defn my-profile []
|
||||
(let [username (subscribe [:get :username])
|
||||
phone-number (subscribe [:get :phone-number])
|
||||
email (subscribe [:get :email])
|
||||
status (subscribe [:get :status])]
|
||||
(fn []
|
||||
[scroll-view {:style st/profile}
|
||||
[touchable-highlight {:style st/back-btn-touchable
|
||||
:on-press #(dispatch [:navigate-back])}
|
||||
[view st/back-btn-container
|
||||
[icon :back st/back-btn-icon]]]
|
||||
[touchable-highlight {:style st/actions-btn-touchable
|
||||
:on-press (fn []
|
||||
;; TODO not implemented
|
||||
)}
|
||||
[view st/actions-btn-container
|
||||
[icon :dots st/actions-btn-icon]]]
|
||||
[view st/status-block
|
||||
[view st/user-photo-container
|
||||
[user-photo {}]
|
||||
[user-online {:online true}]]
|
||||
[text {:style st/user-name}
|
||||
@username]
|
||||
[text {:style st/status}
|
||||
@status]]
|
||||
[view st/profile-properties-container
|
||||
[profile-property-view {:name "Username"
|
||||
:value @username}]
|
||||
[profile-property-view {:name "Phone number"
|
||||
:value @phone-number}]
|
||||
[profile-property-view {:name "Email"
|
||||
:value @email}]]])))
|
|
@ -0,0 +1,168 @@
|
|||
(ns syng-im.components.profile-styles
|
||||
(:require [syng-im.components.styles :refer [font
|
||||
color-light-blue-transparent
|
||||
color-white
|
||||
color-black
|
||||
color-blue
|
||||
color-blue-transparent
|
||||
selected-message-color
|
||||
online-color
|
||||
separator-color
|
||||
text1-color
|
||||
text2-color]]))
|
||||
|
||||
(def user-photo
|
||||
{:borderRadius 50
|
||||
:width 64
|
||||
:height 64})
|
||||
|
||||
(def user-online-container
|
||||
{:position :absolute
|
||||
:top 44
|
||||
:left 44
|
||||
:width 24
|
||||
:height 24
|
||||
:borderRadius 50
|
||||
:backgroundColor online-color
|
||||
:borderWidth 2
|
||||
:borderColor color-white})
|
||||
|
||||
(def user-online-dot
|
||||
{:position :absolute
|
||||
:top 8
|
||||
:left 5
|
||||
:width 4
|
||||
:height 4
|
||||
:borderRadius 50
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def user-online-dot-left
|
||||
(assoc user-online-dot :left 5))
|
||||
|
||||
(def user-online-dot-right
|
||||
(assoc user-online-dot :left 11))
|
||||
|
||||
(def profile-property-view-container
|
||||
{:height 85
|
||||
:paddingHorizontal 16})
|
||||
|
||||
(def profile-property-view-sub-container
|
||||
{:borderBottomWidth 1
|
||||
:borderBottomColor separator-color})
|
||||
|
||||
(def profile-property-view-label
|
||||
{:marginTop 16
|
||||
:fontSize 14
|
||||
:fontFamily font
|
||||
:color text2-color})
|
||||
|
||||
(def profile-property-view-value
|
||||
{:marginTop 11
|
||||
:height 40
|
||||
:fontSize 16
|
||||
:fontFamily font
|
||||
:color text1-color})
|
||||
|
||||
(def profile
|
||||
{:flex 1
|
||||
:backgroundColor color-white
|
||||
:flexDirection :column})
|
||||
|
||||
(def back-btn-touchable
|
||||
{:position :absolute})
|
||||
|
||||
(def back-btn-container
|
||||
{:width 56
|
||||
:height 56})
|
||||
|
||||
(def back-btn-icon
|
||||
{:marginTop 21
|
||||
:marginLeft 23
|
||||
:width 8
|
||||
:height 14})
|
||||
|
||||
(def actions-btn-touchable
|
||||
{:position :absolute
|
||||
:right 0})
|
||||
|
||||
(def actions-btn-container
|
||||
{:width 56
|
||||
:height 56
|
||||
:alignItems :center
|
||||
:justifyContent :center})
|
||||
|
||||
(def actions-btn-icon
|
||||
{:width 4
|
||||
:height 16})
|
||||
|
||||
(def status-block
|
||||
{:alignSelf :center
|
||||
:alignItems :center
|
||||
:width 249})
|
||||
|
||||
(def user-photo-container
|
||||
{:marginTop 26})
|
||||
|
||||
(def user-name
|
||||
{:marginTop 20
|
||||
:fontSize 18
|
||||
:fontFamily font
|
||||
:color text1-color})
|
||||
|
||||
(def status
|
||||
{:marginTop 10
|
||||
:fontFamily font
|
||||
:fontSize 14
|
||||
:lineHeight 20
|
||||
:textAlign :center
|
||||
:color text2-color})
|
||||
|
||||
(def btns-container
|
||||
{:marginTop 18
|
||||
:flexDirection :row})
|
||||
|
||||
(def message-btn
|
||||
{:height 40
|
||||
:justifyContent :center
|
||||
:backgroundColor color-blue
|
||||
:paddingLeft 25
|
||||
:paddingRight 25
|
||||
:borderRadius 50})
|
||||
|
||||
(def message-btn-text
|
||||
{:marginTop -2.5
|
||||
:fontSize 14
|
||||
:fontFamily font
|
||||
:color color-white})
|
||||
|
||||
(def more-btn
|
||||
{:marginLeft 10
|
||||
:width 40
|
||||
:height 40
|
||||
:alignItems :center
|
||||
:justifyContent :center
|
||||
:backgroundColor color-blue-transparent
|
||||
:padding 8
|
||||
:borderRadius 50})
|
||||
|
||||
(def more-btn-image
|
||||
{:width 4
|
||||
:height 16})
|
||||
|
||||
(def profile-properties-container
|
||||
{:marginTop 20
|
||||
:alignItems :stretch
|
||||
:flexDirection :column})
|
||||
|
||||
(def report-user-container
|
||||
{:marginTop 50
|
||||
:marginBottom 43
|
||||
:alignItems :center})
|
||||
|
||||
(def report-user-text
|
||||
{:fontSize 14
|
||||
:fontFamily font
|
||||
:lineHeight 21
|
||||
:color text2-color
|
||||
;; IOS:
|
||||
:letterSpacing 0.5})
|
|
@ -26,6 +26,8 @@
|
|||
: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)))
|
||||
|
||||
|
||||
(defn icon [n style]
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
(def title-font "sans-serif-medium")
|
||||
|
||||
(def color-blue "#7099e6")
|
||||
(def color-blue-transparent "#7099e632")
|
||||
(def color-black "#000000de")
|
||||
(def color-purple "#a187d5")
|
||||
(def color-gray "#838c93de")
|
||||
|
@ -16,8 +17,9 @@
|
|||
|
||||
(def text1-color color-black)
|
||||
(def text2-color color-gray)
|
||||
(def text3-color color-blue)
|
||||
(def online-color color-blue)
|
||||
(def new-messages-count-color "#7099e632")
|
||||
(def new-messages-count-color color-blue-transparent)
|
||||
(def chat-background color-light-gray)
|
||||
(def selected-message-color "#E4E9ED")
|
||||
(def separator-color "#0000001f")
|
||||
|
|
|
@ -12,45 +12,49 @@
|
|||
color-purple
|
||||
text1-color
|
||||
text2-color
|
||||
toolbar-background1]]))
|
||||
toolbar-background1]]
|
||||
[syng-im.components.realm :refer [list-view]]
|
||||
[reagent.core :as r]))
|
||||
|
||||
(defn toolbar [{:keys [title nav-action action background-color content style]}]
|
||||
(let [style (merge {:flexDirection :row
|
||||
(defn toolbar [{:keys [title nav-action hide-nav? action custom-action
|
||||
background-color custom-content style]}]
|
||||
(let [style (merge {:flexDirection "row"
|
||||
:backgroundColor (or background-color toolbar-background1)
|
||||
:height 56
|
||||
:elevation 2} style)]
|
||||
[view {:style style}
|
||||
(if nav-action
|
||||
[touchable-highlight {:on-press (:handler nav-action)}
|
||||
(when (not hide-nav?)
|
||||
(if nav-action
|
||||
[touchable-highlight {:on-press (:handler nav-action)}
|
||||
[view {:width 56
|
||||
:height 56
|
||||
: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"}
|
||||
:style {:marginTop 21
|
||||
:marginLeft 23
|
||||
:width 8
|
||||
:height 14}}]]]))
|
||||
(or custom-content
|
||||
[view {:style {:flex 1
|
||||
:alignItems "center"
|
||||
:justifyContent "center"}}
|
||||
[text {:style {:marginTop -2.5
|
||||
:color text1-color
|
||||
:fontSize 16
|
||||
:fontFamily font}}
|
||||
title]])
|
||||
custom-action
|
||||
(when action
|
||||
[touchable-highlight {:on-press (:handler action)}
|
||||
[view {:width 56
|
||||
:height 56
|
||||
:alignItems :center
|
||||
:justifyContent :center}
|
||||
[image (:image nav-action)]]]
|
||||
[touchable-highlight {:on-press #(dispatch [:navigate-back])}
|
||||
[view {:width 56
|
||||
:height 56}
|
||||
[icon :back {:marginTop 21
|
||||
:marginLeft 23
|
||||
:width 8
|
||||
:height 14}]]])
|
||||
(if content
|
||||
[view {:flex 1
|
||||
:alignItems :center
|
||||
:justifyContent :center}
|
||||
content]
|
||||
[view {:flex 1
|
||||
:alignItems :center
|
||||
:justifyContent :center}
|
||||
[text {:marginTop -2.5
|
||||
:color text1-color
|
||||
:fontSize 16
|
||||
:fontFamily font}
|
||||
title]])
|
||||
[touchable-highlight {:on-press (:handler action)}
|
||||
[view {:width 56
|
||||
:height 56
|
||||
:alignItems :center
|
||||
:justifyContent :center}
|
||||
[image (:image action)]]]]))
|
||||
|
||||
:alignItems "center"
|
||||
:justifyContent "center"}
|
||||
[image (:image action)]]])]))
|
||||
|
||||
|
|
|
@ -6,3 +6,34 @@
|
|||
(fn [db _]
|
||||
(let [contacts (reaction (:contacts @db))]
|
||||
(reaction (vals @contacts)))))
|
||||
|
||||
(register-sub :all-contacts
|
||||
(fn [db _]
|
||||
(let [contacts (reaction (:contacts @db))]
|
||||
(reaction (sort-by :name (vals @contacts))))))
|
||||
|
||||
(defn contacts-by-current-chat [fn db]
|
||||
(let [current-chat-id (:current-chat-id @db)
|
||||
chat (reaction (get-in @db [:chats current-chat-id]))
|
||||
contacts (reaction (:contacts @db))]
|
||||
(reaction
|
||||
(when @chat
|
||||
(let [current-participants (->> @chat
|
||||
:contacts
|
||||
(map :identity)
|
||||
set)]
|
||||
(fn #(current-participants (:whisper-identity %))
|
||||
(vals @contacts)))))))
|
||||
|
||||
(register-sub :contact
|
||||
(fn [db _]
|
||||
(let [identity (:contact-identity @db)]
|
||||
(reaction (get-in db [:contacts identity])))))
|
||||
|
||||
(register-sub :all-new-contacts
|
||||
(fn [db _]
|
||||
(contacts-by-current-chat remove db)))
|
||||
|
||||
(register-sub :current-chat-contacts
|
||||
(fn [db _]
|
||||
(contacts-by-current-chat filter db)))
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
;; schema of app-db
|
||||
(def schema {:greeting s/Str})
|
||||
|
||||
(def default-view :discovery)
|
||||
(def default-view :chat-list)
|
||||
|
||||
;; initial state of app-db
|
||||
(def app-db {:identity-password "replace-me-with-user-entered-password"
|
||||
|
@ -22,7 +22,11 @@
|
|||
:signed-up true
|
||||
:view-id default-view
|
||||
:navigation-stack (list default-view)
|
||||
:name "My Name"
|
||||
;; TODO fix hardcoded values
|
||||
:username "My Name"
|
||||
:phone-number "3147984309"
|
||||
:email "myemail@gmail.com"
|
||||
:status "Hi, this is my status"
|
||||
:current-tag nil})
|
||||
|
||||
(def protocol-initialized-path [:protocol-initialized])
|
||||
|
|
|
@ -24,6 +24,11 @@
|
|||
|
||||
;; discovery.cljs
|
||||
|
||||
(def discovery-toolbar-content
|
||||
{:flex 1
|
||||
:alignItems :center
|
||||
:justifyContent :center})
|
||||
|
||||
(def discovery-search-input
|
||||
{:flex 1
|
||||
:marginLeft 18
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
[re-frame.core :refer [register-handler after dispatch debug enrich]]
|
||||
[schema.core :as s :include-macros true]
|
||||
[syng-im.db :refer [app-db schema]]
|
||||
[syng-im.persistence.simple-kv-store :as kv]
|
||||
[syng-im.protocol.state.storage :as storage]
|
||||
[syng-im.db :as db :refer [app-db schema]]
|
||||
[syng-im.protocol.api :refer [init-protocol]]
|
||||
[syng-im.protocol.protocol-handler :refer [make-handler]]
|
||||
[syng-im.models.protocol :refer [update-identity
|
||||
|
@ -11,12 +14,8 @@
|
|||
[syng-im.models.messages :refer [save-message update-message!]]
|
||||
[syng-im.models.commands :refer [set-commands]]
|
||||
[syng-im.handlers.server :as server]
|
||||
[syng-im.chat.suggestions :refer [get-command
|
||||
handle-command
|
||||
get-command-handler
|
||||
load-commands
|
||||
apply-staged-commands
|
||||
check-suggestion]]
|
||||
[syng-im.chat.suggestions :refer [load-commands]]
|
||||
[syng-im.handlers.sign-up :as sign-up-service]
|
||||
[syng-im.models.chats :refer [chat-exists?
|
||||
create-chat
|
||||
chat-add-participants
|
||||
|
@ -64,8 +63,9 @@
|
|||
(nav/preload-data! db [nil view-id]))
|
||||
|
||||
(register-handler :initialize-db
|
||||
(enrich preload-data!)
|
||||
(fn [_ _] app-db))
|
||||
(fn [_ _]
|
||||
(assoc app-db
|
||||
:signed-up (storage/get kv/kv-store :signed-up))))
|
||||
|
||||
(register-handler :set-loading
|
||||
(fn [db [_ value]]
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
(ns syng-im.handlers.content-suggestions
|
||||
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[syng-im.db :as db]
|
||||
[syng-im.utils.logging :as log]
|
||||
[clojure.string :as s]))
|
||||
|
||||
(def suggestions
|
||||
{:phone [{:value "89171111111"
|
||||
:description "Number format 1"}
|
||||
{:value "+79171111111"
|
||||
:description "Number format 2"}
|
||||
{:value "9171111111"
|
||||
:description "Number format 3"}]})
|
||||
|
||||
(defn get-content-suggestions [db command text]
|
||||
(or (when command
|
||||
(when-let [command-suggestions ((:command command) suggestions)]
|
||||
(filterv (fn [s]
|
||||
(and (.startsWith (:value s) (or text ""))
|
||||
(not= (:value s) text)))
|
||||
command-suggestions)))
|
||||
[]))
|
|
@ -70,3 +70,14 @@
|
|||
(-> db
|
||||
(push-view :add-participants)
|
||||
clear-new-participants)))
|
||||
|
||||
(register-handler :show-profile
|
||||
(fn [db [_ identity]]
|
||||
(let [db (assoc db :contact-identity identity)]
|
||||
(dispatch [:navigate-to :profile])
|
||||
db)))
|
||||
|
||||
(register-handler :show-my-profile
|
||||
(fn [db _]
|
||||
(dispatch [:navigate-to :my-profile])
|
||||
db))
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
[syng-im.models.chats :refer [chats-list chat-by-id]]
|
||||
[syng-im.models.contacts :refer [get-contacts
|
||||
contacts-list-exclude
|
||||
contacts-list-include]]
|
||||
contacts-list-include
|
||||
contact-by-identity]]
|
||||
syng-im.chat.subs
|
||||
syng-im.navigation.subs
|
||||
syng-im.discovery.subs
|
||||
|
@ -17,37 +18,10 @@
|
|||
(reaction (k @db))))
|
||||
|
||||
;; -- User data --------------------------------------------------------------
|
||||
|
||||
(register-sub
|
||||
:signed-up
|
||||
(fn [db _]
|
||||
(reaction (:signed-up @db))))
|
||||
|
||||
(register-sub :all-contacts
|
||||
(fn [db _]
|
||||
(let [contacts (reaction (:contacts @db))]
|
||||
(reaction (sort-by :name @contacts)))))
|
||||
|
||||
(defn contacts-by-current-chat [fn db]
|
||||
(let [current-chat-id (:current-chat-id @db)
|
||||
chat (reaction (get-in @db [:chats current-chat-id]))
|
||||
contacts (reaction (:contacts @db))]
|
||||
(reaction
|
||||
(when @chat
|
||||
(let [current-participants (->> @chat
|
||||
:contacts
|
||||
(map :identity)
|
||||
set)]
|
||||
(fn #(current-participants (:whisper-identity %))
|
||||
(vals @contacts)))))))
|
||||
|
||||
(register-sub :all-new-contacts
|
||||
(fn [db _]
|
||||
(contacts-by-current-chat remove db)))
|
||||
|
||||
(register-sub :current-chat-contacts
|
||||
(fn [db _]
|
||||
(contacts-by-current-chat filter db)))
|
||||
|
||||
(register-sub :db
|
||||
(fn [db _] (reaction @db)))
|
||||
|
|
|
@ -8,3 +8,9 @@
|
|||
;; todo check wrong numbers, .getNumber returns empty string
|
||||
(defn format-phone-number [number]
|
||||
(str (.getNumber (js/PhoneNumber. number country-code "international"))))
|
||||
|
||||
(defn valid-mobile-number? [number]
|
||||
(when (string? number)
|
||||
(let [number-obj (js/PhoneNumber. number country-code "international")]
|
||||
(and (.isValid number-obj)
|
||||
(.isMobile number-obj)))))
|
||||
|
|