mirror of
https://github.com/status-im/status-react.git
synced 2025-02-23 08:08:33 +00:00
Add TtT chat flow
Signed-off-by: yenda <eric@status.im>
This commit is contained in:
parent
75e20a0bbd
commit
04ccd0e7d8
@ -79,7 +79,7 @@ A whitelists B if:
|
||||
|
||||
The tribute payment is a regular SNT transaction greater or equal to the value of the snt-amount key in the manifest.
|
||||
|
||||
The id of the transaction is sent along messages in the payload top level `:tribute-tx-id` key as long as the sender isn't sure that he is whitelisted by the recipient (see `whitelisting rules` above).
|
||||
The id of the transaction is sent along messages in the payload top level `:tribute-transaction` key as long as the sender isn't sure that he is whitelisted by the recipient (see `whitelisting rules` above).
|
||||
|
||||
The UI in status app waits for 1 confirmation on chain before allowing the user to send a message to ensure the recipient will see the payment and not ignore the message.
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.commands.protocol :as protocol]
|
||||
[status-im.chat.commands.impl.transactions :as transactions]
|
||||
[status-im.contact.db :as db]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
(keyword (str (protocol/id type) "-button")))
|
||||
|
||||
(defn- contact->address [contact]
|
||||
(str "0x" (db/public-key->address contact)))
|
||||
(str "0x" (ethereum/public-key->address contact)))
|
||||
|
||||
(defn add-chat-contacts
|
||||
"Enrich command-message by adding contact list of the current private or group chat"
|
||||
|
@ -305,9 +305,9 @@
|
||||
protocol/Yielding
|
||||
(yield-control [_ {{{amount :amount asset :asset} :params} :content} {:keys [db] :as cofx}]
|
||||
;; Prefill wallet and navigate there
|
||||
(let [recipient-contact (or
|
||||
(get-in db [:contacts/contacts (:current-chat-id db)])
|
||||
(db.contact/public-key->new-contact (:current-chat-id db)))
|
||||
(let [recipient-contact (or
|
||||
(get-in db [:contacts/contacts (:current-chat-id db)])
|
||||
(db.contact/public-key->new-contact (:current-chat-id db)))
|
||||
|
||||
sender-account (:account/account db)
|
||||
chain (keyword (:chain db))
|
||||
|
@ -1,16 +1,17 @@
|
||||
(ns status-im.chat.models
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.accounts.db :as accounts.db]
|
||||
[status-im.contact-code.core :as contact-code]
|
||||
[status-im.contact.core :as contact.core]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.data-store.user-statuses :as user-statuses-store]
|
||||
[status-im.contact-code.core :as contact-code]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.transport.chat.core :as transport.chat]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.public-chat :as public-chat]
|
||||
[status-im.tribute-to-talk.core :as tribute-to-talk]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.desktop.events :as desktop.events]
|
||||
[status-im.ui.components.react :as react]
|
||||
@ -23,7 +24,8 @@
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.transport.partitioned-topic :as transport.topic]))
|
||||
[status-im.transport.partitioned-topic :as transport.topic]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn- get-chat [cofx chat-id]
|
||||
(get-in cofx [:db :chats chat-id]))
|
||||
@ -267,7 +269,8 @@
|
||||
(set-chat-ui-props {:validation-messages nil}))}
|
||||
(contact-code/listen-to-chat chat-id)
|
||||
(when platform/desktop?
|
||||
(mark-messages-seen chat-id))))
|
||||
(mark-messages-seen chat-id))
|
||||
(tribute-to-talk/check-tribute chat-id)))
|
||||
|
||||
(fx/defn navigate-to-chat
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
@ -345,3 +348,11 @@
|
||||
(re-frame/reg-fx
|
||||
:set-dock-badge-label
|
||||
set-dock-badge-label)
|
||||
|
||||
(fx/defn show-profile
|
||||
{:events [:chat.ui/show-profile]}
|
||||
[cofx identity]
|
||||
(fx/merge (assoc-in cofx [:db :contacts/identity] identity)
|
||||
(contact.core/create-contact identity)
|
||||
(tribute-to-talk/check-tribute identity)
|
||||
(navigation/navigate-to-cofx :profile nil)))
|
||||
|
@ -17,6 +17,7 @@
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.message.transit :as transit]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.tribute-to-talk.core :as tribute-to-talk]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.utils.datetime :as time]
|
||||
@ -473,6 +474,7 @@
|
||||
:whisper-timestamp (quot now 1000)
|
||||
:clock-value (utils.clocks/send
|
||||
last-clock-value))
|
||||
(tribute-to-talk/add-transaction-hash db)
|
||||
(add-message-type chat))]
|
||||
(upsert-and-send cofx message-data)))
|
||||
|
||||
|
@ -1,14 +1,16 @@
|
||||
(ns status-im.contact.core
|
||||
(:require [status-im.accounts.db :as accounts.db]
|
||||
[status-im.chat.models :as chat.models]
|
||||
[status-im.contact-code.core :as contact-code]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.contact.device-info :as device-info]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.transport.message.contact :as message.contact]
|
||||
[status-im.transport.message.protocol :as protocol]
|
||||
[status-im.transport.partitioned-topic :as transport.topic]
|
||||
[status-im.tribute-to-talk.db :as tribute-to-talk]
|
||||
[status-im.tribute-to-talk.whitelist :as whitelist]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.fx :as fx]))
|
||||
@ -16,10 +18,13 @@
|
||||
(fx/defn load-contacts
|
||||
[{:keys [db all-contacts]}]
|
||||
(let [contacts-list (map #(vector (:public-key %) %) all-contacts)
|
||||
contacts (into {} contacts-list)]
|
||||
{:db (-> db
|
||||
(update :contacts/contacts #(merge contacts %))
|
||||
(assoc :contacts/blocked (contact.db/get-blocked-contacts all-contacts)))}))
|
||||
contacts (into {} contacts-list)
|
||||
tr-to-talk-enabled? (-> db tribute-to-talk/get-settings tribute-to-talk/enabled?)]
|
||||
{:db (cond-> (-> db
|
||||
(update :contacts/contacts #(merge contacts %))
|
||||
(assoc :contacts/blocked (contact.db/get-blocked-contacts all-contacts)))
|
||||
tr-to-talk-enabled?
|
||||
(assoc :contacts/whitelist (whitelist/get-contact-whitelist all-contacts)))}))
|
||||
|
||||
(defn build-contact
|
||||
[{{:keys [chats] :account/keys [account]
|
||||
@ -58,7 +63,8 @@
|
||||
"Add a contact and set pending to false"
|
||||
[{:keys [db] :as cofx} public-key]
|
||||
(when (not= (get-in db [:account/account :public-key]) public-key)
|
||||
(let [contact (-> (build-contact cofx public-key)
|
||||
(let [contact (-> (get-in db [:contacts/contacts public-key]
|
||||
(build-contact cofx public-key))
|
||||
(update :system-tags
|
||||
(fnil #(conj % :contact/added) #{})))]
|
||||
(fx/merge cofx
|
||||
@ -68,9 +74,19 @@
|
||||
{:chat-ids [public-key]
|
||||
:topic (transport.topic/discovery-topic-hash)
|
||||
:fetch? false})
|
||||
(whitelist/add-to-whitelist public-key)
|
||||
(send-contact-request contact)
|
||||
(mailserver/process-next-messages-request)))))
|
||||
|
||||
(fx/defn create-contact
|
||||
"Create entry in contacts"
|
||||
[{:keys [db] :as cofx} public-key]
|
||||
(when (not= (get-in db [:account/account :public-key]) public-key)
|
||||
(let [contact (build-contact cofx public-key)]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:contacts/new-identity] "")}
|
||||
(upsert-contact contact)))))
|
||||
|
||||
(fx/defn add-contacts-filter [{:keys [db]} public-key action]
|
||||
(when (not= (get-in db [:account/account :public-key]) public-key)
|
||||
(let [current-public-key (get-in db [:account/account :public-key])]
|
||||
@ -116,7 +132,7 @@
|
||||
:name name
|
||||
:address (or address
|
||||
(:address contact)
|
||||
(contact.db/public-key->address public-key))
|
||||
(ethereum/public-key->address public-key))
|
||||
:device-info (device-info/merge-info
|
||||
timestamp
|
||||
(:device-info contact)
|
||||
@ -131,11 +147,6 @@
|
||||
(def receive-contact-request-confirmation handle-contact-update)
|
||||
(def receive-contact-update handle-contact-update)
|
||||
|
||||
(fx/defn open-chat
|
||||
[cofx public-key]
|
||||
(fx/merge cofx
|
||||
(chat.models/start-chat public-key {:navigation-reset? true})))
|
||||
|
||||
(fx/defn open-contact-toggle-list
|
||||
[{:keys [db :as cofx]}]
|
||||
(fx/merge cofx
|
||||
@ -143,3 +154,11 @@
|
||||
:group/selected-contacts #{}
|
||||
:new-chat-name "")}
|
||||
(navigation/navigate-to-cofx :contact-toggle-list nil)))
|
||||
|
||||
(fx/defn set-tribute
|
||||
[{:keys [db] :as cofx} public-key tribute-to-talk]
|
||||
(let [contact (-> (or (build-contact cofx public-key)
|
||||
(get-in db [:contacts/contacts public-key]))
|
||||
(assoc :tribute-to-talk (or tribute-to-talk
|
||||
{:disabled? true})))]
|
||||
{:db (assoc-in db [:contacts/contacts public-key] contact)}))
|
||||
|
@ -2,6 +2,7 @@
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.js-dependencies :as js-dependencies]
|
||||
[status-im.tribute-to-talk.db :as tribute-to-talk.db]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
status-im.utils.db))
|
||||
@ -10,29 +11,33 @@
|
||||
|
||||
;;Contact
|
||||
|
||||
(spec/def :contact/public-key :global/not-empty-string)
|
||||
(spec/def :contact/name :global/not-empty-string)
|
||||
(spec/def :contact/address (spec/nilable :global/address))
|
||||
(spec/def :contact/photo-path (spec/nilable string?))
|
||||
(spec/def :contact/fcm-token (spec/nilable string?))
|
||||
(spec/def :contact/last-updated (spec/nilable int?))
|
||||
(spec/def :contact/last-online (spec/nilable int?))
|
||||
(spec/def :contact/last-updated (spec/nilable int?))
|
||||
(spec/def :contact/name :global/not-empty-string)
|
||||
(spec/def :contact/public-key :global/not-empty-string)
|
||||
(spec/def :contact/photo-path (spec/nilable string?))
|
||||
|
||||
(spec/def :contact/tags (spec/coll-of string? :kind set?))
|
||||
;; contact/blocked: the user is blocked
|
||||
;; contact/added: the user was added to the contacts and a contact request was sent
|
||||
;; contact/request-received: the user sent a contact request
|
||||
(spec/def :contact/system-tags (spec/coll-of keyword? :kind set?))
|
||||
(spec/def :contact/tags (spec/coll-of string? :kind set?))
|
||||
(spec/def :contact/tribute (spec/nilable int?))
|
||||
(spec/def :contact/tribute-transaction (spec/nilable string?))
|
||||
|
||||
(spec/def :contact/contact (spec/keys :req-un [:contact/public-key
|
||||
(spec/def :contact/contact (spec/keys :req-un [:contact/address
|
||||
:contact/name
|
||||
:contact/address
|
||||
:contact/photo-path
|
||||
:contact/public-key
|
||||
:contact/system-tags]
|
||||
:opt-un [:contact/last-updated
|
||||
:opt-un [:contact/fcm-token
|
||||
:contact/last-online
|
||||
:contact/fcm-token
|
||||
:contact/tags]))
|
||||
:contact/last-updated
|
||||
:contact/tags
|
||||
:contact/tribute
|
||||
:contact/tribute-transaction]))
|
||||
|
||||
;;Contact list ui props
|
||||
(spec/def :contact-list-ui/edit? boolean?)
|
||||
@ -58,19 +63,9 @@
|
||||
(spec/def :contact/new-tag string?)
|
||||
(spec/def :ui/contact (spec/keys :opt [:contact/new-tag]))
|
||||
|
||||
(defn public-key->address [public-key]
|
||||
(let [length (count public-key)
|
||||
normalized-key (case length
|
||||
132 (subs public-key 4)
|
||||
130 (subs public-key 2)
|
||||
128 public-key
|
||||
nil)]
|
||||
(when normalized-key
|
||||
(subs (.sha3 (js-dependencies/web3-prototype) normalized-key #js {:encoding "hex"}) 26))))
|
||||
|
||||
(defn public-key->new-contact [public-key]
|
||||
{:name (gfycat/generate-gfy public-key)
|
||||
:address (public-key->address public-key)
|
||||
:address (ethereum/public-key->address public-key)
|
||||
:photo-path (identicon/identicon public-key)
|
||||
:public-key public-key
|
||||
:system-tags #{}})
|
||||
@ -168,12 +163,17 @@
|
||||
(active? (get-in db [:contacts/contacts public-key]))))
|
||||
|
||||
(defn enrich-contact
|
||||
[{:keys [system-tags] :as contact}]
|
||||
(assoc contact
|
||||
:pending? (pending? contact)
|
||||
:blocked? (blocked? contact)
|
||||
:active? (active? contact)
|
||||
:added? (contains? system-tags :contact/added)))
|
||||
[{:keys [system-tags tribute-to-talk] :as contact}]
|
||||
(let [tribute (:snt-amount tribute-to-talk)
|
||||
tribute-status (tribute-to-talk.db/tribute-status contact)
|
||||
tribute-label (tribute-to-talk.db/status-label tribute-status tribute)]
|
||||
(-> contact
|
||||
(assoc-in [:tribute-to-talk :tribute-status] tribute-status)
|
||||
(assoc-in [:tribute-to-talk :tribute-label] tribute-label)
|
||||
(assoc :pending? (pending? contact)
|
||||
:blocked? (blocked? contact)
|
||||
:active? (active? contact)
|
||||
:added? (contains? system-tags :contact/added)))))
|
||||
|
||||
(defn enrich-contacts
|
||||
[contacts]
|
||||
|
@ -1,10 +1,12 @@
|
||||
(ns status-im.data-store.contacts
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.data-store.realm.core :as core]))
|
||||
|
||||
(defn- deserialize-contact [contact]
|
||||
(-> contact
|
||||
(update :tags #(into #{} %))
|
||||
(update :tribute-to-talk core/deserialize)
|
||||
(update :system-tags
|
||||
#(reduce (fn [acc s]
|
||||
(conj acc (keyword (subs s 1))))
|
||||
@ -14,7 +16,8 @@
|
||||
(defn- serialize-contact [contact]
|
||||
(-> contact
|
||||
(update :device-info #(or (vals %) []))
|
||||
(update :system-tags #(mapv str %))))
|
||||
(update :system-tags #(mapv str %))
|
||||
(update :tribute-to-talk core/serialize)))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:data-store/get-all-contacts
|
||||
|
@ -128,3 +128,5 @@
|
||||
:system-tags {:type "string[]"}
|
||||
:device-info {:type :list
|
||||
:objectType :contact-device-info}}})
|
||||
|
||||
(def v8 (assoc-in v7 [:properties :tribute-to-talk] {:type :string :optional true}))
|
||||
|
@ -1,23 +1,23 @@
|
||||
(ns status-im.data-store.realm.schemas.account.core
|
||||
(:require [status-im.data-store.realm.schemas.account.chat :as chat]
|
||||
[status-im.data-store.realm.schemas.account.transport :as transport]
|
||||
[status-im.data-store.realm.schemas.account.transport-inbox-topic :as transport-inbox-topic]
|
||||
[status-im.data-store.realm.schemas.account.mailserver-topic :as mailserver-topic]
|
||||
(:require [status-im.data-store.realm.schemas.account.browser :as browser]
|
||||
[status-im.data-store.realm.schemas.account.chat :as chat]
|
||||
[status-im.data-store.realm.schemas.account.chat-requests-range :as chat-requests-range]
|
||||
[status-im.data-store.realm.schemas.account.contact :as contact]
|
||||
[status-im.data-store.realm.schemas.account.message :as message]
|
||||
[status-im.data-store.realm.schemas.account.user-status :as user-status]
|
||||
[status-im.data-store.realm.schemas.account.contact-device-info :as contact-device-info]
|
||||
[status-im.data-store.realm.schemas.account.contact-recovery :as contact-recovery]
|
||||
[status-im.data-store.realm.schemas.account.dapp-permissions :as dapp-permissions]
|
||||
[status-im.data-store.realm.schemas.account.installation :as installation]
|
||||
[status-im.data-store.realm.schemas.account.local-storage :as local-storage]
|
||||
[status-im.data-store.realm.schemas.account.mailserver :as mailserver]
|
||||
[status-im.data-store.realm.schemas.account.browser :as browser]
|
||||
[status-im.data-store.realm.schemas.account.dapp-permissions :as dapp-permissions]
|
||||
[status-im.data-store.realm.schemas.account.request :as request]
|
||||
[status-im.data-store.realm.schemas.account.membership-update :as membership-update]
|
||||
[status-im.data-store.realm.schemas.account.installation :as installation]
|
||||
[status-im.data-store.realm.schemas.account.contact-recovery :as contact-recovery]
|
||||
[status-im.data-store.realm.schemas.account.mailserver-requests-gap :as mailserver-requests-gap]
|
||||
[status-im.data-store.realm.schemas.account.mailserver-topic :as mailserver-topic]
|
||||
[status-im.data-store.realm.schemas.account.membership-update :as membership-update]
|
||||
[status-im.data-store.realm.schemas.account.message :as message]
|
||||
[status-im.data-store.realm.schemas.account.migrations :as migrations]
|
||||
[status-im.data-store.realm.schemas.account.chat-requests-range :as chat-requests-range]))
|
||||
[status-im.data-store.realm.schemas.account.request :as request]
|
||||
[status-im.data-store.realm.schemas.account.transport :as transport]
|
||||
[status-im.data-store.realm.schemas.account.transport-inbox-topic :as transport-inbox-topic]
|
||||
[status-im.data-store.realm.schemas.account.user-status :as user-status]))
|
||||
|
||||
(def v1 [chat/v1
|
||||
transport/v1
|
||||
@ -512,6 +512,23 @@
|
||||
contact-recovery/v1
|
||||
mailserver-requests-gap/v1])
|
||||
|
||||
(def v44 [chat/v15
|
||||
chat-requests-range/v1
|
||||
transport/v8
|
||||
contact/v8
|
||||
message/v10
|
||||
mailserver/v11
|
||||
mailserver-topic/v2
|
||||
user-status/v2
|
||||
membership-update/v1
|
||||
installation/v3
|
||||
local-storage/v1
|
||||
browser/v8
|
||||
dapp-permissions/v9
|
||||
contact-device-info/v1
|
||||
contact-recovery/v1
|
||||
mailserver-requests-gap/v1])
|
||||
|
||||
;; put schemas ordered by version
|
||||
(def schemas [{:schema v1
|
||||
:schemaVersion 1
|
||||
@ -641,4 +658,7 @@
|
||||
:migration migrations/v42}
|
||||
{:schema v43
|
||||
:schemaVersion 43
|
||||
:migration (constantly nil)}
|
||||
{:schema v44
|
||||
:schemaVersion 44
|
||||
:migration (constantly nil)}])
|
||||
|
@ -6,7 +6,7 @@
|
||||
{:mainnet "0x744d70fdbe2ba4cf95131626614a1763df805b9e"
|
||||
:testnet "0xc55cf4b03948d7ebc8b9e8bad92643703811d162"}
|
||||
:status/tribute-to-talk
|
||||
{:testnet "0x3da3fc53e24707f36c5b4433b442e896c4955f0e"}
|
||||
{:testnet "0xC61aa0287247a0398589a66fCD6146EC0F295432"}
|
||||
:status/stickers
|
||||
{:testnet "0x39d16CdB56b5a6a89e1A397A13Fe48034694316E"}})
|
||||
|
||||
|
@ -70,6 +70,11 @@
|
||||
network (get-in db [:account/account :networks network-id])]
|
||||
(network->chain-keyword network)))
|
||||
|
||||
(defn snt-symbol [db]
|
||||
(case (chain-keyword db)
|
||||
:mainnet :SNT
|
||||
:STT))
|
||||
|
||||
(defn sha3
|
||||
([s]
|
||||
(.sha3 (dependencies/web3-prototype) (str s)))
|
||||
@ -88,3 +93,16 @@
|
||||
(and address1 address2
|
||||
(= (normalized-address address1)
|
||||
(normalized-address address2))))
|
||||
|
||||
(defn public-key->address [public-key]
|
||||
(let [length (count public-key)
|
||||
normalized-key (case length
|
||||
132 (subs public-key 4)
|
||||
130 (subs public-key 2)
|
||||
128 public-key
|
||||
nil)]
|
||||
(when normalized-key
|
||||
(subs (.sha3 (dependencies/web3-prototype)
|
||||
normalized-key
|
||||
#js {:encoding "hex"})
|
||||
26))))
|
||||
|
@ -6,6 +6,7 @@
|
||||
[status-im.accounts.logout.core :as accounts.logout]
|
||||
[status-im.accounts.recover.core :as accounts.recover]
|
||||
[status-im.accounts.update.core :as accounts.update]
|
||||
[status-im.biometric-auth.core :as biomentric-auth]
|
||||
[status-im.bootnodes.core :as bootnodes]
|
||||
[status-im.browser.core :as browser]
|
||||
[status-im.browser.permissions :as browser.permissions]
|
||||
@ -43,7 +44,6 @@
|
||||
[status-im.stickers.core :as stickers]
|
||||
[status-im.transport.core :as transport]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.tribute-to-talk.core :as tribute-to-talk]
|
||||
[status-im.ui.components.bottom-sheet.core :as bottom-sheet]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.add-new.new-chat.db :as new-chat.db]
|
||||
@ -58,11 +58,10 @@
|
||||
[status-im.utils.logging.core :as logging]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.wallet.custom-tokens.core :as custom-tokens]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[status-im.web3.core :as web3]
|
||||
[status-im.biometric-auth.core :as biomentric-auth]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.wallet.custom-tokens.core :as custom-tokens]))
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
;; init module
|
||||
|
||||
@ -868,12 +867,6 @@
|
||||
(fn [cofx [_ chat-id message-id]]
|
||||
(chat.message/toggle-expand-message cofx chat-id message-id)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/show-profile
|
||||
(fn [cofx [_ identity]]
|
||||
(navigation/navigate-to-cofx
|
||||
(assoc-in cofx [:db :contacts/identity] identity) :profile nil)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/set-chat-input-text
|
||||
(fn [cofx [_ text]]
|
||||
@ -1940,97 +1933,7 @@
|
||||
(stickers/pending-timeout cofx)))
|
||||
|
||||
;; Tribute to Talk
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/menu-item-pressed
|
||||
(fn [cofx _]
|
||||
(tribute-to-talk/open-settings cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/learn-more-pressed
|
||||
(fn [cofx _]
|
||||
(tribute-to-talk/open-learn-more cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/step-back-pressed
|
||||
(fn [cofx _]
|
||||
(tribute-to-talk/step-back cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/step-forward-pressed
|
||||
(fn [cofx _]
|
||||
(tribute-to-talk/step-forward cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/numpad-key-pressed
|
||||
(fn [cofx [_ numpad-key]]
|
||||
(tribute-to-talk/update-snt-amount cofx numpad-key)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/message-changed
|
||||
(fn [cofx [_ message]]
|
||||
(tribute-to-talk/update-message cofx message)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/edit-pressed
|
||||
(fn [cofx _]
|
||||
(tribute-to-talk/start-editing cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/remove-pressed
|
||||
(fn [cofx _]
|
||||
(tribute-to-talk/remove cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.callback/check-manifest-success
|
||||
(fn [cofx [_ identity contenthash]]
|
||||
(tribute-to-talk/fetch-manifest cofx identity contenthash)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.callback/no-manifest-found
|
||||
(fn [cofx [_ identity]]
|
||||
(tribute-to-talk/update-settings cofx nil)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.callback/fetch-manifest-success
|
||||
(fn [cofx [_ identity {:keys [tribute-to-talk]}]]
|
||||
(tribute-to-talk/update-settings cofx tribute-to-talk)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.callback/fetch-manifest-failure
|
||||
(fn [cofx [_ identity contenthash]]
|
||||
(tribute-to-talk/fetch-manifest cofx identity contenthash)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.ui/check-manifest
|
||||
(fn [{:keys [db] :as cofx} [_ identity]]
|
||||
(tribute-to-talk/check-manifest cofx identity)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.callback/manifest-uploaded
|
||||
(fn [cofx [_ hash]]
|
||||
(tribute-to-talk/set-manifest-signing-flow cofx hash)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.callback/manifest-upload-failed
|
||||
(fn [cofx [_ error]]
|
||||
(tribute-to-talk/on-manifest-upload-failed cofx error)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.callback/set-manifest-transaction-completed
|
||||
(fn [cofx [_ id transaction-hash method]]
|
||||
(tribute-to-talk/on-set-manifest-transaction-completed cofx
|
||||
transaction-hash)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk.callback/set-manifest-transaction-failed
|
||||
(fn [cofx [_ error]]
|
||||
(tribute-to-talk/on-set-manifest-transaction-failed cofx
|
||||
error)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:tribute-to-talk/check-set-manifest-transaction-timeout
|
||||
(fn [cofx _]
|
||||
(tribute-to-talk/check-set-manifest-transaction cofx)))
|
||||
|
||||
;; bottom-sheet events
|
||||
(handlers/register-handler-fx
|
||||
|
@ -8,6 +8,7 @@
|
||||
[status-im.chat.commands.input :as commands.input]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.chat.db :as chat.db]
|
||||
[status-im.chat.models :as chat.models]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
@ -15,8 +16,13 @@
|
||||
[status-im.ethereum.transactions.etherscan :as transactions.etherscan]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.fleet.core :as fleet]
|
||||
[status-im.group-chats.db :as group-chats.db]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.tribute-to-talk.core :as tribute-to-talk]
|
||||
[status-im.tribute-to-talk.db :as tribute-to-talk.db]
|
||||
[status-im.tribute-to-talk.whitelist :as whitelist]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.toolbar.styles :as toolbar.styles]
|
||||
[status-im.ui.screens.add-new.new-public-chat.db :as db]
|
||||
[status-im.ui.screens.chat.stickers.styles :as stickers.styles]
|
||||
@ -34,7 +40,6 @@
|
||||
[status-im.utils.universal-links.core :as links]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
status-im.tribute-to-talk.subs
|
||||
status-im.ui.screens.hardwallet.connect.subs
|
||||
status-im.ui.screens.hardwallet.settings.subs
|
||||
status-im.ui.screens.hardwallet.pin.subs
|
||||
@ -473,16 +478,103 @@
|
||||
(fn [[contacts chats account]]
|
||||
(chat.db/active-chats contacts chats account)))
|
||||
|
||||
(defn enrich-current-one-to-one-chat
|
||||
[{:keys [contact] :as current-chat} my-public-key ttt-settings
|
||||
chain-keyword prices currency]
|
||||
(let [{:keys [tribute-to-talk]} contact
|
||||
{:keys [disabled? snt-amount message]} tribute-to-talk
|
||||
whitelisted-by? (whitelist/whitelisted-by? contact)
|
||||
loading? (and (not whitelisted-by?)
|
||||
(not tribute-to-talk))
|
||||
show-input? (or whitelisted-by?
|
||||
disabled?)
|
||||
token (case chain-keyword
|
||||
:mainnet :SNT
|
||||
:STT)
|
||||
tribute-status (if loading?
|
||||
:loading
|
||||
(tribute-to-talk.db/tribute-status contact))
|
||||
tribute-label (tribute-to-talk.db/status-label tribute-status snt-amount)]
|
||||
|
||||
(cond-> (assoc current-chat
|
||||
:tribute-to-talk/tribute-status tribute-status
|
||||
:tribute-to-talk/tribute-label tribute-label)
|
||||
|
||||
(#{:required :pending :paid} tribute-status)
|
||||
(assoc :tribute-to-talk/snt-amount
|
||||
(tribute-to-talk.db/from-wei snt-amount)
|
||||
:tribute-to-talk/message
|
||||
message
|
||||
:tribute-to-talk/fiat-amount (if snt-amount
|
||||
(money/fiat-amount-value
|
||||
snt-amount
|
||||
token
|
||||
(-> currency :code keyword)
|
||||
prices)
|
||||
"0")
|
||||
:tribute-to-talk/fiat-currency (:code currency)
|
||||
:tribute-to-talk/token (str " " (name token)))
|
||||
|
||||
(tribute-to-talk.db/enabled? ttt-settings)
|
||||
(assoc :tribute-to-talk/received? (tribute-to-talk.db/tribute-received?
|
||||
contact))
|
||||
|
||||
(= tribute-status :required)
|
||||
(assoc :tribute-to-talk/on-share-my-profile
|
||||
#(re-frame/dispatch
|
||||
[:profile/share-profile-link my-public-key]))
|
||||
|
||||
show-input?
|
||||
(assoc :show-input? true))))
|
||||
|
||||
(defn enrich-current-chat
|
||||
[{:keys [messages chat-id might-have-join-time-messages?] :as chat}
|
||||
ranges height input-height]
|
||||
(assoc chat
|
||||
:height height
|
||||
:input-height input-height
|
||||
:range
|
||||
(get ranges chat-id)
|
||||
:intro-status
|
||||
(if might-have-join-time-messages?
|
||||
:loading
|
||||
(if (empty? messages)
|
||||
:empty
|
||||
:messages))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat
|
||||
:<- [:chats/active-chats]
|
||||
:<- [:chats/current-chat-id]
|
||||
(fn [[chats current-chat-id]]
|
||||
(let [current-chat (get chats current-chat-id)
|
||||
messages (:messages current-chat)]
|
||||
(if (empty? messages)
|
||||
(assoc current-chat :universal-link (links/generate-link :public-chat :external current-chat-id))
|
||||
current-chat))))
|
||||
:<- [:account/public-key]
|
||||
:<- [:mailserver/ranges]
|
||||
:<- [:chats/content-layout-height]
|
||||
:<- [:chats/current-chat-ui-prop :input-height]
|
||||
:<- [:tribute-to-talk/settings]
|
||||
:<- [:ethereum/chain-keyword]
|
||||
:<- [:prices]
|
||||
:<- [:wallet/currency]
|
||||
(fn [[chats current-chat-id my-public-key ranges height
|
||||
input-height ttt-settings chain-keyword prices currency]]
|
||||
(let [{:keys [group-chat contact messages]
|
||||
:as current-chat}
|
||||
(get chats current-chat-id)]
|
||||
(when current-chat
|
||||
(cond-> (enrich-current-chat current-chat ranges height input-height)
|
||||
(empty? messages)
|
||||
(assoc :universal-link
|
||||
(links/generate-link :public-chat :external current-chat-id))
|
||||
|
||||
(chat.models/public-chat? current-chat)
|
||||
(assoc :show-input? true)
|
||||
|
||||
(and (chat.models/group-chat? current-chat)
|
||||
(group-chats.db/joined? my-public-key current-chat))
|
||||
(assoc :show-input? true)
|
||||
|
||||
(not group-chat)
|
||||
(enrich-current-one-to-one-chat my-public-key ttt-settings
|
||||
chain-keyword prices currency))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat-message
|
||||
@ -1217,12 +1309,6 @@
|
||||
(fn [wallet]
|
||||
(:send-transaction wallet)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.send/symbol
|
||||
:<- [::send-transaction]
|
||||
(fn [send-transaction]
|
||||
(:symbol send-transaction)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:wallet.send/advanced?
|
||||
:<- [::send-transaction]
|
||||
@ -1271,10 +1357,12 @@
|
||||
edit)))
|
||||
|
||||
(defn check-sufficient-funds
|
||||
[transaction balance symbol amount]
|
||||
(assoc transaction :sufficient-funds?
|
||||
(or (nil? amount)
|
||||
(money/sufficient-funds? amount (get balance symbol)))))
|
||||
[{:keys [sufficient-funds?] :as transaction} balance symbol amount]
|
||||
(cond-> transaction
|
||||
(nil? sufficient-funds?)
|
||||
(assoc :sufficient-funds?
|
||||
(or (nil? amount)
|
||||
(money/sufficient-funds? amount (get balance symbol))))))
|
||||
|
||||
(defn check-sufficient-gas
|
||||
[transaction balance symbol amount]
|
||||
@ -1691,3 +1779,99 @@
|
||||
:<- [:search/filter]
|
||||
(fn [[chats search-filter]]
|
||||
(apply-filter search-filter chats extract-chat-attributes)))
|
||||
|
||||
;; TRIBUTE TO TALK
|
||||
(re-frame/reg-sub
|
||||
:tribute-to-talk/settings
|
||||
:<- [:account-settings]
|
||||
:<- [:ethereum/chain-keyword]
|
||||
(fn [[settings chain-keyword]]
|
||||
(get-in settings [:tribute-to-talk chain-keyword])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:tribute-to-talk/screen-params
|
||||
:<- [:screen-params]
|
||||
(fn [screen-params]
|
||||
(get screen-params :tribute-to-talk)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:tribute-to-talk/profile
|
||||
:<- [:tribute-to-talk/settings]
|
||||
:<- [:tribute-to-talk/screen-params]
|
||||
(fn [[{:keys [seen? snt-amount]}
|
||||
{:keys [state unavailable?]}]]
|
||||
(let [state (or state (if snt-amount :completed :disabled))
|
||||
snt-amount (tribute-to-talk.db/from-wei snt-amount)]
|
||||
(when config/tr-to-talk-enabled?
|
||||
(if unavailable?
|
||||
{:subtext "Change network to enable Tribute to Talk"
|
||||
:active? false
|
||||
:icon :main-icons/tribute-to-talk
|
||||
:icon-color colors/gray}
|
||||
(cond-> {:new? (not seen?)}
|
||||
(and (not (and seen?
|
||||
snt-amount
|
||||
(#{:signing :pending :transaction-failed :completed} state))))
|
||||
(assoc :subtext (i18n/label :t/tribute-to-talk-desc))
|
||||
|
||||
(#{:signing :pending} state)
|
||||
(assoc :activity-indicator {:animating true
|
||||
:color colors/blue}
|
||||
:subtext (case state
|
||||
:pending (i18n/label :t/pending-confirmation)
|
||||
:signing (i18n/label :t/waiting-to-sign)))
|
||||
|
||||
(= state :transaction-failed)
|
||||
(assoc :icon :main-icons/warning
|
||||
:icon-color colors/red
|
||||
:subtext (i18n/label :t/transaction-failed))
|
||||
|
||||
(not (#{:signing :pending :transaction-failed} state))
|
||||
(assoc :icon :main-icons/tribute-to-talk)
|
||||
|
||||
(and (= state :completed)
|
||||
(not-empty snt-amount))
|
||||
(assoc :accessory-value (str snt-amount " SNT"))))))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:tribute-to-talk/enabled?
|
||||
:<- [:tribute-to-talk/settings]
|
||||
(fn [settings]
|
||||
(tribute-to-talk.db/enabled? settings)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:tribute-to-talk/settings-ui
|
||||
:<- [:tribute-to-talk/settings]
|
||||
:<- [:tribute-to-talk/screen-params]
|
||||
:<- [:prices]
|
||||
:<- [:wallet/currency]
|
||||
(fn [[{:keys [seen? snt-amount message]
|
||||
:as settings}
|
||||
{:keys [step editing? state error]
|
||||
:or {step :intro}
|
||||
screen-snt-amount :snt-amount
|
||||
screen-message :message} prices currency]]
|
||||
(let [fiat-value (if snt-amount
|
||||
(money/fiat-amount-value
|
||||
snt-amount
|
||||
:SNT
|
||||
(-> currency :code keyword)
|
||||
prices)
|
||||
"0")]
|
||||
(cond-> {:seen? seen?
|
||||
:snt-amount (tribute-to-talk.db/from-wei snt-amount)
|
||||
:message message
|
||||
:enabled? (tribute-to-talk.db/enabled? settings)
|
||||
:error error
|
||||
:step step
|
||||
:state (or state (if snt-amount :completed :disabled))
|
||||
:editing? editing?
|
||||
:fiat-value (str "~" fiat-value " " (:code currency))}
|
||||
|
||||
(= step :set-snt-amount)
|
||||
(assoc :snt-amount (str screen-snt-amount)
|
||||
:disable-button?
|
||||
(boolean (and (= step :set-snt-amount)
|
||||
(or (string/blank? screen-snt-amount)
|
||||
(#{"0" "0.0" "0.00"} screen-snt-amount)
|
||||
(string/ends-with? screen-snt-amount ".")))))))))
|
||||
|
@ -1,13 +1,13 @@
|
||||
(ns ^{:doc "API for whisper filters"}
|
||||
status-im.transport.filters
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.transport.utils :as utils]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.transport.partitioned-topic :as transport.topic]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.contact.core :as contact]))
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn- receive-message [chat-id js-error js-message]
|
||||
(re-frame/dispatch [:transport/messages-received js-error js-message chat-id]))
|
||||
@ -97,7 +97,7 @@
|
||||
(contact/add-contact public-key)
|
||||
|
||||
:open-chat
|
||||
(contact/open-chat public-key)))]
|
||||
(chat/start-chat public-key {:navigation-reset? true})))]
|
||||
filters-fx-fns
|
||||
[(mailserver/process-next-messages-request)])))))
|
||||
|
||||
|
@ -4,8 +4,9 @@
|
||||
[status-im.accounts.db :as accounts.db]
|
||||
[status-im.chat.core :as chat]
|
||||
[status-im.transport.db :as transport.db]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.transport.partitioned-topic :as transport.topic]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.tribute-to-talk.whitelist :as whitelist]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.utils.fx :as fx]
|
||||
[taoensso.timbre :as log]))
|
||||
@ -114,19 +115,24 @@
|
||||
(send-direct-message current-public-key nil this)
|
||||
(send-with-pubkey params)))))
|
||||
(receive [this chat-id signature timestamp cofx]
|
||||
{:chat-received-message/add-fx
|
||||
[(assoc (into {} this)
|
||||
:old-message-id (transport.utils/old-message-id this)
|
||||
:message-id (transport.utils/message-id
|
||||
signature
|
||||
(.-payload (:js-obj cofx)))
|
||||
:chat-id chat-id
|
||||
:whisper-timestamp timestamp
|
||||
:raw-payload-hash (transport.utils/sha3
|
||||
(.-payload (:js-obj cofx)))
|
||||
:from signature
|
||||
:dedup-id (:dedup-id cofx)
|
||||
:js-obj (:js-obj cofx))]})
|
||||
(let [received-message-fx {:chat-received-message/add-fx
|
||||
[(assoc (into {} this)
|
||||
:old-message-id (transport.utils/old-message-id this)
|
||||
:message-id (transport.utils/message-id
|
||||
signature
|
||||
(.-payload (:js-obj cofx)))
|
||||
:chat-id chat-id
|
||||
:whisper-timestamp timestamp
|
||||
:raw-payload-hash (transport.utils/sha3
|
||||
(.-payload (:js-obj cofx)))
|
||||
:from signature
|
||||
:dedup-id (:dedup-id cofx)
|
||||
:js-obj (:js-obj cofx))]}]
|
||||
(whitelist/filter-message cofx
|
||||
received-message-fx
|
||||
message-type
|
||||
(get-in this [:content :tribute-transaction])
|
||||
signature)))
|
||||
(validate [this]
|
||||
(if (spec/valid? :message/message this)
|
||||
this
|
||||
|
@ -3,18 +3,33 @@
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.accounts.update.core :as accounts.update]
|
||||
[status-im.contact.core :as contact]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.ethereum.contracts :as contracts]
|
||||
[status-im.ethereum.core :as ethereum]
|
||||
[status-im.ethereum.json-rpc :as json-rpc]
|
||||
[status-im.ipfs.core :as ipfs]
|
||||
[status-im.ethereum.tokens :as tokens]
|
||||
[status-im.ethereum.transactions.core :as transactions]
|
||||
[status-im.tribute-to-talk.db :as tribute-to-talk.db]
|
||||
[status-im.tribute-to-talk.whitelist :as whitelist]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.contenthash :as contenthash]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.wallet.core :as wallet]
|
||||
[status-im.wallet.db :as wallet.db]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn add-transaction-hash
|
||||
[message db]
|
||||
(let [to (get-in message [:content :chat-id])
|
||||
tribute-transaction-hash
|
||||
(get-in db [:contacts/contacts to :tribute-to-talk :transaction-hash])]
|
||||
(if tribute-transaction-hash
|
||||
(assoc-in message
|
||||
[:content :tribute-transaction]
|
||||
tribute-transaction-hash)
|
||||
message)))
|
||||
|
||||
(fx/defn update-settings
|
||||
[{:keys [db] :as cofx} {:keys [snt-amount message update] :as new-settings}]
|
||||
(let [account-settings (get-in db [:account/account :settings])
|
||||
@ -30,12 +45,13 @@
|
||||
(and (contains? new-settings :update)
|
||||
(nil? update))
|
||||
(dissoc :update))]
|
||||
(accounts.update/update-settings
|
||||
cofx
|
||||
(-> account-settings
|
||||
(assoc-in [:tribute-to-talk chain-keyword]
|
||||
tribute-to-talk-settings))
|
||||
{})))
|
||||
(fx/merge cofx
|
||||
(accounts.update/update-settings
|
||||
(-> account-settings
|
||||
(assoc-in [:tribute-to-talk chain-keyword]
|
||||
tribute-to-talk-settings))
|
||||
{})
|
||||
(whitelist/enable-whitelist))))
|
||||
|
||||
(fx/defn mark-ttt-as-seen
|
||||
[{:keys [db] :as cofx}]
|
||||
@ -43,6 +59,7 @@
|
||||
(update-settings cofx {:seen? true})))
|
||||
|
||||
(fx/defn open-settings
|
||||
{:events [:tribute-to-talk.ui/menu-item-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [settings (tribute-to-talk.db/get-settings db)
|
||||
updated-settings (:update settings)]
|
||||
@ -59,25 +76,53 @@
|
||||
(:snt-amount settings)
|
||||
(merge {:step :edit
|
||||
:editing? true}
|
||||
(update settings :snt-amount tribute-to-talk.db/from-wei))
|
||||
(update settings :snt-amount tribute-to-talk.db/from-wei))
|
||||
:else
|
||||
{:step :intro})))))
|
||||
{:step :intro
|
||||
:snt-amount "0"})))))
|
||||
|
||||
(fx/defn set-step
|
||||
[{:keys [db]} step]
|
||||
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk :step] step)})
|
||||
|
||||
(fx/defn set-step-finish
|
||||
(fx/defn set-tribute-signing-flow
|
||||
[{:keys [db] :as cofx} tribute]
|
||||
(if-let [contract (contracts/get-address db :status/tribute-to-talk)]
|
||||
(wallet/eth-transaction-call
|
||||
cofx
|
||||
{:contract contract
|
||||
:method "setTribute(uint256)"
|
||||
:params [tribute]
|
||||
:on-result [:tribute-to-talk.callback/set-tribute-transaction-sent]
|
||||
:on-error [:tribute-to-talk.callback/set-tribute-transaction-failed]})
|
||||
{:db (assoc-in db
|
||||
[:navigation/screen-params :tribute-to-talk :state]
|
||||
:transaction-failed)}))
|
||||
|
||||
(fx/defn remove
|
||||
{:events [:tribute-to-talk.ui/remove-pressed]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk :state] :signing)}
|
||||
(set-step :finish)))
|
||||
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk]
|
||||
{:step :finish
|
||||
:state :disabled})}
|
||||
(set-tribute-signing-flow 0)))
|
||||
|
||||
(fx/defn set-step-finish
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [tribute (get-in db [:navigation/screen-params :tribute-to-talk :snt-amount])]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk :state] :signing)}
|
||||
(set-tribute-signing-flow (tribute-to-talk.db/to-wei tribute))
|
||||
(set-step :finish))))
|
||||
|
||||
(fx/defn open-learn-more
|
||||
{:events [:tribute-to-talk.ui/learn-more-pressed]}
|
||||
[cofx]
|
||||
(set-step cofx :learn-more))
|
||||
|
||||
(fx/defn step-back
|
||||
{:events [:tribute-to-talk.ui/step-back-pressed]}
|
||||
[cofx]
|
||||
(let [{:keys [step editing?]}
|
||||
(get-in cofx [:db :navigation/screen-params :tribute-to-talk])]
|
||||
@ -90,31 +135,11 @@
|
||||
:edit
|
||||
:intro))
|
||||
|
||||
:personalized-message
|
||||
(set-step cofx :set-snt-amount)
|
||||
|
||||
:finish
|
||||
(set-step cofx :personalized-message))))
|
||||
|
||||
(fx/defn upload-manifest
|
||||
[cofx]
|
||||
(let [{:keys [message snt-amount]}
|
||||
(get-in cofx [:db :navigation/screen-params :tribute-to-talk])
|
||||
manifest {:tribute-to-talk
|
||||
{:message message
|
||||
:snt-amount (tribute-to-talk.db/to-wei snt-amount)}}]
|
||||
(ipfs/add cofx
|
||||
{:value (js/JSON.stringify
|
||||
(clj->js manifest))
|
||||
:on-success
|
||||
(fn [response]
|
||||
[:tribute-to-talk.callback/manifest-uploaded
|
||||
(:hash response)])
|
||||
:on-failure
|
||||
(fn [error]
|
||||
[:tribute-to-talk.callback/manifest-upload-failed error])})))
|
||||
(set-step cofx :set-snt-amount))))
|
||||
|
||||
(fx/defn step-forward
|
||||
{:events [:tribute-to-talk.ui/step-forward-pressed]}
|
||||
[cofx]
|
||||
(let [{:keys [step editing?]}
|
||||
(get-in cofx [:db :navigation/screen-params :tribute-to-talk])]
|
||||
@ -123,12 +148,7 @@
|
||||
(set-step cofx :set-snt-amount)
|
||||
|
||||
:set-snt-amount
|
||||
(set-step cofx :personalized-message)
|
||||
|
||||
:personalized-message
|
||||
(fx/merge cofx
|
||||
(set-step-finish)
|
||||
(upload-manifest))
|
||||
(set-step-finish cofx)
|
||||
|
||||
:finish
|
||||
(navigation/navigate-back cofx))))
|
||||
@ -154,161 +174,219 @@
|
||||
(and (string/includes? snt-amount ".")
|
||||
(> (count (second (string/split snt-amount #"\."))) 1))
|
||||
snt-amount
|
||||
;; Disallow values larger or equal to 1 million
|
||||
(>= (js/parseFloat (str snt-amount numpad-symbol))
|
||||
tribute-to-talk.db/max-snt-amount)
|
||||
snt-amount
|
||||
;; Replace initial "0" by the first digit
|
||||
(and (= snt-amount "0") (not= numpad-symbol "."))
|
||||
(str numpad-symbol)
|
||||
:else (str snt-amount numpad-symbol)))))
|
||||
|
||||
(fx/defn update-snt-amount
|
||||
{:events [:tribute-to-talk.ui/numpad-key-pressed]}
|
||||
[{:keys [db]} numpad-symbol]
|
||||
{:db (update-in db
|
||||
[:navigation/screen-params :tribute-to-talk :snt-amount]
|
||||
#(get-new-snt-amount % numpad-symbol))})
|
||||
|
||||
(fx/defn update-message
|
||||
[{:keys [db]} message]
|
||||
{:db (assoc-in db
|
||||
[:navigation/screen-params :tribute-to-talk :message]
|
||||
message)})
|
||||
|
||||
(fx/defn start-editing
|
||||
{:events [:tribute-to-talk.ui/edit-pressed]}
|
||||
[{:keys [db]}]
|
||||
{:db (assoc-in db
|
||||
[:navigation/screen-params :tribute-to-talk :step]
|
||||
:set-snt-amount)})
|
||||
|
||||
(fx/defn fetch-manifest
|
||||
[{:keys [db] :as cofx} identity contenthash]
|
||||
(contenthash/cat cofx
|
||||
{:contenthash contenthash
|
||||
:on-failure
|
||||
(fn [error]
|
||||
(re-frame/dispatch
|
||||
(if (= 503 error)
|
||||
[:tribute-to-talk.callback/fetch-manifest-failure
|
||||
identity contenthash]
|
||||
[:tribute-to-talk.callback/no-manifest-found identity])))
|
||||
:on-success
|
||||
(fn [manifest-json]
|
||||
(let [manifest (js->clj (js/JSON.parse manifest-json)
|
||||
:keywordize-keys true)]
|
||||
(re-frame/dispatch
|
||||
[:tribute-to-talk.callback/fetch-manifest-success
|
||||
identity manifest])))}))
|
||||
(fx/defn on-check-tribute-success
|
||||
{:events [:tribute-to-talk.callback/check-tribute-success]}
|
||||
[cofx public-key tribute-to-talk]
|
||||
(let [tribute-to-talk (when (tribute-to-talk.db/valid? tribute-to-talk)
|
||||
tribute-to-talk)]
|
||||
(if-let [me? (= public-key
|
||||
(get-in cofx [:db :account/account :public-key]))]
|
||||
(update-settings cofx tribute-to-talk)
|
||||
(contact/set-tribute cofx public-key tribute-to-talk))))
|
||||
|
||||
(fx/defn on-no-tribute-found
|
||||
{:events [:tribute-to-talk.callback/no-tribute-found]}
|
||||
[cofx public-key]
|
||||
(if-let [me? (= public-key
|
||||
(get-in cofx [:db :account/account :public-key]))]
|
||||
(update-settings cofx nil)
|
||||
(contact/set-tribute cofx public-key nil)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:tribute-to-talk/get-manifest
|
||||
:tribute-to-talk/get-tribute
|
||||
(fn [{:keys [contract address on-success]}]
|
||||
(json-rpc/eth-call
|
||||
{:contract contract
|
||||
:method "getManifest(address)"
|
||||
:method "getTribute(address)"
|
||||
:params [address]
|
||||
:outputs ["bytes"]
|
||||
:outputs ["uint256"]
|
||||
:on-success on-success})))
|
||||
|
||||
(fx/defn check-manifest
|
||||
(fx/defn check-tribute
|
||||
[{:keys [db] :as cofx} public-key]
|
||||
(if-let [contract (contracts/get-address db :status/tribute-to-talk)]
|
||||
(let [address (contact.db/public-key->address public-key)]
|
||||
{:tribute-to-talk/get-manifest
|
||||
{:contract contract
|
||||
:address address
|
||||
:on-success
|
||||
(fn [[contenthash]]
|
||||
(re-frame/dispatch
|
||||
(if contenthash
|
||||
[:tribute-to-talk.callback/check-manifest-success
|
||||
public-key
|
||||
contenthash]
|
||||
[:tribute-to-talk.callback/no-manifest-found public-key])))}})
|
||||
;; update settings if checking own manifest or do nothing otherwise
|
||||
(when-let [me? (= identity
|
||||
(get-in cofx [:db :account/account :public-key]))]
|
||||
(update-settings cofx nil))))
|
||||
|
||||
(fx/defn check-own-manifest
|
||||
[cofx]
|
||||
(check-manifest cofx (get-in cofx [:db :account/account :public-key])))
|
||||
|
||||
(fx/defn set-manifest-signing-flow
|
||||
[{:keys [db] :as cofx} hash]
|
||||
(let [contenthash (when hash
|
||||
(contenthash/encode {:hash hash
|
||||
:namespace :ipfs}))]
|
||||
(when (and (not (get-in db [:chats public-key :group-chat]))
|
||||
(not (get-in db [:contacts/contacts public-key :tribute-to-talk
|
||||
:transaction-hash]))
|
||||
(not (whitelist/whitelisted?
|
||||
(get-in db [:contacts/contacts public-key]))))
|
||||
(if-let [contract (contracts/get-address db :status/tribute-to-talk)]
|
||||
(wallet/eth-transaction-call
|
||||
cofx
|
||||
{:contract contract
|
||||
:method "setManifest(bytes)"
|
||||
:params [contenthash]
|
||||
:on-result [:tribute-to-talk.callback/set-manifest-transaction-completed]
|
||||
:on-error [:tribute-to-talk.callback/set-manifest-transaction-failed]})
|
||||
{:db (assoc-in db
|
||||
[:navigation/screen-params :tribute-to-talk :state]
|
||||
:transaction-failed)})))
|
||||
(let [address (ethereum/public-key->address public-key)]
|
||||
{:tribute-to-talk/get-tribute
|
||||
{:contract contract
|
||||
:address address
|
||||
:on-success
|
||||
(fn [[tribute]]
|
||||
(re-frame/dispatch
|
||||
(if (pos? tribute)
|
||||
[:tribute-to-talk.callback/check-tribute-success
|
||||
public-key
|
||||
{:snt-amount (str tribute)}]
|
||||
[:tribute-to-talk.callback/no-tribute-found public-key])))}})
|
||||
;; update settings if checking own manifest or do nothing otherwise
|
||||
(if-let [me? (= public-key
|
||||
(get-in cofx [:db :account/account :public-key]))]
|
||||
|
||||
(fx/defn remove
|
||||
[{:keys [db] :as cofx}]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db
|
||||
[:navigation/screen-params :tribute-to-talk :unavailable?]
|
||||
true)}
|
||||
(update-settings nil))
|
||||
(contact/set-tribute cofx public-key nil)))))
|
||||
|
||||
(fx/defn check-own-tribute
|
||||
[cofx]
|
||||
(check-tribute cofx (get-in cofx [:db :account/account :public-key])))
|
||||
|
||||
(fx/defn pay-tribute
|
||||
{:events [:tribute-to-talk.ui/on-pay-to-chat-pressed]}
|
||||
[{:keys [db] :as cofx} public-key]
|
||||
(let [{:keys [name address public-key tribute-to-talk] :as recipient-contact}
|
||||
(get-in db [:contacts/contacts public-key])
|
||||
{:keys [snt-amount]} tribute-to-talk
|
||||
symbol (ethereum/snt-symbol db)
|
||||
wallet-balance (get-in db [:wallet :balance symbol]
|
||||
(money/bignumber 0))
|
||||
amount-text (str (tribute-to-talk.db/from-wei snt-amount))]
|
||||
(wallet/eth-transaction-call
|
||||
cofx
|
||||
{:contract (contracts/get-address db :status/snt)
|
||||
:method "transfer(address,uint256)"
|
||||
:params [address snt-amount]
|
||||
:details {:to-name name
|
||||
:public-key public-key
|
||||
:from-chat? true
|
||||
:asset symbol
|
||||
:amount-text amount-text
|
||||
:sufficient-funds?
|
||||
(money/sufficient-funds? snt-amount wallet-balance)
|
||||
:send-transaction-message? true}
|
||||
:on-result [:tribute-to-talk.callback/pay-tribute-transaction-sent
|
||||
public-key]})))
|
||||
|
||||
(defn tribute-transaction-trigger
|
||||
[db {:keys [block error?]}]
|
||||
(let [current-block (get db :ethereum/current-block)
|
||||
transaction-block (or block
|
||||
current-block)]
|
||||
(or error?
|
||||
(pos? (- current-block
|
||||
(js/parseInt transaction-block))))))
|
||||
|
||||
(fx/defn on-pay-tribute-transaction-triggered
|
||||
[{:keys [db] :as cofx}
|
||||
public-key
|
||||
{:keys [error? transfer symbol] :as transaction}]
|
||||
(when (and transfer
|
||||
(= symbol (ethereum/snt-symbol db))
|
||||
(not error?))
|
||||
(whitelist/mark-tribute-paid cofx public-key)))
|
||||
|
||||
(fx/defn on-pay-tribute-transaction-sent
|
||||
{:events [:tribute-to-talk.callback/pay-tribute-transaction-sent]}
|
||||
[{:keys [db] :as cofx} public-key id transaction-hash method]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk]
|
||||
{:step :finish
|
||||
:state :disabled})}
|
||||
(set-manifest-signing-flow nil)))
|
||||
{:db (assoc-in db [:contacts/contacts public-key
|
||||
:tribute-to-talk :transaction-hash]
|
||||
transaction-hash)}
|
||||
(navigation/navigate-to-clean :wallet-transaction-sent-modal {})
|
||||
(transactions/watch-transaction
|
||||
transaction-hash
|
||||
{:trigger-fn
|
||||
tribute-transaction-trigger
|
||||
:on-trigger
|
||||
#(on-pay-tribute-transaction-triggered public-key %)})))
|
||||
|
||||
(fx/defn check-set-manifest-transaction
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [transaction (get-in (tribute-to-talk.db/get-settings db) [:update :transaction])]
|
||||
(when transaction
|
||||
(let [confirmed? (pos? (js/parseInt
|
||||
(get-in cofx [:db :wallet :transactions
|
||||
transaction :confirmations]
|
||||
0)))
|
||||
;;TODO support failed transactions
|
||||
failed? false]
|
||||
(cond
|
||||
failed?
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk :state] :transaction-failed)}
|
||||
(update-settings {:update nil}))
|
||||
(fx/defn on-set-tribute-transaction-triggered
|
||||
[{:keys [db] :as cofx}
|
||||
tribute
|
||||
{:keys [error?] :as transaction}]
|
||||
(if error?
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:navigation/screen-params
|
||||
:tribute-to-talk :state]
|
||||
:transaction-failed)}
|
||||
(update-settings {:update nil}))
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:navigation/screen-params
|
||||
:tribute-to-talk :state]
|
||||
(if tribute
|
||||
:completed
|
||||
:disabled))}
|
||||
(check-own-tribute)
|
||||
(update-settings {:update nil}))))
|
||||
|
||||
confirmed?
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk :state] :completed)}
|
||||
check-own-manifest
|
||||
(update-settings {:update nil}))
|
||||
|
||||
(not confirmed?)
|
||||
{:dispatch-later [{:ms 10000
|
||||
:dispatch [:tribute-to-talk/check-set-manifest-transaction-timeout]}]})))))
|
||||
|
||||
(fx/defn on-set-manifest-transaction-completed
|
||||
[{:keys [db] :as cofx} transaction-hash]
|
||||
(fx/defn on-set-tribute-transaction-sent
|
||||
{:events [:tribute-to-talk.callback/set-tribute-transaction-sent]}
|
||||
[{:keys [db] :as cofx} id transaction-hash method]
|
||||
(let [{:keys [snt-amount message]} (get-in db [:navigation/screen-params
|
||||
:tribute-to-talk])]
|
||||
(fx/merge cofx
|
||||
{:db (assoc-in db [:navigation/screen-params :tribute-to-talk :state] :pending)}
|
||||
{:db (assoc-in db [:navigation/screen-params
|
||||
:tribute-to-talk :state]
|
||||
:pending)}
|
||||
(navigation/navigate-to-clean :wallet-transaction-sent-modal {})
|
||||
(update-settings {:update {:transaction transaction-hash
|
||||
:snt-amount snt-amount
|
||||
:message message}})
|
||||
check-set-manifest-transaction)))
|
||||
(transactions/watch-transaction
|
||||
transaction-hash
|
||||
{:trigger-fn
|
||||
tribute-transaction-trigger
|
||||
:on-trigger
|
||||
#(on-set-tribute-transaction-triggered snt-amount %)}))))
|
||||
|
||||
(fx/defn on-set-manifest-transaction-failed
|
||||
(fx/defn on-set-tribute-transaction-failed
|
||||
{:events [:tribute-to-talk.callback/set-tribute-transaction-failed]}
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/error :set-manifest-transaction-failed error)
|
||||
(log/error :set-tribute-transaction-failed error)
|
||||
{:db (assoc-in db
|
||||
[:navigation/screen-params :tribute-to-talk :state]
|
||||
:transaction-failed)})
|
||||
|
||||
(fx/defn on-manifest-upload-failed
|
||||
[{:keys [db] :as cofx} error]
|
||||
(log/error :upload-manifest-failed error)
|
||||
{:db (assoc-in db
|
||||
[:navigation/screen-params :tribute-to-talk :state]
|
||||
:transaction-failed)})
|
||||
(fx/defn watch-set-tribute-transaction
|
||||
"check if there is a pending transaction to set the tribute and
|
||||
add a watch on that transaction
|
||||
if there is a transaction check if the trigger is valid already"
|
||||
[{:keys [db] :as cofx}]
|
||||
(when-let [tribute-update (get (tribute-to-talk.db/get-settings db)
|
||||
:update)]
|
||||
(let [{:keys [transaction snt-amount]} tribute-update]
|
||||
(fx/merge cofx
|
||||
(transactions/watch-transaction
|
||||
transaction
|
||||
{:trigger-fn
|
||||
tribute-transaction-trigger
|
||||
:on-trigger
|
||||
#(on-set-tribute-transaction-triggered snt-amount %)})
|
||||
(when-let [transaction (get-in db [:wallet :transactions
|
||||
transaction])]
|
||||
(transactions/check-transaction transaction))))))
|
||||
|
||||
(fx/defn init
|
||||
[cofx]
|
||||
(fx/merge cofx
|
||||
check-own-manifest
|
||||
check-set-manifest-transaction))
|
||||
(check-own-tribute)
|
||||
(watch-set-tribute-transaction)))
|
||||
|
@ -1,6 +1,14 @@
|
||||
(ns status-im.tribute-to-talk.db
|
||||
(:require [status-im.ethereum.core :as ethereum]
|
||||
[status-im.js-dependencies :as dependencies]))
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.js-dependencies :as dependencies]
|
||||
[status-im.utils.money :as money]))
|
||||
|
||||
(defn tribute-received?
|
||||
[contact]
|
||||
(contains? (:system-tags contact) :tribute-to-talk/received))
|
||||
|
||||
(def max-snt-amount 1000000)
|
||||
|
||||
(defn utils [] (dependencies/web3-utils))
|
||||
|
||||
@ -14,11 +22,52 @@
|
||||
(when s
|
||||
(.fromWei (utils) s)))
|
||||
|
||||
(defn tribute-status
|
||||
[{:keys [system-tags tribute-to-talk] :as contact}]
|
||||
(let [{:keys [snt-amount transaction-hash]} tribute-to-talk]
|
||||
(cond (contains? system-tags :tribute-to-talk/paid) :paid
|
||||
(not (nil? transaction-hash)) :pending
|
||||
(pos? snt-amount) :required
|
||||
:else :none)))
|
||||
|
||||
(defn status-label
|
||||
[tribute-status tribute]
|
||||
(case tribute-status
|
||||
:paid (i18n/label :t/tribute-state-paid)
|
||||
:pending (i18n/label :t/tribute-state-pending)
|
||||
:required (i18n/label :t/tribute-state-required
|
||||
{:snt-amount (from-wei tribute)})
|
||||
nil))
|
||||
|
||||
(defn valid?
|
||||
[{:keys [snt-amount]}]
|
||||
(when (string? snt-amount)
|
||||
(try (let [converted-snt-amount (from-wei snt-amount)]
|
||||
(and (= (to-wei converted-snt-amount)
|
||||
snt-amount)
|
||||
(< 0 (js/parseFloat converted-snt-amount) max-snt-amount)))
|
||||
(catch :default err nil))))
|
||||
|
||||
(defn get-settings
|
||||
[db]
|
||||
(let [chain-keyword (ethereum/chain-keyword db)]
|
||||
(get-in db [:account/account :settings :tribute-to-talk chain-keyword])))
|
||||
|
||||
(defn enabled?
|
||||
[db]
|
||||
(:snt-amount (get-settings db)))
|
||||
[settings]
|
||||
(:snt-amount settings))
|
||||
|
||||
(defn valid-tribute-transaction?
|
||||
[db tribute-required tribute-transaction from-public-key]
|
||||
(let [{:keys [value block from] :as transaction}
|
||||
(get-in db [:wallet :transactions tribute-transaction])
|
||||
current-block (get db :ethereum/current-block)
|
||||
transaction-block (or block
|
||||
current-block)]
|
||||
(and transaction
|
||||
(pos? (- current-block
|
||||
(js/parseInt transaction-block)))
|
||||
(.lessThanOrEqualTo (money/bignumber tribute-required)
|
||||
(money/bignumber value))
|
||||
(ethereum/address= (ethereum/public-key->address from-public-key)
|
||||
from))))
|
||||
|
@ -1,54 +0,0 @@
|
||||
(ns status-im.tribute-to-talk.subs
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.tribute-to-talk.db :as tribute-to-talk]
|
||||
[status-im.utils.money :as money]))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:tribute-to-talk/settings
|
||||
(fn [db]
|
||||
(tribute-to-talk/get-settings db)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:tribute-to-talk/screen-params
|
||||
(fn [db]
|
||||
(get-in db [:navigation/screen-params :tribute-to-talk])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:tribute-to-talk/ui
|
||||
:<- [:tribute-to-talk/settings]
|
||||
:<- [:tribute-to-talk/screen-params]
|
||||
:<- [:prices]
|
||||
:<- [:wallet/currency]
|
||||
(fn [[{:keys [seen? snt-amount message update]}
|
||||
{:keys [step editing? state error]
|
||||
:or {step :intro}
|
||||
screen-snt-amount :snt-amount
|
||||
screen-message :message} prices currency]]
|
||||
(let [fiat-value (if snt-amount
|
||||
(money/fiat-amount-value
|
||||
snt-amount
|
||||
:SNT
|
||||
(-> currency :code keyword)
|
||||
prices)
|
||||
"0")]
|
||||
(cond-> {:seen? seen?
|
||||
:snt-amount (tribute-to-talk/from-wei snt-amount)
|
||||
:message message
|
||||
:disabled? (nil? snt-amount)
|
||||
:error error
|
||||
:step step
|
||||
:state (or state (if snt-amount :completed :disabled))
|
||||
:editing? editing?
|
||||
:fiat-value (str "~" fiat-value " " (:code currency))}
|
||||
|
||||
(= step :set-snt-amount)
|
||||
(assoc :snt-amount (str screen-snt-amount)
|
||||
:disable-button?
|
||||
(boolean (and (= step :set-snt-amount)
|
||||
(or (string/blank? screen-snt-amount)
|
||||
(#{"0" "0.0" "0.00"} screen-snt-amount)
|
||||
(string/ends-with? screen-snt-amount ".")))))
|
||||
|
||||
(= step :personalized-message)
|
||||
(assoc :message screen-message)))))
|
78
src/status_im/tribute_to_talk/whitelist.cljs
Normal file
78
src/status_im/tribute_to_talk/whitelist.cljs
Normal file
@ -0,0 +1,78 @@
|
||||
(ns status-im.tribute-to-talk.whitelist
|
||||
(:require [status-im.contact.db :as contact.db]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.tribute-to-talk.db :as tribute-to-talk.db]
|
||||
[status-im.utils.fx :as fx]))
|
||||
|
||||
(defn whitelisted-by? [{:keys [system-tags]}]
|
||||
(or (contains? system-tags :contact/request-received)
|
||||
(contains? system-tags :tribute-to-talk/paid)
|
||||
(contains? system-tags :tribute-to-talk/received)))
|
||||
|
||||
(defn whitelisted? [{:keys [system-tags]}]
|
||||
(or (contains? system-tags :contact/added)
|
||||
(contains? system-tags :tribute-to-talk/paid)
|
||||
(contains? system-tags :tribute-to-talk/received)))
|
||||
|
||||
(defn get-contact-whitelist
|
||||
[contacts]
|
||||
(reduce (fn [acc {:keys [public-key] :as contact}]
|
||||
(if (whitelisted? contact)
|
||||
(conj acc public-key) acc))
|
||||
(hash-set) contacts))
|
||||
|
||||
(fx/defn add-to-whitelist
|
||||
"Add contact to whitelist"
|
||||
[{:keys [db]} public-key]
|
||||
{:db (update db :contacts/whitelist (fnil conj #{}) public-key)})
|
||||
|
||||
(defn- mark-tribute
|
||||
[{:keys [db now] :as cofx} public-key tag]
|
||||
(let [contact (-> (contact.db/public-key->contact
|
||||
(:contacts/contacts db)
|
||||
public-key)
|
||||
(assoc :last-updated now)
|
||||
(update :system-tags conj tag))]
|
||||
(fx/merge cofx
|
||||
{:db (-> db
|
||||
(assoc-in [:contacts/contacts public-key] contact))
|
||||
:data-store/tx [(contacts-store/save-contact-tx contact)]}
|
||||
(add-to-whitelist public-key))))
|
||||
|
||||
(fx/defn mark-tribute-paid
|
||||
[cofx public-key]
|
||||
(mark-tribute cofx public-key :tribute-to-talk/paid))
|
||||
|
||||
(fx/defn mark-tribute-received
|
||||
[cofx public-key]
|
||||
(mark-tribute cofx public-key :tribute-to-talk/received))
|
||||
|
||||
(fx/defn enable-whitelist
|
||||
[{:keys [db] :as cofx}]
|
||||
(if (tribute-to-talk.db/enabled? (tribute-to-talk.db/get-settings db))
|
||||
{:db (assoc db :contacts/whitelist
|
||||
(get-contact-whitelist (vals (:contacts/contacts db))))}
|
||||
{:db (dissoc db :contacts/whitelist)}))
|
||||
|
||||
(fx/defn filter-message
|
||||
"clojure semantics of filter, if true the message is allowed
|
||||
if it is a user message and tribute to talk is enabled, the user must be
|
||||
in the whitelist or there must be a valid tribute transaction id passed
|
||||
along the message"
|
||||
[{:keys [db] :as cofx} received-message-fx message-type tribute-transaction from]
|
||||
;; if it is not a user-message or the user is whitelisted it passes
|
||||
(if (or (not= :user-message message-type)
|
||||
(contains? (:contacts/whitelist db) from))
|
||||
received-message-fx
|
||||
;; if ttt is disabled it passes
|
||||
(if-let [snt-amount (:snt-amount (tribute-to-talk.db/get-settings db))]
|
||||
(let [contact (get-in db [:contacts/contacts from])]
|
||||
;; if the tribute is not paid the message is dropped
|
||||
;; otherwise it passes and the user is added to the whitelist
|
||||
;; through system tags
|
||||
(when (tribute-to-talk.db/valid-tribute-transaction?
|
||||
db snt-amount tribute-transaction from)
|
||||
(fx/merge cofx
|
||||
received-message-fx
|
||||
(mark-tribute-received from))))
|
||||
received-message-fx)))
|
@ -96,6 +96,18 @@
|
||||
(when dapp?
|
||||
[dapp-badge styles])])
|
||||
|
||||
(defn contact-icon-view-chat [contact]
|
||||
[contact-icon-view contact
|
||||
{:container styles/container-chat-list
|
||||
:online-view-wrapper styles/online-view-wrapper
|
||||
:online-view styles/online-view
|
||||
:online-dot-left styles/online-dot-left
|
||||
:online-dot-right styles/online-dot-right
|
||||
:size 60
|
||||
:chat-icon styles/chat-icon-chat-list
|
||||
:default-chat-icon (styles/default-chat-icon-chat-list colors/default-chat-color)
|
||||
:default-chat-icon-text styles/default-chat-icon-text}])
|
||||
|
||||
(defn contact-icon-contacts-tab [contact]
|
||||
[contact-icon-view contact
|
||||
{:container styles/container-chat-list
|
||||
|
@ -3,7 +3,7 @@
|
||||
[status-im.react-native.js-dependencies :as rn-dependencies]
|
||||
[status-im.ui.components.qr-code-viewer.styles :as styles]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.profile.tribute-to-talk.views :as tr-to-talk])
|
||||
[status-im.ui.screens.profile.tribute-to-talk.views :as tribute-to-talk])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn qr-code [props]
|
||||
@ -11,16 +11,17 @@
|
||||
(rn-dependencies/qr-code)
|
||||
(clj->js (merge {:inverted true} props))))
|
||||
|
||||
(defview qr-code-viewer-component [{:keys [style hint-style footer-style footer-button value hint legend]}]
|
||||
(letsubs [{:keys [width]} [:dimensions/window]
|
||||
{:keys [disabled?]} [:tribute-to-talk/ui]]
|
||||
[(react/scroll-view) {:content-container-style {:align-items :center
|
||||
:margin-top 16
|
||||
:justify-content :center}
|
||||
:style (merge {:flex 1} style)}
|
||||
(when-not disabled?
|
||||
(defview qr-code-viewer-component
|
||||
[{:keys [style hint-style footer-style footer-button value hint legend
|
||||
show-tribute-to-talk-warning?]}]
|
||||
(letsubs [{:keys [width]} [:dimensions/window]]
|
||||
[(react/scroll-view) {:content-container-style {:align-items :center
|
||||
:margin-top 16
|
||||
:justify-content :center}
|
||||
:style (merge {:flex 1} style)}
|
||||
(when show-tribute-to-talk-warning?
|
||||
[react/view {:style {:margin-horizontal 16}}
|
||||
[tr-to-talk/enabled-note]])
|
||||
[tribute-to-talk/enabled-note]])
|
||||
(when width
|
||||
(let [size (int (min width styles/qr-code-max-width))]
|
||||
[react/view {:style (styles/qr-code-container size)
|
||||
@ -40,8 +41,9 @@
|
||||
:margin-bottom 16}}
|
||||
[footer-button value]])]))
|
||||
|
||||
(defn qr-code-viewer [{:keys [style hint-style footer-style footer-button value hint legend]
|
||||
:as params}]
|
||||
(defn qr-code-viewer
|
||||
[{:keys [style hint-style footer-style footer-button value hint legend]
|
||||
:as params}]
|
||||
(if value
|
||||
[qr-code-viewer-component params]
|
||||
[react/view [react/text "no value"]]))
|
||||
|
@ -21,13 +21,12 @@
|
||||
|
||||
(views/defview gap
|
||||
[{:keys [gaps first-gap?]} idx list-ref]
|
||||
(views/letsubs [in-progress? [:chats/fetching-gap-in-progress?
|
||||
(views/letsubs [{:keys [range intro-status]} [:chats/current-chat]
|
||||
in-progress? [:chats/fetching-gap-in-progress?
|
||||
(if first-gap?
|
||||
[:first-gap]
|
||||
(:ids gaps))]
|
||||
connected? [:mailserver/connected?]
|
||||
range [:chats/range]
|
||||
intro-status [:chats/current-chat-intro-status]]
|
||||
connected? [:mailserver/connected?]]
|
||||
(let [ids (:ids gaps)
|
||||
intro-loading? (= intro-status :loading)]
|
||||
(when-not (and first-gap? intro-loading?)
|
||||
@ -52,4 +51,3 @@
|
||||
"\n"
|
||||
(i18n/label :t/load-messages-before
|
||||
{:date date})))])])]]]))))
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
(ns status-im.ui.screens.chat.photos
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.chat.styles.photos :as style]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.image :as utils.image]))
|
||||
[status-im.utils.image :as utils.image])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn photo [photo-path {:keys [size
|
||||
accessibility-label]}]
|
||||
@ -14,10 +14,10 @@
|
||||
:accessibility-label (or accessibility-label :chat-icon)}]
|
||||
[react/view {:style (style/photo-border size)}]])
|
||||
|
||||
(defview member-photo [from]
|
||||
(defview member-photo [from & [size]]
|
||||
(letsubs [photo-path [:chats/photo-path from]]
|
||||
(photo (if (string/blank? photo-path)
|
||||
(identicon/identicon from)
|
||||
photo-path)
|
||||
{:accessibility-label :member-photo
|
||||
:size style/default-size})))
|
||||
:size (or size style/default-size)})))
|
||||
|
@ -1,7 +1,5 @@
|
||||
(ns status-im.ui.screens.chat.styles.main
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as component.styles]
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def scroll-root
|
||||
{:flex 1})
|
||||
@ -193,12 +191,27 @@
|
||||
|
||||
(def empty-chat-container
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-vertical 50
|
||||
:margin-right 6})
|
||||
|
||||
#_(defn intro-header-container
|
||||
[height status no-messages]
|
||||
(let [adjusted-height (if (< height 280) 324 height)]
|
||||
(if (or no-messages (= status (or :loading :empty)))
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:height adjusted-height
|
||||
:padding-horizontal 32}
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 32})))
|
||||
|
||||
(defn intro-header-container
|
||||
[height status no-messages]
|
||||
(let [adjusted-height (if (< height 280) 324 height)]
|
||||
@ -207,13 +220,11 @@
|
||||
:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:height adjusted-height
|
||||
:padding-horizontal 32}
|
||||
:height adjusted-height}
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 32})))
|
||||
:align-items :center})))
|
||||
|
||||
(defn intro-header-icon [diameter color]
|
||||
{:width diameter
|
||||
@ -231,22 +242,36 @@
|
||||
:line-height 72})
|
||||
|
||||
(def intro-header-chat-name
|
||||
{:font-size 22
|
||||
:font-weight "700"
|
||||
:line-height 28
|
||||
:text-align :center
|
||||
:margin-bottom 8
|
||||
:color colors/black})
|
||||
{:font-size 22
|
||||
:font-weight "700"
|
||||
:line-height 28
|
||||
:text-align :center
|
||||
:margin-bottom 8
|
||||
:margin-horizontal 32
|
||||
:color colors/black})
|
||||
|
||||
(def intro-header-description-container
|
||||
{:flex-wrap :wrap
|
||||
:align-items :flex-start
|
||||
:flex-direction :row})
|
||||
{:flex-wrap :wrap
|
||||
:align-items :flex-start
|
||||
:flex-direction :row
|
||||
:margin-horizontal 32})
|
||||
|
||||
(def loading-text
|
||||
{:color colors/gray
|
||||
:font-size 15
|
||||
:line-height 22
|
||||
:letter-spacing -0.2
|
||||
:margin-right 4
|
||||
:text-align :center})
|
||||
|
||||
(def empty-chat-text-name
|
||||
{:margin-bottom 5})
|
||||
|
||||
(def intro-header-description
|
||||
{:color colors/gray
|
||||
:line-height 22
|
||||
:text-align :center})
|
||||
{:color colors/gray
|
||||
:line-height 22
|
||||
:text-align :center
|
||||
:margin-horizontal 32})
|
||||
|
||||
(def group-chat-icon
|
||||
{:color colors/white
|
||||
@ -272,4 +297,33 @@
|
||||
{:color colors/blue
|
||||
:margin-bottom 40})
|
||||
|
||||
(def messages-list-vertical-padding 46)
|
||||
(def messages-list-vertical-padding 46)
|
||||
|
||||
(def are-you-friends-bubble
|
||||
{:border-radius 8
|
||||
:border-width 1
|
||||
:margin-top 4
|
||||
:border-color colors/gray-lighter
|
||||
:align-self :flex-start
|
||||
:padding-vertical 12
|
||||
:margin-horizontal 8
|
||||
:padding-horizontal 16
|
||||
:margin-bottom 50})
|
||||
|
||||
(def are-you-friends-text
|
||||
{:line-height 22
|
||||
:text-align :center
|
||||
:font-size 15
|
||||
:color colors/gray})
|
||||
|
||||
(def share-my-profile
|
||||
{:color colors/blue
|
||||
:text-align :center
|
||||
:margin-top 11
|
||||
:line-height 22
|
||||
:font-size 15})
|
||||
|
||||
(def tribute-received-note
|
||||
{:font-size 13
|
||||
:line-height 18
|
||||
:text-align :center})
|
||||
|
@ -1,10 +1,9 @@
|
||||
(ns status-im.ui.screens.chat.views
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.chat.models :as models.chat]
|
||||
[status-im.contact.db :as contact.db]
|
||||
[status-im.group-chats.db :as group-chats.db]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.tribute-to-talk.core :as tribute-to-talk]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.button.view :as buttons]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
@ -21,19 +20,20 @@
|
||||
[status-im.ui.screens.chat.bottom-info :as bottom-info]
|
||||
[status-im.ui.screens.chat.input.input :as input]
|
||||
[status-im.ui.screens.chat.message.datemark :as message-datemark]
|
||||
[status-im.ui.screens.chat.message.gap :as gap]
|
||||
[status-im.ui.screens.chat.message.message :as message]
|
||||
[status-im.ui.screens.chat.message.options :as message-options]
|
||||
[status-im.ui.screens.chat.stickers.views :as stickers]
|
||||
[status-im.ui.screens.chat.styles.main :as style]
|
||||
[status-im.ui.screens.chat.toolbar-content :as toolbar-content]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[status-im.ui.screens.chat.message.gap :as gap]
|
||||
[reagent.core :as reagent])
|
||||
[status-im.ui.screens.profile.tribute-to-talk.views
|
||||
:as
|
||||
tribute-to-talk.views]
|
||||
[status-im.utils.platform :as platform])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn add-contact-bar [public-key]
|
||||
(defn add-contact-bar
|
||||
[public-key]
|
||||
[react/touchable-highlight
|
||||
{:on-press
|
||||
#(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])
|
||||
@ -44,11 +44,13 @@
|
||||
{:color colors/blue}]
|
||||
[react/i18n-text {:style style/add-contact-text :key :add-to-contacts}]]])
|
||||
|
||||
(defn- on-options [chat-id chat-name group-chat? public?]
|
||||
(defn- on-options
|
||||
[chat-id chat-name group-chat? public?]
|
||||
(list-selection/show {:title chat-name
|
||||
:options (actions/actions group-chat? chat-id public?)}))
|
||||
|
||||
(defn chat-toolbar [{:keys [chat-name group-chat chat-id contact]} public? modal?]
|
||||
(defn chat-toolbar
|
||||
[{:keys [chat-name group-chat chat-id contact]} public? modal?]
|
||||
[react/view
|
||||
[status-bar/status-bar (when modal? {:type :modal-white})]
|
||||
[toolbar/toolbar
|
||||
@ -59,16 +61,18 @@
|
||||
toolbar/nav-back-home)
|
||||
[toolbar-content/toolbar-content-view]
|
||||
(when-not modal?
|
||||
[toolbar/actions [{:icon :main-icons/more
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :chat-menu-button}
|
||||
:handler #(on-options chat-id chat-name group-chat public?)}]])]
|
||||
[toolbar/actions
|
||||
[{:icon :main-icons/more
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :chat-menu-button}
|
||||
:handler #(on-options chat-id chat-name group-chat public?)}]])]
|
||||
[connectivity/connectivity-view]
|
||||
(when (and (not group-chat)
|
||||
(not (contact.db/added? contact)))
|
||||
[add-contact-bar chat-id])])
|
||||
|
||||
(defmulti message-row (fn [{{:keys [type]} :row}] type))
|
||||
(defmulti message-row
|
||||
(fn [{{:keys [type]} :row}] type))
|
||||
|
||||
(defmethod message-row :datemark
|
||||
[{{:keys [value]} :row}]
|
||||
@ -111,9 +115,25 @@
|
||||
[(react/animated-view) {:style (style/message-view-animated opacity)}
|
||||
message-view])]]))
|
||||
|
||||
(defn tribute-to-talk-header
|
||||
[name]
|
||||
[react/nested-text {:style (assoc style/intro-header-description
|
||||
:margin-bottom 32)}
|
||||
(i18n/label :t/tribute-required-by-account {:account-name name})
|
||||
[{:style {:color colors/blue}
|
||||
:on-press #(re-frame/dispatch [:navigate-to :tribute-learn-more])}
|
||||
(str " " (i18n/label :learn-more))]])
|
||||
|
||||
(defn intro-header
|
||||
[name]
|
||||
[react/text {:style (assoc style/intro-header-description
|
||||
:margin-bottom 32)}
|
||||
(str (i18n/label :t/empty-chat-description-one-to-one) name)])
|
||||
|
||||
(defn join-chat-button [chat-id]
|
||||
[buttons/secondary-button {:style style/join-button
|
||||
:on-press #(re-frame/dispatch [:group-chats.ui/join-pressed chat-id])}
|
||||
[buttons/secondary-button
|
||||
{:style style/join-button
|
||||
:on-press #(re-frame/dispatch [:group-chats.ui/join-pressed chat-id])}
|
||||
(i18n/label :t/join-group-chat)])
|
||||
|
||||
(defn decline-chat [chat-id]
|
||||
@ -135,7 +155,9 @@
|
||||
[inviter-name {:keys [name group-chat color chat-id]}]
|
||||
[react/view style/empty-chat-container
|
||||
[react/view {:style {:margin-bottom 170}}
|
||||
[chat-icon.screen/profile-icon-view nil name color false 100 {:default-chat-icon-text style/group-chat-icon}]]
|
||||
[chat-icon.screen/profile-icon-view
|
||||
nil name color false 100
|
||||
{:default-chat-icon-text style/group-chat-icon}]]
|
||||
[react/view {:style style/group-chat-join-footer}
|
||||
[react/view {:style style/group-chat-join-container}
|
||||
[react/view
|
||||
@ -146,96 +168,175 @@
|
||||
[join-chat-button chat-id]
|
||||
[decline-chat chat-id]]]])
|
||||
|
||||
;; TODO refactor this big view into chunks
|
||||
(defview chat-intro-header-container
|
||||
(defn group-chat-description-loading
|
||||
[]
|
||||
[react/view {:style (merge style/intro-header-description-container
|
||||
{:margin-bottom 36
|
||||
:height 44})}
|
||||
[react/text {:style style/intro-header-description}
|
||||
(i18n/label :t/loading)]
|
||||
[react/activity-indicator {:animating true
|
||||
:size :small
|
||||
:color colors/gray}]])
|
||||
|
||||
(defn group-chat-description-container
|
||||
[{:keys [group-chat name pending-invite-inviter-name
|
||||
inviter-name color chat-id chat-name public?
|
||||
universal-link]} no-messages]
|
||||
(letsubs [intro-status [:chats/current-chat-intro-status]
|
||||
height [:chats/content-layout-height]
|
||||
input-height [:chats/current-chat-ui-prop :input-height]
|
||||
{:keys [:lowest-request-from :highest-request-to]} [:chats/range]
|
||||
all-loaded? [:chats/all-loaded?]]
|
||||
(let [icon-text (if public? chat-id name)
|
||||
intro-name (if public? chat-name name)]
|
||||
;; TODO This when check ought to be unnecessary but for now it prevents
|
||||
;; jerky motion when fresh chat is created, when input-height can be null
|
||||
;; affecting the calculation of content-layout-height to be briefly adjusted
|
||||
(when (or input-height pending-invite-inviter-name)
|
||||
[react/touchable-without-feedback
|
||||
{:style {:flex 1
|
||||
:align-items :flex-start}
|
||||
:on-press (fn [_]
|
||||
(re-frame/dispatch
|
||||
[:chat.ui/set-chat-ui-props {:messages-focused? true
|
||||
:show-stickers? false}])
|
||||
(react/dismiss-keyboard!))}
|
||||
[react/view
|
||||
(style/intro-header-container height intro-status no-messages)
|
||||
;; Icon section
|
||||
[react/view {:style {:margin-top 42
|
||||
:margin-bottom 24}}
|
||||
[chat-icon.screen/chat-intro-icon-view
|
||||
icon-text chat-id
|
||||
{:default-chat-icon (style/intro-header-icon 120 color)
|
||||
:default-chat-icon-text style/intro-header-icon-text
|
||||
:size 120}]]
|
||||
;; Chat title section
|
||||
[react/text {:style style/intro-header-chat-name} intro-name]
|
||||
;; Description section
|
||||
(if group-chat
|
||||
(cond
|
||||
(= intro-status :loading)
|
||||
[react/view {:style (merge style/intro-header-description-container
|
||||
{:margin-bottom 36
|
||||
:height 44})}
|
||||
[react/text {:style style/intro-header-description}
|
||||
(i18n/label :t/loading)]
|
||||
[react/activity-indicator {:animating true
|
||||
:size :small
|
||||
:color colors/gray}]]
|
||||
contact universal-link range intro-status] :as chat}]
|
||||
(let [{:keys [lowest-request-from highest-request-to]} range]
|
||||
(case intro-status
|
||||
:loading
|
||||
[group-chat-description-loading]
|
||||
|
||||
(= intro-status :empty)
|
||||
(when public?
|
||||
[react/nested-text {:style (merge style/intro-header-description
|
||||
{:margin-bottom 36})}
|
||||
(let [quiet-hours (quot (- highest-request-to lowest-request-from)
|
||||
(* 60 60))
|
||||
quiet-time (if (<= quiet-hours 24)
|
||||
(i18n/label :t/quiet-hours
|
||||
{:quiet-hours quiet-hours})
|
||||
(i18n/label :t/quiet-days
|
||||
{:quiet-days (quot quiet-hours 24)}))]
|
||||
(i18n/label :t/empty-chat-description-public
|
||||
{:quiet-hours quiet-time}))
|
||||
[{:style {:color colors/blue}
|
||||
:on-press #(list-selection/open-share
|
||||
{:message
|
||||
(i18n/label
|
||||
:t/share-public-chat-text {:link universal-link})})}
|
||||
(i18n/label :t/empty-chat-description-public-share-this)]])
|
||||
:empty
|
||||
(when public?
|
||||
[react/nested-text {:style (merge style/intro-header-description
|
||||
{:margin-bottom 36})}
|
||||
(let [quiet-hours (quot (- highest-request-to lowest-request-from)
|
||||
(* 60 60))
|
||||
quiet-time (if (<= quiet-hours 24)
|
||||
(i18n/label :t/quiet-hours
|
||||
{:quiet-hours quiet-hours})
|
||||
(i18n/label :t/quiet-days
|
||||
{:quiet-days (quot quiet-hours 24)}))]
|
||||
(i18n/label :t/empty-chat-description-public
|
||||
{:quiet-hours quiet-time}))
|
||||
[{:style {:color colors/blue}
|
||||
:on-press #(list-selection/open-share
|
||||
{:message
|
||||
(i18n/label
|
||||
:t/share-public-chat-text {:link universal-link})})}
|
||||
(i18n/label :t/empty-chat-description-public-share-this)]])
|
||||
|
||||
(= intro-status :messages)
|
||||
(when (not public?)
|
||||
(if pending-invite-inviter-name
|
||||
[react/nested-text {:style style/intro-header-description}
|
||||
[{:style {:color :black}} pending-invite-inviter-name]
|
||||
(i18n/label :t/join-group-chat-description
|
||||
{:username ""
|
||||
:group-name intro-name})]
|
||||
(if (not= inviter-name "Unknown")
|
||||
[react/nested-text {:style style/intro-header-description}
|
||||
(i18n/label :t/joined-group-chat-description
|
||||
{:username ""
|
||||
:group-name intro-name})
|
||||
[{:style {:color :black}} inviter-name]]
|
||||
[react/text {:style style/intro-header-description}
|
||||
(i18n/label :t/created-group-chat-description
|
||||
{:group-name intro-name})]))))
|
||||
[react/nested-text {:style (merge style/intro-header-description
|
||||
{:margin-bottom 36})}
|
||||
(i18n/label :t/empty-chat-description-one-to-one)
|
||||
[{} intro-name]])]]))))
|
||||
:messages
|
||||
(when (not public?)
|
||||
(if pending-invite-inviter-name
|
||||
[react/nested-text {:style style/intro-header-description}
|
||||
[{:style {:color :black}} pending-invite-inviter-name]
|
||||
(i18n/label :t/join-group-chat-description
|
||||
{:username ""
|
||||
:group-name chat-name})]
|
||||
(if (not= inviter-name "Unknown")
|
||||
[react/nested-text {:style style/intro-header-description}
|
||||
(i18n/label :t/joined-group-chat-description
|
||||
{:username ""
|
||||
:group-name chat-name})
|
||||
[{:style {:color :black}} inviter-name]]
|
||||
[react/text {:style style/intro-header-description}
|
||||
(i18n/label :t/created-group-chat-description
|
||||
{:group-name chat-name})]))))))
|
||||
|
||||
(defn pay-to-chat-messages
|
||||
[snt-amount chat-id tribute-status tribute-label
|
||||
fiat-amount fiat-currency token]
|
||||
[tribute-to-talk.views/pay-to-chat-message
|
||||
{:snt-amount snt-amount
|
||||
:public-key chat-id
|
||||
:tribute-status tribute-status
|
||||
:tribute-label tribute-label
|
||||
:fiat-amount fiat-amount
|
||||
:fiat-currency fiat-currency
|
||||
:token token
|
||||
:style {:margin-horizontal 8
|
||||
:align-items :flex-start
|
||||
:align-self (if snt-amount :flex-start :flex-end)}}])
|
||||
|
||||
(defn one-to-one-chat-description-container
|
||||
[{:keys [chat-id name contact show-input? tribute-to-talk]
|
||||
:tribute-to-talk/keys [my-message received? message tribute-status
|
||||
tribute-label snt-amount on-share-my-profile
|
||||
fiat-amount fiat-currency token]}]
|
||||
(case tribute-status
|
||||
:loading
|
||||
[react/view (assoc (dissoc style/empty-chat-container :flex)
|
||||
:justify-content :flex-end)
|
||||
[react/view {:style {:align-items :center :justify-content :flex-end}}
|
||||
[react/view {:style {:flex-direction :row :justify-content :center}}
|
||||
[react/text {:style style/loading-text}
|
||||
(i18n/label :t/loading)]
|
||||
[react/activity-indicator {:color colors/gray
|
||||
:animating true}]]]]
|
||||
|
||||
:required
|
||||
[react/view
|
||||
[tribute-to-talk-header name]
|
||||
[pay-to-chat-messages snt-amount chat-id tribute-status tribute-label
|
||||
fiat-amount fiat-currency token]
|
||||
[react/view {:style style/are-you-friends-bubble}
|
||||
[react/text {:style (assoc style/are-you-friends-text
|
||||
:font-weight "500")}
|
||||
(i18n/label :t/tribute-to-talk-are-you-friends)]
|
||||
[react/text {:style style/are-you-friends-text}
|
||||
(i18n/label :t/tribute-to-talk-ask-to-be-added)]
|
||||
[react/text {:style style/share-my-profile
|
||||
:on-press on-share-my-profile}
|
||||
(i18n/label :t/share-my-profile)]]]
|
||||
|
||||
:pending
|
||||
[react/view
|
||||
[tribute-to-talk-header name]
|
||||
[pay-to-chat-messages snt-amount chat-id tribute-status tribute-label
|
||||
fiat-amount fiat-currency token]]
|
||||
|
||||
(:paid :none)
|
||||
[react/view
|
||||
[intro-header name]
|
||||
(when (= tribute-status :paid)
|
||||
[pay-to-chat-messages snt-amount chat-id tribute-status tribute-label
|
||||
fiat-amount fiat-currency token])
|
||||
(when received?
|
||||
[pay-to-chat-messages nil nil nil nil nil nil nil])
|
||||
|
||||
(when (or (= tribute-status :paid) received?)
|
||||
[react/view {:style {:margin-top 16 :margin-horizontal 8}}
|
||||
[react/nested-text {:style style/tribute-received-note}
|
||||
(when received?
|
||||
[{:style (assoc style/tribute-received-note :color colors/gray)}
|
||||
(i18n/label :tribute-to-talk-tribute-received1)])
|
||||
[{:style (assoc style/tribute-received-note :font-weight "500")}
|
||||
name]
|
||||
[{:style (assoc style/tribute-received-note :color colors/gray)}
|
||||
(i18n/label (if received? :tribute-to-talk-tribute-received2
|
||||
:tribute-to-talk-contact-received-your-tribute))]]])]
|
||||
|
||||
[intro-header name]))
|
||||
|
||||
(defn chat-intro-header-container
|
||||
[{:keys [group-chat name pending-invite-inviter-name
|
||||
inviter-name color chat-id chat-name public?
|
||||
contact universal-link intro-status height input-height] :as chat}
|
||||
no-messages]
|
||||
(let [icon-text (if public? chat-id name)
|
||||
intro-name (if public? chat-name name)]
|
||||
;; TODO This when check ought to be unnecessary but for now it prevents
|
||||
;; jerky motion when fresh chat is created, when input-height can be null
|
||||
;; affecting the calculation of content-layout-height to be briefly adjusted
|
||||
(when (or input-height
|
||||
pending-invite-inviter-name
|
||||
(not= (get-in contact [:tribute-to-talk :snt-amount]) 0))
|
||||
[react/touchable-without-feedback
|
||||
{:style {:flex 1
|
||||
:align-items :flex-start}
|
||||
:on-press (fn [_]
|
||||
(re-frame/dispatch
|
||||
[:chat.ui/set-chat-ui-props {:messages-focused? true
|
||||
:show-stickers? false}])
|
||||
(react/dismiss-keyboard!))}
|
||||
[react/view (style/intro-header-container height intro-status no-messages)
|
||||
;; Icon section
|
||||
[react/view {:style {:margin-top 42
|
||||
:margin-bottom 24}}
|
||||
[chat-icon.screen/chat-intro-icon-view
|
||||
icon-text chat-id
|
||||
{:default-chat-icon (style/intro-header-icon 120 color)
|
||||
:default-chat-icon-text style/intro-header-icon-text
|
||||
:size 120}]]
|
||||
;; Chat title section
|
||||
[react/text {:style style/intro-header-chat-name} intro-name]
|
||||
;; Description section
|
||||
(if group-chat
|
||||
[group-chat-description-container chat]
|
||||
[one-to-one-chat-description-container chat])]])))
|
||||
|
||||
(defonce messages-list-ref (atom nil))
|
||||
|
||||
@ -257,9 +358,10 @@
|
||||
default-limit-step)))
|
||||
|
||||
(defview messages-view
|
||||
[{:keys [group-chat chat-id pending-invite-inviter-name] :as chat}
|
||||
[{:keys [group-chat chat-id pending-invite-inviter-name contact] :as chat}
|
||||
modal?]
|
||||
(letsubs [messages [:chats/current-chat-messages-stream]
|
||||
photo-path [:chats/photo-path chat-id]
|
||||
current-public-key [:account/public-key]]
|
||||
{:component-will-mount
|
||||
(fn []
|
||||
@ -353,14 +455,10 @@
|
||||
:idx #(or (:message-id message-obj) (:value message-obj))
|
||||
:list-ref messages-list-ref}]))]]])))
|
||||
|
||||
(defn show-input-container? [my-public-key current-chat]
|
||||
(or (not (models.chat/group-chat? current-chat))
|
||||
(group-chats.db/joined? my-public-key current-chat)))
|
||||
|
||||
(defview chat-root [modal?]
|
||||
(letsubs [{:keys [public? chat-id] :as current-chat} [:chats/current-chat]
|
||||
(letsubs [{:keys [public? chat-id show-input?] :as current-chat}
|
||||
[:chats/current-chat]
|
||||
current-chat-id [:chats/current-chat-id]
|
||||
my-public-key [:account/public-key]
|
||||
show-bottom-info? [:chats/current-chat-ui-prop :show-bottom-info?]
|
||||
show-message-options? [:chats/current-chat-ui-prop :show-message-options?]
|
||||
show-stickers? [:chats/current-chat-ui-prop :show-stickers?]]
|
||||
@ -385,7 +483,7 @@
|
||||
(if platform/desktop?
|
||||
[messages-view-desktop current-chat modal?]
|
||||
[messages-view current-chat modal?])]
|
||||
(when (show-input-container? my-public-key current-chat)
|
||||
(when show-input?
|
||||
[input/container])
|
||||
(when show-stickers?
|
||||
[stickers/stickers-view])
|
||||
|
@ -1,20 +1,20 @@
|
||||
(ns status-im.ui.screens.home.views.inner-item
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[clojure.string :as str]
|
||||
[status-im.constants :as constants]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.receiving :as commands-receiving]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.home.styles :as styles]
|
||||
[status-im.utils.core :as utils]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.ui.components.list.views :as list]))
|
||||
[status-im.utils.datetime :as time])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defview command-short-preview [message]
|
||||
(letsubs [id->command [:chats/id->command]
|
||||
@ -38,7 +38,7 @@
|
||||
[react/image {:style {:margin 2 :width 30 :height 30}
|
||||
:source {:uri (:uri content)}}]
|
||||
|
||||
(str/blank? (:text content))
|
||||
(string/blank? (:text content))
|
||||
[react/text {:style styles/last-message-text}
|
||||
""]
|
||||
|
||||
@ -111,6 +111,10 @@
|
||||
[react/view styles/message-status-container
|
||||
[message-timestamp timestamp]]]
|
||||
[react/view styles/item-lower-container
|
||||
[message-content-text {:content last-message-content
|
||||
:content-type last-message-content-type}]
|
||||
(let [{:keys [tribute-status tribute-label]} (:tribute-to-talk contact)]
|
||||
(if (or group-chat
|
||||
(#{:none :paid} tribute-status))
|
||||
[message-content-text {:content last-message-content
|
||||
:content-type last-message-content-type}]
|
||||
[react/text {:style styles/last-message-text} tribute-label]))
|
||||
[unviewed-indicator chat-id]]]]]))
|
||||
|
@ -16,26 +16,29 @@
|
||||
toolbar/default-nav-back
|
||||
[toolbar/content-title ""]])
|
||||
|
||||
(defn actions [{:keys [public-key added?]}]
|
||||
(concat (if added?
|
||||
[{:label (i18n/label :t/in-contacts)
|
||||
:icon :main-icons/in-contacts
|
||||
:disabled? true
|
||||
:accessibility-label :in-contacts-button}]
|
||||
[{:label (i18n/label :t/add-to-contacts)
|
||||
:icon :main-icons/add-contact
|
||||
:action #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])
|
||||
:accessibility-label :add-to-contacts-button}])
|
||||
[{:label (i18n/label :t/send-message)
|
||||
:icon :main-icons/message
|
||||
:action #(re-frame/dispatch [:contact.ui/send-message-pressed {:public-key public-key}])
|
||||
:accessibility-label :start-conversation-button}
|
||||
{:label (i18n/label :t/send-transaction)
|
||||
:icon :main-icons/send
|
||||
:action #(re-frame/dispatch [:profile/send-transaction public-key])
|
||||
:accessibility-label :send-transaction-button}]
|
||||
(when-not platform/desktop?
|
||||
[{:label (i18n/label :t/share-profile-link)
|
||||
(defn actions
|
||||
[{:keys [public-key added? tribute-to-talk] :as contact}]
|
||||
(let [{:keys [tribute-status tribute-label]} tribute-to-talk]
|
||||
(concat (if added?
|
||||
[{:label (i18n/label :t/in-contacts)
|
||||
:icon :main-icons/in-contacts
|
||||
:disabled? true
|
||||
:accessibility-label :in-contacts-button}]
|
||||
[{:label (i18n/label :t/add-to-contacts)
|
||||
:icon :main-icons/add-contact
|
||||
:action #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])
|
||||
:accessibility-label :add-to-contacts-button}])
|
||||
[(cond-> {:label (i18n/label :t/send-message)
|
||||
: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))
|
||||
{:label (i18n/label :t/send-transaction)
|
||||
:icon :main-icons/send
|
||||
:action #(re-frame/dispatch [:profile/send-transaction public-key])
|
||||
:accessibility-label :send-transaction-button}
|
||||
{:label (i18n/label :t/share-profile-link)
|
||||
:icon :main-icons/share
|
||||
:action #(re-frame/dispatch [:profile/share-profile-link public-key])
|
||||
:accessibility-label :share-profile-link}])))
|
||||
|
@ -98,24 +98,6 @@
|
||||
{:typography :main-medium
|
||||
:color colors/gray})
|
||||
|
||||
(def personalized-message-container
|
||||
{:flex-grow 1
|
||||
:align-items :center
|
||||
:margin-horizontal 16
|
||||
:justify-content :flex-start})
|
||||
|
||||
(def personalized-message-title
|
||||
{:margin-top 24
|
||||
:margin-bottom 10
|
||||
:align-self :flex-start})
|
||||
|
||||
(def personalized-message-input
|
||||
{:border-radius 8
|
||||
:background-color colors/gray-lighter
|
||||
:text-align-vertical :top
|
||||
:padding-horizontal 16
|
||||
:padding-vertical 16})
|
||||
|
||||
(def edit-view-message-container
|
||||
{:border-radius 8
|
||||
:background-color colors/blue-light
|
||||
@ -220,22 +202,29 @@
|
||||
:width 238
|
||||
:border-color colors/gray-lighter})
|
||||
|
||||
(def chat-sample-bubble
|
||||
(defn chat-bubble [tribute-sender?]
|
||||
{:background-color (if tribute-sender? colors/blue-light colors/blue)
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 6
|
||||
:margin-top 4
|
||||
:border-radius 8})
|
||||
|
||||
(def pay-to-chat-bubble
|
||||
{:background-color colors/blue-light
|
||||
:padding-horizontal 12
|
||||
:padding-top 8
|
||||
:padding-vertical 8
|
||||
:margin-top 4
|
||||
:border-radius 8})
|
||||
|
||||
(def pay-to-chat-container
|
||||
{:justify-content :flex-start
|
||||
{:justify-content :center
|
||||
:align-items :center
|
||||
:flex-direction :row
|
||||
:height 44})
|
||||
:padding-top 12
|
||||
:padding-bottom 4})
|
||||
|
||||
(def pay-to-chat-text
|
||||
{:typography :main-medium
|
||||
:color colors/blue})
|
||||
{:color colors/blue})
|
||||
|
||||
(defn payment-status-icon [pending?]
|
||||
{:width 24
|
||||
|
@ -3,7 +3,6 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[status-im.tribute-to-talk.core :as tribute-to-talk]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.ui.components.icons.vector-icons :as icons]
|
||||
@ -19,36 +18,35 @@
|
||||
|
||||
(defn steps-numbers [editing?]
|
||||
{:intro 1
|
||||
:set-snt-amount (if editing? 1 2)
|
||||
:personalized-message (if editing? 2 3)})
|
||||
:set-snt-amount (if editing? 1 2)})
|
||||
|
||||
(def step-forward-label
|
||||
{:intro :t/get-started
|
||||
:set-snt-amount :t/continue
|
||||
:personalized-message :t/tribute-to-talk-sign-and-set-tribute
|
||||
:finish :t/ok-got-it})
|
||||
|
||||
(defn intro
|
||||
[]
|
||||
[react/view {:style styles/intro-container}
|
||||
[react/view {:style {:flex 1
|
||||
:min-height 32}}]
|
||||
[(react/scroll-view)
|
||||
[react/view {:style styles/intro-container}
|
||||
[react/view {:style {:flex 1
|
||||
:min-height 32}}]
|
||||
|
||||
[react/image {:source (resources/get-image :tribute-to-talk)
|
||||
:style styles/intro-image}]
|
||||
[react/view {:style {:flex 1
|
||||
:min-height 32}}]
|
||||
[react/image {:source (resources/get-image :tribute-to-talk)
|
||||
:style styles/intro-image}]
|
||||
[react/view {:style {:flex 1
|
||||
:min-height 32}}]
|
||||
|
||||
[react/view
|
||||
[react/i18n-text {:style styles/intro-text
|
||||
:key :tribute-to-talk}]
|
||||
[react/i18n-text {:style (assoc styles/description-label :margin-top 12)
|
||||
:key :tribute-to-talk-desc}]
|
||||
[react/view {:style styles/learn-more-link}
|
||||
[react/text {:style styles/learn-more-link-text
|
||||
:on-press #(re-frame/dispatch
|
||||
[:tribute-to-talk.ui/learn-more-pressed])}
|
||||
(i18n/label :t/learn-more)]]]])
|
||||
[react/view
|
||||
[react/i18n-text {:style styles/intro-text
|
||||
:key :tribute-to-talk}]
|
||||
[react/i18n-text {:style (assoc styles/description-label :margin-top 12)
|
||||
:key :tribute-to-talk-desc}]
|
||||
[react/view {:style styles/learn-more-link}
|
||||
[react/text {:style styles/learn-more-link-text
|
||||
:on-press #(re-frame/dispatch
|
||||
[:tribute-to-talk.ui/learn-more-pressed])}
|
||||
(i18n/label :t/learn-more)]]]]])
|
||||
|
||||
(defn snt-asset-value
|
||||
[fiat-value]
|
||||
@ -107,26 +105,6 @@
|
||||
[react/i18n-text {:style (assoc styles/description-label :margin-horizontal 16)
|
||||
:key :tribute-to-talk-set-snt-amount}]])
|
||||
|
||||
(defn personalized-message
|
||||
[message]
|
||||
[(react/scroll-view)
|
||||
{:content-container-style styles/personalized-message-container}
|
||||
[react/view {:style styles/personalized-message-title}
|
||||
[react/nested-text {:style {:text-align :center}}
|
||||
(i18n/label :t/personalized-message)
|
||||
[{:style styles/description-label} (str " (" (i18n/label :t/optional) ")")]]]
|
||||
[react/text-input
|
||||
(cond-> {:style (assoc styles/personalized-message-input :height 144
|
||||
:align-self :stretch)
|
||||
:multiline true
|
||||
:on-change-text #(re-frame/dispatch
|
||||
[:tribute-to-talk.ui/message-changed %1])
|
||||
:placeholder (i18n/label :t/tribute-to-talk-message-placeholder)}
|
||||
(not (string/blank? message))
|
||||
(assoc :default-value message))]
|
||||
[react/text {:style (assoc styles/description-label :margin-top 16 :margin-horizontal 32)}
|
||||
(i18n/label :t/tribute-to-talk-you-can-leave-a-message)]])
|
||||
|
||||
(defn finish
|
||||
[snt-amount state]
|
||||
[react/view {:style styles/intro-container}
|
||||
@ -218,7 +196,7 @@
|
||||
(i18n/label :t/tribute-to-talk-add-friends)]])
|
||||
|
||||
(defn edit
|
||||
[snt-amount message fiat-value]
|
||||
[snt-amount fiat-value]
|
||||
[(react/scroll-view) {:content-container-style styles/edit-container}
|
||||
[react/view {:style styles/edit-screen-top-row}
|
||||
[react/view {:style {:flex-direction :row
|
||||
@ -239,12 +217,6 @@
|
||||
[:tribute-to-talk.ui/edit-pressed])
|
||||
:style styles/edit-label}
|
||||
(i18n/label :t/edit)]]
|
||||
(when-not (string/blank? message)
|
||||
[react/view {:flex-direction :row
|
||||
:margin-bottom 16}
|
||||
[react/view {:style styles/edit-view-message-container}
|
||||
[react/text message]]
|
||||
[react/view {:flex 1}]])
|
||||
[separator]
|
||||
[react/text {:style styles/edit-note}
|
||||
(i18n/label :t/tribute-to-talk-you-require-snt)]
|
||||
@ -265,43 +237,43 @@
|
||||
:min-height 24}]
|
||||
[enabled-note]])
|
||||
|
||||
(defn pay-to-chat-message [{:keys [snt-amount fiat-amount fiat-currency
|
||||
personalized-message style public-key tribute-status]}]
|
||||
(defn pay-to-chat-message
|
||||
[{:keys [snt-amount style public-key tribute-status
|
||||
tribute-label fiat-amount fiat-currency token]}]
|
||||
[react/view {:style style}
|
||||
[react/view {:style {:flex-direction :row
|
||||
:align-items :center}}
|
||||
[react/view {:style {:background-color colors/white
|
||||
:justify-content :center :align-items :center}}
|
||||
:justify-content :center
|
||||
:align-items :center}}
|
||||
[icons/icon :tiny-icons/tribute-to-talk {:color colors/blue}]]
|
||||
[react/text {:style {:color colors/gray
|
||||
:font-size 13
|
||||
:margin-left 4}}
|
||||
(i18n/label :t/tribute-to-talk)]]
|
||||
(when-not (string/blank? personalized-message)
|
||||
[react/view {:style styles/chat-sample-bubble}
|
||||
[react/text (i18n/label :t/tribute-to-talk-sample-text)]])
|
||||
[react/view {:style styles/chat-sample-bubble}
|
||||
;;TODO replace hardcoded values
|
||||
[react/nested-text {:style {:font-size 22}}
|
||||
(str snt-amount)
|
||||
[{:style {:font-size 22 :color colors/gray}} " SNT"]]
|
||||
[react/nested-text
|
||||
{:style {:font-size 12}}
|
||||
(str "~" fiat-amount)
|
||||
[{:style {:font-size 12 :color colors/gray}} (str " " fiat-currency)]]
|
||||
[react/view {:style styles/pay-to-chat-container}
|
||||
(if (or (nil? public-key) (= tribute-status :required))
|
||||
[react/text (cond-> {:style styles/pay-to-chat-text}
|
||||
public-key
|
||||
(assoc :on-press #(re-frame/dispatch [:tribute-to-talk.ui/on-pay-to-chat-pressed
|
||||
public-key])))
|
||||
(i18n/label :t/pay-to-chat)]
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
[react/view {:style (styles/payment-status-icon (= tribute-status :pending))}
|
||||
[icons/icon (if (= tribute-status :pending) :tiny-icons/tiny-pending :tiny-icons/tiny-check)
|
||||
{:color (if (= tribute-status :pending) colors/black colors/white)}]]
|
||||
[react/text {:style styles/payment-status-text}
|
||||
nil]])]]])
|
||||
(when snt-amount
|
||||
[react/view {:style styles/pay-to-chat-bubble}
|
||||
[react/nested-text {:style {:font-size 22}}
|
||||
(str snt-amount)
|
||||
[{:style {:font-size 22 :color colors/gray}} token]]
|
||||
[react/nested-text
|
||||
{:style {:font-size 12}}
|
||||
(str "~" fiat-amount)
|
||||
[{:style {:font-size 12 :color colors/gray}}
|
||||
(str " " fiat-currency)]]
|
||||
(if (or (nil? public-key) (= tribute-status :required))
|
||||
[react/view {:style styles/pay-to-chat-container}
|
||||
[react/text (cond-> {:style styles/pay-to-chat-text}
|
||||
public-key
|
||||
(assoc :on-press
|
||||
#(re-frame/dispatch [:tribute-to-talk.ui/on-pay-to-chat-pressed
|
||||
public-key])))
|
||||
(i18n/label :t/pay-to-chat)]]
|
||||
[react/view {:style styles/pay-to-chat-container}
|
||||
[react/view {:style (styles/payment-status-icon (= tribute-status :pending))}
|
||||
[icons/icon (if (= tribute-status :pending) :tiny-icons/tiny-pending :tiny-icons/tiny-check)
|
||||
{:color (if (= tribute-status :pending) colors/black colors/white)}]]
|
||||
[react/text {:style styles/payment-status-text} tribute-label]])])])
|
||||
|
||||
(defn learn-more [owner?]
|
||||
[react/view {:flex 1}
|
||||
@ -323,17 +295,19 @@
|
||||
:t/tribute-to-talk-paywall-learn-more-1))]]
|
||||
[separator]
|
||||
[pay-to-chat-message {:snt-amount 1000
|
||||
:fiat-amount 3.48
|
||||
:fiat-currency (i18n/label :t/usd-currency)
|
||||
:personalized-message (i18n/label :t/tribute-to-talk-sample-text)
|
||||
:style (assoc styles/learn-more-section :margin-top 24)}]
|
||||
:token " SNT"
|
||||
:fiat-currency "USD"
|
||||
:fiat-amount "5"
|
||||
:style (assoc styles/learn-more-section
|
||||
:align-items :flex-start
|
||||
:margin-top 24)}]
|
||||
[react/view {:style styles/learn-more-text-container-2}
|
||||
[react/text {:style styles/learn-more-text}
|
||||
(i18n/label (if owner? :t/tribute-to-talk-learn-more-2
|
||||
:t/tribute-to-talk-paywall-learn-more-2))]]
|
||||
[react/view {:style (assoc styles/learn-more-section
|
||||
:flex-direction :row
|
||||
:align-item :flex-stretch
|
||||
:align-items :stretch
|
||||
:padding-horizontal 16
|
||||
:padding-vertical 12)}
|
||||
[react/view {:style (styles/icon-view colors/blue-light)}
|
||||
@ -347,9 +321,9 @@
|
||||
:t/tribute-to-talk-paywall-learn-more-3))]]]])
|
||||
|
||||
(defview tribute-to-talk []
|
||||
(letsubs [{:keys [step snt-amount editing? message
|
||||
(letsubs [{:keys [step snt-amount editing?
|
||||
fiat-value disable-button? state]}
|
||||
[:tribute-to-talk/ui]]
|
||||
[:tribute-to-talk/settings-ui]]
|
||||
[react/keyboard-avoiding-view {:style styles/container}
|
||||
[(react/safe-area-view) {:style {:flex 1}}
|
||||
[status-bar/status-bar]
|
||||
@ -380,9 +354,8 @@
|
||||
(case step
|
||||
:intro [intro]
|
||||
:set-snt-amount [set-snt-amount snt-amount]
|
||||
:edit [edit snt-amount message fiat-value]
|
||||
:edit [edit snt-amount fiat-value]
|
||||
:learn-more [learn-more step]
|
||||
:personalized-message [personalized-message message]
|
||||
:finish [finish snt-amount state])
|
||||
|
||||
(when-not (#{:learn-more :edit} step)
|
||||
|
@ -83,7 +83,8 @@
|
||||
:style styles/share-link-button}]))
|
||||
|
||||
(defview qr-viewer []
|
||||
(letsubs [{:keys [value contact]} [:qr-modal]]
|
||||
(letsubs [{:keys [value contact]} [:qr-modal]
|
||||
ttt-enabled? [:tribute-to-talk/enabled?]]
|
||||
[react/view styles/qr-code-viewer
|
||||
[status-bar/status-bar {:type :modal-white}]
|
||||
[qr-viewer-toolbar (:name contact) value]
|
||||
@ -92,7 +93,8 @@
|
||||
{:style styles/qr-code
|
||||
:value value
|
||||
:hint (i18n/label :t/qr-code-public-key-hint)
|
||||
:legend (str value)}
|
||||
:legend (str value)
|
||||
:show-tribute-to-talk-warning? ttt-enabled?}
|
||||
(when-not platform/desktop?
|
||||
{:footer-button qr-code-share-button}))]]))
|
||||
|
||||
@ -284,36 +286,14 @@
|
||||
:accessory-value active-contacts-count
|
||||
:action-fn #(re-frame/dispatch [:navigate-to :contacts-list])}])
|
||||
|
||||
(defn tribute-to-talk-item [state snt-amount seen?]
|
||||
(defn tribute-to-talk-item
|
||||
[opts]
|
||||
[list.views/big-list-item
|
||||
(cond-> {:text (i18n/label :t/tribute-to-talk)
|
||||
:accessibility-label :notifications-button
|
||||
:new? (not seen?)
|
||||
:action-fn #(re-frame/dispatch
|
||||
[:tribute-to-talk.ui/menu-item-pressed])}
|
||||
(and (not (and seen?
|
||||
snt-amount
|
||||
(#{:signing :pending :transaction-failed} state))))
|
||||
(assoc :subtext (i18n/label :t/tribute-to-talk-desc))
|
||||
|
||||
(#{:signing :pending} state)
|
||||
(assoc :activity-indicator {:animating true
|
||||
:color colors/blue}
|
||||
:subtext (case state
|
||||
:pending (i18n/label :t/pending-confirmation)
|
||||
:signing (i18n/label :t/waiting-to-sign)))
|
||||
|
||||
(= state :transaction-failed)
|
||||
(assoc :icon :main-icons/warning
|
||||
:icon-color colors/red
|
||||
:subtext (i18n/label :t/transaction-failed))
|
||||
|
||||
(not (#{:signing :pending :transaction-failed} state))
|
||||
(assoc :icon :main-icons/tribute-to-talk)
|
||||
|
||||
(and (= state :completed)
|
||||
(not-empty snt-amount))
|
||||
(assoc :accessory-value (str snt-amount " SNT")))])
|
||||
(merge {:text (i18n/label :t/tribute-to-talk)
|
||||
:accessibility-label :notifications-button
|
||||
:action-fn #(re-frame/dispatch
|
||||
[:tribute-to-talk.ui/menu-item-pressed])}
|
||||
opts)])
|
||||
|
||||
(defview extensions-settings []
|
||||
(letsubs [{:keys [label view on-close]} [:get-screen-params :my-profile-ext-settings]]
|
||||
@ -332,9 +312,7 @@
|
||||
login-data [:accounts/login]
|
||||
scroll (reagent/atom nil)
|
||||
active-contacts-count [:contacts/active-count]
|
||||
{tribute-to-talk-seen? :seen?
|
||||
snt-amount :snt-amount
|
||||
tribute-to-talk-state :state} [:tribute-to-talk/ui]]
|
||||
tribute-to-talk [:tribute-to-talk/profile]]
|
||||
(let [shown-account (merge current-account changed-account)
|
||||
;; We scroll on the component once rendered. setTimeout is necessary,
|
||||
;; likely to allow the animation to finish.
|
||||
@ -367,11 +345,8 @@
|
||||
:on-change-text-event :my-profile/update-name}]]
|
||||
[share-profile-item (dissoc current-account :mnemonic)]
|
||||
[contacts-list-item active-contacts-count]
|
||||
(when config/tr-to-talk-enabled?
|
||||
[tribute-to-talk-item
|
||||
tribute-to-talk-state
|
||||
snt-amount
|
||||
tribute-to-talk-seen?])
|
||||
(when tribute-to-talk
|
||||
[tribute-to-talk-item tribute-to-talk])
|
||||
[my-profile-settings current-account shown-account currency (nil? login-data) extensions]
|
||||
(when (nil? login-data)
|
||||
[advanced shown-account on-show-advanced])]]])))
|
||||
|
@ -43,6 +43,9 @@
|
||||
[status-im.test.search.core]
|
||||
[status-im.test.sign-in.flow]
|
||||
[status-im.test.transport.core]
|
||||
[status-im.test.tribute-to-talk.core]
|
||||
[status-im.test.tribute-to-talk.db]
|
||||
[status-im.test.tribute-to-talk.whitelist]
|
||||
[status-im.test.ui.screens.add-new.models]
|
||||
[status-im.test.ui.screens.currency-settings.models]
|
||||
[status-im.test.ui.screens.wallet.db]
|
||||
@ -119,6 +122,9 @@
|
||||
'status-im.test.search.core
|
||||
'status-im.test.sign-in.flow
|
||||
'status-im.test.transport.core
|
||||
'status-im.test.tribute-to-talk.core
|
||||
'status-im.test.tribute-to-talk.db
|
||||
'status-im.test.tribute-to-talk.whitelist
|
||||
'status-im.test.ui.screens.add-new.models
|
||||
'status-im.test.ui.screens.currency-settings.models
|
||||
'status-im.test.ui.screens.wallet.db
|
||||
|
110
test/cljs/status_im/test/tribute_to_talk/core.cljs
Normal file
110
test/cljs/status_im/test/tribute_to_talk/core.cljs
Normal file
@ -0,0 +1,110 @@
|
||||
(ns status-im.test.tribute-to-talk.core
|
||||
(:require [cljs.test :refer-macros [deftest testing is]]
|
||||
[status-im.tribute-to-talk.core :as tribute-to-talk]
|
||||
[status-im.utils.money :as money]))
|
||||
|
||||
(deftest get-new-snt-amount
|
||||
(testing "staying under the limit"
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"999999.9" "9")
|
||||
"999999.99")))
|
||||
(testing "getting over the limit"
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"100000" "0")
|
||||
"100000")))
|
||||
(testing "replace initial 0 by the first digit"
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"0" "1")
|
||||
"1")))
|
||||
(testing "disallow more than two dots"
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"0." ".")
|
||||
"0."))
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"0.0" ".")
|
||||
"0.0")))
|
||||
(testing "disallow more than two digits after dot"
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"0.0" "0")
|
||||
"0.00"))
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"0.00" "1")
|
||||
"0.00")))
|
||||
(testing "0 remains if removed is pressed on last digit"
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"0" :remove)
|
||||
"0"))
|
||||
(is (= (tribute-to-talk/get-new-snt-amount
|
||||
"1" :remove)
|
||||
"0")))
|
||||
(testing "dot is removed when last digit after dot is removed"
|
||||
(= (tribute-to-talk/get-new-snt-amount
|
||||
"1." :remove)
|
||||
"1")
|
||||
(= (tribute-to-talk/get-new-snt-amount
|
||||
"1.1" :remove)
|
||||
"1")))
|
||||
|
||||
(def recipient-pk "0x04263d74e55775280e75b4a4e9a45ba59fc372793a869c5d9c4fa2100556d9963e3f4fbfa1724ec94a46e6da057540ab248ed1f5eb956e36e3129ecd50fade2c97")
|
||||
(def recipient-address "0xdff1a5e4e57d9723b3294e0f4413372e3ea9a8ff")
|
||||
|
||||
(def user-cofx
|
||||
{:db {:account/account
|
||||
{:address "954d4393515747ea75808a0301fb73317ae1e460"
|
||||
:network "testnet_rpc"
|
||||
:networks {"testnet_rpc" {:config {:NetworkId 3}}}
|
||||
:settings {:tribute-to-talk {:testnet {:snt-amount "1000000000000000000"}}}}
|
||||
:contacts/contacts
|
||||
{recipient-pk {:name "bob"
|
||||
:address recipient-address
|
||||
:public-key recipient-pk
|
||||
:tribute-to-talk {:snt-amount "1000000000000000000"}}}
|
||||
:wallet {:balance {:STT (money/bignumber "1000000000000000000")}}}})
|
||||
|
||||
(deftest pay-tribute
|
||||
(testing "transaction with enough funds"
|
||||
(let [results (tribute-to-talk/pay-tribute
|
||||
user-cofx
|
||||
recipient-pk)]
|
||||
(is (= (dissoc (get-in results [:db :wallet :send-transaction]) :amount)
|
||||
{:on-result
|
||||
[:tribute-to-talk.callback/pay-tribute-transaction-sent
|
||||
"0x04263d74e55775280e75b4a4e9a45ba59fc372793a869c5d9c4fa2100556d9963e3f4fbfa1724ec94a46e6da057540ab248ed1f5eb956e36e3129ecd50fade2c97"],
|
||||
:to-name "bob",
|
||||
:amount-text "1",
|
||||
:method "eth_sendTransaction",
|
||||
:symbol :ETH,
|
||||
:send-transaction-message? true,
|
||||
:from-chat? true,
|
||||
:from "0x954d4393515747ea75808a0301fb73317ae1e460",
|
||||
:id "approve",
|
||||
:sufficient-funds? true,
|
||||
:on-error nil,
|
||||
:public-key
|
||||
"0x04263d74e55775280e75b4a4e9a45ba59fc372793a869c5d9c4fa2100556d9963e3f4fbfa1724ec94a46e6da057540ab248ed1f5eb956e36e3129ecd50fade2c97",
|
||||
:asset :STT,
|
||||
:to "0xc55cf4b03948d7ebc8b9e8bad92643703811d162",
|
||||
:data
|
||||
"0xa9059cbb000000000000000000000000dff1a5e4e57d9723b3294e0f4413372e3ea9a8ff0000000000000000000000000000000000000000000000000de0b6b3a7640000"}))))
|
||||
|
||||
(testing "insufficient funds"
|
||||
(is (= (get-in (tribute-to-talk/pay-tribute
|
||||
(assoc-in user-cofx [:db :wallet] nil)
|
||||
recipient-pk)
|
||||
[:db :wallet :send-transaction :sufficient-funds?])
|
||||
false))))
|
||||
|
||||
(deftest tribute-transaction-trigger
|
||||
(testing "transaction error"
|
||||
(is (tribute-to-talk/tribute-transaction-trigger
|
||||
{:ethereum/current-block 10}
|
||||
{:block "5"
|
||||
:error? true})))
|
||||
(testing "transaction confirmed"
|
||||
(is (tribute-to-talk/tribute-transaction-trigger
|
||||
{:ethereum/current-block 10}
|
||||
{:block "5"})))
|
||||
(testing "transaction not confirmed yet"
|
||||
(is (not (tribute-to-talk/tribute-transaction-trigger
|
||||
{:ethereum/current-block 5}
|
||||
{:block "5"})))))
|
81
test/cljs/status_im/test/tribute_to_talk/db.cljs
Normal file
81
test/cljs/status_im/test/tribute_to_talk/db.cljs
Normal file
@ -0,0 +1,81 @@
|
||||
(ns status-im.test.tribute-to-talk.db
|
||||
(:require [cljs.test :refer-macros [deftest testing is]]
|
||||
[status-im.tribute-to-talk.db :as db]))
|
||||
|
||||
(deftest tribute-status
|
||||
(is (= (db/tribute-status {:system-tags #{:tribute-to-talk/paid}
|
||||
:tribute-to-talk {:snt-amount 1000
|
||||
:transaction-hash "0x"}})
|
||||
:paid))
|
||||
(is (= (db/tribute-status {:tribute-to-talk {:snt-amount 1000
|
||||
:transaction-hash "0x"}})
|
||||
:pending))
|
||||
(is (= (db/tribute-status {:tribute-to-talk {:snt-amount 1000}})
|
||||
:required))
|
||||
(is (= (db/tribute-status {:tribute-to-talk {:snt-amount 0}})
|
||||
:none))
|
||||
(is (= (db/tribute-status {})
|
||||
:none)))
|
||||
|
||||
(deftest valid?
|
||||
(is (db/valid? {:snt-amount "1000"}))
|
||||
(is (not (db/valid? {:snt-amount "-1000"})))
|
||||
(is (not (db/valid? {:snt-amount "1000001000000000000000000"})))
|
||||
(is (not (db/valid? {:snt-amount 5})))
|
||||
(is (not (db/valid? {:snt-amount "abcdef"}))))
|
||||
|
||||
(def sender-pk "0x04263d74e55775280e75b4a4e9a45ba59fc372793a869c5d9c4fa2100556d9963e3f4fbfa1724ec94a46e6da057540ab248ed1f5eb956e36e3129ecd50fade2c97")
|
||||
(def sender-address "0xdff1a5e4e57d9723b3294e0f4413372e3ea9a8ff")
|
||||
|
||||
(deftest valid-tribute-transaction?
|
||||
(testing "a valid transaction"
|
||||
(is (db/valid-tribute-transaction?
|
||||
{:wallet {:transactions
|
||||
{"transaction-hash-1"
|
||||
{:value "1000000000000000000"
|
||||
:block "5"
|
||||
:from sender-address}}}
|
||||
:ethereum/current-block 8}
|
||||
"1000000000000000000"
|
||||
"transaction-hash-1"
|
||||
sender-pk)))
|
||||
(testing "a transaction"
|
||||
(testing "with insufficient value transfered"
|
||||
(is (not (db/valid-tribute-transaction?
|
||||
{:wallet {:transactions
|
||||
{"transaction-hash-1"
|
||||
{:value "1"
|
||||
:block "5"
|
||||
:from sender-address}}}
|
||||
:ethereum/current-block 8}
|
||||
"1000000000000000000"
|
||||
"transaction-hash-1"
|
||||
sender-pk)))
|
||||
(testing "that was not confirmed yet"
|
||||
(is (not (db/valid-tribute-transaction?
|
||||
{:wallet {:transactions
|
||||
{"transaction-hash-1"
|
||||
{:value "1000000000000000000"
|
||||
:block "8"
|
||||
:from sender-address}}}
|
||||
:ethereum/current-block 8}
|
||||
"1000000000000000000"
|
||||
"transaction-hash-1"
|
||||
sender-pk))))
|
||||
(testing "from someone else"
|
||||
(is (not (db/valid-tribute-transaction?
|
||||
{:wallet {:transactions
|
||||
{"transaction-hash-1"
|
||||
{:value "1000000000000000000"
|
||||
:block "5"
|
||||
:from "another address"}}}
|
||||
:ethereum/current-block 8}
|
||||
"1000000000000000000"
|
||||
"transaction-hash-1"
|
||||
sender-pk))))))
|
||||
(testing "a transaction that does not exist"
|
||||
(is (not (db/valid-tribute-transaction?
|
||||
{:ethereum/current-block 8}
|
||||
"1000000000000000000"
|
||||
"transaction-hash-1"
|
||||
sender-pk)))))
|
131
test/cljs/status_im/test/tribute_to_talk/whitelist.cljs
Normal file
131
test/cljs/status_im/test/tribute_to_talk/whitelist.cljs
Normal file
@ -0,0 +1,131 @@
|
||||
(ns status-im.test.tribute-to-talk.whitelist
|
||||
(:require [cljs.test :refer-macros [deftest testing is]]
|
||||
[status-im.tribute-to-talk.whitelist :as whitelist]))
|
||||
|
||||
(def user-contacts
|
||||
{"not whitelisted"
|
||||
{:public-key "not whitelisted"
|
||||
:system-tags #{}}
|
||||
"not whitelisted2"
|
||||
{:public-key "not whitelisted2"
|
||||
:system-tags #{:contact/request-received}}
|
||||
"whitelisted because tribute paid"
|
||||
{:public-key "whitelisted because tribute paid"
|
||||
:system-tags #{:tribute-to-talk/paid}}
|
||||
"whitelisted because tribute received"
|
||||
{:public-key "whitelisted because tribute received"
|
||||
:system-tags #{:tribute-to-talk/received}}
|
||||
"whitelisted because added"
|
||||
{:public-key "whitelisted because added"
|
||||
:system-tags #{:contact/added}}})
|
||||
|
||||
(deftest get-contact-whitelist
|
||||
(is (= 3
|
||||
(count (whitelist/get-contact-whitelist
|
||||
(vals user-contacts))))))
|
||||
|
||||
(deftest add-to-whitelist
|
||||
(testing "adding contact to whitelist"
|
||||
(is (= #{"bob" "bob2"}
|
||||
(get-in (whitelist/add-to-whitelist
|
||||
{:db {:contacts/whitelist #{"bob2"}}} "bob")
|
||||
[:db :contacts/whitelist])))
|
||||
(testing "when there is no whitelist yet"
|
||||
(is (= #{"bob"}
|
||||
(get-in (whitelist/add-to-whitelist
|
||||
{:db {}} "bob")
|
||||
[:db :contacts/whitelist]))
|
||||
(whitelist/add-to-whitelist {:db {}} "bob")))
|
||||
(testing "when already added"
|
||||
(is (= #{"bob"}
|
||||
(get-in (whitelist/add-to-whitelist
|
||||
{:db {:contacts/whitelist #{"bob"}}} "bob")
|
||||
[:db :contacts/whitelist]))))))
|
||||
|
||||
(deftest mark-tribute-paid
|
||||
(let [result (whitelist/mark-tribute-paid {:db {}} "bob")]
|
||||
(testing "contact was added to whitelist"
|
||||
(is (= (get-in result
|
||||
[:db :contacts/whitelist])
|
||||
#{"bob"})))
|
||||
(testing "contact was tagged as tribute paid"
|
||||
(is (= (get-in result
|
||||
[:db :contacts/contacts "bob" :system-tags])
|
||||
#{:tribute-to-talk/paid})))
|
||||
(testing "change is persisted"
|
||||
(is (:data-store/tx result)))))
|
||||
|
||||
(deftest mark-tribute-received
|
||||
(let [result (whitelist/mark-tribute-received {:db {}} "bob")]
|
||||
(testing "contact was added to whitelist"
|
||||
(is (= (get-in result
|
||||
[:db :contacts/whitelist])
|
||||
#{"bob"})))
|
||||
(testing "contact was tagged as tribute paid"
|
||||
(is (= (get-in result
|
||||
[:db :contacts/contacts "bob" :system-tags])
|
||||
#{:tribute-to-talk/received})))
|
||||
(testing "change is persisted"
|
||||
(is (:data-store/tx result)))))
|
||||
|
||||
(def sender-pk "0x04263d74e55775280e75b4a4e9a45ba59fc372793a869c5d9c4fa2100556d9963e3f4fbfa1724ec94a46e6da057540ab248ed1f5eb956e36e3129ecd50fade2c97")
|
||||
(def sender-address "0xdff1a5e4e57d9723b3294e0f4413372e3ea9a8ff")
|
||||
|
||||
(def ttt-enabled-account
|
||||
{:db {:account/account {:network "testnet_rpc"
|
||||
:networks {"testnet_rpc" {:config {:NetworkId 3}}}
|
||||
:settings {:tribute-to-talk {:testnet {:snt-amount "1000000000000000000"}}}}
|
||||
:contacts/contacts user-contacts
|
||||
:wallet {:transactions
|
||||
{"transaction-hash-1"
|
||||
{:value "1000000000000000000"
|
||||
:block "5"
|
||||
:from sender-address}}}
|
||||
:ethereum/current-block 8}})
|
||||
|
||||
(def ttt-disabled-account
|
||||
{:db {:account/account {:network "testnet_rpc"
|
||||
:networks {"testnet_rpc" {:config {:NetworkId 3}}}
|
||||
:settings {:tribute-to-talk {}}}
|
||||
:contacts/contacts user-contacts}})
|
||||
|
||||
(deftest enable-whitelist
|
||||
(testing "ttt enabled account"
|
||||
(is (= (get-in (whitelist/enable-whitelist ttt-enabled-account)
|
||||
[:db :contacts/whitelist]))))
|
||||
(testing "ttt disabled account"
|
||||
(is (not (get-in (whitelist/enable-whitelist ttt-disabled-account)
|
||||
[:db :contacts/whitelist])))))
|
||||
|
||||
(deftest filter-message
|
||||
(testing "not a user message"
|
||||
(whitelist/filter-message
|
||||
ttt-enabled-account
|
||||
:unfiltered-fx
|
||||
:not-user-message
|
||||
nil
|
||||
"public-key"))
|
||||
(testing "user is whitelisted"
|
||||
(whitelist/filter-message
|
||||
(whitelist/enable-whitelist ttt-enabled-account)
|
||||
:unfiltered-fx
|
||||
:user-message
|
||||
nil
|
||||
"whitelisted because added"))
|
||||
(testing "tribute to talk is disabled"
|
||||
(whitelist/filter-message
|
||||
ttt-disabled-account
|
||||
:unfiltered-fx
|
||||
:user-message
|
||||
nil
|
||||
"public-key"))
|
||||
(testing "user is not whitelisted but transaction is valid"
|
||||
(let [result (whitelist/filter-message
|
||||
ttt-enabled-account
|
||||
#(assoc % :message-received true)
|
||||
:user-message
|
||||
"transaction-hash-1"
|
||||
sender-pk)]
|
||||
(is (contains? (get-in result [:db :contacts/whitelist])
|
||||
sender-pk))
|
||||
(is (:message-received result)))))
|
@ -919,7 +919,6 @@
|
||||
"tribute-to-talk": "Tribute to talk",
|
||||
"tribute-to-talk-desc": "Monetize your attention by requiring SNT for new people to start a chat",
|
||||
"tribute-to-talk-set-snt-amount": "Set the amount of SNT required for new people to start a chat",
|
||||
"personalized-message": "Personalized message",
|
||||
"optional": "optional",
|
||||
"pending-confirmation": "Pending confirmation...",
|
||||
"waiting-to-sign": "Waiting to sign transaction...",
|
||||
@ -953,7 +952,9 @@
|
||||
"tribute-to-talk-paywall-learn-more-1": "Our time and attention are our most valuable assets. Tribute to Talk lets you contact new people in exchange for an SNT payment.",
|
||||
"tribute-to-talk-paywall-learn-more-2": "To start a chat with someone who has a tribute set, simply pay the required SNT and you will be added as a contact.",
|
||||
"tribute-to-talk-paywall-learn-more-3": "If you know them, you can share your profile outside of Status to be added for free.",
|
||||
"tribute-to-talk-contact-received-your-tribute": " received your tribute. You are now contacts and can securely chat with each other.",
|
||||
"tribute-to-talk-tribute-received1": "Tribute received. You and ",
|
||||
"tribute-to-talk-tribute-received2": " are now contacts and can securely chat with each other.",
|
||||
"tribute-to-talk-contact-received-your-tribute": " received your tribute. You can now securely chat with each other.",
|
||||
"pay-to-chat": "Pay to chat",
|
||||
"share-chat": "Share chat",
|
||||
"share-link": "Share link",
|
||||
|
@ -644,7 +644,6 @@
|
||||
"peers": "주변 노드 (Peers)",
|
||||
"pending": "대기 중",
|
||||
"permissions": "권한",
|
||||
"personalized-message": "개인 메시지",
|
||||
"pfs": "PFS 활성화",
|
||||
"pfs-warning-content": "PFS 지원은 아직 테스트 중이므로 스테이터스는 오류에 대해 책임지지 않습니다. PFS를 활성화하면, 0.9.32 이상의 버전을 사용하는 유저들은 귀하의 개인, 공개 메시지를 읽을 수 있습니다. 아직 모든 메시지에 대한 PFS를 보장하지는 않으며, 귀하의 메시지를 암호화하지만 수신 메시지는 암호화 하지 않습니다.",
|
||||
"pfs-warning-title": "경고, 테스트 중인 기능임",
|
||||
|
Loading…
x
Reference in New Issue
Block a user