diff --git a/android/app/src/main/res/drawable-hdpi/icon_ok_purple.png b/android/app/src/main/res/drawable-hdpi/icon_ok_purple.png new file mode 100644 index 0000000000..b28a5ca6d0 Binary files /dev/null and b/android/app/src/main/res/drawable-hdpi/icon_ok_purple.png differ diff --git a/android/app/src/main/res/drawable-mdpi/icon_ok_purple.png b/android/app/src/main/res/drawable-mdpi/icon_ok_purple.png new file mode 100644 index 0000000000..b6c7a413fd Binary files /dev/null and b/android/app/src/main/res/drawable-mdpi/icon_ok_purple.png differ diff --git a/android/app/src/main/res/drawable-xhdpi/icon_ok_purple.png b/android/app/src/main/res/drawable-xhdpi/icon_ok_purple.png new file mode 100644 index 0000000000..3357120bb0 Binary files /dev/null and b/android/app/src/main/res/drawable-xhdpi/icon_ok_purple.png differ diff --git a/android/app/src/main/res/drawable-xxhdpi/icon_ok_purple.png b/android/app/src/main/res/drawable-xxhdpi/icon_ok_purple.png new file mode 100644 index 0000000000..b294224264 Binary files /dev/null and b/android/app/src/main/res/drawable-xxhdpi/icon_ok_purple.png differ diff --git a/android/app/src/main/res/drawable-xxxhdpi/icon_ok_purple.png b/android/app/src/main/res/drawable-xxxhdpi/icon_ok_purple.png new file mode 100644 index 0000000000..9429e65fbf Binary files /dev/null and b/android/app/src/main/res/drawable-xxxhdpi/icon_ok_purple.png differ diff --git a/src/status_im/android/core.cljs b/src/status_im/android/core.cljs index f79098ed24..080a91fa54 100644 --- a/src/status_im/android/core.cljs +++ b/src/status_im/android/core.cljs @@ -13,10 +13,9 @@ [status-im.chat.screen :refer [chat]] [status-im.chats-list.screen :refer [chats-list]] [status-im.new-group.screen :refer [new-group]] - [status-im.participants.views.create :refer [new-participants]] + [status-im.participants.views.add :refer [new-participants]] [status-im.participants.views.remove :refer [remove-participants]] [status-im.group-settings.screen :refer [group-settings]] - [status-im.group-settings.views.chat-name-edit :refer [chat-name-edit]] [status-im.profile.screen :refer [profile my-profile]] [status-im.utils.utils :refer [toast]] [status-im.utils.encryption])) @@ -44,7 +43,6 @@ :chat-list [main-tabs] :new-group [new-group] :group-settings [group-settings] - :chat-name-edit [chat-name-edit] :contact-list [main-tabs] :chat [chat] :profile [profile] diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 9317aef352..3564ea8e69 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -6,12 +6,13 @@ [status-im.protocol.api :as api] [status-im.models.messages :as messages] [status-im.constants :refer [text-content-type - content-type-command]] + content-type-command]] [status-im.utils.random :as random] [status-im.chat.sign-up :as sign-up-service] [status-im.models.chats :as chats] [status-im.navigation.handlers :as nav] - [status-im.utils.handlers :as u])) + [status-im.utils.handlers :as u] + [status-im.persistence.realm :as r])) (register-handler :set-show-actions (fn [db [_ show-actions]] @@ -187,7 +188,8 @@ ((enrich add-commands)) ((enrich clear-input)) ((enrich clear-staged-commands)) - ((after send-message!)) + ;; todo uncomment once + ;((after send-message!)) ((after save-message-to-realm!)) ((after save-commands-to-realm!)) ((after handle-commands)))) @@ -283,10 +285,14 @@ (defmethod nav/preload-data! :chat [{:keys [current-chat-id] :as db} [_ _ id]] - (-> db - (assoc :current-chat-id (or id current-chat-id)) - load-messages! - init-chat)) + (let [chat-id (or id current-chat-id) + messages (get-in db [:chats chat-id :messages]) + db' (assoc db :current-chat-id chat-id)] + (if (seq messages) + db' + (-> db' + load-messages! + init-chat)))) (defn prepare-chat [{:keys [contacts] :as db} [_ contcat-id]] @@ -321,3 +327,45 @@ (register-handler :switch-command-suggestions (fn [db [_]] (suggestions/switch-command-suggestions db))) + +(defn remove-chat + [{:keys [current-chat-id] :as db} _] + (update db :chats dissoc current-chat-id)) + +(defn notify-about-leaving! + [{:keys [current-chat-id]} _] + (api/leave-group-chat current-chat-id)) + +; todo do we really need this message? +(defn leaving-message! + [{:keys [current-chat-id]} _] + (messages/save-message + current-chat-id + {:from "system" + :msg-id (random/id) + :content "You left this chat" + :content-type text-content-type})) + +(defn delete-messages! + [{:keys [current-chat-id]} _] + (r/write + (fn [] + (r/delete (r/get-by-field :msgs :chat-id current-chat-id))))) + +(defn delete-chat! + [{:keys [current-chat-id]} _] + (r/write + (fn [] + (-> (r/get-by-field :chats :chat-id current-chat-id) + (r/single) + (r/delete))))) + +(register-handler :leave-group-chat + ;; todo oreder of operations tbd + (after (fn [_ _] (dispatch [:navigation-replace :chat-list]))) + (-> remove-chat + ;; todo uncomment + ;((after notify-about-leaving!)) + ;((after leaving-message!)) + ((after delete-messages!)) + ((after delete-chat!)))) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/chat/screen.cljs index 17f7293fee..f292983cc7 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/chat/screen.cljs @@ -67,8 +67,8 @@ (defn on-action-selected [position] (case position - 0 (dispatch [:show-add-participants]) - 1 (dispatch [:show-remove-participants]) + 0 (dispatch [:navigate-to :add-participants]) + 1 (dispatch [:navigate-to :remove-participants]) 2 (dispatch [:leave-group-chat]))) (defn overlay [{:keys [on-click-outside]} items] @@ -119,13 +119,13 @@ :icon :menu_group :icon-style {:width 25 :height 19} - :handler #(dispatch [:show-add-participants])} + :handler #(dispatch [:navigate-to :add-participants])} {:title "Remove Contact from chat" :subtitle "Alex, John" :icon :search_gray_copy :icon-style {:width 17 :height 17} - :handler #(dispatch [:show-remove-participants])} + :handler #(dispatch [:navigate-to :remove-participants])} {:title "Leave Chat" :icon :muted :icon-style {:width 18 diff --git a/src/status_im/chats_list/views/chat_list_item.cljs b/src/status_im/chats_list/views/chat_list_item.cljs index db7dfd5f83..412979d42b 100644 --- a/src/status_im/chats_list/views/chat_list_item.cljs +++ b/src/status_im/chats_list/views/chat_list_item.cljs @@ -10,7 +10,7 @@ (defn chat-list-item [{:keys [chat-id] :as chat}] [touchable-highlight - {:on-press #(dispatch [:show-chat chat-id :push])} + {:on-press #(dispatch [:navigate-to :chat chat-id])} ;; TODO add [photo-path delivery-status new-messages-count online] values to chat-obj [view [chat-list-item-inner-view (merge chat {:photo-path nil diff --git a/src/status_im/components/react.cljs b/src/status_im/components/react.cljs index d65c06dc0e..930f6deedf 100644 --- a/src/status_im/components/react.cljs +++ b/src/status_im/components/react.cljs @@ -35,9 +35,11 @@ (def picker-item (r/adapt-react-class (.-Item (.-Picker js/React)))) -(defn icon [n style] - [image {:source {:uri (keyword (str "icon_" (name n)))} - :style style}]) +(defn icon + ([n] (icon n {})) + ([n style] + [image {:source {:uri (keyword (str "icon_" (name n)))} + :style style}])) ;(def react-linear-gradient (.-default (js/require "react-native-linear-gradient"))) ;(def linear-gradient (r/adapt-react-class react-linear-gradient)) diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index af51988239..a6b34c65ef 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -7,27 +7,28 @@ (def default-view :chat-list) ;; initial state of app-db -(def app-db {:identity-password "replace-me-with-user-entered-password" - :identity "me" - :contacts [] - :contacts-ids #{} - :selected-contacts #{} - :current-chat-id "console" - :chat {:command nil - :last-message nil} - :chats {} - :chats-updated-signal 0 - :show-actions false - :new-participants #{} - :signed-up true - :view-id default-view - :navigation-stack (list default-view) +(def app-db {:identity-password "replace-me-with-user-entered-password" + :identity "me" + :contacts [] + :contacts-ids #{} + :selected-contacts #{} + :current-chat-id "console" + :chat {:command nil + :last-message nil} + :chats {} + :chats-updated-signal 0 + :show-actions false + :selected-participants #{} + :signed-up true + :view-id default-view + :navigation-stack (list default-view) ;; TODO fix hardcoded values - :username "My Name" - :phone-number "3147984309" - :email "myemail@gmail.com" - :status "Hi, this is my status" - :current-tag nil}) + :username "My Name" + :phone-number "3147984309" + :email "myemail@gmail.com" + :status "Hi, this is my status" + :current-tag nil + :disable-group-creation false}) (def protocol-initialized-path [:protocol-initialized]) (defn chat-input-text-path [chat-id] diff --git a/src/status_im/group_settings/handlers.cljs b/src/status_im/group_settings/handlers.cljs index d62ae27276..82eab18d7b 100644 --- a/src/status_im/group_settings/handlers.cljs +++ b/src/status_im/group_settings/handlers.cljs @@ -1,72 +1,144 @@ (ns status-im.group-settings.handlers - (:require [re-frame.core :refer [register-handler debug dispatch]] + (:require [re-frame.core :refer [register-handler debug dispatch after + enrich]] [status-im.persistence.realm :as r] - [status-im.models.messages :refer [clear-history]])) + [status-im.chat.handlers :refer [delete-messages!]] + [status-im.protocol.api :as api] + [status-im.utils.random :as random] + [status-im.models.contacts :as contacts] + [status-im.models.messages :as messages] + [status-im.models.chats :as chats] + [status-im.constants :refer [text-content-type]] + [status-im.utils.handlers :as u] + [status-im.navigation.handlers :as nav])) -(defn set-chat-name [db] - (let [chat-id (:current-chat-id db) - name (:new-chat-name db)] - (r/write (fn [] - (-> (r/get-by-field :chats :chat-id chat-id) - (r/single) - (aset "name" name)))) - (assoc-in db [:chats chat-id :name] name))) +(defmethod nav/preload-data! :group-settings + [db _] + (assoc db :selected-participants #{})) -(defn set-chat-color [db] - (let [chat-id (:current-chat-id db) - color (:new-chat-color db)] - (r/write (fn [] - (-> (r/get-by-field :chats :chat-id chat-id) - (r/single) - (aset "color" color)))) - (assoc-in db [:chats chat-id :color] color))) +(defn save-chat-property! + [db-name property-name] + (fn [{:keys [current-chat-id] :as db} _] + (let [property (db-name db)] + (r/write (fn [] + (-> (r/get-by-field :chats :chat-id current-chat-id) + (r/single) + (aset (name property-name) property))))))) -(defn delete-chat [chat-id] - (r/write - (fn [] - (-> (r/get-by-field :chats :chat-id chat-id) - (r/single) - (r/delete)))) - ;; TODO temp. Update chat in db atom - (dispatch [:initialize-chats])) +(defn update-chat-property + [db-name property-name] + (fn [{:keys [current-chat-id] :as db} _] + (let [property (db-name db)] + (assoc-in db [:chats current-chat-id property-name] property)))) + +(defn prepare-chat-settings + [{:keys [current-chat-id] :as db} _] + (let [{:keys [name color]} (-> db + (get-in [:chats current-chat-id]) + (select-keys [:name :color]))] + (-> db + (assoc :new-chat-name name + :new-chat-color color + :group-settings {})))) (register-handler :show-group-settings - (fn [db _] - (let [chat-id (:current-chat-id db) - chat-name (get-in db [:chats chat-id :name]) - chat-color (get-in db [:chats chat-id :color]) - db (assoc db - :new-chat-name chat-name - :new-chat-color chat-color - :group-settings-show-color-picker false - :group-settings-selected-member nil)] - (dispatch [:navigate-to :group-settings]) - db))) + (after (fn [_ _] (dispatch [:navigate-to :group-settings]))) + prepare-chat-settings) (register-handler :set-chat-name - (fn [db [action]] - (set-chat-name db))) + (after (save-chat-property! :new-chat-name :name)) + (update-chat-property :new-chat-name :name)) (register-handler :set-chat-color - (fn [db [action]] - (set-chat-color db))) + (after (save-chat-property! :new-chat-color :color)) + (update-chat-property :new-chat-color :color)) -(register-handler :set-new-chat-name - (fn [db [action name]] - (assoc db :new-chat-name name))) - -(register-handler :set-new-chat-color - (fn [db [action color]] - (assoc db :new-chat-color color))) - -(register-handler :select-group-chat-member - (fn [db [action identity]] - (assoc db :group-settings-selected-member identity))) - -(register-handler :set-group-settings-show-color-picker - (fn [db [action show?]] - (assoc db :group-settings-show-color-picker show?))) +(defn clear-messages + [{:keys [current-chat-id] :as db} _] + (assoc-in db [:chats current-chat-id :messages] '())) (register-handler :clear-history - (fn [db [action]] - (clear-history (:current-chat-id db)))) + (after delete-messages!) + clear-messages) + +(register-handler :group-settings + (fn [db [_ k v]] + (assoc-in db [:group-settings k] v))) + +(defn remove-identities [collection identities] + (remove #(identities (:identity %)) collection)) + +(defn remove-members + [{:keys [current-chat-id selected-participants] :as db} _] + (update-in db [:chats current-chat-id :contacts] + remove-identities selected-participants)) + +(defn remove-members-from-realm! + [{:keys [current-chat-id selected-participants] :as db} _] + (let [chat (get-in db [:chats current-chat-id])] + (r/write + (fn [] + (r/create + :chats + (update chat :contacts remove-identities selected-participants) + true))))) + +(defn notify-about-removing! + [{:keys [current-chat-id selected-participants]} _] + (doseq [participant selected-participants] + (api/group-remove-participant current-chat-id participant))) + +(defn system-message [msg-id content] + {:from "system" + :msg-id msg-id + :content content + :content-type text-content-type}) + +(defn removed-participant-msg [chat-id identity] + (let [contact-name (:name (contacts/contact-by-identity identity))] + (->> (str "You've removed " (or contact-name identity)) + (system-message (random/id)) + (messages/save-message chat-id)))) + +(defn create-removing-messages! + [{:keys [current-chat-id selected-participants]} _] + (doseq [participant selected-participants] + (removed-participant-msg current-chat-id participant))) + +(defn deselect-members [db _] + (assoc db :selected-participants #{})) + +(register-handler :remove-participants + ;; todo check if user have rights to add/remove participants + ;; todo order of operations tbd + (-> remove-members + ;; todo shouldn't this be done only after receiving of the "ack message" + ;; about the api call that removes participants from the group? + ((after remove-members-from-realm!)) + ;; todo uncomment + ;((after notify-about-removing!)) + ((after create-removing-messages!)) + ((enrich deselect-members)) + debug)) + +(defn add-memebers + [{:keys [current-chat-id selected-participants] :as db} _] + (let [new-identities (map #(hash-map :identity %) selected-participants)] + (update db [:chats current-chat-id :contacts] concat new-identities))) + +(defn add-members-to-realm! + [{:keys [current-chat-id selected-participants]} _] + (chats/chat-add-participants current-chat-id selected-participants)) + +(defn notify-about-new-members! + [{:keys [current-chat-id selected-participants]} _] + (doseq [identity selected-participants] + (api/group-add-participant current-chat-id identity))) + +(register-handler :add-new-participants + ;; todo order of operations tbd + (-> add-memebers + ((after add-members-to-realm!)) + ;; todo uncomment + ;((after notify-about-new-members!)) + ((enrich deselect-members)))) diff --git a/src/status_im/group_settings/screen.cljs b/src/status_im/group_settings/screen.cljs index 7199d142a3..86c38a77de 100644 --- a/src/status_im/group_settings/screen.cljs +++ b/src/status_im/group_settings/screen.cljs @@ -15,25 +15,25 @@ [status-im.group-settings.styles.group-settings :as st] [status-im.group-settings.views.member :refer [member-view]])) -(defn remove-member [{:keys [whisper-identity]}] - (dispatch [:chat-remove-member whisper-identity])) +(defn remove-member [] + (dispatch [:remove-participants])) (defn close-member-menu [] - (dispatch [:select-group-chat-member nil])) + (dispatch [:set :selected-participants #{}])) (defview member-menu [] - [member [:group-settings-selected-member]] - [modal {:animated false - :transparent false - :onRequestClose close-member-menu} - [touchable-highlight {:style st/modal-container - :on-press close-member-menu} - [view st/modal-inner-container - [text {:style st/modal-member-name} - (:name member)] - [touchable-highlight {:on-press #(remove-member member)} - [text {:style st/modal-remove-text} - "Remove"]]]]]) + [{:keys [name] :as participant} [:selected-participant]] + (when participant + [modal {:animated false + :transparent false + :onRequestClose close-member-menu} + [touchable-highlight {:style st/modal-container + :on-press close-member-menu} + [view st/modal-inner-container + [text {:style st/modal-member-name} name] + [touchable-highlight {:on-press remove-member} + [text {:style st/modal-remove-text} + "Remove"]]]]])) (defview chat-members [] [members [:current-chat-contacts]] @@ -41,9 +41,6 @@ (for [member members] ^{:key member} [member-view member])]) -(defn show-chat-name-edit [] - (dispatch [:navigate-to :chat-name-edit])) - (defn setting-view [{:keys [icon-style custom-icon handler title subtitle] icon-name :icon}] [touchable-highlight {:on-press handler} @@ -58,15 +55,15 @@ subtitle])]]]) (defn close-chat-color-picker [] - (dispatch [:set-group-settings-show-color-picker false])) + (dispatch [:group-settings :show-color-picker false])) (defn set-chat-color [] (close-chat-color-picker) (dispatch [:set-chat-color])) (defview chat-color-picker [] - [show-color-picker [:get :group-settings-show-color-picker] - new-color [:get :new-chat-color]] + [show-color-picker [:group-settings :show-color-picker] + new-color [:get :new-chat-color]] [modal {:animated false :transparent false :onRequestClose close-chat-color-picker} @@ -74,11 +71,11 @@ :on-press close-chat-color-picker} [view st/modal-color-picker-inner-container [picker {:selectedValue new-color - :onValueChange #(dispatch [:set-new-chat-color %])} - [picker-item {:label "Blue" :value "#7099e6"}] - [picker-item {:label "Purple" :value "#a187d5"}] - [picker-item {:label "Green" :value "green"}] - [picker-item {:label "Red" :value "red"}]] + :onValueChange #(dispatch [:set :new-chat-color %])} + [picker-item {:label "Blue" :value "#7099e6"}] + [picker-item {:label "Purple" :value "#a187d5"}] + [picker-item {:label "Green" :value "green"}] + [picker-item {:label "Red" :value "red"}]] [touchable-highlight {:on-press set-chat-color} [text {:style st/modal-color-picker-save-btn-text} "Save"]]]]]) @@ -88,7 +85,7 @@ [view {:style (st/chat-color-icon chat-color)}]) (defn show-chat-color-picker [] - (dispatch [:set-group-settings-show-color-picker true])) + (dispatch [:group-settings :show-color-picker true])) (defn settings-view [] ;; TODO implement settings handlers @@ -105,22 +102,22 @@ {:icon :muted :icon-style {:width 18 :height 21}})) - {:icon :close-gray - :icon-style {:width 12 - :height 12} - :title "Clear history" - :handler #(dispatch [:clear-history])} - {:icon :bin - :icon-style {:width 12 - :height 18} - :title "Delete and leave" - :handler #(dispatch [:leave-group-chat])}]] + {:icon :close-gray + :icon-style {:width 12 + :height 12} + :title "Clear history" + :handler #(dispatch [:clear-history])} + {:icon :bin + :icon-style {:width 12 + :height 18} + :title "Delete and leave" + :handler #(dispatch [:leave-group-chat])}]] [view st/settings-container (for [setting settings] ^{:key setting} [setting-view setting])])) (defview chat-icon [] - [name [:chat :name] + [name [:chat :name] color [:chat :color]] [view (st/chat-icon color) [text {:style st/chat-icon-text} (first name)]]) @@ -129,25 +126,44 @@ [toolbar {:title "Chat settings" :custom-action [chat-icon]}]) +(defn focus [] + (dispatch [:set ::name-input-focused true])) + +(defn blur [] + (dispatch [:set ::name-input-focused false])) + +(defn save [] + (dispatch [:set-chat-name])) + +(defview chat-name [] + [name [:chat :name] + new-name [:get :new-chat-name] + focused? [:get ::name-input-focused]] + [view + [text {:style st/chat-name-text} "Chat name"] + [view (st/chat-name-value-container focused?) + [text-input {:style st/chat-name-value + :ref #(when (and % focused?) (.focus %)) + :on-change-text #(dispatch [:set :new-chat-name %]) + :on-focus focus + :on-blur blur} + name] + (if (or focused? (not= name new-name)) + [touchable-highlight {:style st/chat-name-btn-edit-container + :on-press save} + [view [icon :ok-purple st/add-members-icon]]] + [touchable-highlight {:style st/chat-name-btn-edit-container + :on-press focus} + [text {:style st/chat-name-btn-edit-text} "Edit"]])]]) + (defview group-settings [] - [chat-name [:chat :name] - selected-member [:group-settings-selected-member] - show-color-picker [:get :group-settings-show-color-picker]] + [show-color-picker [:group-settings :show-color-picker]] [view st/group-settings [new-group-toolbar] [scroll-view st/body - [text {:style st/chat-name-text} - "Chat name"] - [view st/chat-name-value-container - [text {:style st/chat-name-value} - chat-name] - [touchable-highlight {:style st/chat-name-btn-edit-container - :on-press show-chat-name-edit} - [text {:style st/chat-name-btn-edit-text} - "Edit"]]] - [text {:style st/members-text} - "Members"] - [touchable-highlight {:on-press #(dispatch [:show-add-participants])} + [chat-name] + [text {:style st/members-text} "Members"] + [touchable-highlight {:on-press #(dispatch [:navigate-to :add-participants])} [view st/add-members-container [icon :add-gray st/add-members-icon] [text {:style st/add-members-text} @@ -158,5 +174,4 @@ [settings-view]] (when show-color-picker [chat-color-picker]) - (when selected-member - [member-menu])]) + [member-menu]]) diff --git a/src/status_im/group_settings/styles/chat_name_edit.cljs b/src/status_im/group_settings/styles/chat_name_edit.cljs deleted file mode 100644 index d185480652..0000000000 --- a/src/status_im/group_settings/styles/chat_name_edit.cljs +++ /dev/null @@ -1,19 +0,0 @@ -(ns status-im.group-settings.styles.chat-name-edit - (:require [status-im.components.styles :refer [font - color-white - text1-color]])) - -(def save-action-icon - {:width 18 - :height 14}) - -(def chat-name-container - {:flex 1 - :flexDirection :column - :backgroundColor color-white}) - -(def chat-name-input - {:marginLeft 12 - :fontSize 14 - :fontFamily font - :color text1-color}) diff --git a/src/status_im/group_settings/styles/group_settings.cljs b/src/status_im/group_settings/styles/group_settings.cljs index ee0db62b50..20b2a42d30 100644 --- a/src/status_im/group_settings/styles/group_settings.cljs +++ b/src/status_im/group_settings/styles/group_settings.cljs @@ -24,17 +24,17 @@ :backgroundColor color-white}) (def modal-member-name - {:color text2-color - :fontFamily font - :fontSize 14 - :lineHeight 20}) + {:color text2-color + :fontFamily font + :fontSize 14 + :lineHeight 20}) (def modal-remove-text - {:margin 10 - :color text1-color - :fontFamily font - :fontSize 14 - :lineHeight 20}) + {:margin 10 + :color text1-color + :fontFamily font + :fontSize 14 + :lineHeight 20}) (def modal-color-picker-inner-container {:borderRadius 10 @@ -42,12 +42,12 @@ :backgroundColor color-white}) (def modal-color-picker-save-btn-text - {:margin 10 - :alignSelf :center - :color text1-color - :fontFamily font - :fontSize 14 - :lineHeight 20}) + {:margin 10 + :alignSelf :center + :color text1-color + :fontFamily font + :fontSize 14 + :lineHeight 20}) (def chat-members-container {:marginBottom 10}) @@ -85,14 +85,14 @@ :fontSize 14 :lineHeight 20}) -(def chat-name-value-container +(defn chat-name-value-container [focused?] {:flexDirection :row :marginLeft 16 :height 56 :alignItems :center :justifyContent :center - :borderBottomWidth 1 - :borderBottomColor separator-color}) + :borderBottomWidth 2 + :borderBottomColor (if focused? color-purple separator-color)}) (def chat-name-value {:flex 1 @@ -105,11 +105,11 @@ :justifyContent :center}) (def chat-name-btn-edit-text - {:marginTop -1 - :color text2-color - :fontFamily font - :fontSize 16 - :lineHeight 20}) + {:marginTop -1 + :color text2-color + :fontFamily font + :fontSize 16 + :lineHeight 20}) (def members-text {:marginTop 24 diff --git a/src/status_im/group_settings/subs.cljs b/src/status_im/group_settings/subs.cljs index 55085b2256..f2b6ac1db3 100644 --- a/src/status_im/group_settings/subs.cljs +++ b/src/status_im/group_settings/subs.cljs @@ -1,14 +1,13 @@ (ns status-im.group-settings.subs (:require-macros [reagent.ratom :refer [reaction]]) - (:require [re-frame.core :refer [register-sub]] - [status-im.models.contacts :refer [contact-by-identity]])) + (:require [re-frame.core :refer [register-sub]])) -(register-sub :group-settings-selected-member - (fn [db [_]] +(register-sub :selected-participant + (fn [db _] (reaction - (let [identity (get @db :group-settings-selected-member)] - (contact-by-identity identity))))) + (let [identity (first (:selected-participants @db))] + (get-in @db [:contacts identity]))))) -(register-sub :group-settings-show-color-picker - (fn [db [_]] - (reaction (get @db :group-settings-show-color-picker)))) +(register-sub :group-settings + (fn [db [_ k]] + (reaction (get-in @db [:group-settings k])))) diff --git a/src/status_im/group_settings/views/chat_name_edit.cljs b/src/status_im/group_settings/views/chat_name_edit.cljs deleted file mode 100644 index 523b94653b..0000000000 --- a/src/status_im/group_settings/views/chat_name_edit.cljs +++ /dev/null @@ -1,31 +0,0 @@ -(ns status-im.group-settings.views.chat-name-edit - (:require-macros [status-im.utils.views :refer [defview]]) - (:require [reagent.core :as r] - [re-frame.core :refer [subscribe dispatch dispatch-sync]] - [status-im.components.react :refer [view text-input]] - [status-im.components.toolbar :refer [toolbar]] - [status-im.group-settings.styles.chat-name-edit :as st] - [status-im.components.styles :refer [toolbar-background2 - text2-color]])) - -(defn save-group-chat-name [] - (dispatch [:set-chat-name]) - (dispatch [:navigate-back])) - -(defn chat-name-edit-toolbar [chat-name] - [toolbar {:background-color toolbar-background2 - :title "Edit chat name" - ;; TODO change to dark 'ok' icon - :action {:image {:source {:uri :icon_ok} - :style st/save-action-icon} - :handler save-group-chat-name}}]) - -(defview chat-name-edit [] - [new-chat-name [:get :new-chat-name]] - [view st/chat-name-container - [chat-name-edit-toolbar] - [text-input {:style st/chat-name-input - :autoFocus true - :placeholderTextColor text2-color - :onChangeText #(dispatch [:set-new-chat-name %])} - new-chat-name]]) diff --git a/src/status_im/group_settings/views/member.cljs b/src/status_im/group_settings/views/member.cljs index 73889c611f..240d6a09c8 100644 --- a/src/status_im/group_settings/views/member.cljs +++ b/src/status_im/group_settings/views/member.cljs @@ -38,6 +38,6 @@ [text {:style st/role-text} role])] [touchable-highlight - {:on-press #(dispatch [:select-group-chat-member whisper-identity])} + {:on-press #(dispatch [:set :selected-participants #{whisper-identity}])} [view st/more-btn [icon :more-vertical st/more-btn-icon]]]]) diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs index e7d2687eed..4010049665 100644 --- a/src/status_im/handlers.cljs +++ b/src/status_im/handlers.cljs @@ -1,46 +1,23 @@ (ns status-im.handlers (:require - [re-frame.core :refer [register-handler after dispatch debug enrich]] + [re-frame.core :refer [register-handler after dispatch debug]] [schema.core :as s :include-macros true] - [status-im.persistence.realm :as r] [status-im.db :refer [app-db schema]] [status-im.persistence.simple-kv-store :as kv] [status-im.protocol.state.storage :as storage] - [status-im.db :as db :refer [app-db schema]] - [status-im.protocol.api :refer [init-protocol]] - [status-im.protocol.protocol-handler :refer [make-handler]] - [status-im.models.protocol :refer [update-identity - set-initialized]] - [status-im.models.contacts :as contacts] - [status-im.models.messages :refer [save-message - update-message! - clear-history]] [status-im.models.commands :refer [set-commands]] - [status-im.handlers.server :as server] [status-im.chat.suggestions :refer [load-commands]] - [status-im.models.chats :refer [chat-exists? - create-chat - chat-add-participants - chat-remove-participants - set-chat-active - re-join-group-chat - chat-by-id2]] [status-im.utils.logging :as log] - [status-im.protocol.api :as api] - [status-im.constants :refer [text-content-type - content-type-command]] - [status-im.navigation :refer [nav-push - nav-replace - nav-pop]] [status-im.utils.crypt :refer [gen-random-bytes]] - [status-im.utils.random :as random] [status-im.utils.handlers :as u] status-im.chat.handlers - [status-im.group-settings.handlers :refer [delete-chat]] + status-im.group-settings.handlers status-im.navigation.handlers - status-im.discovery.handlers status-im.contacts.handlers - status-im.new-group.handlers)) + status-im.discovery.handlers + status-im.new-group.handlers + status-im.participants.handlers + status-im.protocol.handlers)) ;; -- Middleware ------------------------------------------------------------ ;; @@ -63,6 +40,11 @@ (fn [db [_ k v]] (assoc db k v)))) +(register-handler :set-in + (debug + (fn [db [_ path v]] + (assoc-in db path v)))) + (register-handler :initialize-db (fn [_ _] (assoc app-db @@ -100,192 +82,8 @@ (log/debug action commands) (set-commands db commands))) -;; -- Protocol -------------------------------------------------------------- - -(register-handler :initialize-protocol - (u/side-effect! - (fn [db [_]] - (init-protocol (make-handler db))))) - -(register-handler :protocol-initialized - (fn [db [_ identity]] - (-> db - (update-identity identity) - (set-initialized true)))) - -(defn system-message [msg-id content] - {:from "system" - :msg-id msg-id - :content content - :content-type text-content-type}) - -(defn joined-chat-msg [chat-id from msg-id] - (let [contact-name (:name (contacts/contact-by-identity from))] - (save-message chat-id {:from "system" - :msg-id (str msg-id "_" from) - :content (str (or contact-name from) " received chat invitation") - :content-type text-content-type}))) - -(defn participant-invited-to-group-msg [chat-id identity from msg-id] - (let [inviter-name (:name (contacts/contact-by-identity from)) - invitee-name (if (= identity (api/my-identity)) - "You" - (:name (contacts/contact-by-identity identity)))] - (save-message chat-id {:from "system" - :msg-id msg-id - :content (str (or inviter-name from) " invited " (or invitee-name identity)) - :content-type text-content-type}))) - -(defn participant-removed-from-group-msg [chat-id identity from msg-id] - (let [remover-name (:name (contacts/contact-by-identity from)) - removed-name (:name (contacts/contact-by-identity identity))] - (->> (str (or remover-name from) " removed " (or removed-name identity)) - (system-message msg-id) - (save-message chat-id)))) - -(defn you-removed-from-group-msg [chat-id from msg-id] - (let [remover-name (:name (contacts/contact-by-identity from))] - (->> (str (or remover-name from) " removed you from group chat") - (system-message msg-id) - (save-message chat-id)))) - -(defn participant-left-group-msg [chat-id from msg-id] - (let [left-name (:name (contacts/contact-by-identity from))] - (->> (str (or left-name from) " left") - (system-message msg-id) - (save-message chat-id)))) - -(defn removed-participant-msg [chat-id identity] - (let [contact-name (:name (contacts/contact-by-identity identity))] - (->> (str "You've removed " (or contact-name identity)) - (system-message (random/id)) - (save-message chat-id)))) - -(defn left-chat-msg [chat-id] - (save-message chat-id {:from "system" - :msg-id (random/id) - :content "You left this chat" - :content-type text-content-type})) - -(register-handler :group-chat-invite-acked - (u/side-effect! - (fn [_ [action from group-id ack-msg-id]] - (log/debug action from group-id ack-msg-id) - (joined-chat-msg group-id from ack-msg-id)))) - -(register-handler :participant-removed-from-group - (u/side-effect! - (fn [_ [action from group-id identity msg-id]] - (log/debug action msg-id from group-id identity) - (chat-remove-participants group-id [identity]) - (participant-removed-from-group-msg group-id identity from msg-id)))) - -(register-handler :you-removed-from-group - (u/side-effect! - (fn [_ [action from group-id msg-id]] - (log/debug action msg-id from group-id) - (you-removed-from-group-msg group-id from msg-id) - (set-chat-active group-id false)))) - -(register-handler :participant-left-group - (u/side-effect! - (fn [_ [action from group-id msg-id]] - (log/debug action msg-id from group-id) - (when-not (= (api/my-identity) from) - (participant-left-group-msg group-id from msg-id))))) - -(register-handler :participant-invited-to-group - (u/side-effect! - (fn [_ [action from group-id identity msg-id]] - (log/debug action msg-id from group-id identity) - (participant-invited-to-group-msg group-id identity from msg-id)))) - -(register-handler :acked-msg - (u/side-effect! - (fn [_ [action from msg-id]] - (log/debug action from msg-id) - (update-message! {:msg-id msg-id - :delivery-status :delivered})))) - -(register-handler :msg-delivery-failed - (u/side-effect! - (fn [_ [action msg-id]] - (log/debug action msg-id) - (update-message! {:msg-id msg-id - :delivery-status :failed})))) - -(register-handler :leave-group-chat - (u/side-effect! - (fn [db [action]] - (log/debug action) - (let [chat-id (:current-chat-id db)] - (api/leave-group-chat chat-id) - (set-chat-active chat-id false) - (left-chat-msg chat-id) - (delete-chat chat-id) - (dispatch [:navigate-back]))))) - ;; -- User data -------------------------------------------------------------- (register-handler :load-user-phone-number (fn [db [_]] ;; todo fetch phone number from db (assoc db :user-phone-number "123"))) - -;; -- Chats -------------------------------------------------------------- -(defn update-new-participants-selection [db identity add?] - (update db :new-participants (fn [new-participants] - (if add? - (conj new-participants identity) - (disj new-participants identity))))) - -(register-handler :select-new-participant - (fn [db [action identity add?]] - (log/debug action identity add?) - (update-new-participants-selection db identity add?))) - -(register-handler :remove-selected-participants - (fn [db [action]] - (log/debug action) - (let [identities (vec (:new-participants db)) - chat-id (:current-chat-id db)] - (chat-remove-participants chat-id identities) - (dispatch [:navigate-back]) - (doseq [ident identities] - (api/group-remove-participant chat-id ident) - (removed-participant-msg chat-id ident))))) - -(register-handler :add-new-participants - (fn [db [action navigator]] - (log/debug action) - (let [identities (vec (:new-participants db)) - chat-id (:current-chat-id db)] - (chat-add-participants chat-id identities) - (dispatch [:navigate-back]) - (doseq [ident identities] - (api/group-add-participant chat-id ident)) - db))) - -(defn chat-remove-member [db] - (let [chat (get-in db [:chats (:current-chat-id db)]) - identity (:group-settings-selected-member db)] - (r/write - (fn [] - (r/create :chats - (update chat :contacts - (fn [members] - (filter #(not= (:identity %) identity) members))) - true))) - ;; TODO temp. Update chat in db atom - (dispatch [:initialize-chats]) - db)) - -(register-handler :chat-remove-member - (fn [db [action]] - (let [chat-id (:current-chat-id db) - identity (:group-settings-selected-member db) - db (chat-remove-member db)] - (dispatch [:select-group-chat-member nil]) - ;; TODO fix and uncomment - (api/group-remove-participant chat-id identity) - (removed-participant-msg chat-id identity) - db))) diff --git a/src/status_im/models/messages.cljs b/src/status_im/models/messages.cljs index 80e4656e8b..5c8c17fa5f 100644 --- a/src/status_im/models/messages.cljs +++ b/src/status_im/models/messages.cljs @@ -62,10 +62,3 @@ (fn [] (when (r/exists? :msgs :msg-id msg-id) (r/create :msgs msg true))))) - -(defn clear-history [chat-id] - (r/write - (fn [] - (r/delete (r/get-by-field :msgs :chat-id chat-id)))) - ;; TODO temp. Update chat in db atom - (dispatch [:initialize-chats])) diff --git a/src/status_im/navigation.cljs b/src/status_im/navigation.cljs deleted file mode 100644 index f80b7d3df7..0000000000 --- a/src/status_im/navigation.cljs +++ /dev/null @@ -1,17 +0,0 @@ -(ns status-im.navigation) - -(def ^{:dynamic true :private true} *nav-render* - "Flag to suppress navigator re-renders from outside om when pushing/popping." - true) - -(defn nav-pop [nav] - (binding [*nav-render* true] - (.pop nav))) - -(defn nav-push [nav route] - (binding [*nav-render* true] - (.push nav (clj->js route)))) - -(defn nav-replace [nav route] - (binding [*nav-render* true] - (.replace nav (clj->js route)))) diff --git a/src/status_im/navigation/handlers.cljs b/src/status_im/navigation/handlers.cljs index 28f331a78a..c47134e429 100644 --- a/src/status_im/navigation/handlers.cljs +++ b/src/status_im/navigation/handlers.cljs @@ -18,7 +18,9 @@ (update :navigation-stack replace-top-element view-id) (assoc :view-id view-id))) -(defmulti preload-data! (fn [_ [_ view-id]] view-id)) +(defmulti preload-data! + (fn [db [_ view-id]] (or view-id (:view-id db)))) + (defmethod preload-data! :default [db _] db) (register-handler :navigate-to @@ -27,10 +29,12 @@ (push-view db view-id))) (register-handler :navigation-replace + (enrich preload-data!) (fn [db [_ view-id]] (replace-view db view-id))) (register-handler :navigate-back + (enrich preload-data!) (fn [{:keys [navigation-stack] :as db} _] (if (>= 1 (count navigation-stack)) db @@ -46,32 +50,10 @@ (push-view :new-group) (assoc :new-group #{}))))) -(register-handler :show-chat - (fn [db [_ chat-id nav-type]] - (let [update-view-id-fn (if (= :replace nav-type) replace-view push-view)] - (-> db - (update-view-id-fn :chat) - (assoc :current-chat-id chat-id))))) - (register-handler :show-contacts (fn [db _] (push-view db :contact-list))) -(defn clear-new-participants [db] - (assoc db :new-participants #{})) - -(register-handler :show-remove-participants - (fn [db _] - (-> db - (push-view :remove-participants) - clear-new-participants))) - -(register-handler :show-add-participants - (fn [db _] - (-> db - (push-view :add-participants) - clear-new-participants))) - (defn show-profile [db [_ identity]] (-> db diff --git a/src/status_im/new_group/handlers.cljs b/src/status_im/new_group/handlers.cljs index 7c890399fd..4a48a3ebd1 100644 --- a/src/status_im/new_group/handlers.cljs +++ b/src/status_im/new_group/handlers.cljs @@ -56,14 +56,31 @@ (defn show-chat! [{:keys [new-group-id]} _] - (dispatch [:show-chat new-group-id :replace])) + (dispatch [:navigation-replace :chat new-group-id])) + +(defn enable-creat-buttion + [db _] + (assoc db :disable-group-creation false)) (register-handler :create-new-group (-> start-group-chat! ((enrich prepare-chat)) ((enrich add-chat)) ((after create-chat!)) - ((after show-chat!)))) + ((after show-chat!)) + ((enrich enable-creat-buttion)))) + +(defn disable-creat-button + [db _] + (assoc db :disable-group-creation true)) + +(defn dispatch-create-group + [_ [_ group-name]] + (dispatch [:create-new-group group-name])) + +(register-handler :init-group-creation + (after dispatch-create-group) + disable-creat-button) ; todo rewrite (register-handler :group-chat-invite-received diff --git a/src/status_im/new_group/screen.cljs b/src/status_im/new_group/screen.cljs index c58832e1dc..a620959d50 100644 --- a/src/status_im/new_group/screen.cljs +++ b/src/status_im/new_group/screen.cljs @@ -18,12 +18,14 @@ (defview new-group-toolbar [] - [group-name [:get ::group-name]] + [group-name [:get ::group-name] + creation-disabled? [:get :disable-group-creation]] [toolbar {:title "New group chat" :action {:image {:source res/v ;; {:uri "icon_search"} :style st/toolbar-icon} - :handler #(dispatch [:create-new-group group-name])}}]) + :handler (when-not creation-disabled? + #(dispatch [:init-group-creation group-name]))}}]) (defview group-name-input [] [group-name [:get ::group-name]] diff --git a/src/status_im/new_group/subs.cljs b/src/status_im/new_group/subs.cljs index 57d01e1aae..6753a5eacb 100644 --- a/src/status_im/new_group/subs.cljs +++ b/src/status_im/new_group/subs.cljs @@ -1,9 +1,7 @@ (ns status-im.new-group.subs (:require-macros [reagent.ratom :refer [reaction]]) - (:require [re-frame.core :refer [register-sub]])) + (:require [re-frame.core :refer [register-sub]] + [status-im.utils.subs :as u])) (register-sub :is-contact-selected? - (fn [db [_ id]] - (-> (:selected-contacts @db) - (contains? id) - (reaction)))) + (u/contains-sub :selected-contacts)) diff --git a/src/status_im/new_group/views/contact.cljs b/src/status_im/new_group/views/contact.cljs index a87b7d5fe2..cfec8a409d 100644 --- a/src/status_im/new_group/views/contact.cljs +++ b/src/status_im/new_group/views/contact.cljs @@ -8,7 +8,6 @@ (defn on-toggle [whisper-identity] (fn [checked?] - (println checked?) (let [action (if checked? :select-contact :deselect-contact)] (dispatch [action whisper-identity])))) diff --git a/src/status_im/participants/handlers.cljs b/src/status_im/participants/handlers.cljs new file mode 100644 index 0000000000..fe0e5581c0 --- /dev/null +++ b/src/status_im/participants/handlers.cljs @@ -0,0 +1,23 @@ +(ns status-im.participants.handlers + (:require [status-im.navigation.handlers :as nav] + [re-frame.core :refer [register-handler debug]])) + +(defmethod nav/preload-data! :add-participants + [db _] + (assoc db :selected-participants #{})) + +(defmethod nav/preload-data! :remove-participants + [db _] + (assoc db :selected-participants #{})) + +(defn deselect-participant + [db [_ id]] + (update db :selected-participants disj id)) + +(register-handler :deselect-participant deselect-participant) + +(defn select-participant + [db [_ id]] + (update db :selected-participants conj id)) + +(register-handler :select-participant (debug select-participant)) diff --git a/src/status_im/participants/subs.cljs b/src/status_im/participants/subs.cljs new file mode 100644 index 0000000000..d351667a8a --- /dev/null +++ b/src/status_im/participants/subs.cljs @@ -0,0 +1,7 @@ +(ns status-im.participants.subs + (:require-macros [reagent.ratom :refer [reaction]]) + (:require [re-frame.core :refer [register-sub]] + [status-im.utils.subs :as u])) + +(register-sub :is-participant-selected? + (u/contains-sub :selected-participants)) diff --git a/src/status_im/participants/views/add.cljs b/src/status_im/participants/views/add.cljs new file mode 100644 index 0000000000..5bab93ea1c --- /dev/null +++ b/src/status_im/participants/views/add.cljs @@ -0,0 +1,30 @@ +(ns status-im.participants.views.add + (:require-macros [status-im.utils.views :refer [defview]]) + (:require [re-frame.core :refer [subscribe dispatch]] + [status-im.resources :as res] + [status-im.components.react :refer [view list-view list-item]] + [status-im.components.toolbar :refer [toolbar]] + [status-im.utils.listview :refer [to-datasource]] + [status-im.participants.views.contact :refer [participant-contact]] + [reagent.core :as r] + [status-im.participants.styles :as st])) + +(defn new-participants-toolbar [] + [toolbar + {:title "Add Participants" + :action {:image {:source res/v ;; {:uri "icon_search"} + :style st/new-participant-image} + :handler #(do (dispatch [:add-new-participants]) + (dispatch [:navigate-back]))}}]) + +(defn new-participants-row + [row _ _] + (list-item [participant-contact row])) + +(defview new-participants [] + [contacts [:all-new-contacts]] + [view st/participants-container + [new-participants-toolbar] + [list-view {:dataSource (to-datasource contacts) + :renderRow new-participants-row + :style st/participants-list}]]) diff --git a/src/status_im/participants/views/contact.cljs b/src/status_im/participants/views/contact.cljs index de6ccd9287..0311510e9b 100644 --- a/src/status_im/participants/views/contact.cljs +++ b/src/status_im/participants/views/contact.cljs @@ -1,4 +1,5 @@ (ns status-im.participants.views.contact + (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] [status-im.components.react :refer [view]] [status-im.contacts.views.contact-inner :refer [contact-inner-view]] @@ -6,14 +7,17 @@ [reagent.core :as r] [status-im.participants.styles :as st])) -(defn participant-contact [{:keys [whisper-identity] :as contact}] - ;; todo must be moved to handlers - (let [checked (r/atom false)] - (fn [{:keys [whisper-identity] :as contact}] - [view st/participant-container - [item-checkbox {:onToggle (fn [checked?] - (reset! checked checked?) - (dispatch [:select-new-participant whisper-identity checked?])) - :checked @checked - :size 30}] - [contact-inner-view contact]]))) +;; todo duplication +(defn on-toggle [whisper-identity] + (fn [checked?] + (let [action (if checked? :select-participant :deselect-participant)] + (dispatch [action whisper-identity])))) + +(defview participant-contact + [{:keys [whisper-identity] :as contact}] + [checked [:is-participant-selected? whisper-identity]] + [view st/participant-container + [item-checkbox {:onToggle (on-toggle whisper-identity) + :checked checked + :size 30}] + [contact-inner-view contact]]) diff --git a/src/status_im/participants/views/create.cljs b/src/status_im/participants/views/create.cljs deleted file mode 100644 index a0ede9b5ef..0000000000 --- a/src/status_im/participants/views/create.cljs +++ /dev/null @@ -1,30 +0,0 @@ -(ns status-im.participants.views.create - (:require [re-frame.core :refer [subscribe dispatch]] - [status-im.resources :as res] - [status-im.components.react :refer [view list-view list-item]] - [status-im.components.toolbar :refer [toolbar]] - [status-im.utils.listview :refer [to-datasource]] - [status-im.participants.views.contact :refer [participant-contact]] - [reagent.core :as r] - [status-im.participants.styles :as st])) - -(defn new-participants-toolbar [] - [toolbar - {:title "Add Participants" - :action {:image {:source res/v ;; {:uri "icon_search"} - :style st/new-participant-image} - :handler #(dispatch [:add-new-participants])}}]) - -(defn new-participants-row - [row _ _] - (list-item [participant-contact row])) - -(defn new-participants [] - (let [contacts (subscribe [:all-new-contacts])] - (fn [] - (let [contacts-ds (to-datasource @contacts)] - [view st/participants-container - [new-participants-toolbar] - [list-view {:dataSource contacts-ds - :renderRow new-participants-row - :style st/participants-list}]])))) diff --git a/src/status_im/participants/views/remove.cljs b/src/status_im/participants/views/remove.cljs index 68aa8f0cd4..e7b8103ffe 100644 --- a/src/status_im/participants/views/remove.cljs +++ b/src/status_im/participants/views/remove.cljs @@ -1,4 +1,5 @@ (ns status-im.participants.views.remove + (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.resources :as res] [status-im.components.react :refer [view text-input text image @@ -13,21 +14,20 @@ (defn remove-participants-toolbar [] [toolbar - {:title "Remove Participants" - :action {:handler #(dispatch [:remove-selected-participants]) - :image {:source res/trash-icon ;; {:uri "icon_search"} - :style st/remove-participants-image}}}]) + {:title "Remove Participants" + :action {:handler #(do (dispatch [:remove-participants]) + (dispatch [:navigate-back])) + :image {:source res/trash-icon ;; {:uri "icon_search"} + :style st/remove-participants-image}}}]) (defn remove-participants-row [row _ _] (r/as-element [participant-contact row])) -(defn remove-participants [] - (let [contacts (subscribe [:current-chat-contacts])] - (fn [] - (let [contacts-ds (to-datasource @contacts)] - [view st/participants-container - [remove-participants-toolbar] - [list-view {:dataSource contacts-ds - :renderRow remove-participants-row - :style st/participants-list}]])))) +(defview remove-participants [] + [contacts [:current-chat-contacts]] + [view st/participants-container + [remove-participants-toolbar] + [list-view {:dataSource (to-datasource contacts) + :renderRow remove-participants-row + :style st/participants-list}]]) diff --git a/src/status_im/profile/screen.cljs b/src/status_im/profile/screen.cljs index 3f0c8d2779..40d10c44a1 100644 --- a/src/status_im/profile/screen.cljs +++ b/src/status_im/profile/screen.cljs @@ -32,7 +32,7 @@ (defn message-user [identity] (when identity - (dispatch [:show-chat identity :push]))) + (dispatch [:navigate-to :chat identity]))) (defview profile [] [{:keys [name whisper-identity phone-number]} [:contact]] diff --git a/src/status_im/protocol/handlers.cljs b/src/status_im/protocol/handlers.cljs new file mode 100644 index 0000000000..4b51c9ec65 --- /dev/null +++ b/src/status_im/protocol/handlers.cljs @@ -0,0 +1,115 @@ +; todo everything inside this namespace must be revievew in common with future +; changes in protocol lib +(ns status-im.protocol.handlers + (:require [status-im.utils.handlers :as u] + [status-im.utils.logging :as log] + [status-im.protocol.api :as api] + [re-frame.core :refer [register-handler dispatch debug]] + [status-im.models.contacts :as contacts] + [status-im.protocol.api :refer [init-protocol]] + [status-im.protocol.protocol-handler :refer [make-handler]] + [status-im.models.protocol :refer [update-identity + set-initialized]] + [status-im.constants :refer [text-content-type]] + [status-im.models.messages :as messages] + [status-im.models.chats :as chats])) + +(register-handler :initialize-protocol + (u/side-effect! + (fn [db [_]] + (init-protocol (make-handler db))))) + +(register-handler :protocol-initialized + (fn [db [_ identity]] + (-> db + (update-identity identity) + (set-initialized true)))) + +(defn system-message [msg-id content] + {:from "system" + :msg-id msg-id + :content content + :content-type text-content-type}) + +(defn joined-chat-msg [chat-id from msg-id] + (let [contact-name (:name (contacts/contact-by-identity from))] + (messages/save-message chat-id {:from "system" + :msg-id (str msg-id "_" from) + :content (str (or contact-name from) " received chat invitation") + :content-type text-content-type}))) + +(defn participant-invited-to-group-msg [chat-id identity from msg-id] + (let [inviter-name (:name (contacts/contact-by-identity from)) + invitee-name (if (= identity (api/my-identity)) + "You" + (:name (contacts/contact-by-identity identity)))] + (messages/save-message chat-id {:from "system" + :msg-id msg-id + :content (str (or inviter-name from) " invited " (or invitee-name identity)) + :content-type text-content-type}))) + +(defn participant-removed-from-group-msg [chat-id identity from msg-id] + (let [remover-name (:name (contacts/contact-by-identity from)) + removed-name (:name (contacts/contact-by-identity identity))] + (->> (str (or remover-name from) " removed " (or removed-name identity)) + (system-message msg-id) + (messages/save-message chat-id)))) + +(defn you-removed-from-group-msg [chat-id from msg-id] + (let [remover-name (:name (contacts/contact-by-identity from))] + (->> (str (or remover-name from) " removed you from group chat") + (system-message msg-id) + (messages/save-message chat-id)))) + +(defn participant-left-group-msg [chat-id from msg-id] + (let [left-name (:name (contacts/contact-by-identity from))] + (->> (str (or left-name from) " left") + (system-message msg-id) + (messages/save-message chat-id)))) + +(register-handler :group-chat-invite-acked + (u/side-effect! + (fn [_ [action from group-id ack-msg-id]] + (log/debug action from group-id ack-msg-id) + (joined-chat-msg group-id from ack-msg-id)))) + +(register-handler :participant-removed-from-group + (u/side-effect! + (fn [_ [action from group-id identity msg-id]] + (log/debug action msg-id from group-id identity) + (chats/chat-remove-participants group-id [identity]) + (participant-removed-from-group-msg group-id identity from msg-id)))) + +(register-handler :you-removed-from-group + (u/side-effect! + (fn [_ [action from group-id msg-id]] + (log/debug action msg-id from group-id) + (you-removed-from-group-msg group-id from msg-id) + (chats/set-chat-active group-id false)))) + +(register-handler :participant-left-group + (u/side-effect! + (fn [_ [action from group-id msg-id]] + (log/debug action msg-id from group-id) + (when-not (= (api/my-identity) from) + (participant-left-group-msg group-id from msg-id))))) + +(register-handler :participant-invited-to-group + (u/side-effect! + (fn [_ [action from group-id identity msg-id]] + (log/debug action msg-id from group-id identity) + (participant-invited-to-group-msg group-id identity from msg-id)))) + +(register-handler :acked-msg + (u/side-effect! + (fn [_ [action from msg-id]] + (log/debug action from msg-id) + (messages/update-message! {:msg-id msg-id + :delivery-status :delivered})))) + +(register-handler :msg-delivery-failed + (u/side-effect! + (fn [_ [action msg-id]] + (log/debug action msg-id) + (messages/update-message! {:msg-id msg-id + :delivery-status :failed})))) diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 8c1125d35d..972c57887c 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -5,8 +5,13 @@ status-im.group-settings.subs status-im.discovery.subs status-im.contacts.subs - status-im.new-group.subs)) + status-im.new-group.subs + status-im.participants.subs)) (register-sub :get (fn [db [_ k]] (reaction (k @db)))) + +(register-sub :get-in + (fn [db [_ path]] + (reaction (get-in @db path)))) diff --git a/src/status_im/utils/subs.cljs b/src/status_im/utils/subs.cljs new file mode 100644 index 0000000000..3be283c37e --- /dev/null +++ b/src/status_im/utils/subs.cljs @@ -0,0 +1,11 @@ +(ns status-im.utils.subs + (:require-macros [reagent.ratom :refer [reaction]])) + +(defn contains-sub + "Creates subscrition that cheks if collection (map or set) contains element" + [collection] + (fn [db [_ element]] + (println "WWWWWWWWWW" (type db)) + (-> (collection @db) + (contains? element) + (reaction))))