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})}]
children))
(defn- icon-column
(defn icon-column
[{:keys [icon icon-bg-color icon-color size icon-container-style]}]
(when icon
(let [icon-size (size->icon-size size)]

View File

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

View File

@ -142,6 +142,15 @@
:image-path (utils/safe-replace image-path #"file://" "")
: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
[cofx audio-path duration current-chat-id]
(when-not (string/blank? audio-path)

View File

@ -28,7 +28,7 @@
add-timestamp))
;; 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?
"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")
identicon/identicon (constantly "generated")]
(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])]
(testing "it sets the name"
(is (= topic (:name chat))))

View File

@ -7,12 +7,6 @@
[status-im.navigation :as navigation]
[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
[{:keys [db] :as cofx}
public-key
@ -48,7 +42,7 @@
public-key)
(assoc :last-updated now)
(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
{:db (-> db
;; add the contact to blocked contacts
@ -61,7 +55,7 @@
(re-frame/dispatch [:hide-popover])))
;; reset navigation to avoid going back to non existing one to one chat
(if from-one-to-one-chat?
remove-current-chat-id
(navigation/navigate-to-cofx :home {})
(navigation/navigate-back)))))
(fx/defn unblock-contact

View File

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

View File

@ -1245,10 +1245,24 @@
(fn [{:keys [db]} [_ 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
(handlers/register-handler-fx
:screens/on-will-focus
(fn [cofx [_ view-id]]
(fn [{:keys [db] :as cofx} [_ view-id]]
(fx/merge cofx
#(case view-id
:keycard-settings (keycard/settings-screen-did-load %)
@ -1257,10 +1271,28 @@
:keycard-login-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 %)
;; We need this as if you click on universal-links you transition
;; from chat to chat, and therefore we won't be loading new
;; messages
:chat (chat.loading/load-messages %)
(:chat :group-chat-profile) (reset-current-chat % (get db :inactive-chat-id))
:multiaccounts (keycard/multiaccounts-screen-did-load %)
(: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))))
(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}})
(and public-key (not own))
(navigation/navigate-to-cofx (assoc-in cofx [:db :contacts/identity] public-key)
:tabs
{:screen :chat-stack
:params {:screen :profile}})
(fx/merge cofx
{:db (assoc db :contacts/identity public-key)
:dispatch [:navigate-to :profile]}
(navigation/navigate-back))
:else
{: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/cursor :chats/cursor)
(reg-root-key-sub :chats/input-with-mentions :chats/input-with-mentions)
(reg-root-key-sub :inactive-chat-id :inactive-chat-id)
;;browser
(reg-root-key-sub :browsers :browser/browsers)
(reg-root-key-sub :browser/options :browser/options)
@ -612,8 +613,8 @@
:chats/active-chats
:<- [::chats]
(fn [chats]
(reduce-kv (fn [acc id {:keys [is-active] :as chat}]
(if is-active
(reduce-kv (fn [acc id {:keys [is-active profile-public-key] :as chat}]
(if (and is-active (not profile-public-key))
(assoc acc id chat)
acc))
{}
@ -650,9 +651,10 @@
:chats/current-chat
:<- [:chats/current-raw-chat]
:<- [:multiaccount/public-key]
:<- [:inactive-chat-id]
(fn [[{:keys [group-chat] :as current-chat}
my-public-key]]
(when current-chat
my-public-key inactive-chat-id]]
(when (and current-chat (= (:chat-id current-chat) inactive-chat-id))
(cond-> current-chat
(chat.models/public-chat? current-chat)
(assoc :show-input? true)
@ -812,7 +814,7 @@
(re-frame/reg-sub
:chats/sending-image
:<- [:chats/current-chat]
:<- [:chats/current-raw-chat]
(fn [{:keys [metadata]}]
(get-in metadata [:sending-image])))

View File

@ -12,7 +12,9 @@
[taoensso.timbre :as log]))
(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]
(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

@ -13,6 +13,7 @@
(defn container-style [{:keys [animation minimized]}]
(merge {:flex-direction :row
:padding-vertical 4
:align-items :center}
(if-not minimized
(:base spacing/padding-horizontal)
@ -36,7 +37,8 @@
(when-not minimized
{: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]}]
(let [wrapper (if on-press
[rn/touchable-opacity {:on-press on-press}]
@ -78,5 +80,5 @@
subtitle]])]]
(when-not minimized
[animated/view {:pointer-events :none
:style (header-bottom-separator)}])]]))))
:style (when bottom-separator (header-bottom-separator))}])]]))))

View File

@ -75,7 +75,7 @@
(def tabs
(reagent/adapt-react-class
(fn [props]
(let [{:keys [navigate index route]} (bean props)
(let [{:keys [navigate index route state]} (bean props)
{:keys [keyboard-shown]
:or {keyboard-shown false}} (when platform/android? (rn/use-keyboard))
{:keys [bottom]} (safe-area/use-safe-area)
@ -99,7 +99,10 @@
[tab
{:icon icon
: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
:count-subscription count-subscription
:active? (= (str index) (str route-index))
@ -113,5 +116,6 @@
index (get state :index)]
(reagent/as-element
[tabs {:navigate navigate
:state (oget props "state")
:route (navigation/get-active-route-name state)
: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?
(fx/merge cofx
(contact/add-contact chat-key nil)
(navigation/navigate-to-cofx :contacts-list {}))
(navigation/navigate-to-cofx :my-profile {}))
(chat/start-chat cofx chat-key))
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (get-validation-label validation-result)

View File

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

View File

@ -159,7 +159,7 @@
:accessibility-label :delete-transaccent-button
: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 []
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])]
[react/view
@ -177,6 +177,7 @@
(when from-preview?
(re-frame/dispatch [:navigate-back]))
(hide-sheet-and-dispatch [:chat.ui/show-profile from]))}])
(when-not cant-be-replied
[quo/list-item
{:theme :accent
:title (i18n/label :t/message-reply)
@ -184,7 +185,7 @@
:on-press #(do
(when from-preview?
(re-frame/dispatch [:navigate-back]))
(hide-sheet-and-dispatch [:chat.ui/reply-to-message message]))}]
(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
#_[quo/list-item
{:theme :accent

View File

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

View File

@ -281,6 +281,7 @@
(fn []
(let [{:keys [chat-id show-input? group-chat admins invitation-admin] :as current-chat}
@(re-frame/subscribe [:chats/current-chat])]
(when current-chat
[react/view {:style {:flex 1}}
[connectivity/connectivity
[topbar]
@ -313,4 +314,4 @@
:set-active-panel set-active-panel
:text-input-ref text-input-ref
:on-text-change on-text-change}]
[bottom-sheet @active-panel]])]))))
[bottom-sheet @active-panel]])])))))

View File

@ -6,9 +6,9 @@
[status-im.ui.components.react :as react]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.i18n :as i18n]
[status-im.ui.components.invite.views :as invite]
[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]]))
(defn contacts-list-item [{:keys [public-key] :as contact}]
@ -21,21 +21,10 @@
:chevron true
: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 []
(letsubs [blocked-contacts-count [:contacts/blocked-count]
contacts [:contacts/active]]
[react/view {:flex 1}
[topbar/topbar {:title (i18n/label :t/contacts)}]
[react/scroll-view {:flex 1}
[add-new-contact]
[:<>
(when (pos? blocked-contacts-count)
[react/view {:margin-vertical 16}
[quo/list-item
@ -51,11 +40,27 @@
[list.views/flat-list
{:data contacts
:key-fn :address
:render-fn contacts-list-item}]
[react/view {:align-items :center :flex 1 :justify-content :center}
[react/text {:style {:color colors/gray :margin-vertical 24}}
(i18n/label :t/you-dont-have-contacts)]
[invite/button]])]]))
:render-fn contacts-list-item
:footer [react/view {:height 68}]}]
[react/view {:padding-horizontal 32 :margin-top 32}
[react/view {: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}
[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 []
(letsubs [blocked-contacts [:contacts/blocked]]

View File

@ -59,30 +59,6 @@
:margin-horizontal 40
: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
{:align-items :center
:justify-content :center})

View File

@ -19,7 +19,8 @@
[status-im.utils.utils :as utils]
[cljs-bean.core :as bean]
[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]))
(defn welcome-image-wrapper []
@ -158,16 +159,11 @@
(views/defview plus-button []
(views/letsubs [logging-in? [:multiaccounts/login]]
[react/view styles/action-button-container
[quo/button {:type :scale
:accessibility-label :new-chat-button
:on-press (when-not logging-in?
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))}
[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}])]]]))
[components.plus-button/plus-button
{:on-press (when-not logging-in?
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))
:loading logging-in?
:accessibility-label :new-chat-button}]))
(defn home []
[react/keyboard-avoiding-view {:style styles/home-container}

View File

@ -12,3 +12,13 @@
(def contact-profile-detail-share-icon
{: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.utils.platform :as platform]
[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]))
(defn actions
[{:keys [public-key added? tribute-to-talk] :as contact}]
(let [{:keys [tribute-status tribute-label]} tribute-to-talk]
(concat [(cond-> {:label (i18n/label :t/send-message)
[{:keys [public-key added? blocked?] :as contact} muted?]
(concat [{:label (i18n/label :t/chat)
:icon :main-icons/message
:action #(re-frame/dispatch [:contact.ui/send-message-pressed {:public-key public-key}])
:accessibility-label :start-conversation-button}
(not (#{:none :paid} tribute-status))
(assoc :subtext tribute-label))]
;;TODO hide temporary for v1
#_{:label (i18n/label :t/send-transaction)
:icon :main-icons/send
:action #(re-frame/dispatch [:profile/send-transaction public-key])
:accessibility-label :send-transaction-button}
:accessibility-label :start-conversation-button}]
(if added?
[{:label (i18n/label :t/remove-from-contacts)
:icon :main-icons/remove-contact
:selected true
:accessibility-label :in-contacts-button
:action #(re-frame/dispatch [:contact.ui/remove-contact-pressed contact])}]
;; TODO sheets temporary disabled
;:action #(re-frame/dispatch [:bottom-sheet/show-sheet
; {:content sheets/remove-contact
; :content-height 150}
; contact])
[{:label (i18n/label :t/add-to-contacts)
:icon :main-icons/add-contact
:accessibility-label :add-to-contacts-button
:action #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])}]))))
;; TODO sheets temporary disabled
;:action #(re-frame/dispatch [:bottom-sheet/show-sheet
; {:content sheets/add-contact
; :content-height 150}
; contact])
:action #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])}])
(when platform/ios?
[{:label (i18n/label (if muted? :t/unmute :t/mute))
:icon :main-icons/notification
:accessibility-label :mute-chat
:selected muted?
:action #(re-frame/dispatch [::chat.models/mute-chat-toggled public-key (not muted?)])}])
[{:label (i18n/label (if blocked? :t/unblock :t/block))
:negative true
:selected blocked?
:icon :main-icons/cancel
:action (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}]))
:accessibility-label (if blocked?
:unblock-contact
:block-contact)}]))
(defn render-detail [{:keys [public-key names name] :as detail}]
[quo/list-item
@ -78,9 +84,7 @@
(i18n/label :t/profile-details)]]
[render-detail contact]]))
(defn render-chat-settings [{:keys [public-key names]}]
(let [muted? (:muted @(re-frame/subscribe [:chats/chat public-key]))]
[react/view
(defn nickname-settings [{:keys [names]}]
[quo/list-item
{:title (i18n/label :t/nickname)
:size :small
@ -88,39 +92,7 @@
:accessory :text
:accessory-text (or (:nickname names) (i18n/label :t/none))
: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))]])
:chevron true}])
(defn save-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]]
[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/letsubs [{:keys [public-key name ens-verified]
: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
{:view :share-chat-key
:address public-key}
(when (and ens-verified name)
{:ens-name name}))])]
(when contact
[react/view
{:style
(merge {:flex 1})}
[react/view {:flex 1}
[quo/animated-header
{:use-insets true
{:use-insets false
:right-accessories [{:icon :main-icons/share
:accessibility-label :share-button
:on-press on-share}]
:left-accessories [{:icon :main-icons/arrow-left
:left-accessories [{:icon :main-icons/close
:accessibility-label :back-button
:on-press #(re-frame/dispatch [:navigate-back])}]
:extended-header (profile-header/extended-header
{:on-press on-share
:bottom-separator false
:title first-name
:photo (multiaccounts/displayed-photo contact)
:monospace (not ens-verified)
:subtitle second-name})}
[react/view {:padding-top 12}
(for [{:keys [label subtext accessibility-label icon action disabled?]} (actions contact)
[react/view {:height 1 :background-color colors/gray-lighter :margin-top 8}]
[nickname-settings 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]
^{:key label}
[quo/list-item {:theme :accent
:title label
:subtitle subtext
: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]]]))))
[button-item action])]
[react/view {:height 1 :background-color colors/gray-lighter :margin-top 16}]
[status]]]))))

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
{:margin-top 12
:margin-horizontal 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.universal-links.utils :as universal-links]
[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]))
(views/defview share-chat-key []
@ -55,14 +63,37 @@
:accessibility-label :share-my-contact-code-button}
(i18n/label :t/share-link)]]])))
(defn tribute-to-talk-item
[opts]
[quo/list-item
(merge {:title (i18n/label :t/tribute-to-talk)
:accessibility-label :notifications-button
:on-press #(re-frame/dispatch
[:tribute-to-talk.ui/menu-item-pressed])}
opts)])
(def state (reagent/atom {:tab :status}))
(defn tabs []
(let [{:keys [tab]} @state]
[react/view {:flex-direction :row :padding-horizontal 4 :margin-top 16}
[tabs/tab-title state :status (i18n/label :t/my-status) (= tab :status)]
[tabs/tab-title state :contacts (i18n/label :t/contacts) (= tab :contacts)]
[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 []
(let [{:keys [preferred-name
@ -70,10 +101,18 @@
notifications-enabled?
keycard-pairing]}
@(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])
registrar (stateofus/get-cached-registrar chain)]
registrar (stateofus/get-cached-registrar chain)
{:keys [tab]} @state]
[:<>
[tabs]
[react/view {:height 1 :background-color colors/gray-lighter}]
(cond
(= tab :status)
[my-status]
(= tab :contacts)
[contacts-list/contacts-list]
(= tab :settings)
[:<>
[quo/list-item
(cond-> {:title (or (when registrar preferred-name)
@ -93,21 +132,6 @@
:icon :main-icons/username}
registrar
(assoc :on-press #(re-frame/dispatch [:navigate-to :ens-main registrar])))]
;; TODO replace this with list-item config map
;; left it as it is because not sure how to enable it for testing
(when tribute-to-talk [tribute-to-talk-item tribute-to-talk])
[quo/list-item
{:title (i18n/label :t/contacts)
:icon :main-icons/in-contacts
:accessibility-label :contacts-button
:accessory :text
:accessory-text (if (pos? active-contacts-count)
(str active-contacts-count)
(i18n/label :t/none))
:chevron true
:on-press #(re-frame/dispatch [:navigate-to :contacts-list])}]
[react/view {:padding-top 16}
[quo/list-header (i18n/label :t/settings)]]
[quo/list-item
{:icon :main-icons/security
:title (i18n/label :t/privacy-and-security)
@ -186,7 +210,7 @@
:accessibility-label :log-out-button
:theme :negative
:on-press
#(re-frame/dispatch [:multiaccounts.logout.ui/logout-pressed])}]]]))
#(re-frame/dispatch [:multiaccounts.logout.ui/logout-pressed])}]]])]))
(defn my-profile []
(fn []
@ -195,10 +219,12 @@
on-share #(re-frame/dispatch [:show-popover
{:view :share-chat-key
:address public-key
:ens-name preferred-name}])]
[react/view {:style {:flex 1}}
:ens-name preferred-name}])
{:keys [tab]} @state]
[react/view {:flex 1}
[quo/animated-header
{:right-accessories [{:icon :main-icons/share
{:right-accessories [{:accessibility-label :share-header-button
:icon :main-icons/share
:on-press on-share}]
:use-insets true
:extended-header (profile-header/extended-header
@ -208,5 +234,11 @@
:monospace (not ens-verified)
:subtitle (if (and ens-verified public-key)
(gfy/generate-gfy public-key)
public-key)})}
[content]]])))
(utils/get-shortened-address public-key))
: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]
[status-im.ui.screens.home.views :as home]
[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.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.screens.stickers.views :as stickers]))
@ -16,14 +14,10 @@
[stack {:initial-route-name :home
:header-mode :none}
[{:name :home
:on-focus [::chat.models/offload-all-messages]
:style {:padding-bottom tabbar.styles/tabs-diff}
:component home/home}
{:name :chat
:component chat/chat}
{:name :profile
:insets {:top false}
:component profile.contact/profile}
{:name :group-chat-profile
:insets {:top false}
:component profile.group-chat/group-chat-profile}

View File

@ -35,6 +35,12 @@
(get-active-route-name (bean inner-state))
(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 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.profile.contact.views :as contact]
[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 bottom-tabs (navigation/create-bottom-tabs))
@ -135,7 +136,15 @@
{:name :request-transaction
:transition :presentation-ios
: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?
[{:name :quo-preview

View File

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

View File

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

View File

@ -58,17 +58,6 @@
[icons/icon :main-icons/add {:color colors/blue}]]
[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]]
(fn [{:keys [icon decimals amount color value] :as token}]
[quo/list-item

View File

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

View File

@ -72,9 +72,8 @@
public-key
(navigation/navigate-to-cofx (assoc-in cofx [:db :contacts/identity] public-key)
:tabs
{:screen :chat-stack
:params {:screen :profile}})))
:profile
{})))
(fx/defn handle-eip681 [cofx data]
(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",
"owner": "status-im",
"repo": "status-go",
"version": "v0.62.13",
"commit-sha1": "7467ca7b103f685dd64d73485555f90c181a4484",
"src-sha256": "0gv9jxn5c5arnxdr33rfw2zkly9c2nyss59vbdyf444140bd6y6y"
"version": "v0.62.14",
"commit-sha1": "b3880027710ee7a28bbdeacbe099412627485d62",
"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-title": "Looks like youve tapped \na blank keycard",
"block": "Block",
"unblock": "Unblock",
"block-contact": "Block this user",
"block-contact-details": "Blocking will delete this user's previous messages and stop new ones from reaching you",
"blocked-users": "Blocked users",
@ -276,6 +277,7 @@
"data": "Data",
"datetime-ago": "ago",
"datetime-ago-format": "{{number}} {{time-intervals}} {{ago}}",
"datetime-ago-format-short": "{{number}}{{time-intervals}}",
"datetime-day": {
"one": "day",
"other": "days"
@ -292,6 +294,22 @@
"one": "second",
"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-yesterday": "yesterday",
"decimals": "Decimals",
@ -1279,8 +1297,16 @@
"address-or-ens-name": "Address or ENS name",
"name-optional": "Name (optional)",
"mute": "Mute",
"unmute": "Unmute",
"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.",
"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",
"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"
}