Online Status Indicator (#12716)

This commit is contained in:
Parvesh Monu 2021-10-29 21:55:01 +05:30 committed by GitHub
parent ec319974bd
commit 1034d542db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 815 additions and 90 deletions

View File

@ -218,4 +218,7 @@
(set! pin-background (:pin-background old-colors-mapping-colors))) (set! pin-background (:pin-background old-colors-mapping-colors)))
(reset! theme-type type))) (reset! theme-type type)))
;; Colors related to Visibility Status
(def color-online "#7CDA00")
(def color-dnd "#FA6565")
(def color-inactive "#939BA1")

View File

@ -162,3 +162,9 @@
(def ^:const activity-center-notification-type-private-group-chat 2) (def ^:const activity-center-notification-type-private-group-chat 2)
(def ^:const activity-center-notification-type-mention 3) (def ^:const activity-center-notification-type-mention 3)
(def ^:const activity-center-notification-type-reply 4) (def ^:const activity-center-notification-type-reply 4)
(def ^:const visibility-status-unknown 0)
(def ^:const visibility-status-automatic 1)
(def ^:const visibility-status-dnd 2)
(def ^:const visibility-status-always-online 3)
(def ^:const visibility-status-inactive 4)

View File

@ -1,7 +1,8 @@
(ns status-im.data-store.settings (ns status-im.data-store.settings
(:require (:require
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.ethereum.eip55 :as eip55])) [status-im.ethereum.eip55 :as eip55]
[status-im.data-store.visibility-status-updates :as visibility-status-updates]))
(defn rpc->networks [networks] (defn rpc->networks [networks]
(reduce (fn [acc {:keys [id] :as network}] (reduce (fn [acc {:keys [id] :as network}]
@ -50,4 +51,5 @@
(update :link-previews-enabled-sites set) (update :link-previews-enabled-sites set)
(update :custom-bootnodes rpc->custom-bootnodes) (update :custom-bootnodes rpc->custom-bootnodes)
(update :custom-bootnodes-enabled? rpc->custom-bootnodes) (update :custom-bootnodes-enabled? rpc->custom-bootnodes)
(update :currency keyword))) (update :currency keyword)
(visibility-status-updates/<-rpc-settings)))

View File

@ -0,0 +1,24 @@
(ns status-im.data-store.visibility-status-updates
(:require [clojure.set :as clojure.set]
[re-frame.core :as re-frame]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.utils.fx :as fx]
[taoensso.timbre :as log]))
(defn <-rpc [visibility-status-update]
(clojure.set/rename-keys visibility-status-update {:publicKey :public-key
:statusType :status-type}))
(defn <-rpc-settings [settings]
(-> settings
(clojure.set/rename-keys
{:current-user-status :current-user-visibility-status})
(update :current-user-visibility-status <-rpc)))
(fx/defn fetch-visibility-status-updates-rpc [_]
{::json-rpc/call [{:method "wakuext_statusUpdates"
:params []
:on-success #(re-frame/dispatch
[:visibility-status-updates/visibility-status-updates-loaded
(:statusUpdates ^js %)])
:on-failure #(log/error
"failed to fetch visibility-status-updates" %)}]})

View File

@ -32,6 +32,7 @@
:tooltips {} :tooltips {}
:dimensions/window (dimensions/window) :dimensions/window (dimensions/window)
:registry {} :registry {}
:visibility-status-updates {}
:stickers/packs-owned #{} :stickers/packs-owned #{}
:stickers/packs-pending #{} :stickers/packs-pending #{}
:keycard {:nfc-enabled? false :keycard {:nfc-enabled? false

View File

@ -131,6 +131,8 @@
"wakuext_enablePushNotificationsBlockMentions" {} "wakuext_enablePushNotificationsBlockMentions" {}
"wakuext_disablePushNotificationsBlockMentions" {} "wakuext_disablePushNotificationsBlockMentions" {}
"wakuext_unreadActivityCenterNotificationsCount" {} "wakuext_unreadActivityCenterNotificationsCount" {}
"wakuext_setUserStatus" {}
"wakuext_statusUpdates" {}
"multiaccounts_getIdentityImages" {} "multiaccounts_getIdentityImages" {}
"multiaccounts_getIdentityImage" {} "multiaccounts_getIdentityImage" {}
"multiaccounts_storeIdentityImage" {} "multiaccounts_storeIdentityImage" {}

View File

@ -27,6 +27,8 @@
status-im.wallet.choose-recipient.core status-im.wallet.choose-recipient.core
status-im.wallet.accounts.core status-im.wallet.accounts.core
status-im.popover.core status-im.popover.core
status-im.visibility-status-popover.core
status-im.visibility-status-updates.core
status-im.bottom-sheet.core status-im.bottom-sheet.core
status-im.add-new.core status-im.add-new.core
status-im.search.core status-im.search.core

View File

@ -64,6 +64,17 @@
(str "@" (or username ens-name))) (str "@" (or username ens-name)))
(or alias (gfycat/generate-gfy public-key))))) (or alias (gfycat/generate-gfy public-key)))))
(defn contact-by-identity [contacts identity]
(or (get contacts identity)
(contact-with-names {:public-key identity})))
(defn contact-two-names-by-identity [contact current-multiaccount identity]
(let [me? (= (:public-key current-multiaccount) identity)]
(if me?
[(or (:preferred-name current-multiaccount)
(gfycat/generate-gfy identity))]
(contact-two-names contact false))))
(def photo-quality-thumbnail :thumbnail) (def photo-quality-thumbnail :thumbnail)
(def photo-quality-large :large) (def photo-quality-large :large)

View File

@ -37,7 +37,8 @@
[status-im.notifications-center.core :as notifications-center] [status-im.notifications-center.core :as notifications-center]
[status-im.navigation :as navigation] [status-im.navigation :as navigation]
[status-im.signing.eip1559 :as eip1559] [status-im.signing.eip1559 :as eip1559]
[status-im.data-store.chats :as data-store.chats])) [status-im.data-store.chats :as data-store.chats]
[status-im.data-store.visibility-status-updates :as visibility-status-updates-store]))
(re-frame/reg-fx (re-frame/reg-fx
::initialize-communities-enabled ::initialize-communities-enabled
@ -338,7 +339,8 @@
(get-group-chat-invitations) (get-group-chat-invitations)
(multiaccounts/get-profile-picture) (multiaccounts/get-profile-picture)
(multiaccounts/switch-preview-privacy-mode-flag) (multiaccounts/switch-preview-privacy-mode-flag)
(link-preview/request-link-preview-whitelist)))) (link-preview/request-link-preview-whitelist)
(visibility-status-updates-store/fetch-visibility-status-updates-rpc))))
(defn get-new-auth-method [auth-method save-password?] (defn get-new-auth-method [auth-method save-password?]
(when save-password? (when save-password?

View File

@ -136,7 +136,9 @@
(fn [^js evn] (fn [^js evn]
(let [view-id (keyword (.-componentName evn))] (let [view-id (keyword (.-componentName evn))]
(when (get views/screens view-id) (when (get views/screens view-id)
(when (and (not= view-id :bottom-sheet) (not= view-id :popover)) (when (and (not= view-id :bottom-sheet)
(not= view-id :popover)
(not= view-id :visibility-status-popover))
(set-view-id view-id) (set-view-id view-id)
(when-not @curr-modal (when-not @curr-modal
(reset! pushed-screen-id view-id)))))))) (reset! pushed-screen-id view-id))))))))
@ -146,7 +148,8 @@
(.registerComponentDidDisappearListener (.registerComponentDidDisappearListener
(.events Navigation) (.events Navigation)
(fn [^js evn] (fn [^js evn]
(when-not (#{"popover" "bottom-sheet" "signing-sheet"} (.-componentName evn)) (when-not (#{"popover" "bottom-sheet" "signing-sheet" "visibility-status-popover"}
(.-componentName evn))
(doseq [[_ {:keys [ref value]}] @quo.text-input/text-input-refs] (doseq [[_ {:keys [ref value]}] @quo.text-input/text-input-refs]
(.setNativeProps ^js ref (clj->js {:text value}))) (.setNativeProps ^js ref (clj->js {:text value})))
(doseq [[^js text-input default-value] @react/text-input-refs] (doseq [[^js text-input default-value] @react/text-input-refs]
@ -290,6 +293,18 @@
(re-frame/reg-fx :show-popover (fn [] (show-overlay "popover"))) (re-frame/reg-fx :show-popover (fn [] (show-overlay "popover")))
(re-frame/reg-fx :hide-popover (fn [] (dissmiss-overlay "popover"))) (re-frame/reg-fx :hide-popover (fn [] (dissmiss-overlay "popover")))
;; VISIBILITY STATUS POPOVER
(defonce visibility-status-popover-reg
(.registerComponent Navigation
"visibility-status-popover"
(fn [] (gestureHandlerRootHOC views/visibility-status-popover-comp))
(fn [] views/visibility-status-popover-comp)))
(re-frame/reg-fx :show-visibility-status-popover
(fn [] (show-overlay "visibility-status-popover")))
(re-frame/reg-fx :hide-visibility-status-popover
(fn [] (dissmiss-overlay "visibility-status-popover")))
;; BOTTOM SHEETS ;; BOTTOM SHEETS
(defonce bottom-sheet-reg (defonce bottom-sheet-reg
(.registerComponent Navigation (.registerComponent Navigation

View File

@ -7,6 +7,7 @@
[status-im.notifications.local :as local-notifications] [status-im.notifications.local :as local-notifications]
[status-im.chat.models.message :as models.message] [status-im.chat.models.message :as models.message]
[status-im.chat.models.link-preview :as link.preview] [status-im.chat.models.link-preview :as link.preview]
[status-im.visibility-status-updates.core :as visibility-status-updates]
[status-im.utils.fx :as fx] [status-im.utils.fx :as fx]
[taoensso.timbre :as log])) [taoensso.timbre :as log]))
@ -41,7 +42,8 @@
{:db (assoc db {:db (assoc db
:peers-summary peers-summary :peers-summary peers-summary
:peers-count peers-count)} :peers-count peers-count)}
(mailserver/peers-summary-change previous-summary)))) (mailserver/peers-summary-change previous-summary)
(visibility-status-updates/peers-summary-change peers-count))))
(fx/defn wakuv2-peer-stats (fx/defn wakuv2-peer-stats
[{:keys [db]} peer-stats] [{:keys [db]} peer-stats]

View File

@ -40,7 +40,8 @@
[status-im.notifications.core :as notifications] [status-im.notifications.core :as notifications]
[status-im.utils.currency :as currency] [status-im.utils.currency :as currency]
[clojure.set :as clojure.set] [clojure.set :as clojure.set]
[quo.design-system.colors :as colors])) [quo.design-system.colors :as colors]
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]))
;; TOP LEVEL =========================================================================================================== ;; TOP LEVEL ===========================================================================================================
@ -86,6 +87,7 @@
(reg-root-key-sub :app-state :app-state) (reg-root-key-sub :app-state :app-state)
(reg-root-key-sub :home-items-show-number :home-items-show-number) (reg-root-key-sub :home-items-show-number :home-items-show-number)
(reg-root-key-sub :waku/v2-peer-stats :peer-stats) (reg-root-key-sub :waku/v2-peer-stats :peer-stats)
(reg-root-key-sub :visibility-status-updates :visibility-status-updates)
;;NOTE this one is not related to ethereum network ;;NOTE this one is not related to ethereum network
;; it is about cellular network/ wifi network ;; it is about cellular network/ wifi network
@ -200,6 +202,7 @@
(reg-root-key-sub :intro-wizard-state :intro-wizard) (reg-root-key-sub :intro-wizard-state :intro-wizard)
(reg-root-key-sub :popover/popover :popover/popover) (reg-root-key-sub :popover/popover :popover/popover)
(reg-root-key-sub :visibility-status-popover/popover :visibility-status-popover/popover)
(reg-root-key-sub :add-account :add-account) (reg-root-key-sub :add-account :add-account)
(reg-root-key-sub :keycard :keycard) (reg-root-key-sub :keycard :keycard)
@ -292,6 +295,36 @@
(fn [communities [_ id]] (fn [communities [_ id]]
(get-in communities [id :chats]))) (get-in communities [id :chats])))
(re-frame/reg-sub
:communities/community-members
:<- [:communities]
(fn [communities [_ id]]
(get-in communities [id :members])))
(re-frame/reg-sub
:communities/sorted-community-members
(fn [[_ community-id]]
(let [contacts (re-frame/subscribe [:contacts/contacts])
multiaccount (re-frame/subscribe [:multiaccount])
members (re-frame/subscribe
[:communities/community-members community-id])]
[contacts multiaccount members]))
(fn [[contacts multiaccount members] _]
(let [names (reduce
(fn [acc identity]
(let [me? (= (:public-key multiaccount)
identity)
contact (when-not me?
(multiaccounts/contact-by-identity
contacts identity))
name (first
(multiaccounts/contact-two-names-by-identity
contact multiaccount identity))]
(assoc acc identity name))) {} (keys members))]
(->> members
(sort-by #(get names (get % 0)))
(sort-by #(visibility-status-utils/visibility-status-order (get % 0)))))))
(re-frame/reg-sub (re-frame/reg-sub
:communities/communities :communities/communities
:<- [:communities/enabled?] :<- [:communities/enabled?]
@ -355,6 +388,11 @@
;;GENERAL ============================================================================================================== ;;GENERAL ==============================================================================================================
(re-frame/reg-sub
:visibility-status-updates/visibility-status-update
:<- [:visibility-status-updates]
(fn [visibility-status-updates [_ public-key]]
(get visibility-status-updates public-key)))
(re-frame/reg-sub (re-frame/reg-sub
:multiaccount/logged-in? :multiaccount/logged-in?
@ -784,6 +822,12 @@
(string/blank? (security/safe-unmask-data seed)) (string/blank? (security/safe-unmask-data seed))
false)))) false))))
(re-frame/reg-sub
:multiaccount/current-user-visibility-status
:<- [:multiaccount]
(fn [{:keys [current-user-visibility-status]}]
current-user-visibility-status))
;;CHAT ============================================================================================================== ;;CHAT ==============================================================================================================
(re-frame/reg-sub (re-frame/reg-sub
@ -2208,6 +2252,15 @@
(fn [contacts] (fn [contacts]
(contact.db/get-active-contacts contacts))) (contact.db/get-active-contacts contacts)))
(re-frame/reg-sub
:contacts/sorted-contacts
:<- [:contacts/active]
(fn [active-contacts]
(->> active-contacts
(sort-by :alias)
(sort-by
#(visibility-status-utils/visibility-status-order (:public-key %))))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active-count :contacts/active-count
:<- [:contacts/active] :<- [:contacts/active]
@ -2265,8 +2318,7 @@
:contacts/contact-by-identity :contacts/contact-by-identity
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [contacts [_ identity]] (fn [contacts [_ identity]]
(or (get contacts identity) (multiaccounts/contact-by-identity contacts identity)))
(multiaccounts/contact-with-names {:public-key identity}))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-added? :contacts/contact-added?
@ -2281,11 +2333,8 @@
[(re-frame/subscribe [:contacts/contact-by-identity identity]) [(re-frame/subscribe [:contacts/contact-by-identity identity])
(re-frame/subscribe [:multiaccount])]) (re-frame/subscribe [:multiaccount])])
(fn [[contact current-multiaccount] [_ identity]] (fn [[contact current-multiaccount] [_ identity]]
(let [me? (= (:public-key current-multiaccount) identity)] (multiaccounts/contact-two-names-by-identity contact current-multiaccount
(if me? identity)))
[(or (:preferred-name current-multiaccount)
(gfycat/generate-gfy identity))]
(multiaccounts/contact-two-names contact false)))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-name-by-identity :contacts/contact-name-by-identity

View File

@ -19,6 +19,7 @@
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.multiaccounts.model :as multiaccounts.model] [status-im.multiaccounts.model :as multiaccounts.model]
[status-im.notifications-center.core :as notifications-center] [status-im.notifications-center.core :as notifications-center]
[status-im.visibility-status-updates.core :as models.visibility-status-updates]
[clojure.string :as string])) [clojure.string :as string]))
(fx/defn process-next (fx/defn process-next
@ -42,6 +43,8 @@
^js activity-notifications (.-activityCenterNotifications response-js) ^js activity-notifications (.-activityCenterNotifications response-js)
^js pin-messages (.-pinMessages response-js) ^js pin-messages (.-pinMessages response-js)
^js removed-messages (.-removedMessages response-js) ^js removed-messages (.-removedMessages response-js)
^js visibility-status-updates (.-statusUpdates response-js)
^js current-visibility-status (.-currentStatus response-js)
sync-handler (when-not process-async process-response)] sync-handler (when-not process-async process-response)]
(cond (cond
@ -149,7 +152,23 @@
(js-delete response-js "removedMessages") (js-delete response-js "removedMessages")
(fx/merge cofx (fx/merge cofx
(process-next response-js sync-handler) (process-next response-js sync-handler)
(models.message/handle-removed-messages removed-messages-clj)))))) (models.message/handle-removed-messages removed-messages-clj)))
(seq visibility-status-updates)
(let [visibility-status-updates-clj (types/js->clj visibility-status-updates)]
(js-delete response-js "statusUpdates")
(fx/merge cofx
(process-next response-js sync-handler)
(models.visibility-status-updates/handle-visibility-status-updates
visibility-status-updates-clj)))
(some? current-visibility-status)
(let [current-visibility-status-clj (types/js->clj current-visibility-status)]
(js-delete response-js "currentStatus")
(fx/merge cofx
(process-next response-js sync-handler)
(models.visibility-status-updates/sync-visibility-status-update
current-visibility-status-clj))))))
(defn group-by-and-update-unviewed-counts (defn group-by-and-update-unviewed-counts
"group messages by current chat, profile updates, transactions and update unviewed counters in db for not curent chats" "group messages by current chat, profile updates, transactions and update unviewed counters in db for not curent chats"

View File

@ -6,7 +6,9 @@
[status-im.ui.components.chat-icon.styles :as styles] [status-im.ui.components.chat-icon.styles :as styles]
[quo.design-system.colors :as colors] [quo.design-system.colors :as colors]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.screens.chat.photos :as photos])) [status-im.ui.screens.chat.photos :as photos]
[status-im.profile.db :as profile.db]
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]))
;;TODO REWORK THIS NAMESPACE ;;TODO REWORK THIS NAMESPACE
@ -42,6 +44,24 @@
[react/view (:default-chat-icon styles) [react/view (:default-chat-icon styles)
[react/text {:style (:default-chat-icon-text styles)} emoji]])) [react/text {:style (:default-chat-icon-text styles)} emoji]]))
(defn profile-photo-plus-dot-view
[{:keys [public-key photo-container photo-path community?]}]
(let [photo-path (if (nil? photo-path)
@(re-frame.core/subscribe [:chats/photo-path public-key])
photo-path)
photo-container (if (nil? photo-container)
styles/container-chat-list photo-container)
size (:width photo-container)
identicon? (when photo-path (profile.db/base64-png? photo-path))
dot-styles (visibility-status-utils/icon-visibility-status-dot
public-key size identicon?)]
[react/view {:style photo-container
:accessibility-label :profile-photo}
[photos/photo photo-path {:size size}]
(when-not community?
[react/view {:style dot-styles
:accessibility-label :profile-photo-dot}])]))
(defn emoji-chat-icon-view (defn emoji-chat-icon-view
[chat-id group-chat name emoji styles] [chat-id group-chat name emoji styles]
[react/view (:container styles) [react/view (:container styles)
@ -49,8 +69,8 @@
(if (string/blank? emoji) (if (string/blank? emoji)
[default-chat-icon name styles] [default-chat-icon name styles]
[emoji-chat-icon emoji styles]) [emoji-chat-icon emoji styles])
(let [photo-path @(re-frame.core/subscribe [:chats/photo-path chat-id])] [profile-photo-plus-dot-view {:public-key chat-id
[photos/photo photo-path styles]))]) :photo-container (:default-chat-icon styles)}])])
(defn chat-icon-view-toolbar (defn chat-icon-view-toolbar
[chat-id group-chat name color emoji] [chat-id group-chat name color emoji]
@ -131,7 +151,8 @@
(if-not (string/blank? photo-path) (if-not (string/blank? photo-path)
[photos/photo photo-path styles])))) [photos/photo photo-path styles]))))
(defn profile-icon-view [photo-path name color emoji edit? size override-styles] (defn profile-icon-view
[photo-path name color emoji edit? size override-styles public-key community?]
(let [styles (merge {:container {:width size :height size} (let [styles (merge {:container {:width size :height size}
:size size :size size
:chat-icon styles/chat-icon-profile :chat-icon styles/chat-icon-profile
@ -141,7 +162,10 @@
(styles/emoji-chat-icon-text size))} override-styles)] (styles/emoji-chat-icon-text size))} override-styles)]
[react/view (:container styles) [react/view (:container styles)
(if (and photo-path (seq photo-path)) (if (and photo-path (seq photo-path))
[photos/photo photo-path styles] [profile-photo-plus-dot-view {:photo-path photo-path
:public-key public-key
:photo-container (:container styles)
:community? community?}]
(if (string/blank? emoji) (if (string/blank? emoji)
[default-chat-icon name styles] [default-chat-icon name styles]
[emoji-chat-icon emoji styles])) [emoji-chat-icon emoji styles]))

View File

@ -70,51 +70,6 @@
:height 64 :height 64
:border-radius 32})) :border-radius 32}))
(def online-view-wrapper
{:position :absolute
:bottom -2
:right -2
:width 17
:height 17
:border-radius 11
:background-color colors/white})
(def online-view
{:position :absolute
:bottom 2
:right 2
:width 13
:height 13
:border-radius 9
:background-color colors/blue})
(def online-view-profile
(merge online-view
{:width 24
:height 24
:border-radius 12}))
(def online-dot
{:position :absolute
:top 5
:width 3
:height 3
:border-radius 2
:background-color colors/white})
(def online-dot-left (merge online-dot {:left 2.8}))
(def online-dot-right (merge online-dot {:left 7.2}))
(def online-dot-profile
(merge online-dot
{:top 8
:width 4
:height 4}))
(def online-dot-left-profile
(merge online-dot-profile {:left 5}))
(def online-dot-right-profile
(merge online-dot-profile {:left 11}))
(def container-chat-list (def container-chat-list
{:width 40 {:width 40
:height 40}) :height 40})

View File

@ -37,8 +37,10 @@
(when-not minimized (when-not minimized
{:padding-top subtitle-margin}))) {:padding-top subtitle-margin})))
(defn extended-header [{:keys [title photo color subtitle subtitle-icon on-edit on-press monospace bottom-separator emoji] (defn extended-header
:or {bottom-separator true}}] [{:keys [title photo color subtitle subtitle-icon on-edit on-press monospace
bottom-separator emoji public-key community?]
:or {bottom-separator true}}]
(fn [{:keys [animation minimized]}] (fn [{:keys [animation minimized]}]
(let [wrapper (if on-press (let [wrapper (if on-press
[rn/touchable-opacity {:on-press on-press}] [rn/touchable-opacity {:on-press on-press}]
@ -57,7 +59,7 @@
[chat-icon.screen/profile-icon-view [chat-icon.screen/profile-icon-view
photo title color emoji (and (not minimized) on-edit) photo title color emoji (and (not minimized) on-edit)
(if minimized avatar-minimized-size avatar-extended-size) (if minimized avatar-minimized-size avatar-extended-size)
nil]]]) nil public-key community?]]])
[animated/view {:style (header-text) [animated/view {:style (header-text)
:pointer-events :box-none} :pointer-events :box-none}
[quo/text {:animated? true [quo/text {:animated? true

View File

@ -51,8 +51,9 @@
{:title first-name {:title first-name
:subtitle second-name :subtitle second-name
:accessibility-label :member-item :accessibility-label :member-item
:icon [chat-icon/contact-icon-contacts-tab :icon [chat-icon/profile-photo-plus-dot-view
(multiaccounts/displayed-photo member)] {:public-key public-key
:photo-path (multiaccounts/displayed-photo member)}]
:accessory (when (not= public-key my-public-key) :accessory (when (not= public-key my-public-key)
[quo/button {:on-press [quo/button {:on-press
#(>evt [:bottom-sheet/show-sheet #(>evt [:bottom-sheet/show-sheet
@ -89,17 +90,17 @@
(let [{:keys [community-id]} (<sub [:get-screen-params])] (let [{:keys [community-id]} (<sub [:get-screen-params])]
(fn [] (fn []
(let [my-public-key (<sub [:multiaccount/public-key]) (let [my-public-key (<sub [:multiaccount/public-key])
{:keys [members {:keys [permissions
permissions can-manage-users?]} (<sub [:communities/community community-id])
can-manage-users?]} (<sub [:communities/community community-id])] sorted-members (<sub [:communities/sorted-community-members
community-id])]
[:<> [:<>
[topbar/topbar {:title (i18n/label :t/community-members-title) [topbar/topbar {:title (i18n/label :t/community-members-title)
:subtitle (str (count sorted-members))}]
:subtitle (str (count members))}]
[header community-id] [header community-id]
(when (and can-manage-users? (= constants/community-on-request-access (:access permissions))) (when (and can-manage-users? (= constants/community-on-request-access (:access permissions)))
[requests-to-join community-id]) [requests-to-join community-id])
[rn/flat-list {:data (keys members) [rn/flat-list {:data (keys sorted-members)
:render-data {:community-id community-id :render-data {:community-id community-id
:my-public-key my-public-key :my-public-key my-public-key
:can-kick-users? (and can-manage-users? :can-kick-users? (and can-manage-users?

View File

@ -41,7 +41,8 @@
(get-in community [:images :large :uri])) (get-in community [:images :large :uri]))
:subtitle (if show-members-count? :subtitle (if show-members-count?
(i18n/label-pluralize members-count :t/community-members {:count members-count}) (i18n/label-pluralize members-count :t/community-members {:count members-count})
(i18n/label :t/open-membership))}) (i18n/label :t/open-membership))
:community? true})
:use-insets true} :use-insets true}
[:<> [:<>
(when-not (string/blank? description) (when-not (string/blank? description)

View File

@ -15,8 +15,9 @@
[quo/list-item [quo/list-item
{:title first-name {:title first-name
:subtitle second-name :subtitle second-name
:icon [chat-icon.screen/contact-icon-contacts-tab :icon [chat-icon.screen/profile-photo-plus-dot-view
(multiaccounts/displayed-photo contact)] {:public-key public-key
:photo-path (multiaccounts/displayed-photo contact)}]
:chevron true :chevron true
:on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}])) :on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}]))
@ -30,7 +31,7 @@
(defview contacts-list [] (defview contacts-list []
(letsubs [blocked-contacts-count [:contacts/blocked-count] (letsubs [blocked-contacts-count [:contacts/blocked-count]
contacts [:contacts/active]] sorted-contacts [:contacts/sorted-contacts]]
[react/scroll-view {:flex 1} [react/scroll-view {:flex 1}
[add-new-contact] [add-new-contact]
(when (pos? blocked-contacts-count) (when (pos? blocked-contacts-count)
@ -44,9 +45,9 @@
:accessory :text :accessory :text
:accessory-text blocked-contacts-count :accessory-text blocked-contacts-count
:on-press #(re-frame/dispatch [:navigate-to :blocked-users-list])}]]) :on-press #(re-frame/dispatch [:navigate-to :blocked-users-list])}]])
(if (seq contacts) (if (seq sorted-contacts)
[list.views/flat-list [list.views/flat-list
{:data contacts {:data sorted-contacts
:key-fn :address :key-fn :address
:render-fn contacts-list-item}] :render-fn contacts-list-item}]
[react/view {:align-items :center [react/view {:align-items :center

View File

@ -205,7 +205,8 @@
:title first-name :title first-name
:photo (multiaccounts/displayed-photo contact) :photo (multiaccounts/displayed-photo contact)
:monospace (not ens-verified) :monospace (not ens-verified)
:subtitle second-name})] :subtitle second-name
:public-key public-key})]
[react/view {:height 1 :background-color colors/gray-lighter :margin-top 8}] [react/view {:height 1 :background-color colors/gray-lighter :margin-top 8}]
[nickname-settings contact] [nickname-settings contact]
[pin-settings public-key (count pinned-messages)] [pin-settings public-key (count pinned-messages)]

View File

@ -17,7 +17,9 @@
[status-im.ui.components.profile-header.view :as profile-header] [status-im.ui.components.profile-header.view :as profile-header]
[status-im.ui.screens.profile.user.edit-picture :as edit] [status-im.ui.screens.profile.user.edit-picture :as edit]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[status-im.ethereum.stateofus :as stateofus]) [status-im.ethereum.stateofus :as stateofus]
[quo.design-system.spacing :as spacing]
[status-im.ui.screens.profile.visibility-status.views :as visibility-status])
(:require-macros [status-im.utils.views :as views])) (:require-macros [status-im.utils.views :as views]))
(views/defview share-chat-key [] (views/defview share-chat-key []
@ -64,6 +66,9 @@
chain @(re-frame/subscribe [:chain-keyword]) chain @(re-frame/subscribe [:chain-keyword])
registrar (stateofus/get-cached-registrar chain)] registrar (stateofus/get-cached-registrar chain)]
[:<> [:<>
[visibility-status/visibility-status-button
visibility-status/calculate-button-height-and-dispatch-popover]
[quo/separator {:style {:margin-top (:tiny spacing/spacing)}}]
[quo/list-item [quo/list-item
(cond-> {:title (or (when registrar preferred-name) (cond-> {:title (or (when registrar preferred-name)
(i18n/label :t/ens-usernames)) (i18n/label :t/ens-usernames))

View File

@ -0,0 +1,76 @@
(ns status-im.ui.screens.profile.visibility-status.styles
(:require [quo.design-system.colors :as colors]))
(defn visibility-status-button-container []
{:background-color (:interactive-02 @colors/theme)
:margin-left 16
:border-radius 16
:border-top-left-radius 4
:align-self :flex-start
:flex-direction :row
:align-items :center
:justify-content :center
:padding 6
:padding-right 12})
(defn visibility-status-dot [dot-color size]
{:background-color dot-color
:width size
:height size
:border-radius (/ size 2)
:border-width 1
:border-color colors/white})
(defn visibility-status-profile-dot [color size border-width margin-left]
(merge (visibility-status-dot color size)
{:margin-right 6
:margin-left margin-left
:border-width border-width}))
(defn visibility-status-text []
{:color (:text-01 @colors/theme)
:font-size 16
:text-align :center})
(defn visibility-status-subtitle []
{:color (:text-02 @colors/theme)
:font-size 16
:margin-left 22
:margin-right 6})
(defn visibility-status-option []
{:flex-direction :row
:align-items :center})
(defn visibility-status-options [scale position]
{:background-color (if (colors/dark?)
(:interactive-02 @colors/theme)
colors/white)
:border-radius 16
:border-top-left-radius 4
:justify-content :center
:align-self :flex-start
:left 16
:top -76
:padding-bottom 6
:padding-top 8
:transform [{:scaleY scale}
{:translateY position}]})
(defn visibility-status-popover-container []
{:position :absolute
:top 0
:bottom 0
:left 0
:right 0})
(defn visibility-status-popover-ios-backdrop [alpha-value]
{:flex 1
:background-color colors/black-persist
:opacity alpha-value})
(defn visibility-status-popover-child-container [window-height]
{:position :absolute
:height window-height
:left 0
:right 0})

View File

@ -0,0 +1,95 @@
(ns status-im.ui.screens.profile.visibility-status.utils
(:require [status-im.constants :as constants]
[status-im.i18n.i18n :as i18n]
[status-im.ui.screens.profile.visibility-status.styles :as styles]
[status-im.utils.handlers :refer [<sub]]
[status-im.utils.datetime :as datetime]
[quo.design-system.colors :as colors]
[clojure.string :as string]))
;; Specs:
;; :visibility-status-automatic
;; To Send - "visibility-status-automatic" status ping every 5 minutes
;; Display - Online for up to 5 minutes from the last clock, after that Offline
;; :visibility-status-always-online
;; To Send - "visibility-status-always-online" status ping every 5 minutes
;; Display - Online for up to 2 weeks from the last clock, after that Offline
;; :visibility-status-inactive
;; To Send - A single "visibility-status-inactive" status ping
;; Display - Offline forever
;; Note: Only send pings if the user interacted with the app in the last x minutes.
(def visibility-status-type-data
{constants/visibility-status-unknown
{:color colors/red
:title (i18n/label :t/error)}
constants/visibility-status-automatic
{:color colors/color-online
:title (i18n/label :t/status-automatic)
:subtitle (i18n/label :t/status-automatic-subtitle)}
constants/visibility-status-dnd
{:color colors/color-dnd
:title (i18n/label :t/status-dnd)
:subtitle (i18n/label :t/status-dnd-subtitle)}
constants/visibility-status-always-online
{:color colors/color-online
:title (i18n/label :t/status-always-online)}
constants/visibility-status-inactive
{:color colors/color-inactive
:title (i18n/label :t/status-inactive)
:subtitle (i18n/label :t/status-inactive-subtitle)}})
;; Currently, Another user is broadcasting their status updates at the rate of 5 minutes.
;; So for status-type automatic, we need to show
;; that user online a little longer than that time. (broadcast receiving delay)
(defn calculate-real-status-type-and-time-left
[{:keys [status-type clock]}]
(let [status-lifespan (if (= status-type
constants/visibility-status-automatic)
(datetime/minutes 5.05)
(datetime/weeks 2))
status-expire-time (+ (datetime/to-ms clock) status-lifespan)
time-left (- status-expire-time (datetime/timestamp))
status-type (if (or (nil? status-type)
(and
(not= status-type
constants/visibility-status-inactive)
(neg? time-left)))
constants/visibility-status-inactive
status-type)]
{:real-status-type status-type
:time-left time-left}))
(defn dot-color
[{:keys [status-type] :as visibility-status-update} my-icon?]
(if my-icon?
(if (= status-type constants/visibility-status-inactive)
colors/color-inactive colors/color-online)
(let [{:keys [real-status-type]}
(calculate-real-status-type-and-time-left visibility-status-update)]
(:color (get visibility-status-type-data real-status-type)))))
(defn my-icon? [public-key]
(or (string/blank? public-key)
(= public-key (<sub [:multiaccount/public-key]))))
(defn visibility-status-update [public-key my-icon?]
(if my-icon?
(<sub [:multiaccount/current-user-visibility-status])
(<sub [:visibility-status-updates/visibility-status-update public-key])))
(defn icon-visibility-status-dot [public-key container-size identicon?]
(let [my-icon? (my-icon? public-key)
visibility-status-update (visibility-status-update public-key my-icon?)
size (/ container-size 4)
margin (if identicon? (/ size 6) (/ size 7))
dot-color (dot-color visibility-status-update my-icon?)]
(merge (styles/visibility-status-dot dot-color size)
{:bottom margin
:right margin
:position :absolute})))
(defn visibility-status-order [public-key]
(let [my-icon? (my-icon? public-key)
visibility-status-update (visibility-status-update public-key my-icon?)
dot-color (dot-color visibility-status-update my-icon?)]
(if (= dot-color colors/color-online) 0 1)))

View File

@ -0,0 +1,200 @@
(ns status-im.ui.screens.profile.visibility-status.views
(:require-macros [status-im.utils.views :as views])
(:require ["react-native" :refer (BackHandler)]
[quo.core :as quo]
[quo.design-system.colors :as colors]
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ui.components.animation :as anim]
[status-im.ui.components.react :as react]
[status-im.utils.platform :as platform]
[status-im.utils.handlers :refer [<sub]]
[status-im.constants :as constants]
[status-im.ui.screens.profile.visibility-status.styles :as styles]
[status-im.ui.screens.profile.visibility-status.utils :as utils]))
;; === Code Related to visibility-status-button ===
(def button-ref (atom nil))
(defn dispatch-popover [top]
(re-frame/dispatch [:show-visibility-status-popover {:top top}]))
(defn dispatch-visibility-status-update [status-type]
(re-frame/dispatch
[:visibility-status-updates/delayed-visibility-status-update status-type]))
(defn calculate-button-height-and-dispatch-popover []
(.measure @button-ref
(fn [_ _ _ _ _ py]
(dispatch-popover py))))
(defn profile-visibility-status-dot [status-type color]
(let [automatic? (= status-type
constants/visibility-status-automatic)
[border-width margin-left size] (if automatic? [1 -10 12] [0 6 10])]
[:<>
(when automatic?
[rn/view {:style (styles/visibility-status-profile-dot
colors/color-inactive size border-width 6)}])
[rn/view {:style (styles/visibility-status-profile-dot
color size border-width margin-left)}]]))
(defn visibility-status-button [on-press props]
(let [logged-in? (<sub [:multiaccount/logged-in?])
{:keys [status-type]} (<sub [:multiaccount/current-user-visibility-status])
status-type (if (and logged-in? (nil? status-type))
(do
(dispatch-visibility-status-update
constants/visibility-status-automatic)
constants/visibility-status-automatic)
status-type)
{:keys [color title]} (get utils/visibility-status-type-data status-type)]
[rn/touchable-opacity
(merge
{:on-press on-press
:accessibility-label :visibility-status-button
:style (styles/visibility-status-button-container)
:ref #(reset! button-ref ^js %)} props)
[profile-visibility-status-dot status-type color]
[rn/text {:style (styles/visibility-status-text)} title]]))
;; === Code Related to visibility-status-popover ===
(def scale (anim/create-value 0))
(def position (anim/create-value 0))
(def alpha-value (anim/create-value 0))
(defn hide-options []
(anim/start
(anim/parallel
[(anim/timing scale {:toValue 0
:duration 140
:useNativeDriver true})
(anim/timing position {:toValue 50
:duration 210
:useNativeDriver true})
(anim/timing alpha-value {:toValue 0
:duration 200
:useNativeDriver true})])))
(defn show-options []
(anim/start
(anim/parallel
[(anim/timing scale {:toValue 1
:duration 210
:useNativeDriver true})
(anim/timing position {:toValue 80
:duration 70
:useNativeDriver true})
(anim/timing alpha-value {:toValue 0.4
:duration 200
:useNativeDriver true})])))
(defn status-option-pressed [request-close status-type]
(request-close)
(dispatch-visibility-status-update status-type))
(defn status-option [{:keys [request-close status-type]}]
(let [{:keys [color title subtitle]}
(get utils/visibility-status-type-data status-type)]
[rn/touchable-opacity {:style {:padding 6}
:accessibility-label :visibility-status-option
:on-press #(status-option-pressed
request-close status-type)}
[rn/view {:style (styles/visibility-status-option)}
[profile-visibility-status-dot status-type color]
[rn/text {:style (styles/visibility-status-text)} title]]
(when-not (nil? subtitle)
[rn/text {:style (styles/visibility-status-subtitle)} subtitle])]))
(defn visibility-status-options [request-close top]
[react/view {:position :absolute
:top (int top)}
[visibility-status-button request-close {:ref nil :active-opacity 1}]
[react/animated-view {:style
(styles/visibility-status-options scale position)
:accessibility-label :visibility-status-options}
[status-option
{:status-type constants/visibility-status-always-online
:request-close request-close}]
[quo/separator {:style {:margin-top 8}}]
[status-option
{:status-type constants/visibility-status-inactive
:request-close request-close}]
[quo/separator]
[status-option
{:status-type constants/visibility-status-automatic
:request-close request-close}]]])
(defn popover-view [_ window-height]
(let [clear-timeout (atom nil)
current-popover (reagent/atom nil)
update? (reagent/atom nil)
request-close (fn []
(reset! clear-timeout
(js/setTimeout
#(do (reset! current-popover nil)
(re-frame/dispatch
[:hide-visibility-status-popover]))
200))
(hide-options)
true)
on-show (fn []
(show-options)
(when platform/android?
(.removeEventListener BackHandler
"hardwareBackPress"
request-close)
(.addEventListener BackHandler
"hardwareBackPress"
request-close)))
on-hide (fn []
(when platform/android?
(.removeEventListener BackHandler
"hardwareBackPress"
request-close)))]
(reagent/create-class
{:UNSAFE_componentWillUpdate
(fn [_ [_ popover _]]
(when @clear-timeout (js/clearTimeout @clear-timeout))
(cond
@update?
(do (reset! update? false)
(on-show))
(and @current-popover popover)
(do (reset! update? true)
(js/setTimeout #(reset! current-popover popover) 600)
(hide-options))
popover
(do (reset! current-popover popover)
(on-show))
:else
(do (reset! current-popover nil)
(on-hide))))
:component-will-unmount on-hide
:reagent-render
(fn []
(when @current-popover
(let [{:keys [top]} @current-popover]
[react/view
{:style (styles/visibility-status-popover-container)}
(when platform/ios?
[react/animated-view
{:style (styles/visibility-status-popover-ios-backdrop
alpha-value)}])
[react/view
{:style (styles/visibility-status-popover-child-container
window-height)}
[react/touchable-highlight
{:style {:flex 1}
:on-press request-close}
[visibility-status-options request-close top]]]])))})))
(views/defview visibility-status-popover []
(views/letsubs [popover [:visibility-status-popover/popover]
{window-height :height} [:dimensions/window]]
[popover-view popover window-height]))

View File

@ -5,6 +5,7 @@
[status-im.ui.screens.screens :as screens] [status-im.ui.screens.screens :as screens]
[oops.core :refer [oget]] [oops.core :refer [oget]]
[status-im.ui.screens.popover.views :as popover] [status-im.ui.screens.popover.views :as popover]
[status-im.ui.screens.profile.visibility-status.views :as visibility-status-views]
[status-im.ui.screens.bottom-sheets.views :as bottom-sheets] [status-im.ui.screens.bottom-sheets.views :as bottom-sheets]
[status-im.ui.screens.signing.views :as signing] [status-im.ui.screens.signing.views :as signing]
[status-im.ui.screens.wallet.send.views :as wallet.send.views] [status-im.ui.screens.wallet.send.views :as wallet.send.views]
@ -86,6 +87,16 @@
(when js/goog.DEBUG (when js/goog.DEBUG
[reloader/reload-view])]))) [reloader/reload-view])])))
(def visibility-status-popover-comp
(reagent/reactify-component
(fn []
^{:key (str "visibility-status-popover" @reloader/cnt)}
[react/safe-area-provider
[inactive]
[visibility-status-views/visibility-status-popover]
(when js/goog.DEBUG
[reloader/reload-view])])))
(def sheet-comp (def sheet-comp
(reagent/reactify-component (reagent/reactify-component
(fn [] (fn []

View File

@ -20,6 +20,8 @@
(def hour (* 60 minute)) (def hour (* 60 minute))
(def day (* 24 hour)) (def day (* 24 hour))
(def week (* 7 day)) (def week (* 7 day))
(defn weeks [w]
(* w week))
(def units [{:name :t/datetime-second-short :limit 60 :in-second 1} (def units [{:name :t/datetime-second-short :limit 60 :in-second 1}
{:name :t/datetime-minute-short :limit 3600 :in-second 60} {:name :t/datetime-minute-short :limit 3600 :in-second 60}
{:name :t/datetime-hour-short :limit 86400 :in-second 3600} {:name :t/datetime-hour-short :limit 86400 :in-second 3600}
@ -144,6 +146,9 @@
(defn timestamp [] (defn timestamp []
(inst-ms (js/Date.))) (inst-ms (js/Date.)))
(defn timestamp-sec []
(int (/ (timestamp) 1000)))
(defn timestamp->year-month-day-date [ms] (defn timestamp->year-month-day-date [ms]
(unparse (:year-month-day formatters) (to-date ms))) (unparse (:year-month-day formatters) (to-date ms)))
@ -167,3 +172,6 @@
(str day (or (s (mod (- m 20) 10)) (str day (or (s (mod (- m 20) 10))
(s m) (s m)
(s 0))))) (s 0)))))
(defn to-ms [sec]
(* 1000 sec))

View File

@ -0,0 +1,21 @@
(ns status-im.visibility-status-popover.core
(:require [status-im.utils.fx :as fx]))
(fx/defn show-visibility-status-popover
{:events [:show-visibility-status-popover]}
[_ value]
{:show-visibility-status-popover nil
:dispatch-later [{:ms 250
:dispatch [:show-visibility-status-popover-db value]}]
:dismiss-keyboard nil})
(fx/defn show-visibility-status-popover-db
{:events [:show-visibility-status-popover-db]}
[{:keys [db]} value]
{:db (assoc db :visibility-status-popover/popover value)})
(fx/defn hide-visibility-status-popover
{:events [:hide-visibility-status-popover]}
[{:keys [db]}]
{:db (dissoc db :visibility-status-popover/popover)
:hide-visibility-status-popover nil})

View File

@ -0,0 +1,179 @@
(ns status-im.visibility-status-updates.core
(:require [status-im.data-store.visibility-status-updates :as visibility-status-updates-store]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.utils.fx :as fx]
[status-im.constants :as constants]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.utils.datetime :as datetime]
[status-im.ui.screens.profile.visibility-status.utils :as utils]))
(defn valid-status-type? [status-type]
(some #(= status-type %)
(list constants/visibility-status-always-online
constants/visibility-status-inactive
constants/visibility-status-automatic)))
(defn process-visibility-status-update
[acc {:keys [public-key clock] :as visibility-status-update}]
(let [{:keys [real-status-type time-left]}
(utils/calculate-real-status-type-and-time-left visibility-status-update)]
(cond-> (assoc-in acc
[:visibility-status-updates public-key]
visibility-status-update)
(= real-status-type constants/visibility-status-automatic)
(update :dispatch-later
#(conj % {:ms time-left
:dispatch [:visibility-status-updates/timeout-user-online-status
public-key clock]})))))
(fx/defn load-visibility-status-updates
{:events [:visibility-status-updates/visibility-status-updates-loaded]}
[{:keys [db]} visibility-status-updates-loaded]
(let [{:keys [visibility-status-updates dispatch-later]}
(reduce (fn [acc visibility-status-update-loaded]
(let [{:keys [public-key] :as visibility-status-update}
(visibility-status-updates-store/<-rpc
visibility-status-update-loaded)]
(process-visibility-status-update acc visibility-status-update)))
{} visibility-status-updates-loaded)]
(merge {:db (assoc db :visibility-status-updates visibility-status-updates)}
(when dispatch-later {:utils/dispatch-later dispatch-later}))))
(defn handle-my-visibility-status-updates
[acc my-current-status clock visibility-status-update]
(let [status-type (:status-type visibility-status-update)]
(if (and (valid-status-type? status-type)
(or
(nil? my-current-status)
(> clock (:clock my-current-status))))
(-> acc
(update :current-user-visibility-status
merge {:clock clock :status-type status-type})
(assoc :dispatch [:visibility-status-updates/send-visibility-status-updates?
(not= status-type constants/visibility-status-inactive)]))
acc)))
(defn handle-other-visibility-status-updates
[acc public-key clock visibility-status-update]
(let [status-type (:status-type visibility-status-update)
visibility-status-update-old
(get-in acc [:visibility-status-updates public-key])]
(if (and (valid-status-type? status-type)
(or
(nil? visibility-status-update-old)
(> clock (:clock visibility-status-update-old))))
(process-visibility-status-update acc visibility-status-update)
acc)))
(fx/defn handle-visibility-status-updates
[{:keys [db]} visibility-status-updates-received]
(let [visibility-status-updates-old (get db :visibility-status-updates {})
my-public-key (get-in
db [:multiaccount :public-key])
my-current-status (get-in
db [:multiaccount :current-user-visibility-status])
{:keys [visibility-status-updates
current-user-visibility-status
dispatch dispatch-later]}
(reduce (fn [acc visibility-status-update-received]
(let [{:keys [public-key clock] :as visibility-status-update}
(visibility-status-updates-store/<-rpc
visibility-status-update-received)]
(if (= public-key my-public-key)
(handle-my-visibility-status-updates
acc my-current-status clock visibility-status-update)
(handle-other-visibility-status-updates
acc public-key clock visibility-status-update))))
{:visibility-status-updates visibility-status-updates-old
:current-user-visibility-status my-current-status}
visibility-status-updates-received)]
(merge {:db (-> db
(update-in [:visibility-status-updates]
merge visibility-status-updates)
(update-in [:multiaccount :current-user-visibility-status]
merge current-user-visibility-status))}
(when dispatch {:dispatch dispatch})
(when dispatch-later {:utils/dispatch-later dispatch-later}))))
(fx/defn update-visibility-status
{:events [:visibility-status-updates/update-visibility-status]}
[{:keys [db] :as cofx} status-type]
{:db (update-in db [:multiaccount :current-user-visibility-status]
merge {:status-type status-type
:clock (datetime/timestamp-sec)})
::json-rpc/call [{:method "wakuext_setUserStatus"
:params [status-type ""]
:on-success #()}]})
(fx/defn send-visibility-status-updates?
{:events [:visibility-status-updates/send-visibility-status-updates?]}
[cofx val]
(multiaccounts.update/multiaccount-update cofx
:send-status-updates? val
{}))
(fx/defn visibility-status-option-pressed
{:events [:visibility-status-updates/visibility-status-option-pressed]}
[{:keys [db] :as cofx} status-type]
(let [events-to-dispatch-later
(cond-> [{:ms 10 :dispatch
[:visibility-status-updates/update-visibility-status
status-type]}]
(and
(= status-type constants/visibility-status-inactive)
(> (:peers-count db) 0))
;; Disable broadcasting further updates
(conj {:ms 1000
:dispatch
[:visibility-status-updates/send-visibility-status-updates? false]}))]
(fx/merge cofx
{:dispatch-later events-to-dispatch-later}
;; Enable broadcasting for current broadcast
(send-visibility-status-updates? true))))
(fx/defn timeout-user-online-status
{:events [:visibility-status-updates/timeout-user-online-status]}
[{:keys [db]} public-key clock]
(let [current-clock (get-in db [:visibility-status-updates public-key :clock] 0)]
(when (= current-clock clock)
{:db (update-in db [:visibility-status-updates public-key]
merge {:status-type constants/visibility-status-inactive})})))
(fx/defn delayed-visibility-status-update
{:events [:visibility-status-updates/delayed-visibility-status-update]}
[{:keys [db]} status-type]
{:dispatch-later
[{:ms 200
:dispatch
[:visibility-status-updates/visibility-status-option-pressed status-type]}]})
(fx/defn peers-summary-change
[{:keys [db] :as cofx} peers-count]
(let [send-visibility-status-updates?
(get-in db [:multiaccount :send-status-updates?])
status-type
(get-in db [:multiaccount :current-user-visibility-status :status-type])]
(when (and
(> peers-count 0)
send-visibility-status-updates?
(= status-type constants/visibility-status-inactive))
(fx/merge cofx
{:dispatch-later [{:ms 1000 :dispatch
[:visibility-status-updates/send-visibility-status-updates? false]}]
:db (assoc-in db [:multiaccount :send-status-updates?] false)}
(update-visibility-status status-type)))))
(fx/defn sync-visibility-status-update
[{:keys [db] :as cofx} visibility-status-update-received]
(let [my-current-status (get-in db [:multiaccount :current-user-visibility-status])
{:keys [status-type clock]} (visibility-status-updates-store/<-rpc
visibility-status-update-received)]
(when (and (valid-status-type? status-type)
(or
(nil? my-current-status)
(> clock (:clock my-current-status))))
(fx/merge cofx
{:db (update-in db [:multiaccount :current-user-visibility-status]
merge {:clock clock :status-type status-type})}
(send-visibility-status-updates?
(not= status-type constants/visibility-status-inactive))))))

View File

@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>", "_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v0.89.14", "version": "v0.89.15",
"commit-sha1": "c20e8ebdeffd14a881d8092ee64e5180ad53449e", "commit-sha1": "9693d59e614899557e8b2f4f19ad541bbad3be39",
"src-sha256": "0jbmgj0m1hv1nx3frbzs7lsn8nqspsir5kpzn8lldfgkfgpv96h7" "src-sha256": "19nl5g5vhrsm510mi0nddi5n67h6z27nx6vixk72bwyvlpz22sij"
} }

View File

@ -1674,5 +1674,12 @@
"disable-later-in-settings": "You can disable this later in Settings", "disable-later-in-settings": "You can disable this later in Settings",
"use-as-profile-picture": "Use as profile picture", "use-as-profile-picture": "Use as profile picture",
"view-on-opensea": "View on OpenSea", "view-on-opensea": "View on OpenSea",
"profile-picture-updated": "Profile picture updated" "profile-picture-updated": "Profile picture updated",
"status-automatic": "Automatic",
"status-automatic-subtitle": "Set status automatically",
"status-dnd": "Do not disturb",
"status-dnd-subtitle": "Mutes all notifications",
"status-always-online": "Always Online",
"status-inactive": "Inactive",
"status-inactive-subtitle": "Hides your online status"
} }