diff --git a/android/app/src/main/res/drawable-hdpi/icon_dots.png b/android/app/src/main/res/drawable-hdpi/icon_dots.png new file mode 100644 index 0000000000..7f9961ec1b Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_dots.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_dots.png b/android/app/src/main/res/drawable-mdpi/icon_dots.png new file mode 100644 index 0000000000..a5a003f459 Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_dots.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_dots.png b/android/app/src/main/res/drawable-xhdpi/icon_dots.png new file mode 100644 index 0000000000..e4d3d40921 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_dots.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_dots.png b/android/app/src/main/res/drawable-xxhdpi/icon_dots.png new file mode 100644 index 0000000000..464cfeb09f Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_dots.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_dots.png b/android/app/src/main/res/drawable-xxxhdpi/icon_dots.png new file mode 100644 index 0000000000..972f7be2fd Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_dots.png differ diff --git a/src/syng_im/android/core.cljs b/src/syng_im/android/core.cljs index a2ecc6c3d5..8cdc69d449 100644 --- a/src/syng_im/android/core.cljs +++ b/src/syng_im/android/core.cljs @@ -15,7 +15,7 @@ [syng-im.components.chats.new-group :refer [new-group]] [syng-im.components.chat.new-participants :refer [new-participants]] [syng-im.components.chat.remove-participants :refer [remove-participants]] - [syng-im.components.profile :refer [profile]] + [syng-im.components.profile :refer [profile my-profile]] [syng-im.utils.logging :as log] [syng-im.utils.utils :refer [toast]] [syng-im.navigation :as nav] @@ -48,7 +48,8 @@ :new-group [new-group] :contact-list [contact-list] :chat [chat] - :profile [profile])))) + :profile [profile] + :my-profile [my-profile])))) (defn init [] (dispatch-sync [:initialize-db]) diff --git a/src/syng_im/components/chat.cljs b/src/syng_im/components/chat.cljs index 1644bc8b6f..e11d48e727 100644 --- a/src/syng_im/components/chat.cljs +++ b/src/syng_im/components/chat.cljs @@ -7,7 +7,6 @@ icon navigator touchable-highlight - toolbar-android list-view list-item android?]] @@ -18,6 +17,7 @@ [syng-im.utils.listview :refer [to-datasource to-datasource2]] [syng-im.components.invertible-scroll-view :refer [invertible-scroll-view]] + [syng-im.components.toolbar :refer [toolbar]] [syng-im.components.chat.chat-message :refer [chat-message]] [syng-im.components.chat.chat-message-new :refer [chat-message-new]])) @@ -81,20 +81,39 @@ [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 chat-id]} (subscribe [:chat-properties [:group-chat :chat-id]])] @@ -125,10 +144,31 @@ :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])}])] + :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 [])}])] [view st/actions-wrapper [view st/actions-separator] [view st/actions-view @@ -139,40 +179,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]}]))) (defn messages-view [group-chat] (let [messages (subscribe [:chat :messages]) @@ -191,7 +239,7 @@ show-actions-atom (subscribe [:show-actions])] (fn [] [view st/chat-view - [toolbar] + [chat-toolbar] [messages-view @group-chat] (when @group-chat [typing-all]) (when is-active [chat-message-new]) diff --git a/src/syng_im/components/chat_styles.cljs b/src/syng_im/components/chat_styles.cljs index f66e57ed89..43a7aeb373 100644 --- a/src/syng_im/components/chat_styles.cljs +++ b/src/syng_im/components/chat_styles.cljs @@ -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})) diff --git a/src/syng_im/components/discovery/discovery.cljs b/src/syng_im/components/discovery/discovery.cljs index 21acf38988..7d0732e396 100644 --- a/src/syng_im/components/discovery/discovery.cljs +++ b/src/syng_im/components/discovery/discovery.cljs @@ -25,17 +25,18 @@ []))) (defn title-content [showSearch] - (if showSearch - [text-input {:underlineColorAndroid "transparent" - :style st/discovery-search-input - :autoFocus true - :placeholder "Type your search tags here" - :onSubmitEditing (fn [e] - (let [search (aget e "nativeEvent" "text") - hashtags (get-hashtags search)] - (dispatch [:broadcast-status search hashtags])))}] - [view - [text {:style st/discovery-title} "Discover"]])) + [view st/discovery-toolbar-content + (if showSearch + [text-input {:underlineColorAndroid "transparent" + :style st/discovery-search-input + :autoFocus true + :placeholder "Type your search tags here" + :onSubmitEditing (fn [e] + (let [search (aget e "nativeEvent" "text") + hashtags (get-hashtags search)] + (dispatch [:broadcast-status search hashtags])))}] + [view + [text {:style st/discovery-title} "Discover"]])]) (defn create-fake-discovery [] (let [number (rand-int 999)] @@ -61,7 +62,7 @@ :height 12}} :handler create-fake-discovery} :title "Add Participants" - :content (title-content @showSearch) + :custom-content [title-content @showSearch] :action {:image {:source {:uri "icon_search"} :style {:width 17 :height 17}} diff --git a/src/syng_im/components/discovery/styles.cljs b/src/syng_im/components/discovery/styles.cljs index 9c988558f9..0044f86c94 100644 --- a/src/syng_im/components/discovery/styles.cljs +++ b/src/syng_im/components/discovery/styles.cljs @@ -24,6 +24,11 @@ ;; discovery.cljs +(def discovery-toolbar-content + {:flex 1 + :alignItems :center + :justifyContent :center}) + (def discovery-search-input {:flex 1 :marginLeft 18 @@ -172,4 +177,4 @@ (def icon-search {:width 17 - :height 17}) \ No newline at end of file + :height 17}) diff --git a/src/syng_im/components/drawer.cljs b/src/syng_im/components/drawer.cljs index c1f7b807f2..362127f69d 100644 --- a/src/syng_im/components/drawer.cljs +++ b/src/syng_im/components/drawer.cljs @@ -36,42 +36,44 @@ name]]) (defn drawer-menu [navigator] - [view st/drawer-menu - [view st/user-photo-container - [user-photo {}]] - [view st/name-container - [text {:style st/name-text} - "Status"]] - [view st/menu-items-container - [menu-item {:name "Profile" - :handler (fn [] - (dispatch [:show-profile navigator]))}] - [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"]]]]) + (let [username (subscribe [: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 300 + [drawer-layout-android {:drawerWidth 260 :drawerPosition js/React.DrawerLayoutAndroid.positions.Left :render-navigation-view #(r/as-element [drawer-menu navigator]) :ref (fn [drawer] diff --git a/src/syng_im/components/profile.cljs b/src/syng_im/components/profile.cljs index 7ce6bea22d..85b64b6475 100644 --- a/src/syng_im/components/profile.cljs +++ b/src/syng_im/components/profile.cljs @@ -41,10 +41,10 @@ (let [contact (subscribe [:contact])] (fn [] [scroll-view {:style st/profile} - [touchable-highlight {:style st/profile-back-button-touchable + [touchable-highlight {:style st/back-btn-touchable :on-press #(dispatch [:navigate-back])} - [view st/profile-back-button-container - [icon :back st/profile-back-button-icon]]] + [view st/back-btn-container + [icon :back st/back-btn-icon]]] [view st/status-block [view st/user-photo-container [user-photo {}] @@ -74,3 +74,36 @@ [touchable-opacity {} [text {:style st/report-user-text} "REPORT USER"]]]]]))) + +(defn my-profile [] + (let [username (subscribe [:username]) + phone-number (subscribe [:phone-number]) + email (subscribe [:email]) + status (subscribe [: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}]]]))) diff --git a/src/syng_im/components/profile_styles.cljs b/src/syng_im/components/profile_styles.cljs index 11c58ccf04..347b89c282 100644 --- a/src/syng_im/components/profile_styles.cljs +++ b/src/syng_im/components/profile_styles.cljs @@ -68,19 +68,33 @@ :backgroundColor color-white :flexDirection :column}) -(def profile-back-button-touchable +(def back-btn-touchable {:position :absolute}) -(def profile-back-button-container +(def back-btn-container {:width 56 :height 56}) -(def profile-back-button-icon +(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 diff --git a/src/syng_im/components/toolbar.cljs b/src/syng_im/components/toolbar.cljs index 2b5608f078..f66ddf5735 100644 --- a/src/syng_im/components/toolbar.cljs +++ b/src/syng_im/components/toolbar.cljs @@ -17,44 +17,44 @@ [syng-im.utils.listview :refer [to-realm-datasource]] [reagent.core :as r])) -(defn toolbar [{:keys [navigator title nav-action action background-color content style]}] +(defn toolbar [{:keys [navigator 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} - [image {:source {:uri "icon_back"} - :style {:marginTop 21 - :marginLeft 23 - :width 8 - :height 14}}]]]) - (if content - [view {:style {:flex 1 - :alignItems "center" - :justifyContent "center"}} - content] - [view {:style {:flex 1 - :alignItems "center" - :justifyContent "center"}} - [text {:style {: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)]]]])) + [image (:image action)]]])])) diff --git a/src/syng_im/db.cljs b/src/syng_im/db.cljs index 54280b7d11..27a48ce65d 100644 --- a/src/syng_im/db.cljs +++ b/src/syng_im/db.cljs @@ -7,8 +7,7 @@ (def default-view :chat-list) ;; initial state of app-db -(def app-db {:greeting "Hello Clojure in iOS and Android!" - :identity-password "replace-me-with-user-entered-password" +(def app-db {:identity-password "replace-me-with-user-entered-password" :identity "me" :contacts [] :current-chat-id "console" @@ -22,7 +21,11 @@ :signed-up false :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]) diff --git a/src/syng_im/handlers.cljs b/src/syng_im/handlers.cljs index 063c6f67dd..c776b061b6 100644 --- a/src/syng_im/handlers.cljs +++ b/src/syng_im/handlers.cljs @@ -457,6 +457,12 @@ (dispatch [:navigate-to :profile]) db))) +(register-handler :show-my-profile + (fn [db [action]] + (log/debug action) + (dispatch [:navigate-to :my-profile]) + db)) + ;; -- Chats -------------------------------------------------------------- (register-handler :show-chat diff --git a/src/syng_im/subs.cljs b/src/syng_im/subs.cljs index 695001b450..f09e537391 100644 --- a/src/syng_im/subs.cljs +++ b/src/syng_im/subs.cljs @@ -94,14 +94,28 @@ ;; -- User data -------------------------------------------------------------- -;; (register-sub -;; :get-user-phone-number -;; (fn [db _] -;; (reaction -;; (get @db :user-phone-number)))) +(register-sub :username + (fn [db _] + (reaction + (get @db :username)))) + +(register-sub :phone-number + (fn [db _] + (reaction + (get @db :phone-number)))) + +(register-sub :email + (fn [db _] + (reaction + (get @db :email)))) + +(register-sub :status + (fn [db _] + (reaction + (get @db :status)))) (register-sub - :get-user-identity + :get-user-identity (fn [db _] (reaction (get @db :user-identity))))