Implement stickers market

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
Andrey Shovkoplyas 2019-01-07 13:50:06 +01:00
parent b0c1a3244d
commit 2430992fb4
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
38 changed files with 435 additions and 24 deletions

1
.env
View File

@ -17,3 +17,4 @@ PFS_ENCRYPTION_ENABLED=1
DEV_BUILD=1
ERC20_CONTRACT_WARNINGS=1
MAILSERVER_CONFIRMATIONS_ENABLED=0
STICKERS_ENABLED=1

View File

@ -13,3 +13,4 @@ EXTENSIONS=1
PFS_ENCRYPTION_ENABLED=1
ERC20_CONTRACT_WARNINGS=1
MAILSERVER_CONFIRMATIONS_ENABLED=0
STICKERS_ENABLED=0

View File

@ -17,3 +17,4 @@ PAIRING_ENABLED=1
ERC20_CONTRACT_WARNINGS=1
MAILSERVER_CONFIRMATIONS_ENABLED=0
HARDWALLET_ENABLED=0
STICKERS_ENABLED=1

View File

@ -15,3 +15,4 @@ EXTENSIONS=1
PFS_ENCRYPTION_ENABLED=1
ERC20_CONTRACT_WARNINGS=1
MAILSERVER_CONFIRMATIONS_ENABLED=0
STICKERS_ENABLED=0

View File

@ -14,3 +14,4 @@ EXTENSIONS=1
PFS_ENCRYPTION_ENABLED=1
ERC20_CONTRACT_WARNINGS=1
MAILSERVER_CONFIRMATIONS_ENABLED=0
STICKERS_ENABLED=0

View File

@ -15,3 +15,4 @@ MAINNET_WARNING_ENABLED=1
EXTENSIONS=1
PFS_ENCRYPTION_ENABLED=1
ERC20_CONTRACT_WARNINGS=0
STICKERS_ENABLED=0

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="" fill-opacity="0" d="M11 5V11.1716C11 11.702 11.2107 12.2107 11.5858 12.5858L16 17" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 273 B

View File

@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path fill="" fill-rule="evenodd" clip-rule="evenodd" d="M12 21C16.9706 21 21 16.9706 21 12C21 11 19 9 17 7C15 5 13 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21ZM18.6754 14.1133C18.8578 13.5363 18.3885 12.9999 17.7902 12.9091C14.3405 12.3859 11.6142 9.65947 11.0909 6.20975C11.0001 5.61148 10.4637 5.14216 9.88675 5.32464C7.05362 6.2207 5 8.87053 5 12C5 15.866 8.13401 19 12 19C15.1295 19 17.7793 16.9464 18.6754 14.1133ZM14.252 14.3066C13.6103 14.7446 12.8356 15.0001 12 15.0001C11.1645 15.0001 10.3897 14.7446 9.74808 14.3066C9.406 14.073 8.93416 14.0659 8.64127 14.3588L8.28771 14.7124C7.99482 15.0053 7.99233 15.4845 8.31932 15.7387C9.33518 16.5286 10.6132 17.0001 12 17.0001C13.3868 17.0001 14.6649 16.5286 15.6807 15.7387C16.0077 15.4844 16.0052 15.0053 15.7123 14.7124L15.3588 14.3588C15.0659 14.0659 14.594 14.073 14.252 14.3066Z"/>
</svg>

After

Width:  |  Height:  |  Size: 946 B

View File

@ -0,0 +1,3 @@
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M32 57C43.9849 57 54 48.5666 56.4348 37.3104C56.8707 35.2954 54.898 33.7413 52.8441 33.9201C52.2364 33.973 51.6213 34 51 34C39.402 34 30 24.598 30 13C30 12.3787 30.027 11.7636 30.0799 11.1558C30.2587 9.10201 28.7046 7.1293 26.6896 7.56516C15.4334 9.99996 7 20.0151 7 32C7 45.8071 18.1929 57 32 57ZM51 32C52.6564 32 54.2622 31.7883 55.7923 31.3907C56.2883 31.2619 56.5268 30.712 56.2604 30.2743C55.6851 29.3292 54.8263 28.2039 53.7315 26.9266C51.5421 24.3722 48.603 21.4314 45.5858 18.4142C42.5686 15.397 39.6278 12.4579 37.0734 10.2685C35.7961 9.1737 34.6708 8.31492 33.7257 7.73965C33.288 7.4732 32.7381 7.71168 32.6093 8.20766C32.2117 9.73781 32 11.3436 32 13C32 23.4934 40.5066 32 51 32ZM32 59C46.9117 59 59 46.9117 59 32C59 29 53 23 47 17C41 11 35 5 32 5C17.0883 5 5 17.0883 5 32C5 46.9117 17.0883 59 32 59ZM22.6947 47.7193C25.0714 45.4242 28.3594 44 32 44C35.6406 44 38.9286 45.4242 41.3053 47.7193C41.7026 48.103 42.3357 48.0919 42.7193 47.6946C43.103 47.2974 43.0919 46.6643 42.6947 46.2806C39.9529 43.633 36.1699 42 32 42C27.8302 42 24.0471 43.633 21.3053 46.2807C20.9081 46.6643 20.897 47.2974 21.2807 47.6947C21.6643 48.0919 22.2974 48.103 22.6947 47.7193Z" fill="#939BA1"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -82,3 +82,13 @@
(accounts.update/update-settings cofx
(assoc settings :web3-opt-in? opt-in)
{})))
(fx/defn update-recent-stickers [cofx stickers]
(accounts.update/account-update cofx
{:recent-stickers stickers}
{}))
(fx/defn update-stickers [cofx stickers]
(accounts.update/account-update cofx
{:stickers stickers}
{}))

View File

@ -147,6 +147,15 @@
:content (cond-> {:chat-id current-chat-id
:text message-text})})))
(fx/defn send-sticker-fx
[{:keys [db] :as cofx} uri current-chat-id]
(when-not (string/blank? uri)
(chat.message/send-message cofx {:chat-id current-chat-id
:content-type constants/content-type-sticker
:content (cond-> {:chat-id current-chat-id
:uri uri
:text "Update to latest version to see a nice sticker here!"})})))
(fx/defn send-current-message
"Sends message from current chat input"
[{{:keys [current-chat-id id->command access-scope->command-id] :as db} :db :as cofx}]

View File

@ -7,6 +7,7 @@
(def ethereum-rpc-url "http://localhost:8545")
(def content-type-text "text/plain")
(def content-type-sticker "sticker")
(def content-type-status "status")
(def content-type-command "command")
(def content-type-command-request "command-request")

View File

@ -56,7 +56,9 @@
(update :settings core/serialize)
(update :extensions serialize-extensions)
(update :bootnodes serialize-bootnodes)
(update :networks serialize-networks)))
(update :networks serialize-networks)
(update :recent-stickers #(if (nil? %) [] %))
(update :stickers #(if (nil? %) [] %))))
(defn save-account-tx
"Returns tx function for saving account"

View File

@ -14,8 +14,7 @@
[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.migrations :as migrations]
[taoensso.timbre :as log]))
[status-im.data-store.realm.schemas.account.migrations :as migrations]))
(def v1 [chat/v1
transport/v1
@ -471,4 +470,4 @@
:migration (constantly nil)}
{:schema v33
:schemaVersion 33
:migration (constantly nil)}])
:migration (constantly nil)}])

View File

@ -225,3 +225,8 @@
(def v18 (assoc-in v17
[:properties :installation-name]
{:type :string :optional true}))
(def v19 (update v18 :properties merge {:stickers
{:type "string[]" :optional true}
:recent-stickers
{:type "string[]" :optional true}}))

View File

@ -86,6 +86,11 @@
extension/v12
account/v18])
(def v23 [network/v1
bootnode/v4
extension/v12
account/v19])
;; put schemas ordered by version
(def schemas [{:schema v1
:schemaVersion 1
@ -152,4 +157,7 @@
:migration migrations/v21}
{:schema v22
:schemaVersion 22
:migration (constantly nil)}
{:schema v23
:schemaVersion 23
:migration (constantly nil)}])

View File

@ -48,7 +48,9 @@
[status-im.utils.datetime :as time]
[status-im.chat.commands.core :as commands]
[status-im.chat.models.loading :as chat-loading]
[status-im.node.core :as node]))
[status-im.node.core :as node]
[cljs.reader :as edn]
[status-im.stickers.core :as stickers]))
;; init module
@ -775,6 +777,14 @@
(fn [{{:keys [current-chat-id]} :db :as cofx} [_ message-text]]
(chat.input/send-plain-text-message-fx cofx message-text current-chat-id)))
(handlers/register-handler-fx
:chat/send-sticker
(fn [{{:keys [current-chat-id] :account/keys [account]} :db :as cofx} [_ {:keys [uri]}]]
(fx/merge
cofx
(accounts/update-recent-stickers (conj (remove #(= uri %) (:recent-stickers account)) uri))
(chat.input/send-sticker-fx uri current-chat-id))))
(handlers/register-handler-fx
:chat/disable-cooldown
(fn [cofx _]
@ -1573,3 +1583,30 @@
[(re-frame/inject-cofx :random-id-generator)]
(fn [cofx [_ public-key]]
(contact-recovery/show-contact-recovery-message cofx public-key)))
(handlers/register-handler-fx
:stickers/load-sticker-pack-success
(fn [{:keys [db]} [_ edn-string]]
(let [{{:keys [id] :as pack} 'meta} (edn/read-string edn-string)]
{:db (-> db (assoc-in [:stickers/packs id] (assoc pack :edn edn-string)))})))
(handlers/register-handler-fx
:stickers/install-pack
(fn [cofx [_ id]]
(stickers/install-stickers-pack cofx id)))
(handlers/register-handler-fx
:stickers/load-packs
(fn [_ _]
{;;TODO request list of packs from contract
:http-get-n (mapv (fn [uri] {:url uri
:success-event-creator (fn [o]
[:stickers/load-sticker-pack-success o])
:failure-event-creator (fn [o] nil)})
;;TODO for testing ONLY
["https://ipfs.infura.io/ipfs/QmbgsCFEz4ubLFzF3SFfCxDEeXeMxe4yypxC3W1Ro9rLXS/"])}))
(handlers/register-handler-fx
:stickers/select-pack
(fn [{:keys [db]} [_ id]]
{:db (assoc db :stickers/selected-pack id)}))

View File

@ -31,7 +31,8 @@
[taoensso.timbre :as log]
[status-im.utils.fx :as fx]
[status-im.chat.models :as chat-model]
[status-im.accounts.db :as accounts.db]))
[status-im.accounts.db :as accounts.db]
[status-im.stickers.core :as stickers]))
(defn init-store!
"Try to decrypt the database, move on if successful otherwise go back to
@ -231,9 +232,9 @@
#(when (dev-mode? %)
(models.dev-server/start))
(browser/initialize-browsers)
(browser/initialize-dapp-permissions)
(extensions.registry/initialize)
(stickers/init-stickers-packs)
(accounts.update/update-sign-in-time)
#(when-not (or (creating-account? %)
(finishing-hardwallet-setup? %))

View File

@ -0,0 +1,17 @@
(ns status-im.stickers.core
(:require [status-im.utils.fx :as fx]
[cljs.reader :as edn]
[status-im.accounts.core :as accounts]))
(fx/defn init-stickers-packs [{:keys [db]}]
(let [sticker-packs (map #(get (edn/read-string %) 'meta) (get-in db [:account/account :stickers]))]
{:db (assoc db :stickers/packs-installed (into {} (map #(vector (:id %) %) sticker-packs)))}))
(fx/defn install-stickers-pack [{{:account/keys [account] :as db} :db :as cofx} id]
(let [pack (get-in db [:stickers/packs id])]
(fx/merge
cofx
{:db (-> db
(assoc-in [:stickers/packs-installed id] pack)
(assoc :stickers/selected-pack id))}
(accounts/update-stickers (conj (:stickers account) (:edn pack))))))

View File

@ -3,7 +3,8 @@
(:require [cljs.spec.alpha :as spec]
[clojure.string :as s]
status-im.contact.db
[status-im.utils.clocks :as utils.clocks]))
[status-im.utils.clocks :as utils.clocks]
[status-im.constants :as constants]))
;; required
(spec/def ::ack (spec/coll-of string? :kind vector?))
@ -60,9 +61,11 @@
(spec/def :message.content/response-to string?)
(spec/def :message.content/response-to-v2 string?)
(spec/def :message.content/command-path (spec/tuple string? (spec/coll-of (spec/or :scope keyword? :chat-id string?) :kind set? :min-count 1)))
(spec/def :message.content/uri (spec/and string? (complement s/blank?)))
(spec/def :message.content/params (spec/map-of keyword? any?))
(spec/def ::content-type #{"text/plain" "command" "command-request"})
(spec/def ::content-type #{constants/content-type-text constants/content-type-command
constants/content-type-command-request constants/content-type-sticker})
(spec/def ::message-type #{:group-user-message :public-group-user-message :user-message})
(spec/def ::clock-value (spec/and pos-int?
utils.clocks/safe-timestamp?))
@ -95,16 +98,22 @@
:req-opt [:message.content/response-to]))
(spec/def :message.command/content (spec/keys :req-un [:message.content/command-path :message.content/params]))
(spec/def :message.sticker/content (spec/keys :req-un [:message.content/uri]))
(defmulti content-type :content-type)
(defmethod content-type "command" [_]
(defmethod content-type constants/content-type-command [_]
(spec/merge :message/message-common
(spec/keys :req-un [:message.command/content])))
(defmethod content-type "command-request" [_]
(defmethod content-type constants/content-type-command-request [_]
(spec/merge :message/message-common
(spec/keys :req-un [:message.command/content])))
(defmethod content-type constants/content-type-sticker [_]
(spec/merge :message/message-common
(spec/keys :req-un [:message.sticker/content])))
(defmethod content-type :default [_]
(spec/merge :message/message-common
(spec/keys :req-un [:message.text/content])))

View File

@ -122,7 +122,7 @@
(validate [this]
(if (spec/valid? :message/message this)
this
(log/warn "failed to validate Message" (spec/explain :message/message this)))))
(log/warn "failed to validate Message" (spec/explain-str :message/message this)))))
(defrecord MessagesSeen [message-ids]
StatusMessage

View File

@ -104,7 +104,8 @@
:icons/reply (js/require "./resources/icons/reply.svg")
:icons/indicator-big (js/require "./resources/icons/indicator-big.svg")
:icons/indicator-middle (js/require "./resources/icons/indicator-middle.svg")
:icons/indicator-small (js/require "./resources/icons/indicator-small.svg")}
:icons/indicator-small (js/require "./resources/icons/indicator-small.svg")
:icons/stickers (js/require "./resources/icons/stickers.svg")}
{:icons/discover (components.svg/slurp-svg "./resources/icons/bottom/discover_gray.svg")
:icons/contacts (components.svg/slurp-svg "./resources/icons/bottom/contacts_gray.svg")
:icons/home (components.svg/slurp-svg "./resources/icons/bottom/home_gray.svg")
@ -185,7 +186,10 @@
:icons/reply (components.svg/slurp-svg "./resources/icons/reply.svg")
:icons/indicator-big (components.svg/slurp-svg "./resources/icons/indicator-big.svg")
:icons/indicator-middle (components.svg/slurp-svg "./resources/icons/indicator-middle.svg")
:icons/indicator-small (components.svg/slurp-svg "./resources/icons/indicator-small.svg")}))
:icons/indicator-small (components.svg/slurp-svg "./resources/icons/indicator-small.svg")
:icons/stickers (components.svg/slurp-svg "./resources/icons/stickers.svg")
:icons/stickers-big (components.svg/slurp-svg "./resources/icons/stickers_big.svg")
:icons/clock (components.svg/slurp-svg "./resources/icons/clock.svg")}))
(defn normalize-property-name [n]
(if (= n :icons/options)

View File

@ -18,7 +18,9 @@
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.utils.platform :as platform]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.utils :as utils]))
[status-im.utils.utils :as utils]
[status-im.utils.config :as config]
[status-im.ui.screens.chat.stickers.views :as stickers]))
(defview basic-text-input [{:keys [set-container-width-fn height single-line-input?]}]
(letsubs [{:keys [input-text]} [:chats/current-chat]
@ -32,6 +34,7 @@
:editable (not cooldown-enabled?)
:blur-on-submit false
:on-focus #(re-frame/dispatch [:chat.ui/set-chat-ui-props {:input-focused? true
:show-stickers? false
:messages-focused? false}])
:on-blur #(re-frame/dispatch [:chat.ui/set-chat-ui-props {:input-focused? false}])
:on-submit-editing #(when single-line-input?
@ -130,7 +133,8 @@
(defview input-container []
(letsubs [margin [:chats/input-margin]
{:keys [input-text]} [:chats/current-chat]
result-box [:chats/current-chat-ui-prop :result-box]]
result-box [:chats/current-chat-ui-prop :result-box]
show-stickers? [:chats/current-chat-ui-prop :show-stickers?]]
(let [single-line-input? (:singleLineInput result-box)]
[react/view {:style (style/root margin)
:on-layout #(let [h (-> (.-nativeEvent %)
@ -141,6 +145,8 @@
[reply-message-view]
[react/view {:style style/input-container}
[input-view {:single-line-input? single-line-input?}]
(when (and config/stickers-enabled? (string/blank? input-text))
[stickers/button show-stickers?])
(if (string/blank? input-text)
[commands-button]
[send-button/send-button-view])]])))

View File

@ -137,6 +137,12 @@
[wrapper message]
[wrapper message [emoji-message message]])
(defmethod message-content constants/content-type-sticker
[wrapper {:keys [content] :as message}]
[wrapper message
[react/image {:style {:margin 10 :width 100 :height 100}
:source {:uri (:uri content)}}]])
(defmethod message-content :default
[wrapper {:keys [content-type] :as message}]
[wrapper message

View File

@ -0,0 +1,13 @@
(ns status-im.ui.screens.chat.stickers.styles)
(def stickers-panel {:flex 1 :margin 5 :flex-direction :row :justify-content :flex-start :flex-wrap :wrap})
(defn pack-icon [background-color icon-size]
{:background-color background-color
:margin-vertical 5
:margin-horizontal 8
:height icon-size
:width icon-size
:border-radius (/ icon-size 2)
:align-items :center
:justify-content :center})

View File

@ -0,0 +1,9 @@
(ns status-im.ui.screens.chat.stickers.subs
(:require [re-frame.core :as re-frame]
status-im.ui.screens.extensions.add.subs))
(re-frame/reg-sub
:stickers/selected-pack
(fn [db]
(get db :stickers/selected-pack)))

View File

@ -0,0 +1,88 @@
(ns status-im.ui.screens.chat.stickers.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :as re-frame]
[status-im.ui.components.react :as react]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.colors :as colors]
[status-im.i18n :as i18n]
[status-im.ui.screens.chat.stickers.styles :as styles]))
(defn button [show-stickers?]
[react/touchable-highlight
{:on-press (fn [_]
(re-frame/dispatch [:chat.ui/set-chat-ui-props {:show-stickers? (not show-stickers?)}])
(react/dismiss-keyboard!))}
[vector-icons/icon :icons/stickers {:container-style {:margin 14 :margin-right 6}
:color (if show-stickers? colors/blue colors/gray)}]])
(defn- no-stickers-yet-panel []
[react/view {:style {:flex 1 :align-items :center :justify-content :center}}
[vector-icons/icon :icons/stickers-big {:color colors/gray}]
[react/text {:style {:margin-top 8 :font-size 17}} (i18n/label :t/you-dont-have-stickers)]
[react/touchable-highlight {:on-press #(do
(re-frame/dispatch [:stickers/load-packs])
(re-frame/dispatch [:navigate-to :stickers]))}
[react/text {:style {:margin-top 17 :font-size 15 :color colors/blue}}
(i18n/label :t/get-stickers)]]])
(defn- on-sticker-click [sticker]
(re-frame/dispatch [:chat.ui/set-chat-ui-props {:show-stickers? false}])
(re-frame/dispatch [:chat/send-sticker sticker])
(react/dismiss-keyboard!))
(defn- stickers-panel [stickers]
[react/scroll-view {:style {:flex 1} :condtent-container-style {:flex 1}}
[react/view {:style styles/stickers-panel}
(for [{:keys [uri] :as sticker} stickers]
^{:key uri}
[react/touchable-highlight {:style {:height 75 :width 75 :margin 5}
:on-press #(on-sticker-click sticker)}
[react/image {:style {:resize-mode :cover :width "100%" :height "100%"} :source {:uri uri}}]])]])
(defview recent-stickers-panel []
(letsubs [stickers [:stickers/recent]]
(if (seq stickers)
[stickers-panel (map #(hash-map :uri %) stickers)]
[react/view {:style {:flex 1 :align-items :center :justify-content :center}}
[vector-icons/icon :icons/stickers-big {:color colors/gray}]
[react/text {:style {:margin-top 8 :font-size 17}} (i18n/label :t/recently-used-stickers)]])))
(def icon-size 28)
(defn pack-icon [{:keys [id on-press selected? background-color]
:or {background-color colors/gray
on-press #(re-frame/dispatch [:stickers/select-pack id])}} icon]
[react/touchable-highlight {:on-press on-press}
[react/view {:style {:align-items :center}}
[react/view {:style (styles/pack-icon background-color icon-size)}
icon]
[react/view {:style {:margin-bottom 5 :height 2 :width 16
:background-color (if selected? colors/blue colors/white)}}]]])
(defn pack-for [packs id]
(some #(when (= id (:id %)) %) packs))
(defview stickers-view []
(letsubs [selected-pack [:stickers/selected-pack]
installed-packs [:stickers/installed-packs-vals]]
[react/view {:style {:background-color :white :height "40%"}}
(cond
(= selected-pack :recent) [recent-stickers-panel]
(not (seq installed-packs)) [no-stickers-yet-panel]
(nil? selected-pack) [recent-stickers-panel]
:else [stickers-panel (:stickers (pack-for installed-packs selected-pack))])
[react/view {:style {:flex-direction :row :padding-horizontal 4}}
[pack-icon {:on-press #(do
(re-frame/dispatch [:stickers/load-packs])
(re-frame/dispatch [:navigate-to :stickers]))
:selected? false :background-color colors/blue}
[vector-icons/icon :icons/add {:width 20 :height 20 :color colors/white}]]
[react/view {:width 4}]
[pack-icon {:id :recent :selected? (or (= :recent selected-pack) (and (nil? selected-pack) (seq installed-packs)))}
[vector-icons/icon :icons/clock]]
;; TODO make scrollable
(for [{:keys [id thumbnail]} installed-packs]
^{:key id}
[pack-icon {:id id :selected? (= id selected-pack)}
[react/image {:style {:width icon-size :height icon-size :border-radius (/ icon-size 2)}
:source {:uri thumbnail}}]])]]))

View File

@ -26,7 +26,8 @@
[status-im.ui.components.animation :as animation]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.toolbar.actions :as toolbar.actions]))
[status-im.ui.components.toolbar.actions :as toolbar.actions]
[status-im.ui.screens.chat.stickers.views :as stickers]))
(defview add-contact-bar [contact-identity]
(letsubs [{:keys [hide-contact?] :as contact} [:contacts/contact-by-identity]]
@ -180,6 +181,7 @@
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?]
current-view [:get :view-id]]
;; this scroll-view is a hack that allows us to use on-blur and on-focus on Android
;; more details here: https://github.com/facebook/react-native/issues/11071
@ -197,6 +199,8 @@
[react/view style/message-view-preview])
(when (show-input-container? my-public-key current-chat)
[input/container])
(when show-stickers?
[stickers/stickers-view])
(when show-bottom-info?
[bottom-info/bottom-info-view])
(when show-message-options?

View File

@ -193,6 +193,11 @@
(spec/def ::hardwallet (spec/nilable map?))
(spec/def :stickers/packs (spec/nilable map?))
(spec/def :stickers/packs-installed (spec/nilable map?))
(spec/def :stickers/selected-pack (spec/nilable any?))
(spec/def :stickers/recent (spec/nilable vector?))
(spec/def ::db (spec/keys :opt [:contacts/contacts
:contacts/dapps
:contacts/new-identity
@ -259,7 +264,11 @@
:ui/contact
:ui/search
:ui/chat
:chats/loading?]
:chats/loading?
:stickers/packs
:stickers/packs-installed
:stickers/selected-pack
:stickers/recent]
:opt-un [::modal
::was-modal?
::rpc-url

View File

@ -32,11 +32,7 @@
[status-im.utils.handlers :as handlers]
[status-im.utils.http :as http]
[status-im.utils.utils :as utils]
[status-im.utils.fx :as fx]
[status-im.utils.platform :as platform]
[taoensso.timbre :as log]
[clojure.string :as str]
[status-im.utils.types :as types]))
[status-im.utils.fx :as fx]))
(defn- http-get [{:keys [url response-validator success-event-creator failure-event-creator timeout-ms]}]
(let [on-success #(re-frame/dispatch (success-event-creator %))

View File

@ -39,6 +39,10 @@
(= constants/content-type-command content-type)
[command-short-preview message]
(= constants/content-type-sticker content-type)
[react/image {:style {:margin 2 :width 30 :height 30}
:source {:uri (:uri content)}}]
(str/blank? (:text content))
[react/text {:style styles/last-message-text}
""]

View File

@ -0,0 +1,28 @@
(ns status-im.ui.screens.stickers.styles
(:require [status-im.ui.components.colors :as colors]))
(def screen
{:flex 1
:background-color colors/white})
(defn sticker-image [sticker-icon-size]
{:margin 16
:width sticker-icon-size
:height sticker-icon-size
:border-radius (/ sticker-icon-size 2)})
(defn price-badge [not-enough-snt?]
{:background-color (if not-enough-snt? colors/gray colors/blue)
:border-radius 14
:flex-direction :row
:padding-horizontal 8
:height 28
:align-items :center})
(def installed-icon
{:height 28
:width 28
:border-radius 14
:background-color colors/green
:align-items :center
:justify-content :center})

View File

@ -0,0 +1,31 @@
(ns status-im.ui.screens.stickers.subs
(:require [re-frame.core :as re-frame]))
(re-frame/reg-sub
:stickers/packs
(fn [db]
(:stickers/packs db)))
(re-frame/reg-sub
:stickers/installed-packs
(fn [db]
(:stickers/packs-installed db)))
(re-frame/reg-sub
:stickers/installed-packs-vals
:<- [:stickers/installed-packs]
(fn [packs]
(vals packs)))
(re-frame/reg-sub
:stickers/all-packs
:<- [:stickers/packs]
:<- [:stickers/installed-packs]
(fn [[packs installed]]
(map #(if (get installed (:id %)) (assoc % :installed true) %) (vals packs))))
(re-frame/reg-sub
:stickers/recent
:<- [:account/account]
(fn [{:keys [recent-stickers]}]
recent-stickers))

View File

@ -0,0 +1,89 @@
(ns status-im.ui.screens.stickers.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.react :as react]
[status-im.ui.screens.stickers.styles :as styles]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.styles :as components.styles]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.utils.money :as money]))
(def thumbnail-icon-size 40)
(defn- thumbnail-icon [uri]
[react/image {:style {:width thumbnail-icon-size :height thumbnail-icon-size :border-radius (/ thumbnail-icon-size 2)}
:source {:uri uri}}])
(defn- installed-icon []
[react/view styles/installed-icon
[icons/icon :icons/ok {:color colors/white :height 20 :width 20}]])
(defview price-badge [price id]
(letsubs [balance [:balance]]
(let [snt (money/wei-> :eth (:SNT balance))
not-enough-snt? (> price snt)
no-snt? (nil? snt)]
[react/touchable-highlight {:on-press #(when (zero? price) (re-frame/dispatch [:stickers/install-pack id]))}
[react/view (styles/price-badge not-enough-snt?)
(when (and (not (zero? price)) (not no-snt?))
[icons/icon :icons/logo {:color colors/white :width 12 :height 12 :container-style {:margin-right 8}}])
[react/text {:style {:font-size 15 :color colors/white}}
(cond (zero? price)
(i18n/label :t/install)
no-snt?
(i18n/label :t/buy-with-snt)
:else
(str price))]]])))
(defn pack-badge [{:keys [name author price thumbnail preview id installed] :as pack}]
[react/view {:margin-bottom 27}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to :stickers-pack pack])}
[react/image {:style {:height 200 :border-radius 20} :source {:uri preview}}]]
[react/view {:height 64 :align-items :center :flex-direction :row}
[thumbnail-icon thumbnail]
[react/view {:padding-horizontal 16 :flex 1}
[react/text {:style {:font-size 15}} name]
[react/text {:style {:font-size 15 :color colors/gray :margin-top 6}} author]]
(if installed
[installed-icon]
[price-badge price id])]])
(defview packs []
(letsubs [packs [:stickers/all-packs]]
[react/view styles/screen
[status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex
[toolbar/simple-toolbar (i18n/label :t/sticker-market)]
[react/view {:style {:padding-top 8 :flex 1}}
[react/scroll-view {:keyboard-should-persist-taps :handled :style {:flex 1 :padding 16}}
[react/view
(for [pack packs]
^{:key pack}
[pack-badge pack])]]]]]))
(def sticker-icon-size 60)
(defview pack []
(letsubs [{:keys [id name author price thumbnail stickers installed]} [:get-screen-params]]
[react/view styles/screen
[status-bar/status-bar]
[react/keyboard-avoiding-view components.styles/flex
[toolbar/simple-toolbar]
[react/view {:height 94 :align-items :center :flex-direction :row :padding-horizontal 16}
[thumbnail-icon thumbnail]
[react/view {:padding-horizontal 16 :flex 1}
[react/text {:style {:font-size 22 :font-weight :bold}} name]
[react/text {:style {:font-size 15 :color colors/gray :margin-top 6}} author]]
(if installed
[installed-icon]
[price-badge price id])]
[react/view {:style {:padding-top 8 :flex 1}}
[react/scroll-view {:keyboard-should-persist-taps :handled :style {:flex 1}}
[react/view {:flex-direction :row :flex-wrap :wrap}
(for [{:keys [uri]} stickers]
^{:key uri}
[react/image {:style (styles/sticker-image sticker-icon-size)
:source {:uri uri}}])]]]]]))

View File

@ -7,9 +7,11 @@
status-im.mailserver.subs
status-im.ui.components.connectivity.subs
status-im.ui.screens.accounts.subs
status-im.ui.screens.chat.stickers.subs
status-im.ui.screens.extensions.subs
status-im.ui.screens.home.subs
status-im.ui.screens.group.subs
status-im.ui.screens.stickers.subs
status-im.ui.screens.wallet.subs
status-im.ui.screens.wallet.collectibles.subs
status-im.ui.screens.wallet.request.subs

View File

@ -64,6 +64,7 @@
[status-im.ui.screens.hardwallet.success.views :refer [hardwallet-success]]
[status-im.ui.screens.profile.seed.views :refer [backup-seed]]
[status-im.ui.screens.about-app.views :as about-app]
[status-im.ui.screens.stickers.views :as stickers]
[status-im.utils.navigation :as navigation]
[reagent.core :as reagent]
[cljs-react-navigation.reagent :as nav-reagent]
@ -167,6 +168,8 @@
:open-dapp open-dapp
:dapp-description dapp-description
:browser browser
:stickers stickers/packs
:stickers-pack stickers/pack
:login login}
:config
{:headerMode "none"

View File

@ -27,6 +27,7 @@
(def cached-webviews-enabled? (enabled? (get-config :CACHED_WEBVIEWS_ENABLED 0)))
(def rn-bridge-threshold-warnings-enabled? (enabled? (get-config :RN_BRIDGE_THRESHOLD_WARNINGS 0)))
(def extensions-enabled? (enabled? (get-config :EXTENSIONS 0)))
(def stickers-enabled? (enabled? (get-config :STICKERS_ENABLED 0)))
(def hardwallet-enabled? (enabled? (get-config :HARDWALLET_ENABLED 0)))
(def dev-build? (enabled? (get-config :DEV_BUILD 0)))
(def erc20-contract-warnings-enabled? (enabled? (get-config :ERC20_CONTRACT_WARNINGS)))

View File

@ -885,5 +885,10 @@
"migrations-erase-accounts-data-button": "Erase account's db",
"account-and-db-password-mismatch-title": "The problem occurred!",
"account-and-db-password-mismatch-content": "Account's and realm db passwords do not match.",
"recover-account-warning": "Your wallet information will be exposed by importing this account."
"recover-account-warning": "Your wallet information will be exposed by importing this account.",
"buy-with-snt": "Buy with SNT",
"sticker-market": "Sticker market",
"you-dont-have-stickers": "You dont have any stickers yet",
"get-stickers": "Get Stickers",
"recently-used-stickers": "Recently used stickers will appear here"
}