my status

Signed-off-by: andrey <motor4ik@gmail.com>
This commit is contained in:
andrey 2020-10-02 11:53:02 +02:00
parent 973bdb61b3
commit eae66c967e
No known key found for this signature in database
GPG Key ID: 89B67245FD2F0272
39 changed files with 783 additions and 439 deletions

View File

@ -64,7 +64,7 @@
:justify-content :space-between})}] :justify-content :space-between})}]
children)) children))
(defn- icon-column (defn icon-column
[{:keys [icon icon-bg-color icon-color size icon-container-style]}] [{:keys [icon icon-bg-color icon-color size icon-container-style]}]
(when icon (when icon
(let [icon-size (size->icon-size size)] (let [icon-size (size->icon-size size)]

View File

@ -162,9 +162,10 @@
(fx/defn add-public-chat (fx/defn add-public-chat
"Adds new public group chat to db" "Adds new public group chat to db"
[cofx topic] [cofx topic profile-public-key]
(upsert-chat cofx (upsert-chat cofx
{:chat-id topic {:chat-id topic
:profile-public-key profile-public-key
:is-active true :is-active true
:name topic :name topic
:chat-name (str "#" topic) :chat-name (str "#" topic)
@ -243,8 +244,9 @@
(fx/defn navigate-to-chat (fx/defn navigate-to-chat
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data" "Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
[cofx chat-id] [{db :db :as cofx} chat-id]
(fx/merge cofx (fx/merge cofx
{:db (assoc db :inactive-chat-id chat-id)}
(preload-chat-data chat-id) (preload-chat-data chat-id)
(navigation/navigate-to-cofx :chat-stack {:screen :chat}))) (navigation/navigate-to-cofx :chat-stack {:screen :chat})))
@ -260,15 +262,18 @@
(transport.filters/load-chat chat-id) (transport.filters/load-chat chat-id)
(navigate-to-chat chat-id)))) (navigate-to-chat chat-id))))
(defn profile-chat-topic [public-key]
(str "@" public-key))
(fx/defn start-public-chat (fx/defn start-public-chat
"Starts a new public chat" "Starts a new public chat"
[cofx topic {:keys [dont-navigate?]}] [cofx topic {:keys [dont-navigate? profile-public-key]}]
(if (new-public-chat.db/valid-topic? topic) (if (or (new-public-chat.db/valid-topic? topic) profile-public-key)
(if (active-chat? cofx topic) (if (active-chat? cofx topic)
(when-not dont-navigate? (when-not dont-navigate?
(navigate-to-chat cofx topic)) (navigate-to-chat cofx topic))
(fx/merge cofx (fx/merge cofx
(add-public-chat topic) (add-public-chat topic profile-public-key)
(transport.filters/load-chat topic) (transport.filters/load-chat topic)
#(when-not dont-navigate? #(when-not dont-navigate?
(navigate-to-chat % topic)))) (navigate-to-chat % topic))))

View File

@ -142,6 +142,15 @@
:image-path (utils/safe-replace image-path #"file://" "") :image-path (utils/safe-replace image-path #"file://" "")
:text (i18n/label :t/update-to-see-image)}))))) :text (i18n/label :t/update-to-see-image)})))))
(fx/defn send-my-status-message
"when not empty, proceed by sending text message with public key topic"
{:events [:profile.ui/send-my-status-message]}
[{{:keys [current-chat-id] :as db} :db :as cofx}]
(let [{:keys [input-text]} (get-in db [:chat/inputs current-chat-id])]
(fx/merge cofx
(send-image)
(send-plain-text-message input-text current-chat-id))))
(fx/defn send-audio-message (fx/defn send-audio-message
[cofx audio-path duration current-chat-id] [cofx audio-path duration current-chat-id]
(when-not (string/blank? audio-path) (when-not (string/blank? audio-path)

View File

@ -28,7 +28,7 @@
add-timestamp)) add-timestamp))
;; any message that comes after this amount of ms will be grouped separately ;; any message that comes after this amount of ms will be grouped separately
(def ^:private group-ms 60000) (def ^:private group-ms 300000)
(defn same-group? (defn same-group?
"Whether a message is in the same group as the one after it. "Whether a message is in the same group as the one after it.

View File

@ -49,7 +49,7 @@
(with-redefs [gfycat/generate-gfy (constantly "generated") (with-redefs [gfycat/generate-gfy (constantly "generated")
identicon/identicon (constantly "generated")] identicon/identicon (constantly "generated")]
(let [topic "topic" (let [topic "topic"
fx (chat/add-public-chat {:db {}} topic) fx (chat/add-public-chat {:db {}} topic nil)
chat (get-in fx [:db :chats topic])] chat (get-in fx [:db :chats topic])]
(testing "it sets the name" (testing "it sets the name"
(is (= topic (:name chat)))) (is (= topic (:name chat))))

View File

@ -7,12 +7,6 @@
[status-im.navigation :as navigation] [status-im.navigation :as navigation]
[status-im.utils.fx :as fx])) [status-im.utils.fx :as fx]))
(fx/defn remove-current-chat-id
[{:keys [db] :as cofx}]
(fx/merge cofx
{:db (dissoc db :current-chat-id)}
(navigation/navigate-to-cofx :home {})))
(fx/defn clean-up-chat (fx/defn clean-up-chat
[{:keys [db] :as cofx} [{:keys [db] :as cofx}
public-key public-key
@ -48,7 +42,7 @@
public-key) public-key)
(assoc :last-updated now) (assoc :last-updated now)
(update :system-tags (fnil conj #{}) :contact/blocked)) (update :system-tags (fnil conj #{}) :contact/blocked))
from-one-to-one-chat? (not (get-in db [:chats (:current-chat-id db) :group-chat]))] from-one-to-one-chat? (not (get-in db [:chats (:inactive-chat-id db) :group-chat]))]
(fx/merge cofx (fx/merge cofx
{:db (-> db {:db (-> db
;; add the contact to blocked contacts ;; add the contact to blocked contacts
@ -61,7 +55,7 @@
(re-frame/dispatch [:hide-popover]))) (re-frame/dispatch [:hide-popover])))
;; reset navigation to avoid going back to non existing one to one chat ;; reset navigation to avoid going back to non existing one to one chat
(if from-one-to-one-chat? (if from-one-to-one-chat?
remove-current-chat-id (navigation/navigate-to-cofx :home {})
(navigation/navigate-back))))) (navigation/navigate-back)))))
(fx/defn unblock-contact (fx/defn unblock-contact

View File

@ -8,10 +8,12 @@
(def one-to-one-chat-type 1) (def one-to-one-chat-type 1)
(def public-chat-type 2) (def public-chat-type 2)
(def private-group-chat-type 3) (def private-group-chat-type 3)
(def profile-chat-type 4)
(defn type->rpc [{:keys [public? group-chat] :as chat}] (defn type->rpc [{:keys [public? group-chat profile-public-key] :as chat}]
(assoc chat :chatType (cond (assoc chat :chatType (cond
public? public-chat-type public? public-chat-type
profile-public-key profile-chat-type
group-chat private-group-chat-type group-chat private-group-chat-type
:else one-to-one-chat-type))) :else one-to-one-chat-type)))
@ -21,6 +23,7 @@
:chat-name (str "#" name) :chat-name (str "#" name)
:public? true :public? true
:group-chat true) :group-chat true)
(= profile-chat-type chatType) (assoc chat :public? true)
(= private-group-chat-type chatType) (assoc chat (= private-group-chat-type chatType) (assoc chat
:chat-name name :chat-name name
:public? false :public? false
@ -72,7 +75,8 @@
:last-message :lastMessage :last-message :lastMessage
:deleted-at-clock-value :deletedAtClockValue :deleted-at-clock-value :deletedAtClockValue
:is-active :active :is-active :active
:last-clock-value :lastClockValue}) :last-clock-value :lastClockValue
:profile-public-key :profile})
(dissoc :public? :group-chat :messages (dissoc :public? :group-chat :messages
:might-have-join-time-messages? :might-have-join-time-messages?
:loaded-unviewed-messages-ids :loaded-unviewed-messages-ids
@ -89,7 +93,8 @@
:lastMessage :last-message :lastMessage :last-message
:active :is-active :active :is-active
:lastClockValue :last-clock-value :lastClockValue :last-clock-value
:invitationAdmin :invitation-admin}) :invitationAdmin :invitation-admin
:profile :profile-public-key})
(update :last-message #(when % (messages/<-rpc %))) (update :last-message #(when % (messages/<-rpc %)))
(dissoc :chatType :members))) (dissoc :chatType :members)))

View File

@ -1245,10 +1245,24 @@
(fn [{:keys [db]} [_ dimensions]] (fn [{:keys [db]} [_ dimensions]]
{:db (assoc db :dimensions/window (dimensions/window dimensions))})) {:db (assoc db :dimensions/window (dimensions/window dimensions))}))
(fx/defn reset-current-profile-chat [{:keys [db] :as cofx} public-key]
(let [chat-id (chat/profile-chat-topic public-key)]
(when-not (= (:current-chat-id db) chat-id)
(fx/merge cofx
(chat/start-public-chat chat-id {:dont-navigate? true :profile-public-key public-key})
(chat/offload-all-messages)
(chat/preload-chat-data chat-id)))))
(fx/defn reset-current-chat [{:keys [db] :as cofx} chat-id]
(when-not (= (:current-chat-id db) chat-id)
(fx/merge cofx
(chat/offload-all-messages)
(chat/preload-chat-data chat-id))))
;; NOTE: Will be removed with the keycard PR ;; NOTE: Will be removed with the keycard PR
(handlers/register-handler-fx (handlers/register-handler-fx
:screens/on-will-focus :screens/on-will-focus
(fn [cofx [_ view-id]] (fn [{:keys [db] :as cofx} [_ view-id]]
(fx/merge cofx (fx/merge cofx
#(case view-id #(case view-id
:keycard-settings (keycard/settings-screen-did-load %) :keycard-settings (keycard/settings-screen-did-load %)
@ -1257,10 +1271,28 @@
:keycard-login-pin (keycard/enter-pin-screen-did-load %) :keycard-login-pin (keycard/enter-pin-screen-did-load %)
:add-new-account-pin (keycard/enter-pin-screen-did-load %) :add-new-account-pin (keycard/enter-pin-screen-did-load %)
:keycard-authentication-method (keycard/authentication-method-screen-did-load %) :keycard-authentication-method (keycard/authentication-method-screen-did-load %)
;; We need this as if you click on universal-links you transition (:chat :group-chat-profile) (reset-current-chat % (get db :inactive-chat-id))
;; from chat to chat, and therefore we won't be loading new
;; messages
:chat (chat.loading/load-messages %)
:multiaccounts (keycard/multiaccounts-screen-did-load %) :multiaccounts (keycard/multiaccounts-screen-did-load %)
(:wallet-stack :wallet) (wallet.events/wallet-will-focus %) (:wallet-stack :wallet) (wallet.events/wallet-will-focus %)
(:my-profile :profile-stack)
(reset-current-profile-chat % (get-in % [:db :multiaccount :public-key]))
:profile
(reset-current-profile-chat % (get-in % [:db :contacts/identity]))
nil)))) nil))))
(handlers/register-handler-fx
:screens/tab-will-change
(fn [{:keys [db] :as cofx} [_ view-id]]
(fx/merge cofx
#(case view-id
;;when we back to chat we want to show inactive chat
:chat
(reset-current-chat % (get db :inactive-chat-id))
(:my-profile :profile-stack)
(reset-current-profile-chat % (get-in % [:db :multiaccount :public-key]))
:profile
(reset-current-profile-chat % (get-in % [:db :contacts/identity]))
nil))))

View File

@ -63,10 +63,10 @@
:params {:screen :my-profile}}) :params {:screen :my-profile}})
(and public-key (not own)) (and public-key (not own))
(navigation/navigate-to-cofx (assoc-in cofx [:db :contacts/identity] public-key) (fx/merge cofx
:tabs {:db (assoc db :contacts/identity public-key)
{:screen :chat-stack :dispatch [:navigate-to :profile]}
:params {:screen :profile}}) (navigation/navigate-back))
:else :else
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code) {:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)

View File

@ -123,6 +123,7 @@
(reg-root-key-sub :chats/mention-suggestions :chats/mention-suggestions) (reg-root-key-sub :chats/mention-suggestions :chats/mention-suggestions)
(reg-root-key-sub :chats/cursor :chats/cursor) (reg-root-key-sub :chats/cursor :chats/cursor)
(reg-root-key-sub :chats/input-with-mentions :chats/input-with-mentions) (reg-root-key-sub :chats/input-with-mentions :chats/input-with-mentions)
(reg-root-key-sub :inactive-chat-id :inactive-chat-id)
;;browser ;;browser
(reg-root-key-sub :browsers :browser/browsers) (reg-root-key-sub :browsers :browser/browsers)
(reg-root-key-sub :browser/options :browser/options) (reg-root-key-sub :browser/options :browser/options)
@ -612,8 +613,8 @@
:chats/active-chats :chats/active-chats
:<- [::chats] :<- [::chats]
(fn [chats] (fn [chats]
(reduce-kv (fn [acc id {:keys [is-active] :as chat}] (reduce-kv (fn [acc id {:keys [is-active profile-public-key] :as chat}]
(if is-active (if (and is-active (not profile-public-key))
(assoc acc id chat) (assoc acc id chat)
acc)) acc))
{} {}
@ -650,9 +651,10 @@
:chats/current-chat :chats/current-chat
:<- [:chats/current-raw-chat] :<- [:chats/current-raw-chat]
:<- [:multiaccount/public-key] :<- [:multiaccount/public-key]
:<- [:inactive-chat-id]
(fn [[{:keys [group-chat] :as current-chat} (fn [[{:keys [group-chat] :as current-chat}
my-public-key]] my-public-key inactive-chat-id]]
(when current-chat (when (and current-chat (= (:chat-id current-chat) inactive-chat-id))
(cond-> current-chat (cond-> current-chat
(chat.models/public-chat? current-chat) (chat.models/public-chat? current-chat)
(assoc :show-input? true) (assoc :show-input? true)
@ -812,7 +814,7 @@
(re-frame/reg-sub (re-frame/reg-sub
:chats/sending-image :chats/sending-image
:<- [:chats/current-chat] :<- [:chats/current-raw-chat]
(fn [{:keys [metadata]}] (fn [{:keys [metadata]}]
(get-in metadata [:sending-image]))) (get-in metadata [:sending-image])))

View File

@ -12,7 +12,9 @@
[taoensso.timbre :as log])) [taoensso.timbre :as log]))
(defn is-public-key? [k] (defn is-public-key? [k]
(string/starts-with? k "0x")) (and
(string? k)
(string/starts-with? k "0x")))
(defn load-filters-rpc [chats on-success on-failure] (defn load-filters-rpc [chats on-success on-failure]
(json-rpc/call {:method (json-rpc/call-ext-method "loadFilters") (json-rpc/call {:method (json-rpc/call-ext-method "loadFilters")

View File

@ -0,0 +1,41 @@
(ns status-im.ui.components.plus-button
(:require [status-im.ui.components.colors :as colors]
[quo.core :as quo]
[status-im.ui.components.react :as react]
[status-im.ui.components.icons.vector-icons :as icons]))
(def action-button-container
{:position :absolute
:z-index 2
:align-items :center
:justify-content :center
:left 0
:right 0
:bottom 16
:height 40})
(defn action-button []
{:width 40
:height 40
:background-color colors/blue
:border-radius 20
:align-items :center
:justify-content :center
:shadow-offset {:width 0 :height 1}
:shadow-radius 6
:shadow-opacity 1
:shadow-color (if (colors/dark?)
"rgba(0, 0, 0, 0.75)"
"rgba(0, 12, 63, 0.2)")
:elevation 2})
(defn plus-button [{:keys [on-press loading accessibility-label]}]
[react/view action-button-container
[quo/button {:type :scale
:accessibility-label (or accessibility-label :plus-button)
:on-press on-press}
[react/view (action-button)
(if loading
[react/activity-indicator {:color colors/white-persist
:animating true}]
[icons/icon :main-icons/add {:color colors/white-persist}])]]])

View File

@ -12,8 +12,9 @@
(def subtitle-margin 4) (def subtitle-margin 4)
(defn container-style [{:keys [animation minimized]}] (defn container-style [{:keys [animation minimized]}]
(merge {:flex-direction :row (merge {:flex-direction :row
:align-items :center} :padding-vertical 4
:align-items :center}
(if-not minimized (if-not minimized
(:base spacing/padding-horizontal) (:base spacing/padding-horizontal)
{:opacity animation}))) {:opacity animation})))
@ -36,7 +37,8 @@
(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-press monospace]}] (defn extended-header [{:keys [title photo color subtitle subtitle-icon on-press monospace bottom-separator]
: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}]
@ -78,5 +80,5 @@
subtitle]])]] subtitle]])]]
(when-not minimized (when-not minimized
[animated/view {:pointer-events :none [animated/view {:pointer-events :none
:style (header-bottom-separator)}])]])))) :style (when bottom-separator (header-bottom-separator))}])]]))))

View File

@ -75,7 +75,7 @@
(def tabs (def tabs
(reagent/adapt-react-class (reagent/adapt-react-class
(fn [props] (fn [props]
(let [{:keys [navigate index route]} (bean props) (let [{:keys [navigate index route state]} (bean props)
{:keys [keyboard-shown] {:keys [keyboard-shown]
:or {keyboard-shown false}} (when platform/android? (rn/use-keyboard)) :or {keyboard-shown false}} (when platform/android? (rn/use-keyboard))
{:keys [bottom]} (safe-area/use-safe-area) {:keys [bottom]} (safe-area/use-safe-area)
@ -99,7 +99,10 @@
[tab [tab
{:icon icon {:icon icon
:label title :label title
:on-press #(navigate (name nav-stack)) :on-press #(let [view-id (navigation/get-index-route-name route-index (bean state))]
(re-frame/dispatch-sync [:screens/tab-will-change view-id])
(reagent/flush)
(navigate (name nav-stack)))
:accessibility-label accessibility-label :accessibility-label accessibility-label
:count-subscription count-subscription :count-subscription count-subscription
:active? (= (str index) (str route-index)) :active? (= (str index) (str route-index))
@ -113,5 +116,6 @@
index (get state :index)] index (get state :index)]
(reagent/as-element (reagent/as-element
[tabs {:navigate navigate [tabs {:navigate navigate
:state (oget props "state")
:route (navigation/get-active-route-name state) :route (navigation/get-active-route-name state)
:index index}]))) :index index}])))

View File

@ -0,0 +1,15 @@
(ns status-im.ui.components.tabs
(:require [status-im.ui.components.react :as react]
[status-im.ui.components.colors :as colors]))
(defn tab-title [state key label active?]
[react/view {:align-items :center}
[react/touchable-highlight {:on-press #(swap! state assoc :tab key)
:underlay-color colors/gray-lighter
:accessibility-label (str label "-item-button")
:style {:border-radius 8}}
[react/view {:padding-horizontal 12 :padding-vertical 8}
[react/text {:style {:font-weight "500" :color (if active? colors/blue colors/gray) :line-height 22}}
label]]]
(when active?
[react/view {:width 24 :height 3 :border-radius 4 :background-color colors/blue}])])

View File

@ -95,7 +95,7 @@
(if new-contact? (if new-contact?
(fx/merge cofx (fx/merge cofx
(contact/add-contact chat-key nil) (contact/add-contact chat-key nil)
(navigation/navigate-to-cofx :contacts-list {})) (navigation/navigate-to-cofx :my-profile {}))
(chat/start-chat cofx chat-key)) (chat/start-chat cofx chat-key))
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code) {:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (get-validation-label validation-result) :content (get-validation-label validation-result)

View File

@ -271,7 +271,6 @@
(js/setTimeout #(on-long-press-fn on-long-press message content) 200)) (js/setTimeout #(on-long-press-fn on-long-press message content) 200))
(on-long-press-fn on-long-press message content)))}) (on-long-press-fn on-long-press message content)))})
[react/view (assoc (style/message-view message) [react/view (assoc (style/message-view message)
:remove-clipped-subviews (not outgoing)
:max-height (when-not (or outgoing modal) :max-height (when-not (or outgoing modal)
(if @collapsible? (if @collapsible?
(if @collapsed? message-height-px nil) (if @collapsed? message-height-px nil)

View File

@ -159,7 +159,7 @@
:accessibility-label :delete-transaccent-button :accessibility-label :delete-transaccent-button
:on-press #(hide-sheet-and-dispatch [:chat.ui/delete-message chat-id message-id])}]])) :on-press #(hide-sheet-and-dispatch [:chat.ui/delete-message chat-id message-id])}]]))
(defn image-long-press [{:keys [content identicon from outgoing] :as message} from-preview?] (defn image-long-press [{:keys [content identicon from outgoing cant-be-replied] :as message} from-preview?]
(fn [] (fn []
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])] (let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
[react/view [react/view
@ -177,14 +177,15 @@
(when from-preview? (when from-preview?
(re-frame/dispatch [:navigate-back])) (re-frame/dispatch [:navigate-back]))
(hide-sheet-and-dispatch [:chat.ui/show-profile from]))}]) (hide-sheet-and-dispatch [:chat.ui/show-profile from]))}])
[quo/list-item (when-not cant-be-replied
{:theme :accent [quo/list-item
:title (i18n/label :t/message-reply) {:theme :accent
:icon :main-icons/reply :title (i18n/label :t/message-reply)
:on-press #(do :icon :main-icons/reply
(when from-preview? :on-press #(do
(re-frame/dispatch [:navigate-back])) (when from-preview?
(hide-sheet-and-dispatch [:chat.ui/reply-to-message message]))}] (re-frame/dispatch [:navigate-back]))
(hide-sheet-and-dispatch [:chat.ui/reply-to-message message]))}])
;; we have only base64 string for image, so we need to find a way how to copy it ;; we have only base64 string for image, so we need to find a way how to copy it
#_[quo/list-item #_[quo/list-item
{:theme :accent {:theme :accent

View File

@ -8,7 +8,7 @@
:height 48 :height 48
:align-items :center :align-items :center
:justify-content :center :justify-content :center
:border-color colors/black-transparent :border-color colors/gray-lighter
:border-top-width 1 :border-top-width 1
:border-bottom-width 1}) :border-bottom-width 1})

View File

@ -281,36 +281,37 @@
(fn [] (fn []
(let [{:keys [chat-id show-input? group-chat admins invitation-admin] :as current-chat} (let [{:keys [chat-id show-input? group-chat admins invitation-admin] :as current-chat}
@(re-frame/subscribe [:chats/current-chat])] @(re-frame/subscribe [:chats/current-chat])]
[react/view {:style {:flex 1}} (when current-chat
[connectivity/connectivity
[topbar]
[react/view {:style {:flex 1}} [react/view {:style {:flex 1}}
(if group-chat [connectivity/connectivity
[invitation-requests chat-id admins] [topbar]
[add-contact-bar chat-id]) [react/view {:style {:flex 1}}
[messages-view {:chat current-chat (if group-chat
:bottom-space (max @bottom-space @panel-space) [invitation-requests chat-id admins]
:pan-responder pan-responder [add-contact-bar chat-id])
:space-keeper space-keeper}]]] [messages-view {:chat current-chat
(when (and group-chat invitation-admin) :bottom-space (max @bottom-space @panel-space)
[accessory/view {:y position-y :pan-responder pan-responder
:on-update-inset on-update} :space-keeper space-keeper}]]]
[invitation-bar chat-id]]) (when (and group-chat invitation-admin)
;; NOTE(rasom): on android we have to place `autocomplete-mentions` [accessory/view {:y position-y
;; outside `accessory/view` because otherwise :keyboardShouldPersistTaps :on-update-inset on-update}
;; :always doesn't work and keyboard is hidden on pressing suggestion. [invitation-bar chat-id]])
;; Scrolling of suggestions doesn't work neither in this case. ;; NOTE(rasom): on android we have to place `autocomplete-mentions`
(when platform/android? ;; outside `accessory/view` because otherwise :keyboardShouldPersistTaps
[components/autocomplete-mentions text-input-ref]) ;; :always doesn't work and keyboard is hidden on pressing suggestion.
(when show-input? ;; Scrolling of suggestions doesn't work neither in this case.
[accessory/view {:y position-y (when platform/android?
:pan-state pan-state [components/autocomplete-mentions text-input-ref])
:has-panel (boolean @active-panel) (when show-input?
:on-close #(set-active-panel nil) [accessory/view {:y position-y
:on-update-inset on-update} :pan-state pan-state
[components/chat-toolbar :has-panel (boolean @active-panel)
{:active-panel @active-panel :on-close #(set-active-panel nil)
:set-active-panel set-active-panel :on-update-inset on-update}
:text-input-ref text-input-ref [components/chat-toolbar
:on-text-change on-text-change}] {:active-panel @active-panel
[bottom-sheet @active-panel]])])))) :set-active-panel set-active-panel
:text-input-ref text-input-ref
:on-text-change on-text-change}]
[bottom-sheet @active-panel]])])))))

View File

@ -6,9 +6,9 @@
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen] [status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.ui.components.invite.views :as invite]
[quo.core :as quo] [quo.core :as quo]
[status-im.ui.components.topbar :as topbar]) [status-im.ui.components.topbar :as topbar]
[status-im.ui.components.icons.vector-icons :as icons])
(:require-macros [status-im.utils.views :refer [defview letsubs]])) (:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn contacts-list-item [{:keys [public-key] :as contact}] (defn contacts-list-item [{:keys [public-key] :as contact}]
@ -21,45 +21,50 @@
: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])}]))
(defn add-new-contact []
[quo/list-item
{:icon :main-icons/add
:theme :accent
:title (i18n/label :t/add-new-contact)
:accessibility-label :add-new-contact-button
:on-press #(re-frame/dispatch [:navigate-to :new-contact])}])
(defview contacts-list [] (defview contacts-list []
(letsubs [blocked-contacts-count [:contacts/blocked-count] (letsubs [blocked-contacts-count [:contacts/blocked-count]
contacts [:contacts/active]] contacts [:contacts/active]]
[react/view {:flex 1} [:<>
[topbar/topbar {:title (i18n/label :t/contacts)}] (when (pos? blocked-contacts-count)
[react/scroll-view {:flex 1} [react/view {:margin-vertical 16}
[add-new-contact] [quo/list-item
(when (pos? blocked-contacts-count) {:title (i18n/label :t/blocked-users)
[react/view {:margin-vertical 16} :icon :main-icons/cancel
[quo/list-item :theme :negative
{:title (i18n/label :t/blocked-users) :accessibility-label :blocked-users-list-button
:icon :main-icons/cancel :chevron true
:theme :negative :accessory :text
:accessibility-label :blocked-users-list-button :accessory-text blocked-contacts-count
:chevron true :on-press #(re-frame/dispatch [:navigate-to :blocked-users-list])}]])
:accessory :text (if (seq contacts)
:accessory-text blocked-contacts-count [list.views/flat-list
:on-press #(re-frame/dispatch [:navigate-to :blocked-users-list])}]]) {:data contacts
(if (seq contacts) :key-fn :address
[list.views/flat-list :render-fn contacts-list-item
{:data contacts :footer [react/view {:height 68}]}]
:key-fn :address [react/view {:padding-horizontal 32 :margin-top 32}
:render-fn contacts-list-item}] [react/view {:border-width 1
[react/view {:align-items :center :flex 1 :justify-content :center} :border-color colors/gray-lighter
[react/text {:style {:color colors/gray :margin-vertical 24}} :border-top-right-radius 16
(i18n/label :t/you-dont-have-contacts)] :border-bottom-left-radius 16
[invite/button]])]])) :border-top-left-radius 16
:border-bottom-right-radius 4
:padding-horizontal 12
:padding-vertical 6}
[react/text {:style {:color colors/gray :line-height 22}}
(i18n/label :t/contacts-descr)]]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :new-contact])}
[react/view {:flex-direction :row
:align-items :center
:align-self :center
:padding 12}
[react/text {:style {:color colors/blue :margin-right 8}}
(i18n/label :t/add-contact)]
[icons/icon :main-icons/add-contact {:color colors/blue}]]]])]))
(defview blocked-users-list [] (defview blocked-users-list []
(letsubs [blocked-contacts [:contacts/blocked]] (letsubs [blocked-contacts [:contacts/blocked]]
[react/view {:flex 1 [react/view {:flex 1
:background-color colors/white} :background-color colors/white}
[topbar/topbar {:title (i18n/label :t/blocked-users)}] [topbar/topbar {:title (i18n/label :t/blocked-users)}]
[react/scroll-view {:style {:background-color colors/white [react/scroll-view {:style {:background-color colors/white

View File

@ -59,30 +59,6 @@
:margin-horizontal 40 :margin-horizontal 40
:color colors/gray}) :color colors/gray})
(def action-button-container
{:position :absolute
:z-index 2
:align-items :center
:align-self :center
:bottom 16
:width 40
:height 40})
(defn action-button []
{:width 40
:height 40
:background-color colors/blue
:border-radius 20
:align-items :center
:justify-content :center
:shadow-offset {:width 0 :height 1}
:shadow-radius 6
:shadow-opacity 1
:shadow-color (if (colors/dark?)
"rgba(0, 0, 0, 0.75)"
"rgba(0, 12, 63, 0.2)")
:elevation 2})
(def empty-chats-header-container (def empty-chats-header-container
{:align-items :center {:align-items :center
:justify-content :center}) :justify-content :center})

View File

@ -19,7 +19,8 @@
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[cljs-bean.core :as bean] [cljs-bean.core :as bean]
[status-im.ui.components.invite.views :as invite] [status-im.ui.components.invite.views :as invite]
[status-im.ui.components.topbar :as topbar]) [status-im.ui.components.topbar :as topbar]
[status-im.ui.components.plus-button :as components.plus-button])
(:require-macros [status-im.utils.views :as views])) (:require-macros [status-im.utils.views :as views]))
(defn welcome-image-wrapper [] (defn welcome-image-wrapper []
@ -158,16 +159,11 @@
(views/defview plus-button [] (views/defview plus-button []
(views/letsubs [logging-in? [:multiaccounts/login]] (views/letsubs [logging-in? [:multiaccounts/login]]
[react/view styles/action-button-container [components.plus-button/plus-button
[quo/button {:type :scale {:on-press (when-not logging-in?
:accessibility-label :new-chat-button #(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))
:on-press (when-not logging-in? :loading logging-in?
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))} :accessibility-label :new-chat-button}]))
[react/view (styles/action-button)
(if logging-in?
[react/activity-indicator {:color colors/white-persist
:animating true}]
[icons/icon :main-icons/add {:color colors/white-persist}])]]]))
(defn home [] (defn home []
[react/keyboard-avoiding-view {:style styles/home-container} [react/keyboard-avoiding-view {:style styles/home-container}

View File

@ -12,3 +12,13 @@
(def contact-profile-detail-share-icon (def contact-profile-detail-share-icon
{:color colors/gray-transparent-40}) {:color colors/gray-transparent-40})
(defn updates-descr-cont []
{:border-width 1
:border-color colors/gray-lighter
:border-top-right-radius 16
:border-bottom-left-radius 16
:border-top-left-radius 16
:border-bottom-right-radius 4
:padding-horizontal 12
:padding-vertical 6})

View File

@ -17,42 +17,48 @@
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation] [status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[reagent.core :as reagent] [reagent.core :as reagent]
[clojure.string :as string]) [clojure.string :as string]
[quo.components.list.item :as list-item]
[status-im.ui.components.list.views :as list]
[status-im.ui.screens.profile.status :as my-status]
[status-im.ui.screens.chat.views :as chat.views])
(:require-macros [status-im.utils.views :as views])) (:require-macros [status-im.utils.views :as views]))
(defn actions (defn actions
[{:keys [public-key added? tribute-to-talk] :as contact}] [{:keys [public-key added? blocked?] :as contact} muted?]
(let [{:keys [tribute-status tribute-label]} tribute-to-talk] (concat [{:label (i18n/label :t/chat)
(concat [(cond-> {:label (i18n/label :t/send-message) :icon :main-icons/message
:icon :main-icons/message :action #(re-frame/dispatch [:contact.ui/send-message-pressed {:public-key public-key}])
:action #(re-frame/dispatch [:contact.ui/send-message-pressed {:public-key public-key}]) :accessibility-label :start-conversation-button}]
:accessibility-label :start-conversation-button} (if added?
(not (#{:none :paid} tribute-status)) [{:label (i18n/label :t/remove-from-contacts)
(assoc :subtext tribute-label))] :icon :main-icons/remove-contact
;;TODO hide temporary for v1 :selected true
#_{:label (i18n/label :t/send-transaction) :accessibility-label :in-contacts-button
:icon :main-icons/send :action #(re-frame/dispatch [:contact.ui/remove-contact-pressed contact])}]
:action #(re-frame/dispatch [:profile/send-transaction public-key]) [{:label (i18n/label :t/add-to-contacts)
:accessibility-label :send-transaction-button} :icon :main-icons/add-contact
(if added? :accessibility-label :add-to-contacts-button
[{:label (i18n/label :t/remove-from-contacts) :action #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])}])
:icon :main-icons/remove-contact (when platform/ios?
:accessibility-label :in-contacts-button [{:label (i18n/label (if muted? :t/unmute :t/mute))
:action #(re-frame/dispatch [:contact.ui/remove-contact-pressed contact])}] :icon :main-icons/notification
;; TODO sheets temporary disabled :accessibility-label :mute-chat
;:action #(re-frame/dispatch [:bottom-sheet/show-sheet :selected muted?
; {:content sheets/remove-contact :action #(re-frame/dispatch [::chat.models/mute-chat-toggled public-key (not muted?)])}])
; :content-height 150} [{:label (i18n/label (if blocked? :t/unblock :t/block))
; contact]) :negative true
[{:label (i18n/label :t/add-to-contacts) :selected blocked?
:icon :main-icons/add-contact :icon :main-icons/cancel
:accessibility-label :add-to-contacts-button :action (if blocked?
:action #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])}])))) #(re-frame/dispatch [:contact.ui/unblock-contact-pressed public-key])
;; TODO sheets temporary disabled #(re-frame/dispatch [:show-popover
;:action #(re-frame/dispatch [:bottom-sheet/show-sheet {:view sheets/block-contact
; {:content sheets/add-contact :prevent-closing? true
; :content-height 150} :public-key public-key}]))
; contact]) :accessibility-label (if blocked?
:unblock-contact
:block-contact)}]))
(defn render-detail [{:keys [public-key names name] :as detail}] (defn render-detail [{:keys [public-key names name] :as detail}]
[quo/list-item [quo/list-item
@ -78,49 +84,15 @@
(i18n/label :t/profile-details)]] (i18n/label :t/profile-details)]]
[render-detail contact]])) [render-detail contact]]))
(defn render-chat-settings [{:keys [public-key names]}] (defn nickname-settings [{:keys [names]}]
(let [muted? (:muted @(re-frame/subscribe [:chats/chat public-key]))] [quo/list-item
[react/view {:title (i18n/label :t/nickname)
[quo/list-item :size :small
{:title (i18n/label :t/nickname) :accessibility-label :profile-nickname-item
:size :small :accessory :text
:accessibility-label :profile-nickname-item :accessory-text (or (:nickname names) (i18n/label :t/none))
:accessory :text :on-press #(re-frame/dispatch [:navigate-to :nickname])
:accessory-text (or (:nickname names) (i18n/label :t/none)) :chevron true}])
:on-press #(re-frame/dispatch [:navigate-to :nickname])
:chevron true}]
;; Mute chat is only supported on ios for now
(when platform/ios?
[quo/list-item
{:title (i18n/label :t/mute)
:active muted?
:accessibility-label :mute-chat
:on-press #(re-frame/dispatch [::chat.models/mute-chat-toggled public-key (not muted?)])
:accessory :switch}])]))
(defn chat-settings [contact]
[react/view
[quo/list-header
[quo/text {:accessibility-label :chat-settings
:color :inherit}
(i18n/label :t/chat-settings)]]
[render-chat-settings contact]])
;; TODO: List item
(defn block-contact-action [{:keys [blocked? public-key]}]
[react/touchable-highlight {:on-press (if blocked?
#(re-frame/dispatch [:contact.ui/unblock-contact-pressed public-key])
#(re-frame/dispatch [:show-popover
{:view sheets/block-contact
:prevent-closing? true
:public-key public-key}]))}
[react/text {:style styles/block-action-label
:accessibility-label (if blocked?
:unblock-contact
:block-contact)}
(if blocked?
(i18n/label :t/unblock-contact)
(i18n/label :t/block-contact))]])
(defn save-nickname [public-key nickname] (defn save-nickname [public-key nickname]
(re-frame/dispatch [:contacts/update-nickname public-key nickname])) (re-frame/dispatch [:contacts/update-nickname public-key nickname]))
@ -167,45 +139,75 @@
(views/letsubs [{:keys [public-key names]} [:contacts/current-contact]] (views/letsubs [{:keys [public-key names]} [:contacts/current-contact]]
[nickname-view public-key names])) [nickname-view public-key names]))
(defn button-item [{:keys [icon label action selected negative]}]
[react/touchable-highlight {:on-press action :style {:flex 1}
:accessibility-label (str label "-item-button")}
[react/view {:flex 1 :align-items :center}
[list-item/icon-column {:icon icon
:size :small
:icon-bg-color (if negative
(if selected colors/red colors/red-light)
(if selected colors/blue colors/blue-light))
:icon-color (if negative
(if selected colors/white colors/red)
(if selected colors/white colors/blue))}]
[react/text {:style {:text-align :center :color (if negative colors/red colors/blue)
:font-size 12 :line-height 16 :margin-top 6}
:number-of-lines 2}
label]]])
(defn status []
(let [messages @(re-frame/subscribe [:chats/current-chat-messages-stream])
no-messages? @(re-frame/subscribe [:chats/current-chat-no-messages?])]
(if no-messages?
[react/view {:padding-horizontal 32 :margin-top 32}
[react/view (styles/updates-descr-cont)
[react/text {:style {:color colors/gray :line-height 22}}
(i18n/label :t/status-updates-descr)]]]
[list/flat-list
{:key-fn #(or (:message-id %) (:value %))
:ref #(reset! my-status/messages-list-ref %)
:on-viewable-items-changed chat.views/on-viewable-items-changed
:on-end-reached #(re-frame/dispatch [:chat.ui/load-more-messages])
:on-scroll-to-index-failed #() ;;don't remove this
:render-fn my-status/render-message
:data messages}])))
(views/defview profile [] (views/defview profile []
(views/letsubs [{:keys [public-key name ens-verified] (views/letsubs [{:keys [public-key name ens-verified]
:as contact} [:contacts/current-contact]] :as contact} [:contacts/current-contact]]
(let [[first-name second-name] (multiaccounts/contact-two-names contact true) (let [muted? (:muted @(re-frame/subscribe [:chats/chat public-key]))
[first-name second-name] (multiaccounts/contact-two-names contact true)
on-share #(re-frame/dispatch [:show-popover (merge on-share #(re-frame/dispatch [:show-popover (merge
{:view :share-chat-key {:view :share-chat-key
:address public-key} :address public-key}
(when (and ens-verified name) (when (and ens-verified name)
{:ens-name name}))])] {:ens-name name}))])]
(when contact (when contact
[react/view [react/view {:flex 1}
{:style
(merge {:flex 1})}
[quo/animated-header [quo/animated-header
{:use-insets true {:use-insets false
:right-accessories [{:icon :main-icons/share :right-accessories [{:icon :main-icons/share
:accessibility-label :share-button
:on-press on-share}] :on-press on-share}]
:left-accessories [{:icon :main-icons/arrow-left :left-accessories [{:icon :main-icons/close
:accessibility-label :back-button :accessibility-label :back-button
:on-press #(re-frame/dispatch [:navigate-back])}] :on-press #(re-frame/dispatch [:navigate-back])}]
:extended-header (profile-header/extended-header :extended-header (profile-header/extended-header
{:on-press on-share {:on-press on-share
:bottom-separator false
: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})}
[react/view {:height 1 :background-color colors/gray-lighter :margin-top 8}]
[react/view {:padding-top 12} [nickname-settings contact]
(for [{:keys [label subtext accessibility-label icon action disabled?]} (actions contact) [react/view {:height 1 :background-color colors/gray-lighter}]
[react/view {:padding-top 17 :flex-direction :row :align-items :stretch :flex 1}
(for [{:keys [label] :as action} (actions contact muted?)
:when label] :when label]
^{:key label} ^{:key label}
[quo/list-item {:theme :accent [button-item action])]
:title label [react/view {:height 1 :background-color colors/gray-lighter :margin-top 16}]
:subtitle subtext [status]]]))))
:icon icon
:accessibility-label accessibility-label
:disabled disabled?
:on-press action}])]
[react/view styles/contact-profile-details-container
[profile-details contact]
[chat-settings contact]]
[block-contact-action contact]]]))))

View File

@ -0,0 +1,108 @@
(ns status-im.ui.screens.profile.my-status.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.ui.components.react :as react]
[status-im.ui.components.topbar :as topbar]
[status-im.i18n :as i18n]
[re-frame.core :as re-frame]
[status-im.ui.components.toolbar :as toolbar]
[quo.core :as quo]
[status-im.ui.components.colors :as colors]
[reagent.core :as reagent]
[clojure.string :as string]
[status-im.ui.components.icons.vector-icons :as icons]
[quo.components.animated.pressable :as pressable]
[status-im.ui.screens.profile.status :as my-status.messages]))
(defn take-picture []
(react/show-image-picker-camera #(re-frame/dispatch [:chat.ui/image-captured (.-path %)]) {}))
(defn buttons []
[react/view {:padding-horizontal 14 :padding-vertical 10 :justify-content :space-between :height 88}
[pressable/pressable {:type :scale
:accessibility-label :take-picture
:on-press take-picture}
[icons/icon :main-icons/camera]]
[react/view {:style {:padding-top 8}}
[pressable/pressable {:on-press #(re-frame/dispatch [:chat.ui/open-image-picker])
:accessibility-label :open-gallery
:type :scale}
[icons/icon :main-icons/gallery]]]])
(defn image-preview [uri]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/camera-roll-pick uri])}
[react/image {:style (merge {:width 72
:height 72
:background-color :black
:resize-mode :cover
:margin-right 4
:border-radius 4})
:source {:uri uri}}]])
(defview photos []
(letsubs [camera-roll-photos [:camera-roll-photos]]
{:component-did-mount #(re-frame/dispatch [:chat.ui/camera-roll-get-photos 20])}
[react/scroll-view {:horizontal true :style {:max-height 88}
:keyboard-should-persist-taps :handled}
[react/view {:height 88 :border-top-width 1 :border-top-color colors/gray-lighter
:flex-direction :row :align-items :center}
[buttons]
(for [img camera-roll-photos]
^{:key (str "image" img)}
(when img
[image-preview img]))]]))
(defview sending-image []
(letsubs [{:keys [uri]} [:chats/sending-image]]
(when uri
[react/view {:margin-horizontal 16 :margin-bottom 16}
[my-status.messages/message-content-image uri true]])))
(defn my-status []
(let [images-opened (reagent/atom false)
input-text (re-frame/subscribe [:chats/current-chat-input-text])]
(fn []
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
[react/view {:flex 1}
[topbar/topbar
{:modal? true
:border-bottom true
:title (i18n/label :t/my-status)}]
[react/scroll-view {:style {:flex 1}
:keyboard-should-persist-taps :handled}
[react/text-input
{:style {:margin 16}
:accessibility-label :my-status-input
:max-length 300
:auto-focus true
:multiline true
:on-change-text #(re-frame/dispatch [:chat.ui/set-chat-input-text %])
:default-value @input-text
:placeholder (i18n/label :t/whats-on-your-mind)}]
[sending-image]]
[react/view
(when @images-opened
[photos])
[react/view
[toolbar/toolbar
{:show-border? true
:left
[quo/button
{:accessibility-label :open-images-panel-button
:type :secondary
:on-press #(swap! images-opened not)}
[icons/icon :main-icons/photo {:color (if @images-opened colors/blue colors/gray)}]]
:right
[quo/button
{:accessibility-label :send-my-status-button
:type :secondary
:after :main-icon/send
:disabled (string/blank? @input-text)
:on-press #(do
(re-frame/dispatch [:profile.ui/send-my-status-message])
(re-frame/dispatch [:navigate-back]))}
(i18n/label :t/wallet-send)]}]
[react/view {:top 0 :bottom 0 :left 0 :right 0 :align-items :center :justify-content :center
:position :absolute :pointerEvents :none}
[react/text {:style {:color colors/gray}}
(str (count @input-text) " / 300")]]]]]])))

View File

@ -0,0 +1,72 @@
(ns status-im.ui.screens.profile.status
(:require [status-im.ui.screens.chat.message.message :as message]
[status-im.ui.components.react :as react]
[status-im.ui.components.colors :as colors]
[status-im.utils.datetime :as datetime]
[status-im.ui.screens.chat.message.gap :as gap]
[status-im.constants :as constants]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ui.components.icons.vector-icons :as icons]))
(defonce messages-list-ref (atom nil))
(defn message-content-image [_ _]
(let [dimensions (reagent/atom [260 260])]
(fn [uri show-close?]
(react/image-get-size
uri
(fn [width height]
(let [k (/ (max width height) 260)]
(reset! dimensions [(/ width k) (/ height k)]))))
[react/view
[react/view {:style {:width (first @dimensions)
:height (last @dimensions)
:border-width 1
:border-color colors/black-transparent
:overflow :hidden
:border-radius 16
:margin-top 8}}
[react/image {:style {:width (first @dimensions) :height (last @dimensions)}
:resize-mode :contain
:source {:uri uri}}]]
(when show-close?
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/cancel-sending-image])
:accessibility-label :cancel-send-image
:style {:left (- (first @dimensions) 28) :top 12 :position :absolute}}
[react/view {:width 24
:height 24
:background-color colors/black-persist
:border-radius 12
:align-items :center
:justify-content :center}
[icons/icon :main-icons/close-circle {:color colors/white-persist}]]])])))
(defn image-message [{:keys [content] :as message}]
[react/touchable-highlight {:on-press (fn [_]
(when (:image content)
(re-frame/dispatch [:navigate-to :image-preview
(assoc message :cant-be-replied true)]))
(react/dismiss-keyboard!))}
[message-content-image (:image content) false]])
(defn message-item [{:keys [content-type content from last-in-group? timestamp] :as message}]
[react/view (merge {:padding-top 16 :padding-horizontal 16}
(when last-in-group?
{:padding-bottom 16
:border-bottom-width 1
:border-bottom-color colors/gray-lighter}))
[react/view {:flex-direction :row :justify-content :space-between}
[message/message-author-name from]
[react/text {:style {:font-size 10 :color colors/gray}} (datetime/time-ago (datetime/to-date timestamp))]]
(if (= content-type constants/content-type-image)
[image-message message]
[message/render-parsed-text (assoc message :outgoing false) (:parsed-text content)])])
(defn render-message [{:keys [type] :as message} idx]
(if (= type :datemark)
[react/view]
(if (= type :gap)
[gap/gap message idx messages-list-ref]
; message content
[message-item message])))

View File

@ -1,6 +1,17 @@
(ns status-im.ui.screens.profile.user.styles) (ns status-im.ui.screens.profile.user.styles
(:require [status-im.ui.components.colors :as colors]))
(def share-link-button (def share-link-button
{:margin-top 12 {:margin-top 12
:margin-horizontal 16 :margin-horizontal 16
:margin-bottom 16}) :margin-bottom 16})
(defn descr-container []
{:border-width 1
:border-color colors/gray-lighter
:border-top-right-radius 16
:border-bottom-left-radius 16
:border-top-left-radius 16
:border-bottom-right-radius 4
:padding-horizontal 12
:padding-vertical 6})

View File

@ -17,7 +17,15 @@
[status-im.utils.gfycat.core :as gfy] [status-im.utils.gfycat.core :as gfy]
[status-im.utils.universal-links.utils :as universal-links] [status-im.utils.universal-links.utils :as universal-links]
[status-im.ui.components.profile-header.view :as profile-header] [status-im.ui.components.profile-header.view :as profile-header]
[status-im.ethereum.stateofus :as stateofus]) [status-im.ui.components.tabs :as tabs]
[status-im.utils.utils :as utils]
[status-im.ui.screens.contacts-list.views :as contacts-list]
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.list.views :as list]
[status-im.ui.screens.profile.status :as my-status]
[status-im.ethereum.stateofus :as stateofus]
[status-im.ui.screens.chat.views :as chat.views])
(: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 []
@ -55,14 +63,37 @@
:accessibility-label :share-my-contact-code-button} :accessibility-label :share-my-contact-code-button}
(i18n/label :t/share-link)]]]))) (i18n/label :t/share-link)]]])))
(defn tribute-to-talk-item (def state (reagent/atom {:tab :status}))
[opts]
[quo/list-item (defn tabs []
(merge {:title (i18n/label :t/tribute-to-talk) (let [{:keys [tab]} @state]
:accessibility-label :notifications-button [react/view {:flex-direction :row :padding-horizontal 4 :margin-top 16}
:on-press #(re-frame/dispatch [tabs/tab-title state :status (i18n/label :t/my-status) (= tab :status)]
[:tribute-to-talk.ui/menu-item-pressed])} [tabs/tab-title state :contacts (i18n/label :t/contacts) (= tab :contacts)]
opts)]) [tabs/tab-title state :settings (i18n/label :t/settings) (= tab :settings)]]))
(defn my-status []
(let [messages @(re-frame/subscribe [:chats/current-chat-messages-stream])
no-messages? @(re-frame/subscribe [:chats/current-chat-no-messages?])]
(if no-messages?
[react/view {:padding-horizontal 32 :margin-top 32}
[react/view (styles/descr-container)
[react/text {:style {:color colors/gray :line-height 22}}
(i18n/label :t/statuses-my-profile-descr)]]
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :my-status])}
[react/view {:flex-direction :row :align-items :center :align-self :center
:padding 12}
[react/text {:style {:color colors/blue :margin-right 8}}
(i18n/label :t/new-status)]
[icons/icon :main-icons/add-circle {:color colors/blue}]]]]
[list/flat-list
{:key-fn #(or (:message-id %) (:value %))
:render-fn my-status/render-message
:data messages
:on-viewable-items-changed chat.views/on-viewable-items-changed
:on-end-reached #(re-frame/dispatch [:chat.ui/load-more-messages])
:on-scroll-to-index-failed #() ;;don't remove this
:footer [react/view {:height 68}]}])))
(defn content [] (defn content []
(let [{:keys [preferred-name (let [{:keys [preferred-name
@ -70,123 +101,116 @@
notifications-enabled? notifications-enabled?
keycard-pairing]} keycard-pairing]}
@(re-frame/subscribe [:multiaccount]) @(re-frame/subscribe [:multiaccount])
active-contacts-count @(re-frame/subscribe [:contacts/active-count])
tribute-to-talk @(re-frame/subscribe [:tribute-to-talk/profile])
chain @(re-frame/subscribe [:chain-keyword]) chain @(re-frame/subscribe [:chain-keyword])
registrar (stateofus/get-cached-registrar chain)] registrar (stateofus/get-cached-registrar chain)
{:keys [tab]} @state]
[:<> [:<>
[quo/list-item [tabs]
(cond-> {:title (or (when registrar preferred-name) [react/view {:height 1 :background-color colors/gray-lighter}]
(i18n/label :t/ens-usernames)) (cond
:subtitle (if registrar (= tab :status)
(if preferred-name [my-status]
(i18n/label :t/ens-your-your-name) (= tab :contacts)
(i18n/label :t/ens-usernames-details)) [contacts-list/contacts-list]
(i18n/label :t/ens-network-restriction)) (= tab :settings)
:subtitle-max-lines (if registrar [:<>
(if preferred-name 1 2) [quo/list-item
1) (cond-> {:title (or (when registrar preferred-name)
:accessibility-label :ens-button (i18n/label :t/ens-usernames))
:container-margin-top 8 :subtitle (if registrar
:disabled (not registrar) (if preferred-name
:chevron true (i18n/label :t/ens-your-your-name)
:icon :main-icons/username} (i18n/label :t/ens-usernames-details))
registrar (i18n/label :t/ens-network-restriction))
(assoc :on-press #(re-frame/dispatch [:navigate-to :ens-main registrar])))] :subtitle-max-lines (if registrar
;; TODO replace this with list-item config map (if preferred-name 1 2)
;; left it as it is because not sure how to enable it for testing 1)
(when tribute-to-talk [tribute-to-talk-item tribute-to-talk]) :accessibility-label :ens-button
[quo/list-item :container-margin-top 8
{:title (i18n/label :t/contacts) :disabled (not registrar)
:icon :main-icons/in-contacts :chevron true
:accessibility-label :contacts-button :icon :main-icons/username}
:accessory :text registrar
:accessory-text (if (pos? active-contacts-count) (assoc :on-press #(re-frame/dispatch [:navigate-to :ens-main registrar])))]
(str active-contacts-count) [quo/list-item
(i18n/label :t/none)) {:icon :main-icons/security
:chevron true :title (i18n/label :t/privacy-and-security)
:on-press #(re-frame/dispatch [:navigate-to :contacts-list])}] :accessibility-label :privacy-and-security-settings-button
[react/view {:padding-top 16} :chevron true
[quo/list-header (i18n/label :t/settings)]] :accessory (when mnemonic
[quo/list-item [components.common/counter {:size 22} 1])
{:icon :main-icons/security :on-press #(re-frame/dispatch [:navigate-to :privacy-and-security])}]
:title (i18n/label :t/privacy-and-security) (when config/quo-preview-enabled?
:accessibility-label :privacy-and-security-settings-button [quo/list-item
:chevron true {:icon :main-icons/appearance
:accessory (when mnemonic :title "Quo Preview"
[components.common/counter {:size 22} 1]) :accessibility-label :appearance-settings-button
:on-press #(re-frame/dispatch [:navigate-to :privacy-and-security])}] :chevron true
(when config/quo-preview-enabled? :on-press #(re-frame/dispatch [:navigate-to :quo-preview])}])
[quo/list-item [quo/list-item
{:icon :main-icons/appearance {:icon :main-icons/appearance
:title "Quo Preview" :title (i18n/label :t/appearance)
:accessibility-label :appearance-settings-button :accessibility-label :appearance-settings-button
:chevron true :chevron true
:on-press #(re-frame/dispatch [:navigate-to :quo-preview])}]) :on-press #(re-frame/dispatch [:navigate-to :appearance])}]
[quo/list-item (if platform/ios?
{:icon :main-icons/appearance [quo/list-item
:title (i18n/label :t/appearance) {:icon :main-icons/notification
:accessibility-label :appearance-settings-button :title (i18n/label :t/notifications)
:chevron true :accessibility-label :notifications-settings-button
:on-press #(re-frame/dispatch [:navigate-to :appearance])}] :chevron true
(if platform/ios? :on-press #(re-frame/dispatch [:navigate-to :notifications])}]
[quo/list-item (when (and platform/android?
{:icon :main-icons/notification config/local-notifications?)
:title (i18n/label :t/notifications) [quo/list-item
:accessibility-label :notifications-settings-button {:icon :main-icons/notification
:chevron true :title (i18n/label :t/notifications)
:on-press #(re-frame/dispatch [:navigate-to :notifications])}] :accessibility-label :notifications-settings-button
(when (and platform/android? :active notifications-enabled?
config/local-notifications?) :on-press #(re-frame/dispatch
[::notifications/switch (not notifications-enabled?)])
:accessory :switch}]))
[quo/list-item
{:icon :main-icons/mobile
:title (i18n/label :t/sync-settings)
:accessibility-label :sync-settings-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :sync-settings])}]
(when (and (or platform/android?
config/keycard-test-menu-enabled?)
keycard-pairing)
[quo/list-item
{:icon :main-icons/keycard
:title (i18n/label :t/keycard)
:accessibility-label :keycard-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :keycard-settings])}])
[quo/list-item
{:icon :main-icons/settings-advanced
:title (i18n/label :t/advanced)
:accessibility-label :advanced-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :advanced-settings])}]
[quo/list-item
{:icon :main-icons/help
:title (i18n/label :t/need-help)
:accessibility-label :help-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :help-center])}]
[quo/list-item
{:icon :main-icons/info
:title (i18n/label :t/about-app)
:accessibility-label :about-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :about-app])}]
[react/view {:padding-vertical 24}
[quo/list-item [quo/list-item
{:icon :main-icons/notification {:icon :main-icons/log-out
:title (i18n/label :t/notifications) :title (i18n/label :t/sign-out)
:accessibility-label :notifications-settings-button :accessibility-label :log-out-button
:active notifications-enabled? :theme :negative
:on-press #(re-frame/dispatch :on-press
[::notifications/switch (not notifications-enabled?)]) #(re-frame/dispatch [:multiaccounts.logout.ui/logout-pressed])}]]])]))
:accessory :switch}]))
[quo/list-item
{:icon :main-icons/mobile
:title (i18n/label :t/sync-settings)
:accessibility-label :sync-settings-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :sync-settings])}]
(when (and (or platform/android?
config/keycard-test-menu-enabled?)
keycard-pairing)
[quo/list-item
{:icon :main-icons/keycard
:title (i18n/label :t/keycard)
:accessibility-label :keycard-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :keycard-settings])}])
[quo/list-item
{:icon :main-icons/settings-advanced
:title (i18n/label :t/advanced)
:accessibility-label :advanced-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :advanced-settings])}]
[quo/list-item
{:icon :main-icons/help
:title (i18n/label :t/need-help)
:accessibility-label :help-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :help-center])}]
[quo/list-item
{:icon :main-icons/info
:title (i18n/label :t/about-app)
:accessibility-label :about-button
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :about-app])}]
[react/view {:padding-vertical 24}
[quo/list-item
{:icon :main-icons/log-out
:title (i18n/label :t/sign-out)
:accessibility-label :log-out-button
:theme :negative
:on-press
#(re-frame/dispatch [:multiaccounts.logout.ui/logout-pressed])}]]]))
(defn my-profile [] (defn my-profile []
(fn [] (fn []
@ -195,18 +219,26 @@
on-share #(re-frame/dispatch [:show-popover on-share #(re-frame/dispatch [:show-popover
{:view :share-chat-key {:view :share-chat-key
:address public-key :address public-key
:ens-name preferred-name}])] :ens-name preferred-name}])
[react/view {:style {:flex 1}} {:keys [tab]} @state]
[react/view {:flex 1}
[quo/animated-header [quo/animated-header
{:right-accessories [{:icon :main-icons/share {:right-accessories [{:accessibility-label :share-header-button
:icon :main-icons/share
:on-press on-share}] :on-press on-share}]
:use-insets true :use-insets true
:extended-header (profile-header/extended-header :extended-header (profile-header/extended-header
{:on-press on-share {:on-press on-share
:title (multiaccounts/displayed-name account) :title (multiaccounts/displayed-name account)
:photo (multiaccounts/displayed-photo account) :photo (multiaccounts/displayed-photo account)
:monospace (not ens-verified) :monospace (not ens-verified)
:subtitle (if (and ens-verified public-key) :subtitle (if (and ens-verified public-key)
(gfy/generate-gfy public-key) (gfy/generate-gfy public-key)
public-key)})} (utils/get-shortened-address public-key))
[content]]]))) :bottom-separator false})}
[content]]
(when-not (= :settings tab)
[components.plus-button/plus-button
{:on-press #(if (= :contacts tab)
(re-frame/dispatch [:navigate-to :new-contact])
(re-frame/dispatch [:navigate-to :my-status]))}])])))

View File

@ -2,10 +2,8 @@
(:require [status-im.ui.screens.routing.core :as navigation] (:require [status-im.ui.screens.routing.core :as navigation]
[status-im.ui.screens.home.views :as home] [status-im.ui.screens.home.views :as home]
[status-im.ui.screens.chat.views :as chat] [status-im.ui.screens.chat.views :as chat]
[status-im.ui.screens.profile.contact.views :as profile.contact]
[status-im.ui.screens.group.views :as group] [status-im.ui.screens.group.views :as group]
[status-im.ui.screens.profile.group-chat.views :as profile.group-chat] [status-im.ui.screens.profile.group-chat.views :as profile.group-chat]
[status-im.chat.models :as chat.models]
[status-im.ui.components.tabbar.styles :as tabbar.styles] [status-im.ui.components.tabbar.styles :as tabbar.styles]
[status-im.ui.screens.stickers.views :as stickers])) [status-im.ui.screens.stickers.views :as stickers]))
@ -16,14 +14,10 @@
[stack {:initial-route-name :home [stack {:initial-route-name :home
:header-mode :none} :header-mode :none}
[{:name :home [{:name :home
:on-focus [::chat.models/offload-all-messages]
:style {:padding-bottom tabbar.styles/tabs-diff} :style {:padding-bottom tabbar.styles/tabs-diff}
:component home/home} :component home/home}
{:name :chat {:name :chat
:component chat/chat} :component chat/chat}
{:name :profile
:insets {:top false}
:component profile.contact/profile}
{:name :group-chat-profile {:name :group-chat-profile
:insets {:top false} :insets {:top false}
:component profile.group-chat/group-chat-profile} :component profile.group-chat/group-chat-profile}

View File

@ -35,6 +35,12 @@
(get-active-route-name (bean inner-state)) (get-active-route-name (bean inner-state))
(some-> (get route :name) keyword)))) (some-> (get route :name) keyword))))
(defn get-index-route-name [index {:keys [routes]}]
(let [route (bean (get routes index))]
(if-let [inner-state (get route :state)]
(get-active-route-name (bean inner-state))
(some-> (get route :name) keyword))))
(def transition-presets TransitionPresets) (def transition-presets TransitionPresets)
(def modal-presentation-ios (merge (js->clj (.-ModalPresentationIOS ^js transition-presets)) (def modal-presentation-ios (merge (js->clj (.-ModalPresentationIOS ^js transition-presets))

View File

@ -24,7 +24,8 @@
[status-im.ui.screens.chat.image.preview.views :as image-preview] [status-im.ui.screens.chat.image.preview.views :as image-preview]
[status-im.ui.screens.profile.contact.views :as contact] [status-im.ui.screens.profile.contact.views :as contact]
[status-im.ui.screens.notifications-settings.views :as notifications-settings] [status-im.ui.screens.notifications-settings.views :as notifications-settings]
[status-im.ui.screens.wallet.send.views :as wallet])) [status-im.ui.screens.wallet.send.views :as wallet]
[status-im.ui.screens.profile.my-status.views :as my-status]))
(defonce main-stack (navigation/create-stack)) (defonce main-stack (navigation/create-stack))
(defonce bottom-tabs (navigation/create-bottom-tabs)) (defonce bottom-tabs (navigation/create-bottom-tabs))
@ -135,7 +136,15 @@
{:name :request-transaction {:name :request-transaction
:transition :presentation-ios :transition :presentation-ios
:insets {:bottom true} :insets {:bottom true}
:component wallet/request-transaction}] :component wallet/request-transaction}
{:name :my-status
:transition :presentation-ios
:insets {:bottom true}
:component my-status/my-status}
{:name :profile
:transition :presentation-ios
:insets {:bottom true}
:component contact/profile}]
(when config/quo-preview-enabled? (when config/quo-preview-enabled?
[{:name :quo-preview [{:name :quo-preview

View File

@ -2,7 +2,6 @@
(:require [status-im.ui.screens.profile.user.views :as profile.user] (:require [status-im.ui.screens.profile.user.views :as profile.user]
[status-im.ui.screens.ens.views :as ens] [status-im.ui.screens.ens.views :as ens]
[status-im.ui.screens.contacts-list.views :as contacts-list] [status-im.ui.screens.contacts-list.views :as contacts-list]
[status-im.ui.screens.profile.contact.views :as profile.contact]
[status-im.ui.screens.bootnodes-settings.edit-bootnode.views [status-im.ui.screens.bootnodes-settings.edit-bootnode.views
:as :as
edit-bootnode] edit-bootnode]
@ -65,9 +64,6 @@
:component ens/name-details} :component ens/name-details}
{:name :blocked-users-list {:name :blocked-users-list
:component contacts-list/blocked-users-list} :component contacts-list/blocked-users-list}
{:name :profile
:insets {:top false}
:component profile.contact/profile}
{:name :bootnodes-settings {:name :bootnodes-settings
:component bootnodes-settings/bootnodes-settings} :component bootnodes-settings/bootnodes-settings}
{:name :installations {:name :installations

View File

@ -15,7 +15,8 @@
[status-im.ui.screens.wallet.accounts.views :as accounts] [status-im.ui.screens.wallet.accounts.views :as accounts]
[status-im.ui.screens.wallet.transactions.views :as history] [status-im.ui.screens.wallet.transactions.views :as history]
[status-im.utils.money :as money] [status-im.utils.money :as money]
[status-im.wallet.utils :as wallet.utils]) [status-im.wallet.utils :as wallet.utils]
[status-im.ui.components.tabs :as tabs])
(:require-macros [status-im.utils.views :as views])) (:require-macros [status-im.utils.views :as views]))
(def state (reagent/atom {:tab :assets})) (def state (reagent/atom {:tab :assets}))
@ -118,9 +119,9 @@
(let [{:keys [tab]} @state] (let [{:keys [tab]} @state]
[react/view {:flex 1} [react/view {:flex 1}
[react/view {:flex-direction :row :margin-bottom 8 :padding-horizontal 4} [react/view {:flex-direction :row :margin-bottom 8 :padding-horizontal 4}
[accounts/tab-title state :assets (i18n/label :t/wallet-assets) (= tab :assets)] [tabs/tab-title state :assets (i18n/label :t/wallet-assets) (= tab :assets)]
[accounts/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)] [tabs/tab-title state :nft (i18n/label :t/wallet-collectibles) (= tab :nft)]
[accounts/tab-title state :history (i18n/label :t/history) (= tab :history)]] [tabs/tab-title state :history (i18n/label :t/history) (= tab :history)]]
(cond (cond
(= tab :assets) (= tab :assets)
[list/flat-list {:data tokens [list/flat-list {:data tokens

View File

@ -58,17 +58,6 @@
[icons/icon :main-icons/add {:color colors/blue}]] [icons/icon :main-icons/add {:color colors/blue}]]
[react/text {:style {:color colors/blue}} (i18n/label :t/add-account)]]]) [react/text {:style {:color colors/blue}} (i18n/label :t/add-account)]]])
(defn tab-title [state key label active?]
[react/view {:align-items :center}
[react/touchable-highlight {:on-press #(swap! state assoc :tab key)
:underlay-color colors/gray-lighter
:style {:border-radius 8}}
[react/view {:padding-horizontal 12 :padding-vertical 9}
[react/text {:style {:font-weight "500" :color (if active? colors/black colors/gray) :line-height 22}}
label]]]
(when active?
[react/view {:width 24 :height 3 :border-radius 4 :background-color colors/blue}])])
(defn render-asset [currency & [on-press]] (defn render-asset [currency & [on-press]]
(fn [{:keys [icon decimals amount color value] :as token}] (fn [{:keys [icon decimals amount color value] :as token}]
[quo/list-item [quo/list-item

View File

@ -16,10 +16,10 @@
(def hour (* 1000 60 60)) (def hour (* 1000 60 60))
(def day (* hour 24)) (def day (* hour 24))
(def week (* 7 day)) (def week (* 7 day))
(def units [{:name :t/datetime-second :limit 60 :in-second 1} (def units [{:name :t/datetime-second-short :limit 60 :in-second 1}
{:name :t/datetime-minute :limit 3600 :in-second 60} {:name :t/datetime-minute-short :limit 3600 :in-second 60}
{:name :t/datetime-hour :limit 86400 :in-second 3600} {:name :t/datetime-hour-short :limit 86400 :in-second 3600}
{:name :t/datetime-day :limit nil :in-second 86400}]) {:name :t/datetime-day-short :limit nil :in-second 86400}])
(def time-zone-offset (hours (- (/ (.getTimezoneOffset ^js (js/Date.)) 60)))) (def time-zone-offset (hours (- (/ (.getTimezoneOffset ^js (js/Date.)) 60))))
@ -113,23 +113,23 @@
(defn format-time-ago [diff unit] (defn format-time-ago [diff unit]
(let [name (label-pluralize diff (:name unit))] (let [name (label-pluralize diff (:name unit))]
(label :t/datetime-ago-format {:ago (label :t/datetime-ago) (if (= :t/datetime-second-short (:name unit))
:number diff (label :t/now)
:time-intervals name}))) (label :t/datetime-ago-format-short {:ago (label :t/datetime-ago)
:number diff
:time-intervals name}))))
(defn seconds-ago [time] (defn seconds-ago [time]
(t/in-seconds (t/interval time (t/now)))) (t/in-seconds (t/interval time (t/now))))
(defn time-ago [time] (defn time-ago [time]
(let [diff (seconds-ago time)] (let [diff (seconds-ago time)
(if (< diff 60) unit (first (drop-while #(and (>= diff (:limit %))
(label :t/active-online) (:limit %))
(let [unit (first (drop-while #(and (>= diff (:limit %)) units))]
(:limit %)) (-> (/ diff (:in-second unit))
units))] Math/floor
(-> (/ diff (:in-second unit)) int
Math/floor (format-time-ago unit))))
int
(format-time-ago unit))))))
(defn to-date [ms] (defn to-date [ms]
(from-long ms)) (from-long ms))

View File

@ -72,9 +72,8 @@
public-key public-key
(navigation/navigate-to-cofx (assoc-in cofx [:db :contacts/identity] public-key) (navigation/navigate-to-cofx (assoc-in cofx [:db :contacts/identity] public-key)
:tabs :profile
{:screen :chat-stack {})))
:params {:screen :profile}})))
(fx/defn handle-eip681 [cofx data] (fx/defn handle-eip681 [cofx data]
(fx/merge cofx (fx/merge cofx

View File

@ -2,7 +2,7 @@
"_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead", "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh <tag>' instead",
"owner": "status-im", "owner": "status-im",
"repo": "status-go", "repo": "status-go",
"version": "v0.62.13", "version": "v0.62.14",
"commit-sha1": "7467ca7b103f685dd64d73485555f90c181a4484", "commit-sha1": "b3880027710ee7a28bbdeacbe099412627485d62",
"src-sha256": "0gv9jxn5c5arnxdr33rfw2zkly9c2nyss59vbdyf444140bd6y6y" "src-sha256": "0g3c1rb0hnqr6wk09n4zk9985qs9m7v44f03vfdsrbzvzx93wgkd"
} }

View File

@ -81,6 +81,7 @@
"blank-keycard-text": "You can proceed with your keycard once you've generated your keys and name", "blank-keycard-text": "You can proceed with your keycard once you've generated your keys and name",
"blank-keycard-title": "Looks like youve tapped \na blank keycard", "blank-keycard-title": "Looks like youve tapped \na blank keycard",
"block": "Block", "block": "Block",
"unblock": "Unblock",
"block-contact": "Block this user", "block-contact": "Block this user",
"block-contact-details": "Blocking will delete this user's previous messages and stop new ones from reaching you", "block-contact-details": "Blocking will delete this user's previous messages and stop new ones from reaching you",
"blocked-users": "Blocked users", "blocked-users": "Blocked users",
@ -276,6 +277,7 @@
"data": "Data", "data": "Data",
"datetime-ago": "ago", "datetime-ago": "ago",
"datetime-ago-format": "{{number}} {{time-intervals}} {{ago}}", "datetime-ago-format": "{{number}} {{time-intervals}} {{ago}}",
"datetime-ago-format-short": "{{number}}{{time-intervals}}",
"datetime-day": { "datetime-day": {
"one": "day", "one": "day",
"other": "days" "other": "days"
@ -292,6 +294,22 @@
"one": "second", "one": "second",
"other": "seconds" "other": "seconds"
}, },
"datetime-day-short": {
"one": "D",
"other": "D"
},
"datetime-hour-short": {
"one": "H",
"other": "H"
},
"datetime-minute-short": {
"one": "M",
"other": "M"
},
"datetime-second-short": {
"one": "S",
"other": "S"
},
"datetime-today": "today", "datetime-today": "today",
"datetime-yesterday": "yesterday", "datetime-yesterday": "yesterday",
"decimals": "Decimals", "decimals": "Decimals",
@ -1279,8 +1297,16 @@
"address-or-ens-name": "Address or ENS name", "address-or-ens-name": "Address or ENS name",
"name-optional": "Name (optional)", "name-optional": "Name (optional)",
"mute": "Mute", "mute": "Mute",
"unmute": "Unmute",
"scan-tokens": "Scan tokens", "scan-tokens": "Scan tokens",
"my-status": "My status",
"warning-sending-to-contract-descr": "The address you entered is a smart contract, sending funds to this address may result in loss of funds. To interact with a DApp, open the DApp in the Status DApp Browser.", "warning-sending-to-contract-descr": "The address you entered is a smart contract, sending funds to this address may result in loss of funds. To interact with a DApp, open the DApp in the Status DApp Browser.",
"contacts-descr": "Your contacts will appear here. You will receive status updates from anyone you add as a contact",
"status-updates-descr": "Status updates will appear here. Add the profile as a contact to receive updates on your timeline.",
"whats-on-your-mind": "Whats on your mind…",
"cant-open-public-chat": "Can't open public chat", "cant-open-public-chat": "Can't open public chat",
"invalid-public-chat-topic": "Invalid public chat topic" "invalid-public-chat-topic": "Invalid public chat topic",
"now": "Now",
"statuses-my-profile-descr": "Status updates are messages you publish to your profile. They can be viewed by anyone visiting your profile inside Status",
"new-status": "New status"
} }