Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2c2fc0a76a |
@@ -35,4 +35,3 @@ LOCAL_PAIRING_ENABLED=1
|
||||
TEST_STATEOFUS=1
|
||||
FAST_CREATE_COMMUNITY_ENABLED=1
|
||||
TEST_NETWORKS_ENABLED=1
|
||||
SHOW_NOT_IMPLEMENTED_FEATURES=1
|
||||
|
||||
@@ -34,6 +34,3 @@ STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
FAST_CREATE_COMMUNITY_ENABLED=1
|
||||
TEST_NETWORKS_ENABLED=1
|
||||
SHOW_NOT_IMPLEMENTED_FEATURES=1
|
||||
DELETE_MESSAGE_FOR_ME_UNDO_TIME_LIMIT=10000
|
||||
DELETE_MESSAGE_UNDO_TIME_LIMIT=10000
|
||||
|
||||
@@ -36,4 +36,3 @@ STICKERS_TEST_ENABLED=1
|
||||
LOCAL_PAIRING_ENABLED=1
|
||||
FAST_CREATE_COMMUNITY_ENABLED=1
|
||||
TEST_NETWORKS_ENABLED=1
|
||||
SHOW_NOT_IMPLEMENTED_FEATURES=1
|
||||
|
||||
@@ -36,12 +36,6 @@ pipeline {
|
||||
))
|
||||
}
|
||||
|
||||
environment {
|
||||
/* Avoid race conditions with other builds using virtualenv. */
|
||||
VIRTUAL_ENV = "${WORKSPACE_TMP}/venv"
|
||||
PATH = "${VIRTUAL_ENV}/bin:${PATH}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Fetch') {
|
||||
steps { script {
|
||||
@@ -58,8 +52,7 @@ pipeline {
|
||||
stage('Setup') {
|
||||
steps { script {
|
||||
dir('test/appium') {
|
||||
sh "python3 -m venv ${VIRTUAL_ENV}"
|
||||
sh 'pip3 install -r requirements.txt'
|
||||
sh 'pip3 install --user -r requirements.txt'
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
@@ -54,12 +54,6 @@ pipeline {
|
||||
))
|
||||
}
|
||||
|
||||
environment {
|
||||
/* Avoid race conditions with other builds using virtualenv. */
|
||||
VIRTUAL_ENV = "${WORKSPACE_TMP}/venv"
|
||||
PATH = "${VIRTUAL_ENV}/bin:${PATH}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
steps { script {
|
||||
@@ -85,8 +79,7 @@ pipeline {
|
||||
stage('Setup') {
|
||||
steps { script {
|
||||
dir('test/appium') {
|
||||
sh "python3 -m venv ${VIRTUAL_ENV}"
|
||||
sh 'pip3 install -r requirements.txt'
|
||||
sh 'pip3 install --user -r requirements.txt'
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
@@ -35,11 +35,6 @@ pipeline {
|
||||
))
|
||||
}
|
||||
|
||||
environment {
|
||||
/* Avoid race conditions with other builds using virtualenv. */
|
||||
VIRTUAL_ENV = "${WORKSPACE_TMP}/venv"
|
||||
PATH = "${VIRTUAL_ENV}/bin:${PATH}"
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Prep') {
|
||||
@@ -56,8 +51,7 @@ pipeline {
|
||||
stage('Setup') {
|
||||
steps { script {
|
||||
dir('test/appium') {
|
||||
sh "python3 -m venv ${VIRTUAL_ENV}"
|
||||
sh 'pip3 install -r requirements.txt'
|
||||
sh 'pip3 install --user -r requirements.txt'
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
@@ -128,19 +128,3 @@ Status-mobile uses `shadow-cljs` for hot reloading changes and uses its own [rel
|
||||
|
||||
### Solution
|
||||
Open react native's [In-App Developer Menu](https://reactnative.dev/docs/debugging#accessing-the-in-app-developer-menu) and press "Disable Fast Refresh" or "Disable Hot Reloading"
|
||||
|
||||
# App crashing after running `make run-ios`
|
||||
|
||||
### Cause
|
||||
It's possible that installing XCode from a `.xip` file might cause XCode to act funny
|
||||
Since it's not installed from the App Store, Or you might be missing a Rosetta installation.
|
||||
|
||||
[Reference/Similar issue](https://github.com/expo/expo-cli/issues/3197)
|
||||
|
||||
You might see something like this after running `make run-ios`:
|
||||
```
|
||||
Underlying error (domain=FBSOpenApplicationServiceErrorDomain, code=1):
|
||||
```
|
||||
### Solution
|
||||
Run `softwareupdate --install-rosetta --agree-to-license`
|
||||
to accept XCode's license and install Rosetta.
|
||||
|
||||
@@ -27,7 +27,6 @@ nix_install_type() {
|
||||
if [[ "$(os_name)" =~ NixOS ]]; then
|
||||
echo "nixos"
|
||||
else
|
||||
USER=$(id -un) # Missing in Docker.
|
||||
case "${NIX_STORE_DIR_GROUP}" in
|
||||
"nixbld") echo "multi";;
|
||||
"30000") echo "multi";;
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 707 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.1 KiB |
@@ -4,7 +4,6 @@
|
||||
[legacy.status-im.bottom-sheet.events :as bottom-sheet]
|
||||
legacy.status-im.communities.e2e
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.contexts.shell.activity-center.events :as activity-center]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -23,10 +22,60 @@
|
||||
{}
|
||||
requests))
|
||||
|
||||
(defn- fetch-community-id-input
|
||||
[{:keys [db]}]
|
||||
(:communities/community-id-input db))
|
||||
|
||||
(rf/defn handle-response
|
||||
[_ response-js]
|
||||
{:dispatch [:sanitize-messages-and-process-response response-js]})
|
||||
|
||||
(rf/defn invite-users
|
||||
{:events [::invite-people-confirmation-pressed]}
|
||||
[cofx user-pk contacts]
|
||||
(let [community-id (fetch-community-id-input cofx)
|
||||
pks (if (seq user-pk)
|
||||
(conj contacts user-pk)
|
||||
contacts)]
|
||||
(when (seq pks)
|
||||
{:json-rpc/call [{:method "wakuext_inviteUsersToCommunity"
|
||||
:params [{:communityId community-id
|
||||
:users pks}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::people-invited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to invite-user community" %)
|
||||
(re-frame/dispatch [::failed-to-invite-people %]))}]})))
|
||||
|
||||
(rf/defn share-community
|
||||
{:events [::share-community-confirmation-pressed]}
|
||||
[cofx user-pk contacts]
|
||||
(let [community-id (fetch-community-id-input cofx)
|
||||
pks (if (seq user-pk)
|
||||
(conj contacts user-pk)
|
||||
contacts)]
|
||||
(when (seq pks)
|
||||
{:json-rpc/call [{:method "wakuext_shareCommunity"
|
||||
:params [{:communityId community-id
|
||||
:users pks}]
|
||||
:js-response true
|
||||
:on-success #(re-frame/dispatch [::people-invited %])
|
||||
:on-error #(do
|
||||
(log/error "failed to invite-user community" %)
|
||||
(re-frame/dispatch [::failed-to-share-community %]))}]})))
|
||||
|
||||
(re-frame/reg-event-fx :communities/invite-people-pressed
|
||||
(fn [{:keys [db]} [id]]
|
||||
{:db (assoc db :communities/community-id-input id)
|
||||
:fx [[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:open-modal :legacy-invite-people-community {:invite? true}]]]}))
|
||||
|
||||
(re-frame/reg-event-fx :communities/share-community-pressed
|
||||
(fn [{:keys [db]} [id]]
|
||||
{:db (assoc db :communities/community-id-input id)
|
||||
:fx [[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:open-modal :legacy-invite-people-community {}]]]}))
|
||||
|
||||
(rf/defn people-invited
|
||||
{:events [::people-invited]}
|
||||
[cofx response-js]
|
||||
@@ -41,14 +90,6 @@
|
||||
[:sanitize-messages-and-process-response response-js]
|
||||
[:activity-center.notifications/fetch-unread-count]]}))
|
||||
|
||||
(rf/defn member-banned
|
||||
{:events [::member-banned]}
|
||||
[cofx response-js]
|
||||
(rf/merge cofx
|
||||
(bottom-sheet/hide-bottom-sheet-old)
|
||||
(handle-response response-js)
|
||||
(activity-center/notifications-fetch-unread-count)))
|
||||
|
||||
(rf/defn member-ban
|
||||
{:events [::member-ban]}
|
||||
[cofx community-id public-key]
|
||||
|
||||
@@ -38,6 +38,22 @@
|
||||
:params []
|
||||
:on-success [:stickers/stickers-recent-success]})))
|
||||
|
||||
(rf/defn load-packs
|
||||
{:events [:stickers/load-packs]}
|
||||
[{:keys [db]}]
|
||||
{:json-rpc/call [{:method "stickers_market"
|
||||
:params [(chain/chain-id db)]
|
||||
:on-success #(re-frame/dispatch [:stickers/stickers-market-success %])}
|
||||
{:method "stickers_installed"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch [:stickers/stickers-installed-success %])}
|
||||
{:method "stickers_pending"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch [:stickers/stickers-pending-success %])}
|
||||
{:method "stickers_recent"
|
||||
:params []
|
||||
:on-success #(re-frame/dispatch [:stickers/stickers-recent-success %])}]})
|
||||
|
||||
(rf/defn pending-pack
|
||||
{:events [:stickers/pending-pack]}
|
||||
[{db :db} id]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
(:require
|
||||
[legacy.status-im.browser.core :as browser]
|
||||
[legacy.status-im.browser.webview-ref :as webview-ref]
|
||||
[legacy.status-im.qr-scanner.core :as qr-scanner]
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||
[legacy.status-im.ui.components.colors :as colors]
|
||||
[legacy.status-im.ui.components.connectivity.view :as connectivity]
|
||||
@@ -104,7 +105,9 @@
|
||||
(if empty-tab
|
||||
[react/touchable-highlight
|
||||
{:accessibility-label :universal-qr-scanner
|
||||
:on-press #(re-frame/dispatch [:open-modal :shell-qr-reader])}
|
||||
:on-press #(re-frame/dispatch
|
||||
[::qr-scanner/scan-code
|
||||
{:handler ::qr-scanner/on-scan-success}])}
|
||||
[icons/icon :main-icons/qr {:color colors/black}]]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(re-frame/dispatch
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
(ns legacy.status-im.ui.screens.communities.invite
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.communities.core :as communities]
|
||||
[legacy.status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
[legacy.status-im.ui.components.core :as quo]
|
||||
[legacy.status-im.ui.components.list.item :as list.item]
|
||||
[legacy.status-im.ui.components.toolbar :as toolbar]
|
||||
[legacy.status-im.ui.components.topbar :as topbar]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.constants :as constants]
|
||||
[utils.debounce :as debounce]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
@@ -48,35 +49,18 @@
|
||||
contacts-selected (reagent/atom #{})
|
||||
{:keys [invite?]} (rf/sub [:get-screen-params])]
|
||||
(fn []
|
||||
(let [theme (quo.theme/use-theme)
|
||||
contacts-data (rf/sub [:contacts/active])
|
||||
{community-id :id
|
||||
:keys [permissions
|
||||
can-manage-users?]}
|
||||
(let [contacts-data (rf/sub [:contacts/active])
|
||||
{:keys [permissions
|
||||
can-manage-users?]}
|
||||
(rf/sub [:communities/edited-community])
|
||||
selected @contacts-selected
|
||||
selected-contacts-count (count selected)
|
||||
contacts (map (fn [{:keys [public-key] :as contact}]
|
||||
(assoc contact :active (contains? selected public-key)))
|
||||
contacts-data)
|
||||
;; no-membership communities can only be shared
|
||||
can-invite? (and can-manage-users?
|
||||
invite?
|
||||
(not= (:access permissions) constants/community-no-membership-access))
|
||||
on-press-share-community (rn/use-callback
|
||||
(fn []
|
||||
(rf/dispatch [:communities/share-community-confirmation-pressed
|
||||
selected community-id])
|
||||
(rf/dispatch [:navigate-back])
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:type :positive
|
||||
:theme theme
|
||||
:text (if (= 1 selected-contacts-count)
|
||||
(i18n/label :t/one-user-was-invited)
|
||||
(i18n/label
|
||||
:t/n-users-were-invited
|
||||
{:count selected-contacts-count}))}]))
|
||||
[community-id selected selected-contacts-count theme])]
|
||||
(not= (:access permissions) constants/community-no-membership-access))]
|
||||
[:<>
|
||||
[topbar/topbar
|
||||
{:title (i18n/label (if can-invite?
|
||||
@@ -97,8 +81,11 @@
|
||||
:center
|
||||
[quo/button
|
||||
{:disabled (and (string/blank? @user-pk)
|
||||
(zero? selected-contacts-count))
|
||||
(zero? (count selected)))
|
||||
:accessibility-label :share-community-link
|
||||
:type :secondary
|
||||
:on-press on-press-share-community}
|
||||
:on-press #(debounce/throttle-and-dispatch
|
||||
[::communities/share-community-confirmation-pressed @user-pk
|
||||
selected]
|
||||
3000)}
|
||||
(i18n/label (if can-invite? :t/invite :t/share))]}]]))))
|
||||
|
||||
@@ -13,11 +13,3 @@
|
||||
:background-color (colors/theme-colors (colors/custom-color customization-color 50)
|
||||
(colors/custom-color customization-color 60)
|
||||
theme)})
|
||||
|
||||
(defn avatar-identifier
|
||||
[theme]
|
||||
{:text-align :center
|
||||
:font-size 36
|
||||
:color (colors/theme-colors colors/black
|
||||
colors/white
|
||||
theme)})
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
(ns quo.components.avatars.group-avatar.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.components.avatars.group-avatar.style :as style]
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
@@ -23,7 +21,7 @@
|
||||
|
||||
(defn- view-internal
|
||||
[_]
|
||||
(fn [{:keys [size theme customization-color picture icon-name emoji chat-name]
|
||||
(fn [{:keys [size theme customization-color picture icon-name]
|
||||
:or {size :size-20
|
||||
customization-color :blue
|
||||
picture nil
|
||||
@@ -40,27 +38,8 @@
|
||||
{:source picture
|
||||
:style {:width container-size
|
||||
:height container-size}}]
|
||||
(cond
|
||||
emoji
|
||||
(if (= size :size-80)
|
||||
[rn/text
|
||||
{:style (style/avatar-identifier theme)}
|
||||
emoji]
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:style (dissoc (style/avatar-identifier theme) :font-size)}
|
||||
emoji])
|
||||
chat-name
|
||||
(if (= size :size-80)
|
||||
[rn/text
|
||||
{:style (style/avatar-identifier theme)}
|
||||
((comp first string/upper-case) chat-name)]
|
||||
[text/text
|
||||
{:size :paragraph-1}
|
||||
((comp first string/upper-case) chat-name)])
|
||||
:else
|
||||
[icon/icon icon-name
|
||||
{:size icon-size
|
||||
:color colors/white-opa-70}]))])))
|
||||
[icon/icon icon-name
|
||||
{:size icon-size
|
||||
:color colors/white-opa-70}])])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
(ns quo.components.community.community-detail-token-gating.component-spec
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[test-helpers.component :as h]))
|
||||
|
||||
(h/describe "Community Detail Token Gating Component"
|
||||
(h/test "render with member permissions"
|
||||
(h/render
|
||||
[quo/community-detail-token-gating
|
||||
{:permissions [{:role 2
|
||||
:role-text "Member"
|
||||
:satisfied? true
|
||||
:tokens [[{:symbol "ETH"
|
||||
:sufficient? true
|
||||
:collectible? false
|
||||
:amount 0.8
|
||||
:img-src nil}]
|
||||
[{:symbol "ETH"
|
||||
:sufficient? false
|
||||
:collectible? false
|
||||
:amount 1
|
||||
:img-src nil}
|
||||
{:symbol "STT"
|
||||
:sufficient? false
|
||||
:collectible? false
|
||||
:amount 10
|
||||
:img-src nil}]]}]}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/you-eligible-to-join-as {:role "Member"}))
|
||||
(h/is-truthy (h/get-by-text "0.8 ETH"))
|
||||
(h/is-truthy (h/get-by-text "1 ETH"))
|
||||
(h/is-truthy (h/get-by-text "10 STT")))
|
||||
|
||||
(h/test "render with admin permissions"
|
||||
(h/render
|
||||
[quo/community-detail-token-gating
|
||||
{:permissions [{:role 1
|
||||
:role-text "Admin"
|
||||
:satisfied? true
|
||||
:tokens [[{:symbol "ETH"
|
||||
:sufficient? true
|
||||
:collectible? false
|
||||
:amount 2
|
||||
:img-src nil}]]}]}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/you-eligible-to-join-as {:role "Admin"}))
|
||||
(h/is-truthy (h/get-by-text "2 ETH")))
|
||||
|
||||
(h/test "render with token master permissions"
|
||||
(h/render-with-theme-provider
|
||||
[quo/community-detail-token-gating
|
||||
{:permissions [{:role 5
|
||||
:role-text "Token Master"
|
||||
:satisfied? true
|
||||
:tokens [[{:symbol "TMANI "
|
||||
:sufficient? true
|
||||
:collectible? true
|
||||
:img-src {:uri "mock-image"}}]]}]}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/you-eligible-to-join-as {:role "Token Master"}))
|
||||
(h/is-truthy (h/get-by-text "TMANI")))
|
||||
|
||||
(h/test "render with token owner permissions"
|
||||
(h/render-with-theme-provider
|
||||
[quo/community-detail-token-gating
|
||||
{:permissions [{:role 6
|
||||
:role-text "Token Owner"
|
||||
:satisfied? true
|
||||
:tokens [[{:symbol "TOANI"
|
||||
:sufficient? true
|
||||
:collectible? true
|
||||
:img-src {:uri "mock-image"}}]]}]}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/you-eligible-to-join-as {:role "Token Owner"}))
|
||||
(h/is-truthy (h/get-by-text "TOANI"))))
|
||||
@@ -1,20 +0,0 @@
|
||||
(ns quo.components.community.community-detail-token-gating.style)
|
||||
|
||||
(def container
|
||||
{:padding-horizontal 20
|
||||
:margin-vertical -4})
|
||||
|
||||
(defn token-row
|
||||
[first?]
|
||||
{:flex-direction :row
|
||||
:margin-top (if first? 8 4)
|
||||
:row-gap 10
|
||||
:column-gap 8
|
||||
:flex-wrap :wrap
|
||||
:margin-bottom 16})
|
||||
|
||||
(def divider
|
||||
{:padding-left 0
|
||||
:height 28
|
||||
:padding-top 0
|
||||
:align-items :flex-start})
|
||||
@@ -1,74 +0,0 @@
|
||||
(ns quo.components.community.community-detail-token-gating.view
|
||||
(:require [clojure.string :as string]
|
||||
[quo.components.community.community-detail-token-gating.style :as style]
|
||||
[quo.components.dividers.divider-label.view :as divider-label]
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.tags.collectible-tag.view :as collectible-tag]
|
||||
[quo.components.tags.token-tag.view :as token-tag]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn- token-view
|
||||
[{:keys [collectible? img-src amount sufficient?] :as token}]
|
||||
(let [token-symbol (:symbol token)]
|
||||
(if collectible?
|
||||
[collectible-tag/view
|
||||
{:collectible-name token-symbol
|
||||
:size :size-24
|
||||
:collectible-img-src img-src
|
||||
:options (when sufficient?
|
||||
:hold)}]
|
||||
[token-tag/view
|
||||
{:token-symbol token-symbol
|
||||
:size :size-24
|
||||
:token-value amount
|
||||
:token-img-src img-src
|
||||
:options (when sufficient? :hold)}])))
|
||||
|
||||
(defn- tokens-row
|
||||
[{:keys [tokens divider? first?]}]
|
||||
[:<>
|
||||
[rn/view
|
||||
{:style (style/token-row first?)}
|
||||
(map-indexed (fn [token-index token]
|
||||
^{:key (str "token-" token-index)}
|
||||
[token-view token])
|
||||
tokens)]
|
||||
(when-not divider?
|
||||
[divider-label/view
|
||||
{:container-style style/divider}
|
||||
[text/text
|
||||
{:size :label
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||
(string/lower-case (i18n/label :t/or))]])])
|
||||
|
||||
(defn- role-view
|
||||
[{:keys [role tokens satisfied? role-text]}]
|
||||
(when (seq tokens)
|
||||
^{:key (str "role-" role)}
|
||||
[:<>
|
||||
[text/text
|
||||
{:size :paragraph-1
|
||||
:weight :medium
|
||||
:style {:margin-top 4}}
|
||||
(if satisfied?
|
||||
(i18n/label :t/you-eligible-to-join-as {:role role-text})
|
||||
(i18n/label :t/you-not-eligible-to-join-as {:role role-text}))]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:style {:margin-bottom 8}}
|
||||
(i18n/label (if satisfied? :t/you-hodl :t/you-must-hold))]
|
||||
|
||||
(map-indexed (fn [index tokens-item]
|
||||
^{:key (str role "-tokens-" index)}
|
||||
[tokens-row
|
||||
{:tokens tokens-item
|
||||
:first? (zero? index)
|
||||
:divider? (= index (dec (count tokens)))}])
|
||||
tokens)]))
|
||||
|
||||
(defn view
|
||||
[{:keys [permissions]}]
|
||||
[rn/view {:style style/container}
|
||||
(map role-view permissions)])
|
||||
@@ -102,7 +102,7 @@
|
||||
:right 8})
|
||||
|
||||
(def token-tag-spacing
|
||||
{:padding-top 10
|
||||
{:margin-top 10
|
||||
:margin-right 8})
|
||||
|
||||
(defn token-row
|
||||
@@ -117,12 +117,11 @@
|
||||
(defn token-row-or-text
|
||||
[padding? theme]
|
||||
(merge
|
||||
{:padding-top 4
|
||||
:margin-bottom -2
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme)}
|
||||
{:margin-top 4
|
||||
:color (colors/theme-colors
|
||||
colors/neutral-50
|
||||
colors/neutral-40
|
||||
theme)}
|
||||
(when padding?
|
||||
{:padding-left 12})))
|
||||
|
||||
|
||||
@@ -7,14 +7,8 @@
|
||||
:align-items :center})
|
||||
|
||||
(def image
|
||||
{:width 72
|
||||
:height 72})
|
||||
|
||||
(def image-container
|
||||
{:width 80
|
||||
:height 80
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
{:width 80
|
||||
:height 80})
|
||||
|
||||
(def text-container
|
||||
{:margin-top 12
|
||||
|
||||
@@ -15,10 +15,9 @@
|
||||
[rn/view {:style (merge styles/container container-style)}
|
||||
(if placeholder?
|
||||
[rn/view {:style styles/image-placeholder}]
|
||||
[rn/view {:style styles/image-container}
|
||||
[fast-image/fast-image
|
||||
{:style styles/image
|
||||
:source image}]])
|
||||
[fast-image/fast-image
|
||||
{:style styles/image
|
||||
:source image}])
|
||||
[rn/view {:style styles/text-container}
|
||||
[text/text
|
||||
{:style (styles/title blur?)
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
(ns quo.components.inputs.input.style
|
||||
(:require
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]))
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn variants-colors
|
||||
[blur? theme]
|
||||
@@ -98,12 +97,9 @@
|
||||
(assoc base-props
|
||||
:text-align-vertical :top
|
||||
:line-height 22)
|
||||
(cond-> base-props
|
||||
:always
|
||||
(assoc :height (if small? 30 38)
|
||||
:line-height nil)
|
||||
platform/ios?
|
||||
(assoc :padding-top (+ padding 2))))))
|
||||
(assoc base-props
|
||||
:height (if small? 30 38)
|
||||
:line-height nil))))
|
||||
|
||||
(defn right-icon-touchable-area
|
||||
[small?]
|
||||
|
||||
@@ -41,24 +41,21 @@
|
||||
(defn user
|
||||
[{:keys [short-chat-key primary-name secondary-name photo-path online? contact? verified?
|
||||
untrustworthy? on-press on-long-press accessory customization-color theme
|
||||
allow-multiple-presses? disabled?]}]
|
||||
allow-multiple-presses?]}]
|
||||
[rn/touchable-highlight
|
||||
{:style container-style
|
||||
:underlay-color (colors/resolve-color customization-color theme 5)
|
||||
:allow-multiple-presses? allow-multiple-presses?
|
||||
:accessibility-label :user-list
|
||||
:on-press (when on-press on-press)
|
||||
:on-long-press (when on-long-press on-long-press)
|
||||
:disabled disabled?}
|
||||
:on-long-press (when on-long-press on-long-press)}
|
||||
[:<>
|
||||
[user-avatar/user-avatar
|
||||
{:full-name primary-name
|
||||
:profile-picture photo-path
|
||||
:online? online?
|
||||
:size :small}]
|
||||
[rn/view
|
||||
{:style {:margin-horizontal 8
|
||||
:flex 1}}
|
||||
[rn/view {:style {:margin-horizontal 8 :flex 1}}
|
||||
[author/view
|
||||
{:primary-name primary-name
|
||||
:secondary-name secondary-name
|
||||
@@ -72,4 +69,4 @@
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||
short-chat-key])]
|
||||
(when accessory
|
||||
[action-icon accessory customization-color disabled? theme])]])
|
||||
[action-icon accessory customization-color theme])]])
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
[quo.components.tags.status-tags :as status-tags]
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
(defn- activity-reply-text-input
|
||||
[{:keys [on-update-reply max-reply-length valid-reply?]} reply-input set-reply-input]
|
||||
[{:keys [on-update-reply max-reply-length valid-reply?]} reply-input]
|
||||
[rn/view
|
||||
[rn/view
|
||||
{:style {:margin-top 16
|
||||
@@ -25,12 +26,12 @@
|
||||
(i18n/label :t/your-answer)]
|
||||
[text/text
|
||||
{:style {:flex-shrink 1
|
||||
:color (if (valid-reply? reply-input)
|
||||
:color (if (valid-reply? @reply-input)
|
||||
colors/neutral-40
|
||||
colors/danger-60)}}
|
||||
(str (count reply-input) "/" max-reply-length)]]
|
||||
(str (count @reply-input) "/" max-reply-length)]]
|
||||
[input/input
|
||||
{:on-change-text #(do (set-reply-input %)
|
||||
{:on-change-text #(do (reset! reply-input %)
|
||||
(when on-update-reply
|
||||
(on-update-reply %)))
|
||||
:auto-capitalize :none
|
||||
@@ -135,7 +136,7 @@
|
||||
(-> button
|
||||
(assoc :size size)
|
||||
(assoc :type subtype)
|
||||
(assoc :disabled? (and replying? disable-when (disable-when reply-input)))
|
||||
(assoc :disabled? (and replying? disable-when (disable-when @reply-input)))
|
||||
(assoc :inner-style
|
||||
{:justify-content :center
|
||||
:padding-bottom 0
|
||||
@@ -152,16 +153,17 @@
|
||||
:blur? blur?}])
|
||||
|
||||
(defn- footer
|
||||
[{:keys [replying? items] :as props}]
|
||||
(let [[reply-input set-reply-input] (rn/use-state "")]
|
||||
[:<>
|
||||
(when replying?
|
||||
[activity-reply-text-input props reply-input set-reply-input])
|
||||
(when items
|
||||
[rn/view style/footer-container
|
||||
(for [item items]
|
||||
^{:key (:key item)}
|
||||
[footer-item-view item replying? reply-input])])]))
|
||||
[_]
|
||||
(let [reply-input (reagent/atom "")]
|
||||
(fn [{:keys [replying? items] :as props}]
|
||||
[:<>
|
||||
(when replying?
|
||||
[activity-reply-text-input props reply-input])
|
||||
(when items
|
||||
[rn/view style/footer-container
|
||||
(for [item items]
|
||||
^{:key (:key item)}
|
||||
[footer-item-view item replying? reply-input])])])))
|
||||
|
||||
(defn view
|
||||
[{:keys [icon
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.svg :as svg]))
|
||||
[react-native.svg :as svg]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- get-path-props
|
||||
[size stroke-width rotation]
|
||||
@@ -48,53 +49,60 @@
|
||||
{:color {:dark colors/neutral-80-opa-40
|
||||
:light colors/white-opa-40}})
|
||||
|
||||
(defn circle-timer
|
||||
[{:keys [color duration size stroke-width trail-color rotation initial-remaining-time]}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
rotation (or rotation :clockwise)
|
||||
duration (or duration 4)
|
||||
stroke-width (or stroke-width 1)
|
||||
size (or size 9)
|
||||
max-stroke-width (max stroke-width 0)
|
||||
{:keys [path path-length]} (get-path-props size max-stroke-width rotation)
|
||||
start-at (get-start-at duration initial-remaining-time)
|
||||
elapsed-time (rn/use-ref-atom 0)
|
||||
prev-frame-time (rn/use-ref-atom nil)
|
||||
frame-request (rn/use-ref-atom nil)
|
||||
[display-time set-display-time] (rn/use-state start-at)
|
||||
swap-elapsed-time-each-frame (fn swap-elapsed-time-each-frame [frame-time]
|
||||
(if (nil? @prev-frame-time)
|
||||
(do (reset! prev-frame-time frame-time)
|
||||
(reset! frame-request (js/requestAnimationFrame
|
||||
swap-elapsed-time-each-frame)))
|
||||
(let [delta (- (/ frame-time 1000)
|
||||
(/ @prev-frame-time 1000))
|
||||
current-elapsed (swap! elapsed-time + delta)
|
||||
current-display-time (+ start-at current-elapsed)
|
||||
completed? (>= current-display-time
|
||||
duration)]
|
||||
(set-display-time
|
||||
(if completed? duration current-display-time))
|
||||
(when-not completed?
|
||||
(reset! prev-frame-time frame-time)))))]
|
||||
(rn/use-effect #(reset! frame-request (js/requestAnimationFrame swap-elapsed-time-each-frame)))
|
||||
(rn/use-unmount #(js/cancelAnimationFrame @frame-request))
|
||||
[rn/view
|
||||
{:style {:position :relative
|
||||
:width size
|
||||
:height size}}
|
||||
[svg/svg
|
||||
{:view-box (str "0 0 " size " " size)
|
||||
:width size
|
||||
:height size}
|
||||
[svg/path
|
||||
{:d path :fill :none :stroke (or trail-color :transparent) :stroke-width stroke-width}]
|
||||
(when-not (= display-time duration)
|
||||
[svg/path
|
||||
{:d path
|
||||
:fill :none
|
||||
:stroke (or color (get-in themes [:color theme]))
|
||||
:stroke-linecap :square
|
||||
:stroke-width stroke-width
|
||||
:stroke-dasharray path-length
|
||||
:stroke-dashoffset (linear-ease display-time 0 path-length duration)}])]]))
|
||||
(defn- circle-timer-internal
|
||||
[{:keys [color duration size stroke-width trail-color rotation initial-remaining-time theme]}]
|
||||
(let [rotation (or rotation :clockwise)
|
||||
duration (or duration 4)
|
||||
stroke-width (or stroke-width 1)
|
||||
size (or size 9)
|
||||
max-stroke-width (max stroke-width 0)
|
||||
{:keys [path path-length]} (get-path-props size max-stroke-width rotation)
|
||||
start-at (get-start-at duration initial-remaining-time)
|
||||
elapsed-time (reagent/atom 0)
|
||||
prev-frame-time (reagent/atom nil)
|
||||
frame-request (reagent/atom nil)
|
||||
display-time (reagent/atom start-at)
|
||||
;; get elapsed frame time
|
||||
swap-elapsed-time-each-frame (fn swap-elapsed-time-each-frame [frame-time]
|
||||
(if (nil? @prev-frame-time)
|
||||
(do (reset! prev-frame-time frame-time)
|
||||
(reset! frame-request (js/requestAnimationFrame
|
||||
swap-elapsed-time-each-frame)))
|
||||
(let [delta (- (/ frame-time 1000)
|
||||
(/ @prev-frame-time 1000))
|
||||
current-elapsed (swap! elapsed-time + delta)
|
||||
current-display-time (+ start-at current-elapsed)
|
||||
completed? (>= current-display-time duration)]
|
||||
(reset! display-time (if completed?
|
||||
duration
|
||||
current-display-time))
|
||||
(when-not completed?
|
||||
(reset! prev-frame-time frame-time)
|
||||
(reset! frame-request (js/requestAnimationFrame
|
||||
swap-elapsed-time-each-frame))))))]
|
||||
(reagent/create-class
|
||||
{:component-will-unmount #(js/cancelAnimationFrame @frame-request)
|
||||
:reagent-render
|
||||
(fn []
|
||||
(reset! frame-request (js/requestAnimationFrame swap-elapsed-time-each-frame))
|
||||
[rn/view
|
||||
{:style {:position :relative
|
||||
:width size
|
||||
:height size}}
|
||||
[svg/svg
|
||||
{:view-box (str "0 0 " size " " size)
|
||||
:width size
|
||||
:height size}
|
||||
[svg/path
|
||||
{:d path :fill :none :stroke (or trail-color :transparent) :stroke-width stroke-width}]
|
||||
(when-not (= @display-time duration)
|
||||
[svg/path
|
||||
{:d path
|
||||
:fill :none
|
||||
:stroke (or color (get-in themes [:color theme]))
|
||||
:stroke-linecap :square
|
||||
:stroke-width stroke-width
|
||||
:stroke-dasharray path-length
|
||||
:stroke-dashoffset (linear-ease @display-time 0 path-length duration)}])]])})))
|
||||
|
||||
(def circle-timer (quo.theme/with-theme circle-timer-internal))
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
[rn/touchable-highlight
|
||||
{:on-press on-press
|
||||
:underlay-color :transparent}
|
||||
(into
|
||||
[into
|
||||
[rn/view
|
||||
{:style (merge (style/action-container theme) style)}]
|
||||
children)])
|
||||
children]])
|
||||
|
||||
(defn toast-undo-action-internal
|
||||
[{:keys [undo-duration undo-on-press theme]}]
|
||||
|
||||
@@ -3,20 +3,23 @@
|
||||
[quo.components.icon :as icon]
|
||||
[quo.components.selectors.filter.style :as style]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn view
|
||||
[{:keys [blur? customization-color on-press-out pressed?]}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
[pressed? set-pressed] (rn/use-state pressed?)
|
||||
on-press-out (fn []
|
||||
(set-pressed (not pressed?))
|
||||
(when on-press-out (on-press-out pressed?)))]
|
||||
[rn/touchable-without-feedback
|
||||
{:accessibility-label :selector-filter
|
||||
:on-press-out on-press-out}
|
||||
[rn/view {:style (style/container-outer customization-color pressed? theme)}
|
||||
[rn/view {:style (style/container-inner pressed? blur? theme)}
|
||||
[icon/icon :i/unread
|
||||
{:color (style/icon-color pressed? theme)
|
||||
:size 20}]]]]))
|
||||
(defn view-internal
|
||||
[initial-props]
|
||||
(let [pressed? (reagent/atom (:pressed? initial-props))]
|
||||
(fn [{:keys [blur? customization-color theme on-press-out]}]
|
||||
[rn/touchable-without-feedback
|
||||
{:accessibility-label :selector-filter
|
||||
:on-press-out (fn []
|
||||
(swap! pressed? not)
|
||||
(when on-press-out
|
||||
(on-press-out @pressed?)))}
|
||||
[rn/view {:style (style/container-outer customization-color @pressed? theme)}
|
||||
[rn/view {:style (style/container-inner @pressed? blur? theme)}
|
||||
[icon/icon :i/unread
|
||||
{:color (style/icon-color @pressed? theme)
|
||||
:size 20}]]]])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -2,20 +2,23 @@
|
||||
(:require
|
||||
[quo.components.selectors.reaction-resource :as reactions.resource]
|
||||
[quo.components.selectors.reactions-selector.style :as style]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn view
|
||||
[{:keys [emoji container-style on-press
|
||||
accessibility-label start-pressed?]
|
||||
:or {accessibility-label :reaction}}]
|
||||
(let [[pressed? set-pressed] (rn/use-state start-pressed?)
|
||||
on-press (fn [e]
|
||||
(set-pressed (not pressed?))
|
||||
(when on-press (on-press e)))]
|
||||
[rn/pressable
|
||||
{:accessibility-label accessibility-label
|
||||
:allow-multiple-presses? true
|
||||
:style (merge (style/container pressed?)
|
||||
container-style)
|
||||
:on-press on-press}
|
||||
[rn/text (reactions.resource/system-emojis emoji)]]))
|
||||
[{:keys [start-pressed?]}]
|
||||
(let [pressed? (reagent/atom start-pressed?)]
|
||||
(fn [{:keys [emoji container-style on-press
|
||||
accessibility-label]
|
||||
:or {accessibility-label :reaction}}]
|
||||
[rn/pressable
|
||||
{:accessibility-label accessibility-label
|
||||
:allow-multiple-presses? true
|
||||
:style (merge (style/container @pressed?)
|
||||
container-style)
|
||||
:on-press (fn [e]
|
||||
(swap! pressed? not)
|
||||
(when on-press
|
||||
(on-press e)))}
|
||||
[rn/text
|
||||
(reactions.resource/system-emojis emoji)]])))
|
||||
|
||||
@@ -3,47 +3,47 @@
|
||||
[quo.components.icon :as icons]
|
||||
[quo.components.selectors.selectors.style :as style]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]))
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn- handle-press
|
||||
[on-change checked-atom checked?]
|
||||
(when checked-atom (swap! checked-atom not))
|
||||
(when on-change (on-change (not checked?))))
|
||||
|
||||
(defn- base-selector
|
||||
[{:keys [default-checked? checked? disabled? blur? customization-color on-change container-style
|
||||
label-prefix outer-style-fn inner-style-fn icon-style-fn theme]
|
||||
:or {customization-color :blue}}]
|
||||
(let [controlled-component? (some? checked?)
|
||||
[internal-checked?
|
||||
set-internal-checked?] (rn/use-state (when-not controlled-component?
|
||||
(or default-checked? false)))
|
||||
actual-checked? (if controlled-component? checked? internal-checked?)
|
||||
accessibility-label (str label-prefix "-" (if actual-checked? "on" "off"))
|
||||
test-id (str label-prefix "-component")
|
||||
outer-styles (outer-style-fn {:checked? actual-checked?
|
||||
[{:keys [default-checked? checked?]}]
|
||||
(let [controlled-component? (some? checked?)
|
||||
internal-checked? (when-not controlled-component?
|
||||
(reagent/atom (or default-checked? false)))]
|
||||
(fn [{:keys [checked? disabled? blur? customization-color on-change container-style
|
||||
label-prefix outer-style-fn inner-style-fn icon-style-fn theme]
|
||||
:or {customization-color :blue}}]
|
||||
(let [actual-checked? (if controlled-component? checked? @internal-checked?)
|
||||
accessibility-label (str label-prefix "-" (if actual-checked? "on" "off"))
|
||||
test-id (str label-prefix "-component")
|
||||
outer-styles (outer-style-fn {:checked? actual-checked?
|
||||
:disabled? disabled?
|
||||
:blur? blur?
|
||||
:container-style container-style
|
||||
:customization-color customization-color
|
||||
:theme theme})
|
||||
on-press (rn/use-callback
|
||||
(fn []
|
||||
(when-not (nil? internal-checked?)
|
||||
(set-internal-checked? (not internal-checked?)))
|
||||
(when on-change (on-change (not actual-checked?))))
|
||||
[internal-checked? actual-checked? on-change])]
|
||||
[rn/pressable
|
||||
(when-not disabled?
|
||||
{:on-press on-press
|
||||
:allow-multiple-presses? true})
|
||||
[rn/view
|
||||
{:style outer-styles
|
||||
:needs-offscreen-alpha-compositing true
|
||||
:accessibility-label accessibility-label
|
||||
:testID test-id}
|
||||
[rn/view
|
||||
{:style (inner-style-fn {:theme theme
|
||||
:checked? actual-checked?
|
||||
:blur? blur?
|
||||
:customization-color customization-color})}
|
||||
(when (and icon-style-fn actual-checked?)
|
||||
[icons/icon :i/check-small (icon-style-fn actual-checked? blur? theme)])]]]))
|
||||
:theme theme})]
|
||||
[rn/pressable
|
||||
(when-not disabled?
|
||||
{:on-press #(handle-press on-change internal-checked? actual-checked?)
|
||||
:allow-multiple-presses? true})
|
||||
[rn/view
|
||||
{:style outer-styles
|
||||
:needs-offscreen-alpha-compositing true
|
||||
:accessibility-label accessibility-label
|
||||
:testID test-id}
|
||||
[rn/view
|
||||
{:style (inner-style-fn {:theme theme
|
||||
:checked? actual-checked?
|
||||
:blur? blur?
|
||||
:customization-color customization-color})}
|
||||
(when (and icon-style-fn actual-checked?)
|
||||
[icons/icon :i/check-small (icon-style-fn actual-checked? blur? theme)])]]]))))
|
||||
|
||||
(defn- toggle
|
||||
[props]
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
[:options {:optional true} [:maybe [:enum :add :hold]]]
|
||||
[:size {:optional true} [:maybe [:enum :size-24 :size-32]]]
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:theme :schema.common/theme]
|
||||
[:collectible-img-src :schema.common/image-source]
|
||||
[:collectible-name :string]
|
||||
[:collectible-id {:optional true} [:maybe :string]]]]]
|
||||
[:collectible-id :string]]]]
|
||||
:any])
|
||||
|
||||
@@ -8,50 +8,52 @@
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hole-view :as hole-view]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [options blur? collectible-img-src collectible-name collectible-id] :as props}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
[container-width
|
||||
set-container-width] (rn/use-state 0)
|
||||
on-layout (rn/use-callback
|
||||
#(set-container-width (oops/oget % :nativeEvent :layout :width)))
|
||||
size (or (:size props) :size-24)]
|
||||
[rn/view {:on-layout on-layout}
|
||||
[hole-view/hole-view
|
||||
{:holes (if options
|
||||
[{:x (- container-width
|
||||
(case size
|
||||
:size-24 10
|
||||
:size-32 12
|
||||
nil))
|
||||
:y (case size
|
||||
:size-24 -6
|
||||
:size-32 -4
|
||||
nil)
|
||||
:width 16
|
||||
:height 16
|
||||
:borderRadius 8}]
|
||||
[])}
|
||||
[rn/view {:style (style/container size options blur? theme)}
|
||||
[rn/image {:style (style/collectible-img size) :source collectible-img-src}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/label theme)}
|
||||
collectible-name]
|
||||
(when collectible-id
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:margin-left 5
|
||||
:style (style/label theme)}
|
||||
collectible-id])]]
|
||||
(when options
|
||||
[rn/view {:style (style/options-icon size)}
|
||||
[icons/icon (if (= options :hold) :i/hold :i/add-token)
|
||||
{:size 20
|
||||
:no-color true}]])]))
|
||||
[]
|
||||
(let [container-width (reagent/atom 0)
|
||||
on-layout #(->> (oops/oget % :nativeEvent :layout :width)
|
||||
(reset! container-width))]
|
||||
(fn [{:keys [options blur? theme collectible-img-src collectible-name collectible-id] :as props}]
|
||||
(let [size (or (:size props) :size-24)]
|
||||
[rn/view
|
||||
{:on-layout on-layout}
|
||||
[hole-view/hole-view
|
||||
{:holes (if options
|
||||
[{:x (- @container-width
|
||||
(case size
|
||||
:size-24 10
|
||||
:size-32 12
|
||||
nil))
|
||||
:y (case size
|
||||
:size-24 -6
|
||||
:size-32 -4
|
||||
nil)
|
||||
:width 16
|
||||
:height 16
|
||||
:borderRadius 8}]
|
||||
[])}
|
||||
[rn/view {:style (style/container size options blur? theme)}
|
||||
[rn/image {:style (style/collectible-img size) :source collectible-img-src}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/label theme)}
|
||||
collectible-name]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:margin-left 5
|
||||
:style (style/label theme)}
|
||||
collectible-id]]]
|
||||
(when options
|
||||
[rn/view {:style (style/options-icon size)}
|
||||
[icons/icon (if (= options :hold) :i/hold :i/add-token)
|
||||
{:size 20
|
||||
:no-color true}]])]))))
|
||||
|
||||
(def view (schema/instrument #'view-internal component-schema/?schema))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
+115
-118
@@ -50,131 +50,128 @@
|
||||
- `fade-end-percentage` Percentage where fading starts relative to the total
|
||||
layout width of the `flat-list` data."
|
||||
|
||||
[{:keys [default-active data fade-end-percentage fade-end? on-change on-scroll scroll-event-throttle
|
||||
scrollable?
|
||||
scroll-on-press? size type labelled? disabled? blurred? icon-color]
|
||||
:or {fade-end-percentage 0.8
|
||||
fade-end? false
|
||||
scroll-event-throttle 64
|
||||
scrollable? false
|
||||
scroll-on-press? false
|
||||
size default-tab-size}
|
||||
:as props}]
|
||||
(let [[active-tab-id
|
||||
set-active-tab-id] (rn/use-state default-active)
|
||||
[fading set-fading] (rn/use-state {:fade-end-percentage fade-end-percentage})
|
||||
flat-list-ref (rn/use-ref-atom nil)
|
||||
maybe-mask-wrapper (rn/use-memo
|
||||
(fn []
|
||||
(if fade-end?
|
||||
[{:keys [default-active fade-end-percentage]
|
||||
:or {fade-end-percentage 0.8}}]
|
||||
(let [active-tab-id (reagent/atom default-active)
|
||||
fading (reagent/atom {:fade-end-percentage fade-end-percentage})
|
||||
flat-list-ref (atom nil)]
|
||||
(fn
|
||||
[{:keys [data
|
||||
fade-end-percentage
|
||||
fade-end?
|
||||
on-change
|
||||
on-scroll
|
||||
scroll-event-throttle
|
||||
scrollable?
|
||||
scroll-on-press?
|
||||
size
|
||||
type
|
||||
labelled?
|
||||
disabled?
|
||||
blurred?
|
||||
icon-color]
|
||||
:or {fade-end-percentage fade-end-percentage
|
||||
fade-end? false
|
||||
scroll-event-throttle 64
|
||||
scrollable? false
|
||||
scroll-on-press? false
|
||||
size default-tab-size}
|
||||
:as props}]
|
||||
(let [maybe-mask-wrapper (if fade-end?
|
||||
[masked-view/masked-view
|
||||
{:mask-element (reagent/as-element
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [:black :transparent]
|
||||
:locations [(get fading :fade-end-percentage)
|
||||
:locations [(get @fading :fade-end-percentage)
|
||||
1]
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 1 :y 0}
|
||||
:pointer-events :none
|
||||
:style {:width "100%"
|
||||
:height "100%"}}])}]
|
||||
[:<>]))
|
||||
[fade-end? fading])
|
||||
on-scroll (rn/use-context
|
||||
(fn [^js e]
|
||||
(when fade-end?
|
||||
(let [offset-x (oget e "nativeEvent.contentOffset.x")
|
||||
content-width (oget e "nativeEvent.contentSize.width")
|
||||
layout-width (oget e "nativeEvent.layoutMeasurement.width")
|
||||
new-percentage (calculate-fade-end-percentage
|
||||
{:offset-x offset-x
|
||||
:content-width content-width
|
||||
:layout-width layout-width
|
||||
:max-fade-percentage fade-end-percentage})]
|
||||
;; Avoid unnecessary re-rendering.
|
||||
(when (not= new-percentage (get fading :fade-end-percentage))
|
||||
(set-fading (assoc fading :fade-end-percentage new-percentage)))))
|
||||
(when on-scroll
|
||||
(on-scroll e)))
|
||||
[fade-end? fading fade-end-percentage])
|
||||
data-count (count data)
|
||||
style-padding-left (get-in props [:style :padding-left])
|
||||
render-fn (rn/use-callback
|
||||
(fn [{:keys [id label resource]} index]
|
||||
[rn/view
|
||||
{:style {:margin-right (if (= size default-tab-size) 12 8)
|
||||
:padding-right (when (= index (dec data-count))
|
||||
style-padding-left)}}
|
||||
|
||||
[tag/tag
|
||||
{:id id
|
||||
:size size
|
||||
:active (= id active-tab-id)
|
||||
:resource resource
|
||||
:blurred? blurred?
|
||||
:icon-color icon-color
|
||||
:disabled? disabled?
|
||||
:label (if labelled?
|
||||
label
|
||||
(when (= type :label) label))
|
||||
:type type
|
||||
:labelled? labelled?
|
||||
:on-press (fn [id]
|
||||
(set-active-tab-id id)
|
||||
(when scroll-on-press?
|
||||
(.scrollToIndex ^js @flat-list-ref
|
||||
#js
|
||||
{:animated true
|
||||
:index index
|
||||
:viewPosition 0.5}))
|
||||
(when on-change
|
||||
(on-change id)))}]])
|
||||
[size default-tab-size data-count style-padding-left active-tab-id blurred?
|
||||
icon-color disabled? labelled? type scroll-on-press? on-change])
|
||||
on-press (rn/use-callback #(do (set-active-tab-id %) (when on-change (on-change %)))
|
||||
[on-change])
|
||||
key-fn (rn/use-callback (comp str :id))
|
||||
ref (rn/use-callback #(reset! flat-list-ref %))
|
||||
clean-props (dissoc props
|
||||
:default-active
|
||||
:fade-end-percentage
|
||||
:fade-end?
|
||||
:on-change
|
||||
:scroll-on-press?
|
||||
:size)]
|
||||
(if scrollable?
|
||||
(conj
|
||||
maybe-mask-wrapper
|
||||
[rn/flat-list
|
||||
(merge
|
||||
clean-props
|
||||
(when scroll-on-press?
|
||||
{:initial-scroll-index (utils.collection/first-index #(= active-tab-id (:id %)) data)})
|
||||
{:ref ref
|
||||
:extra-data (str active-tab-id)
|
||||
:horizontal true
|
||||
:scroll-event-throttle scroll-event-throttle
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:data data
|
||||
:key-fn key-fn
|
||||
:on-scroll on-scroll
|
||||
:render-fn render-fn})])
|
||||
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
(for [{:keys [id label resource]} data]
|
||||
^{:key id}
|
||||
[rn/view {:style {:margin-right 8}}
|
||||
[tag/tag
|
||||
{:id id
|
||||
:size size
|
||||
:type type
|
||||
:label (if labelled?
|
||||
label
|
||||
(when (= type :label) label))
|
||||
:active (= id active-tab-id)
|
||||
:disabled? disabled?
|
||||
:blurred? blurred?
|
||||
:icon-color icon-color
|
||||
:labelled? (if (= type :label) true labelled?)
|
||||
:resource (if (= type :icon) :i/placeholder resource)
|
||||
:on-press on-press}]])])))
|
||||
[:<>])]
|
||||
(if scrollable?
|
||||
(conj
|
||||
maybe-mask-wrapper
|
||||
[rn/flat-list
|
||||
(merge
|
||||
(dissoc props
|
||||
:default-active
|
||||
:fade-end-percentage
|
||||
:fade-end?
|
||||
:on-change
|
||||
:scroll-on-press?
|
||||
:size)
|
||||
(when scroll-on-press?
|
||||
{:initial-scroll-index (utils.collection/first-index #(= @active-tab-id (:id %)) data)})
|
||||
{:ref #(reset! flat-list-ref %)
|
||||
:extra-data (str @active-tab-id)
|
||||
:horizontal true
|
||||
:scroll-event-throttle scroll-event-throttle
|
||||
:shows-horizontal-scroll-indicator false
|
||||
:data data
|
||||
:key-fn (comp str :id)
|
||||
:on-scroll (fn [^js e]
|
||||
(when fade-end?
|
||||
(let [offset-x (oget e "nativeEvent.contentOffset.x")
|
||||
content-width (oget e "nativeEvent.contentSize.width")
|
||||
layout-width (oget e "nativeEvent.layoutMeasurement.width")
|
||||
new-percentage (calculate-fade-end-percentage
|
||||
{:offset-x offset-x
|
||||
:content-width content-width
|
||||
:layout-width layout-width
|
||||
:max-fade-percentage fade-end-percentage})]
|
||||
;; Avoid unnecessary re-rendering.
|
||||
(when (not= new-percentage (get @fading :fade-end-percentage))
|
||||
(swap! fading assoc :fade-end-percentage new-percentage))))
|
||||
(when on-scroll
|
||||
(on-scroll e)))
|
||||
:render-fn (fn [{:keys [id label resource]} index]
|
||||
[rn/view
|
||||
{:style {:margin-right (if (= size default-tab-size) 12 8)
|
||||
:padding-right (when (= index (dec (count data)))
|
||||
(get-in props [:style :padding-left]))}}
|
||||
[tag/tag
|
||||
{:id id
|
||||
:size size
|
||||
:active (= id @active-tab-id)
|
||||
:resource resource
|
||||
:blurred? blurred?
|
||||
:icon-color icon-color
|
||||
:disabled? disabled?
|
||||
:label (if labelled?
|
||||
label
|
||||
(when (= type :label) label))
|
||||
:type type
|
||||
:labelled? labelled?
|
||||
:on-press (fn [id]
|
||||
(reset! active-tab-id id)
|
||||
(when scroll-on-press?
|
||||
(.scrollToIndex ^js @flat-list-ref
|
||||
#js
|
||||
{:animated true
|
||||
:index index
|
||||
:viewPosition 0.5}))
|
||||
(when on-change
|
||||
(on-change id)))}]])})])
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
(for [{:keys [id label resource]} data]
|
||||
^{:key id}
|
||||
[rn/view {:style {:margin-right 8}}
|
||||
[tag/tag
|
||||
(merge {:id id
|
||||
:size size
|
||||
:type type
|
||||
:label (if labelled?
|
||||
label
|
||||
(when (= type :label) label))
|
||||
:active (= id active-tab-id)
|
||||
:disabled? disabled?
|
||||
:blurred? blurred?
|
||||
:icon-color icon-color
|
||||
:labelled? (if (= type :label) true labelled?)
|
||||
:resource (if (= type :icon)
|
||||
:i/placeholder
|
||||
resource)
|
||||
:on-press #(do (reset! active-tab-id %)
|
||||
(when on-change (on-change %)))})]])])))))
|
||||
|
||||
@@ -7,9 +7,10 @@
|
||||
[quo.components.utilities.token.view :as token]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hole-view :as hole-view]))
|
||||
[react-native.hole-view :as hole-view]
|
||||
[reagent.core :as reagent]))
|
||||
|
||||
(defn view
|
||||
(defn- view-internal
|
||||
"Options:
|
||||
- :options - false / :add / :hold (default false)
|
||||
- :size - :size-24 / :size-32 (default :size-24)
|
||||
@@ -17,44 +18,45 @@
|
||||
- :theme - :light / :dark
|
||||
- :token-value - string - token value
|
||||
- :token-symbol - string"
|
||||
[{:keys [options size blur? token-value token-img-src token-symbol]
|
||||
:or {size :size-24}}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
[container-width
|
||||
set-container-width] (rn/use-state 0)
|
||||
on-layout (rn/use-callback #(set-container-width
|
||||
(oget % :nativeEvent :layout :width)))]
|
||||
[rn/view {:on-layout on-layout}
|
||||
[hole-view/hole-view
|
||||
{:holes (if options
|
||||
[{:x (- container-width
|
||||
(case size
|
||||
:size-24 10
|
||||
:size-32 12
|
||||
nil))
|
||||
:y (case size
|
||||
:size-24 -6
|
||||
:size-32 -4
|
||||
nil)
|
||||
:width 16
|
||||
:height 16
|
||||
:borderRadius 8}]
|
||||
[])}
|
||||
[rn/view {:style (style/container size options blur? theme)}
|
||||
[token/view
|
||||
{:style (style/token-img size)
|
||||
:token token-symbol
|
||||
:size (case size
|
||||
:size-24 :size-20
|
||||
:size-32 :size-28)
|
||||
:image-source token-img-src}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/label theme)}
|
||||
(str token-value " " token-symbol)]]]
|
||||
(when options
|
||||
[rn/view {:style (style/options-icon size)}
|
||||
[icons/icon (if (= options :hold) :i/hold :i/add-token)
|
||||
{:size 20
|
||||
:no-color true}]])]))
|
||||
[]
|
||||
(let [container-width (reagent/atom 0)]
|
||||
(fn [{:keys [options size blur? theme token-value token-img-src token-symbol]
|
||||
:or {size :size-24}}]
|
||||
[rn/view
|
||||
{:on-layout #(reset! container-width
|
||||
(oget % :nativeEvent :layout :width))}
|
||||
[hole-view/hole-view
|
||||
{:holes (if options
|
||||
[{:x (- @container-width
|
||||
(case size
|
||||
:size-24 10
|
||||
:size-32 12
|
||||
nil))
|
||||
:y (case size
|
||||
:size-24 -6
|
||||
:size-32 -4
|
||||
nil)
|
||||
:width 16
|
||||
:height 16
|
||||
:borderRadius 8}]
|
||||
[])}
|
||||
[rn/view {:style (style/container size options blur? theme)}
|
||||
[token/view
|
||||
{:style (style/token-img size)
|
||||
:token token-symbol
|
||||
:size (case size
|
||||
:size-24 :size-20
|
||||
:size-32 :size-28)
|
||||
:image-source token-img-src}]
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style (style/label theme)}
|
||||
(str token-value " " token-symbol)]]]
|
||||
(when options
|
||||
[rn/view {:style (style/options-icon size)}
|
||||
[icons/icon (if (= options :hold) :i/hold :i/add-token)
|
||||
{:size 20
|
||||
:no-color true}]])])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
[:map
|
||||
[:type {:optional true} [:enum :default :watch-only :add-account :empty :missing-keypair]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:theme :schema.common/theme]
|
||||
[:metrics? {:optional true} [:maybe :boolean]]
|
||||
[:on-press {:optional true} [:maybe fn?]]])
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- loading-view
|
||||
@@ -95,87 +96,87 @@
|
||||
:end {:x 1 :y 0}}])
|
||||
|
||||
(defn- user-account
|
||||
[{:keys [name balance percentage-value loading? amount customization-color type emoji metrics?
|
||||
on-press]}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
[pressed? set-pressed] (rn/use-state false)
|
||||
on-press-in (rn/use-callback #(set-pressed true))
|
||||
on-press-out (rn/use-callback #(set-pressed false))
|
||||
watch-only? (= :watch-only type)
|
||||
missing-keypair? (= :missing-keypair type)]
|
||||
(if loading?
|
||||
[loading-view
|
||||
{:customization-color customization-color
|
||||
:type type
|
||||
:theme theme
|
||||
:metrics? metrics?}]
|
||||
[rn/pressable
|
||||
{:on-press-in on-press-in
|
||||
:on-press-out on-press-out
|
||||
:style (style/card {:customization-color customization-color
|
||||
:type type
|
||||
:theme theme
|
||||
:pressed? pressed?
|
||||
:metrics? metrics?})
|
||||
:on-press on-press}
|
||||
(when (and customization-color (and (not watch-only?) (not missing-keypair?)))
|
||||
[customization-colors/overlay
|
||||
{:customization-color customization-color
|
||||
:border-radius 16
|
||||
:theme theme
|
||||
:pressed? pressed?}])
|
||||
[rn/view {:style style/profile-container}
|
||||
[rn/view {:style {:padding-bottom 2 :margin-right 2}}
|
||||
[text/text {:style style/emoji} emoji]]
|
||||
[rn/view {:style style/watch-only-container}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:max-width 110
|
||||
:margin-right 4
|
||||
:ellipis-mode :tail
|
||||
:style (style/account-name type theme)}
|
||||
name]
|
||||
(when watch-only? [icon/icon :i/reveal {:color colors/neutral-50 :size 12}])
|
||||
(when missing-keypair?
|
||||
[icon/icon :i/alert {:color (properties/alert-icon-color theme) :size 12}])]]
|
||||
[text/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style (style/account-value type theme)}
|
||||
balance]
|
||||
(when metrics?
|
||||
[rn/view {:style style/metrics-container}
|
||||
[metrics-percentage type theme percentage-value]
|
||||
(when (not= :empty type)
|
||||
[metrics-info type theme amount])])
|
||||
(when watch-only?
|
||||
[gradient-overview theme customization-color])])))
|
||||
[_]
|
||||
(let [pressed? (reagent/atom false)
|
||||
on-press-in #(reset! pressed? true)
|
||||
on-press-out #(reset! pressed? false)]
|
||||
(fn [{:keys [name balance percentage-value loading? amount customization-color type emoji metrics?
|
||||
theme on-press]}]
|
||||
(let [watch-only? (= :watch-only type)
|
||||
missing-keypair? (= :missing-keypair type)]
|
||||
(if loading?
|
||||
[loading-view
|
||||
{:customization-color customization-color
|
||||
:type type
|
||||
:theme theme
|
||||
:metrics? metrics?}]
|
||||
[rn/pressable
|
||||
{:on-press-in on-press-in
|
||||
:on-press-out on-press-out
|
||||
:style (style/card {:customization-color customization-color
|
||||
:type type
|
||||
:theme theme
|
||||
:pressed? @pressed?
|
||||
:metrics? metrics?})
|
||||
:on-press on-press}
|
||||
(when (and customization-color (and (not watch-only?) (not missing-keypair?)))
|
||||
[customization-colors/overlay
|
||||
{:customization-color customization-color
|
||||
:border-radius 16
|
||||
:theme theme
|
||||
:pressed? @pressed?}])
|
||||
[rn/view {:style style/profile-container}
|
||||
[rn/view {:style {:padding-bottom 2 :margin-right 2}}
|
||||
[text/text {:style style/emoji} emoji]]
|
||||
[rn/view {:style style/watch-only-container}
|
||||
[text/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:number-of-lines 1
|
||||
:max-width 110
|
||||
:margin-right 4
|
||||
:ellipis-mode :tail
|
||||
:style (style/account-name type theme)}
|
||||
name]
|
||||
(when watch-only? [icon/icon :i/reveal {:color colors/neutral-50 :size 12}])
|
||||
(when missing-keypair?
|
||||
[icon/icon :i/alert {:color (properties/alert-icon-color theme) :size 12}])]]
|
||||
[text/text
|
||||
{:size :heading-2
|
||||
:weight :semi-bold
|
||||
:style (style/account-value type theme)}
|
||||
balance]
|
||||
(when metrics?
|
||||
[rn/view {:style style/metrics-container}
|
||||
[metrics-percentage type theme percentage-value]
|
||||
(when (not= :empty type)
|
||||
[metrics-info type theme amount])])
|
||||
(when watch-only?
|
||||
[gradient-overview theme customization-color])])))))
|
||||
|
||||
(defn- add-account-view
|
||||
[{:keys [on-press customization-color metrics?]}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
[pressed? set-pressed] (rn/use-state false)
|
||||
on-press-in (rn/use-callback #(set-pressed true))
|
||||
on-press-out (rn/use-callback #(set-pressed false))]
|
||||
[rn/pressable
|
||||
{:on-press on-press
|
||||
:on-press-in on-press-in
|
||||
:on-press-out on-press-out
|
||||
:style (style/add-account-container {:theme theme
|
||||
:metrics? metrics?
|
||||
:pressed? pressed?})}
|
||||
[button/button
|
||||
{:on-press on-press
|
||||
:type :primary
|
||||
:size 24
|
||||
:icon true
|
||||
:accessibility-label :add-account
|
||||
:pressed? pressed?
|
||||
:icon-only? true
|
||||
:customization-color customization-color}
|
||||
:i/add]]))
|
||||
[_]
|
||||
(let [pressed? (reagent/atom false)]
|
||||
(fn [{:keys [on-press customization-color theme metrics?]}]
|
||||
[rn/pressable
|
||||
{:on-press on-press
|
||||
:on-press-in #(reset! pressed? true)
|
||||
:on-press-out #(reset! pressed? false)
|
||||
:style (style/add-account-container {:theme theme
|
||||
:metrics? metrics?
|
||||
:pressed? @pressed?})}
|
||||
[button/button
|
||||
{:type :primary
|
||||
:size 24
|
||||
:icon true
|
||||
:accessibility-label :add-account
|
||||
:on-press on-press
|
||||
:pressed? @pressed?
|
||||
:on-press-in #(reset! pressed? true)
|
||||
:on-press-out #(reset! pressed? false)
|
||||
:customization-color customization-color
|
||||
:icon-only? true}
|
||||
:i/add]])))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [type] :as props}]
|
||||
@@ -184,4 +185,6 @@
|
||||
:add-account [add-account-view props]
|
||||
nil))
|
||||
|
||||
(def view (schema/instrument #'view-internal component-schema/?schema))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
[:props
|
||||
[:map {:closed true}
|
||||
[:status {:optional true} [:maybe [:enum :default :error]]]
|
||||
[:on-change-text {:optional true} [:maybe fn?]]
|
||||
[:theme :schema.common/theme]
|
||||
[:on-inc-press {:optional true} [:maybe fn?]]
|
||||
[:on-dec-press {:optional true} [:maybe fn?]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:min-value {:optional true} [:maybe :int]]
|
||||
[:max-value {:optional true} [:maybe :int]]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
[quo.components.markdown.text :as text]
|
||||
[quo.components.wallet.amount-input.schema :as amount-input.schema]
|
||||
[quo.components.wallet.amount-input.style :as style]
|
||||
[quo.theme]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[schema.core :as schema]))
|
||||
|
||||
@@ -21,34 +21,35 @@
|
||||
icon])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [on-inc-press on-dec-press status value min-value max-value
|
||||
[{:keys [on-inc-press on-dec-press theme status value min-value max-value
|
||||
container-style]
|
||||
:or {value 0
|
||||
min-value 0
|
||||
max-value 999999999}}]
|
||||
(let [theme (quo.theme/use-theme-value)]
|
||||
[rn/view
|
||||
{:style (merge style/container container-style)}
|
||||
[amount-button
|
||||
{:theme theme
|
||||
:accessibility-label :amount-input-dec-button
|
||||
:icon :i/remove
|
||||
:on-press on-dec-press
|
||||
:disabled? (>= min-value value)}]
|
||||
[rn/view {:style style/input-container}
|
||||
[text/text
|
||||
{:number-of-lines 1
|
||||
:accessibility-label :amount-input
|
||||
:weight :semi-bold
|
||||
:size :heading-1
|
||||
:align-self :center
|
||||
:style (style/input-text theme (or status :default))}
|
||||
value]]
|
||||
[amount-button
|
||||
{:theme theme
|
||||
:icon :i/add
|
||||
:accessibility-label :amount-input-inc-button
|
||||
:on-press on-inc-press
|
||||
:disabled? (>= value max-value)}]]))
|
||||
[rn/view
|
||||
{:style (merge style/container container-style)}
|
||||
[amount-button
|
||||
{:theme theme
|
||||
:accessibility-label :amount-input-dec-button
|
||||
:icon :i/remove
|
||||
:on-press on-dec-press
|
||||
:disabled? (>= min-value value)}]
|
||||
[rn/view {:style style/input-container}
|
||||
[text/text
|
||||
{:number-of-lines 1
|
||||
:accessibility-label :amount-input
|
||||
:weight :semi-bold
|
||||
:size :heading-1
|
||||
:align-self :center
|
||||
:style (style/input-text theme (or status :default))}
|
||||
value]]
|
||||
[amount-button
|
||||
{:theme theme
|
||||
:icon :i/add
|
||||
:accessibility-label :amount-input-inc-button
|
||||
:on-press on-inc-press
|
||||
:disabled? (>= value max-value)}]])
|
||||
|
||||
(def view (schema/instrument #'view-internal amount-input.schema/?schema))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal amount-input.schema/?schema)))
|
||||
|
||||
@@ -37,9 +37,8 @@
|
||||
:border? true}]))
|
||||
|
||||
(defn title-view
|
||||
[{:keys [details action selected? type blur? customization-color on-options-press]}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
{:keys [full-name]} details]
|
||||
[{:keys [details action selected? type blur? customization-color on-options-press theme]}]
|
||||
(let [{:keys [full-name]} details]
|
||||
[rn/view
|
||||
{:style style/title-container
|
||||
:accessibility-label :title}
|
||||
@@ -90,7 +89,7 @@
|
||||
[item & _rest]
|
||||
[account-list-card/view item])
|
||||
|
||||
(defn view
|
||||
(defn- view-internal
|
||||
[{:keys [accounts action container-style selected? on-press] :as props}]
|
||||
[rn/pressable
|
||||
{:style (style/container (merge props
|
||||
@@ -109,3 +108,5 @@
|
||||
:render-fn acc-list-card
|
||||
:separator [rn/view {:style {:height 8}}]
|
||||
:style {:padding-horizontal 8}}]])
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
(ns quo.components.wallet.network-link.helpers)
|
||||
|
||||
(def ^:private central-figure-width 63)
|
||||
|
||||
(defn calculate-side-lines-path-1x
|
||||
"Calculates the `d` attribute for the side lines based on the SVG width."
|
||||
[width]
|
||||
(let [side-offset (/ (- width central-figure-width) 2)]
|
||||
{:left (str "M0 57 L" side-offset " 57")
|
||||
:right (str "M" (+ side-offset central-figure-width) " 1 L" width " 1")}))
|
||||
|
||||
(defn calculate-transform
|
||||
"Calculates the transform attribute for the central figure based on the SVG width."
|
||||
[width]
|
||||
(let [translate-x (/ (- width central-figure-width) 2)]
|
||||
(str "translate(" translate-x " 0)")))
|
||||
|
||||
(defn calculate-side-lines-path-2x
|
||||
"Calculates the `d` attribute for the side lines based on the SVG width."
|
||||
[width]
|
||||
(let [side-offset (/ (- width central-figure-width) 2)]
|
||||
{:left (str "M0 113 L" side-offset " 113")
|
||||
:right (str "M" (+ side-offset central-figure-width) " 1 L" width " 1")}))
|
||||
@@ -1,34 +0,0 @@
|
||||
(ns quo.components.wallet.network-link.style)
|
||||
|
||||
(def left-circle-container
|
||||
{:position :absolute
|
||||
:left -3})
|
||||
|
||||
(def right-circle-container
|
||||
{:position :absolute
|
||||
:right -3})
|
||||
|
||||
(def bottom-left-circle-container
|
||||
{:position :absolute
|
||||
:bottom -3
|
||||
:left -3})
|
||||
|
||||
(def top-right-circle-container
|
||||
{:position :absolute
|
||||
:top -3
|
||||
:right -3})
|
||||
|
||||
(def link-linear-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:height 10})
|
||||
|
||||
(def link-1x-container
|
||||
{:flex 1
|
||||
:height 58
|
||||
:justify-content :center})
|
||||
|
||||
(def link-2x-container
|
||||
{:flex 1
|
||||
:height 114
|
||||
:justify-content :center})
|
||||
@@ -1,151 +1,82 @@
|
||||
(ns quo.components.wallet.network-link.view
|
||||
(:require
|
||||
[oops.core :refer [oget]]
|
||||
[quo.components.wallet.network-link.helpers :as helpers]
|
||||
[quo.components.wallet.network-link.schema :as component-schema]
|
||||
[quo.components.wallet.network-link.style :as style]
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.svg :as svg]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn- circle
|
||||
[fill stroke]
|
||||
[svg/svg
|
||||
{:height "8"
|
||||
:width "8"}
|
||||
[svg/circle
|
||||
{:cx "4"
|
||||
:cy "4"
|
||||
:r "3.5"
|
||||
:fill fill
|
||||
:stroke stroke
|
||||
:strokeWidth "1"}]])
|
||||
|
||||
(defn- line
|
||||
[stroke width]
|
||||
[svg/svg
|
||||
{:height "10"
|
||||
:width "100%"
|
||||
:view-box (str "0 0 " width " 10")}
|
||||
[svg/path
|
||||
{:d (str "M0,5 L" width ",5")
|
||||
:stroke stroke
|
||||
:stroke-width "1"}]])
|
||||
|
||||
(defn link-linear
|
||||
[{:keys [source theme]}]
|
||||
(let [[container-width
|
||||
set-container-width] (rn/use-state 100)
|
||||
stroke-color (colors/resolve-color source theme)
|
||||
fill-color (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
on-layout (rn/use-callback #(set-container-width
|
||||
(oget % :nativeEvent :layout :width)))]
|
||||
[rn/view
|
||||
{:style style/link-linear-container
|
||||
:on-layout on-layout}
|
||||
[line stroke-color container-width]
|
||||
[rn/view {:style style/left-circle-container}
|
||||
[circle fill-color stroke-color]]
|
||||
[rn/view {:style style/right-circle-container}
|
||||
[circle fill-color stroke-color]]]))
|
||||
[svg/svg {:xmlns "http://www.w3.org/2000/svg" :width "73" :height "10" :fill :none}
|
||||
[svg/path {:stroke (colors/resolve-color source theme) :d "M68 5H5"}]
|
||||
[svg/circle
|
||||
{:cx "68"
|
||||
:cy "5"
|
||||
:r "4"
|
||||
:fill (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
:stroke (colors/resolve-color source theme)}]
|
||||
[svg/circle
|
||||
{:cx "5"
|
||||
:cy "5"
|
||||
:r "4"
|
||||
:fill (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
:stroke (colors/resolve-color source theme)}]])
|
||||
|
||||
(defn link-1x
|
||||
[{:keys [source destination theme]}]
|
||||
(let [[container-width
|
||||
set-container-width] (rn/use-state 100)
|
||||
stroke-color "url(#gradient)"
|
||||
source-color (colors/resolve-color source theme)
|
||||
destination-color (colors/resolve-color destination theme)
|
||||
fill-color (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
view-box (str "0 0 " container-width " 58")
|
||||
side-lines-path (helpers/calculate-side-lines-path-1x container-width)
|
||||
central-transform (helpers/calculate-transform container-width)
|
||||
on-layout (rn/use-callback #(set-container-width
|
||||
(oget % :nativeEvent :layout :width)))]
|
||||
[rn/view
|
||||
{:style style/link-1x-container
|
||||
:on-layout on-layout}
|
||||
[svg/svg
|
||||
{:xmlns "http://www.w3.org/2000/svg"
|
||||
:height "100%"
|
||||
:width "100%"
|
||||
:view-box view-box
|
||||
:fill :none}
|
||||
[svg/path
|
||||
{:d (:left side-lines-path)
|
||||
:stroke source-color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M63 1L53.6356 1C42.5899 1 33.6356 9.9543 33.6356 21L33.6356 37C33.6356 48.0457 24.6813 57 13.6356 57L2.85889e-05 57"
|
||||
:transform central-transform
|
||||
:stroke stroke-color}]
|
||||
[svg/path
|
||||
{:d (:right side-lines-path)
|
||||
:stroke destination-color}]
|
||||
[svg/defs
|
||||
[svg/linear-gradient
|
||||
{:id "gradient"
|
||||
:x1 "72.271"
|
||||
:x2 "82.385"
|
||||
:y1 "5"
|
||||
:y2 "34.155"
|
||||
:gradient-units "userSpaceOnUse"}
|
||||
[svg/stop {:stop-color (colors/resolve-color destination theme)}]
|
||||
[svg/stop {:offset "1" :stop-color (colors/resolve-color source theme)}]]]]
|
||||
[rn/view {:style style/bottom-left-circle-container}
|
||||
[circle fill-color source-color]]
|
||||
[rn/view {:style style/top-right-circle-container}
|
||||
[circle fill-color destination-color]]]))
|
||||
[svg/svg {:xmlns "http://www.w3.org/2000/svg" :width "73" :height "66" :fill :none}
|
||||
[svg/path
|
||||
{:stroke "url(#gradient)" :d "M68 5h-9.364c-11.046 0-20 8.954-20 20v16c0 11.046-8.955 20-20 20H5"}]
|
||||
[svg/circle
|
||||
{:cx "68"
|
||||
:cy "5"
|
||||
:r "4"
|
||||
:fill (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
:stroke (colors/resolve-color destination theme)}]
|
||||
[svg/circle
|
||||
{:cx "5"
|
||||
:cy "61"
|
||||
:r "4"
|
||||
:fill (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
:stroke (colors/resolve-color source theme)}]
|
||||
[svg/defs
|
||||
[svg/linear-gradient
|
||||
{:id "gradient" :x1 "72.271" :x2 "82.385" :y1 "5" :y2 "34.155" :gradientUnits "userSpaceOnUse"}
|
||||
[svg/stop {:stopColor (colors/resolve-color destination theme)}]
|
||||
[svg/stop {:offset "1" :stopColor (colors/resolve-color source theme)}]]]])
|
||||
|
||||
(defn link-2x
|
||||
[{:keys [source destination theme]}]
|
||||
(let [[container-width
|
||||
set-container-width] (rn/use-state 100)
|
||||
stroke-color "url(#gradient)"
|
||||
source-color (colors/resolve-color source theme)
|
||||
destination-color (colors/resolve-color destination theme)
|
||||
fill-color (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
view-box (str "0 0 " container-width " 114")
|
||||
side-lines-path (helpers/calculate-side-lines-path-2x container-width)
|
||||
central-transform (helpers/calculate-transform container-width)
|
||||
on-layout (rn/use-callback #(set-container-width
|
||||
(oget % :nativeEvent :layout :width)))]
|
||||
[rn/view
|
||||
{:style style/link-2x-container
|
||||
:on-layout on-layout}
|
||||
[svg/svg
|
||||
{:xmlns "http://www.w3.org/2000/svg"
|
||||
:height "100%"
|
||||
:width "100%"
|
||||
:view-box view-box
|
||||
:fill :none}
|
||||
[svg/path
|
||||
{:d (:left side-lines-path)
|
||||
:stroke source-color}]
|
||||
[svg/path
|
||||
{:d
|
||||
"M62.9999 1L53.6356 1C42.5899 1 33.6356 9.9543 33.6356 21L33.6356 93C33.6356 104.046 24.6813 113 13.6356 113L5.71778e-05 113"
|
||||
:transform central-transform
|
||||
:stroke stroke-color}]
|
||||
[svg/path
|
||||
{:d (:right side-lines-path)
|
||||
:stroke destination-color}]
|
||||
[svg/defs
|
||||
[svg/linear-gradient
|
||||
{:id "gradient"
|
||||
:x1 "72.2711"
|
||||
:y1 "5.00001"
|
||||
:x2 "102.867"
|
||||
:y2 "49.0993"
|
||||
:gradient-units "userSpaceOnUse"}
|
||||
[svg/stop {:stop-color (colors/resolve-color destination theme)}]
|
||||
[svg/stop {:offset "1" :stop-color (colors/resolve-color source theme)}]]]]
|
||||
[rn/view {:style style/bottom-left-circle-container}
|
||||
[circle fill-color source-color]]
|
||||
[rn/view {:style style/top-right-circle-container}
|
||||
[circle fill-color destination-color]]]))
|
||||
[svg/svg
|
||||
{:width "73" :height "122" :viewBox "0 0 73 122" :fill "none" :xmlns "http://www.w3.org/2000/svg"}
|
||||
[svg/path
|
||||
{:d
|
||||
"M67.9999 5L58.6356 5C47.5899 5 38.6356 13.9543 38.6356 25L38.6356 97C38.6356 108.046 29.6813 117 18.6356 117L5.00006 117"
|
||||
:stroke "url(#gradient)"}]
|
||||
[svg/circle
|
||||
{:cx "68"
|
||||
:cy "5"
|
||||
:r "4"
|
||||
:fill (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
:stroke (colors/resolve-color destination theme)}]
|
||||
[svg/circle
|
||||
{:cx "5"
|
||||
:cy "117"
|
||||
:r "4"
|
||||
:fill (colors/theme-colors colors/white colors/neutral-90 theme)
|
||||
:stroke (colors/resolve-color source theme)}]
|
||||
[svg/defs
|
||||
[svg/linear-gradient
|
||||
{:id "gradient"
|
||||
:x1 "72.2711"
|
||||
:y1 "5.00001"
|
||||
:x2 "102.867"
|
||||
:y2 "49.0993"
|
||||
:gradientUnits "userSpaceOnUse"}
|
||||
[svg/stop {:stop-color (colors/resolve-color destination theme)}]
|
||||
[svg/stop {:offset "1" :stop-color (colors/resolve-color source theme)}]]]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [shape container-style] :as props}]
|
||||
|
||||
@@ -12,5 +12,6 @@
|
||||
[:amount :int]
|
||||
[:max-amount :int]
|
||||
[:network-name [:or :string :keyword]]]]]]
|
||||
[:container-style {:optional true} [:maybe :map]]]]]
|
||||
[:container-style {:optional true} [:maybe :map]]
|
||||
[:theme :schema.common/theme]]]]
|
||||
:any])
|
||||
|
||||
@@ -29,13 +29,13 @@
|
||||
:background-color (colors/resolve-color network-name nil 10)})
|
||||
|
||||
(defn network-bar
|
||||
[{:keys [bar-max-width on-top? bar-division? theme]
|
||||
[{:keys [max-width on-top? bar-division? theme]
|
||||
{:keys [network-name translate-x-shared-value]} :bar}
|
||||
width-shared-value]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:width width-shared-value
|
||||
:transform [{:translate-x translate-x-shared-value}]}
|
||||
{:max-width bar-max-width
|
||||
{:max-width max-width
|
||||
:flex-direction :row
|
||||
:justify-content :flex-end
|
||||
:background-color (colors/resolve-color network-name nil)
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]
|
||||
[utils.number]))
|
||||
|
||||
@@ -21,73 +22,60 @@
|
||||
(js/clearTimeout (k @timeouts))
|
||||
(swap! timeouts assoc k (js/setTimeout exec-fn-and-remove-timeout ms))))
|
||||
|
||||
(def get-gesture
|
||||
(memoize
|
||||
(fn
|
||||
[[detecting-gesture? slider-width-shared-value max-amount
|
||||
slider-height-shared-value
|
||||
amount-shared-value amount-on-gesture-start width->amount
|
||||
slider-opacity-shared-value on-new-amount set-detecting-gesture]]
|
||||
(-> (gesture/gesture-pan)
|
||||
(gesture/enabled detecting-gesture?)
|
||||
(gesture/on-begin
|
||||
(fn [_]
|
||||
(animation/increase-slider slider-width-shared-value slider-height-shared-value)
|
||||
(reset! amount-on-gesture-start (reanimated/get-shared-value amount-shared-value))))
|
||||
(gesture/on-update
|
||||
(fn [event]
|
||||
(let [new-amount (-> (oops/oget event "translationX")
|
||||
(width->amount)
|
||||
(+ @amount-on-gesture-start)
|
||||
(utils.number/value-in-range 1 max-amount))]
|
||||
(reanimated/set-shared-value amount-shared-value new-amount))))
|
||||
(gesture/on-finalize
|
||||
(fn [_]
|
||||
(animation/decrease-slider slider-width-shared-value slider-height-shared-value)
|
||||
(animation/hide-slider slider-opacity-shared-value)
|
||||
(on-new-amount (reanimated/get-shared-value amount-shared-value))
|
||||
(add-new-timeout :turn-off-gesture #(set-detecting-gesture false) 20)))))))
|
||||
(defn- f-slider
|
||||
[slider-shared-values]
|
||||
[rn/view {:style style/slider-container}
|
||||
[reanimated/view {:style (style/slider slider-shared-values)}]])
|
||||
|
||||
(defn network-bar
|
||||
[{:keys [total-width total-amount on-press on-new-amount allow-press?
|
||||
bar-idx bar-width bar-max-width]
|
||||
{:keys [amount-shared-value
|
||||
max-amount]
|
||||
:as bar} :bar
|
||||
:as props}]
|
||||
(let [[detecting-gesture?
|
||||
set-detecting-gesture] (rn/use-state false)
|
||||
amount-on-gesture-start (rn/use-ref-atom 0)
|
||||
slider-width-shared-value (reanimated/use-shared-value 4)
|
||||
slider-height-shared-value (reanimated/use-shared-value 32)
|
||||
slider-opacity-shared-value (reanimated/use-shared-value 0)
|
||||
network-bar-shared-value (reanimated/interpolate amount-shared-value
|
||||
[0 total-amount]
|
||||
[0 total-width])
|
||||
width->amount #(/ (* % total-amount) total-width)
|
||||
gesture (get-gesture
|
||||
[detecting-gesture? slider-width-shared-value max-amount
|
||||
slider-height-shared-value
|
||||
amount-shared-value amount-on-gesture-start width->amount
|
||||
slider-opacity-shared-value on-new-amount set-detecting-gesture])
|
||||
on-press (rn/use-callback
|
||||
(fn []
|
||||
(when (and (not detecting-gesture?) allow-press?)
|
||||
(on-press bar bar-idx bar-width bar-max-width)
|
||||
(set-detecting-gesture true)
|
||||
(animation/show-slider slider-opacity-shared-value)))
|
||||
[detecting-gesture? allow-press? on-press])]
|
||||
[rn/pressable
|
||||
{:on-press on-press}
|
||||
[reanimated/view
|
||||
{:style (style/network-bar props network-bar-shared-value)
|
||||
:accessibility-label :network-routing-bar}
|
||||
[gesture/gesture-detector {:gesture gesture}
|
||||
[rn/view {:style style/slider-container}
|
||||
[reanimated/view
|
||||
{:style (style/slider {:width-shared-value slider-width-shared-value
|
||||
:height-shared-value slider-height-shared-value
|
||||
:opacity-shared-value slider-opacity-shared-value})}]]]]]))
|
||||
(defn f-network-bar
|
||||
[_]
|
||||
(let [detecting-gesture? (reagent/atom false)
|
||||
amount-on-gesture-start (atom 0)]
|
||||
(fn [{:keys [total-width total-amount on-press on-new-amount allow-press?]
|
||||
{:keys [amount-shared-value
|
||||
max-amount]} :bar
|
||||
:as props}]
|
||||
(let [slider-width-shared-value (reanimated/use-shared-value 4)
|
||||
slider-height-shared-value (reanimated/use-shared-value 32)
|
||||
slider-opacity-shared-value (reanimated/use-shared-value 0)
|
||||
network-bar-shared-value (reanimated/interpolate amount-shared-value
|
||||
[0 total-amount]
|
||||
[0 total-width])
|
||||
width->amount #(/ (* % total-amount) total-width)]
|
||||
[rn/pressable
|
||||
{:on-press (fn []
|
||||
(when (and (not @detecting-gesture?) allow-press?)
|
||||
(on-press)
|
||||
(reset! detecting-gesture? true)
|
||||
(animation/show-slider slider-opacity-shared-value)))}
|
||||
[reanimated/view
|
||||
{:style (style/network-bar props network-bar-shared-value)
|
||||
:accessibility-label :network-routing-bar}
|
||||
[gesture/gesture-detector
|
||||
{:gesture
|
||||
(-> (gesture/gesture-pan)
|
||||
(gesture/enabled @detecting-gesture?)
|
||||
(gesture/on-begin
|
||||
(fn [_]
|
||||
(animation/increase-slider slider-width-shared-value slider-height-shared-value)
|
||||
(reset! amount-on-gesture-start (reanimated/get-shared-value amount-shared-value))))
|
||||
(gesture/on-update
|
||||
(fn [event]
|
||||
(let [new-amount (-> (oops/oget event "translationX")
|
||||
(width->amount)
|
||||
(+ @amount-on-gesture-start)
|
||||
(utils.number/value-in-range 1 max-amount))]
|
||||
(reanimated/set-shared-value amount-shared-value new-amount))))
|
||||
(gesture/on-finalize
|
||||
(fn [_]
|
||||
(animation/decrease-slider slider-width-shared-value slider-height-shared-value)
|
||||
(animation/hide-slider slider-opacity-shared-value)
|
||||
(on-new-amount (reanimated/get-shared-value amount-shared-value))
|
||||
(add-new-timeout :turn-off-gesture #(reset! detecting-gesture? false) 20))))}
|
||||
[:f> f-slider
|
||||
{:width-shared-value slider-width-shared-value
|
||||
:height-shared-value slider-height-shared-value
|
||||
:opacity-shared-value slider-opacity-shared-value}]]]]))))
|
||||
|
||||
(defn- add-bar-shared-values
|
||||
[{:keys [amount] :as network}]
|
||||
@@ -105,113 +93,101 @@
|
||||
(interleave (repeat [rn/view {:style (style/dashed-line-line network-name)}])
|
||||
(repeat [rn/view {:style style/dashed-line-space}])))))
|
||||
|
||||
(defn- network-routing-bars
|
||||
[{:keys [networks total-width total-amount requesting-data? on-amount-selected]}]
|
||||
(let [[selected-network-idx
|
||||
set-selected-network-idx] (rn/use-state nil)
|
||||
[press-locked?
|
||||
set-press-locked] (rn/use-state false)
|
||||
lock-press (rn/use-callback #(set-press-locked true))
|
||||
unlock-press (rn/use-callback #(set-press-locked false))
|
||||
reset-state-values (rn/use-callback #(set-selected-network-idx nil))
|
||||
bar-opacity-shared-value (reanimated/use-shared-value 0)
|
||||
network-bars (map add-bar-shared-values networks)
|
||||
amount->width #(* % (/ total-width total-amount))
|
||||
bars-widths-negative (map #(-> % get-negative-amount amount->width)
|
||||
network-bars)
|
||||
last-bar-idx (dec (count network-bars))
|
||||
network-bar-on-press (rn/use-callback
|
||||
(fn [bar bar-idx bar-width bar-max-width]
|
||||
(when-not selected-network-idx
|
||||
(let [[previous-bars
|
||||
[_ & next-bars]] (split-at bar-idx network-bars)]
|
||||
(animation/move-previous-bars
|
||||
{:bars previous-bars
|
||||
:bars-widths-negative bars-widths-negative})
|
||||
(animation/move-pressed-bar
|
||||
{:bar bar
|
||||
:bars-widths-negative bars-widths-negative
|
||||
:number-previous-bars bar-idx})
|
||||
(animation/move-next-bars
|
||||
{:bars next-bars
|
||||
:bars-widths-negative bars-widths-negative
|
||||
:number-previous-bars (inc bar-idx)
|
||||
:extra-offset (max 0 (- bar-max-width bar-width))
|
||||
:add-new-timeout add-new-timeout}))
|
||||
(animation/show-max-limit-bar bar-opacity-shared-value)
|
||||
(set-selected-network-idx bar-idx)))
|
||||
[selected-network-idx bars-widths-negative network-bars])
|
||||
on-new-amount (rn/use-callback
|
||||
(fn [new-amount]
|
||||
(animation/hide-max-limit-bar bar-opacity-shared-value)
|
||||
(when on-amount-selected
|
||||
(on-amount-selected new-amount selected-network-idx)))
|
||||
[on-amount-selected selected-network-idx])]
|
||||
(rn/use-effect
|
||||
#(when (and (not requesting-data?) selected-network-idx)
|
||||
(let [bar (nth network-bars selected-network-idx)]
|
||||
(animation/hide-pressed-bar bar amount->width))
|
||||
(animation/update-bar-values-and-reset-animations
|
||||
{:new-network-values networks
|
||||
:network-bars network-bars
|
||||
:amount->width amount->width
|
||||
:reset-values-fn reset-state-values
|
||||
:lock-press-fn lock-press
|
||||
:unlock-press-fn unlock-press
|
||||
:add-new-timeout add-new-timeout}))
|
||||
[requesting-data?])
|
||||
[:<>
|
||||
(doall
|
||||
(for [[bar-idx bar] (map-indexed vector network-bars)
|
||||
:let [bar-max-width (amount->width (:max-amount bar))
|
||||
bar-width (-> (:amount-shared-value bar)
|
||||
(reanimated/get-shared-value)
|
||||
(amount->width))
|
||||
hide-division? (or (= last-bar-idx bar-idx) selected-network-idx)
|
||||
this-bar-selected? (= selected-network-idx bar-idx)]]
|
||||
^{:key (str "network-bar-" bar-idx)}
|
||||
[network-bar
|
||||
{:bar bar
|
||||
:bar-idx bar-idx
|
||||
:bar-width bar-width
|
||||
:bar-max-width bar-max-width
|
||||
:total-width total-width
|
||||
:total-amount total-amount
|
||||
:bar-division? hide-division?
|
||||
:on-top? this-bar-selected?
|
||||
:allow-press? (and (or (not selected-network-idx) this-bar-selected?)
|
||||
(not requesting-data?)
|
||||
(not press-locked?))
|
||||
:on-press network-bar-on-press
|
||||
:on-new-amount on-new-amount}]))
|
||||
(defn f-network-routing-bars
|
||||
[_]
|
||||
(let [selected-network-idx (reagent/atom nil)
|
||||
press-locked? (reagent/atom false)
|
||||
lock-press #(reset! press-locked? true)
|
||||
unlock-press #(reset! press-locked? false)
|
||||
reset-state-values #(reset! selected-network-idx nil)]
|
||||
(fn [{:keys [networks total-width total-amount requesting-data? on-amount-selected]}]
|
||||
(let [bar-opacity-shared-value (reanimated/use-shared-value 0)
|
||||
network-bars (map add-bar-shared-values networks)
|
||||
amount->width #(* % (/ total-width total-amount))
|
||||
bars-widths-negative (map #(-> % get-negative-amount amount->width)
|
||||
network-bars)
|
||||
last-bar-idx (dec (count network-bars))]
|
||||
(rn/use-effect
|
||||
#(when (and (not requesting-data?) @selected-network-idx)
|
||||
(let [bar (nth network-bars @selected-network-idx)]
|
||||
(animation/hide-pressed-bar bar amount->width))
|
||||
(animation/update-bar-values-and-reset-animations
|
||||
{:new-network-values networks
|
||||
:network-bars network-bars
|
||||
:amount->width amount->width
|
||||
:reset-values-fn reset-state-values
|
||||
:lock-press-fn lock-press
|
||||
:unlock-press-fn unlock-press
|
||||
:add-new-timeout add-new-timeout}))
|
||||
[requesting-data?])
|
||||
[:<>
|
||||
(doall
|
||||
(for [[bar-idx bar] (map-indexed vector network-bars)
|
||||
:let [bar-max-width (amount->width (:max-amount bar))
|
||||
bar-width (-> (:amount-shared-value bar)
|
||||
(reanimated/get-shared-value)
|
||||
(amount->width))
|
||||
hide-division? (or (= last-bar-idx bar-idx) @selected-network-idx)
|
||||
this-bar-selected? (= @selected-network-idx bar-idx)]]
|
||||
^{:key (str "network-bar-" bar-idx)}
|
||||
[:f> f-network-bar
|
||||
{:bar bar
|
||||
:max-width bar-max-width
|
||||
:total-width total-width
|
||||
:total-amount total-amount
|
||||
:bar-division? hide-division?
|
||||
:on-top? this-bar-selected?
|
||||
:allow-press? (and (or (not @selected-network-idx) this-bar-selected?)
|
||||
(not requesting-data?)
|
||||
(not @press-locked?))
|
||||
:on-press (fn []
|
||||
(when-not @selected-network-idx
|
||||
(let [[previous-bars [_ & next-bars]] (split-at bar-idx network-bars)
|
||||
number-previous-bars bar-idx]
|
||||
(animation/move-previous-bars
|
||||
{:bars previous-bars
|
||||
:bars-widths-negative bars-widths-negative})
|
||||
(animation/move-pressed-bar
|
||||
{:bar bar
|
||||
:bars-widths-negative bars-widths-negative
|
||||
:number-previous-bars number-previous-bars})
|
||||
(animation/move-next-bars
|
||||
{:bars next-bars
|
||||
:bars-widths-negative bars-widths-negative
|
||||
:number-previous-bars (inc number-previous-bars)
|
||||
:extra-offset (max 0 (- bar-max-width bar-width))
|
||||
:add-new-timeout add-new-timeout}))
|
||||
(animation/show-max-limit-bar bar-opacity-shared-value)
|
||||
(reset! selected-network-idx bar-idx)))
|
||||
:on-new-amount (fn [new-amount]
|
||||
(animation/hide-max-limit-bar bar-opacity-shared-value)
|
||||
(when on-amount-selected
|
||||
(on-amount-selected new-amount @selected-network-idx)))}]))
|
||||
|
||||
(let [{:keys [max-amount network-name]} (some->> selected-network-idx
|
||||
(nth network-bars))
|
||||
limit-bar-width (amount->width max-amount)]
|
||||
[reanimated/view
|
||||
{:style (style/max-limit-bar
|
||||
{:opacity-shared-value bar-opacity-shared-value
|
||||
:width limit-bar-width})}
|
||||
[rn/view {:style (style/max-limit-bar-background network-name)}]
|
||||
[dashed-line network-name]])]))
|
||||
(let [{:keys [max-amount network-name]} (some->> @selected-network-idx
|
||||
(nth network-bars))
|
||||
limit-bar-width (amount->width max-amount)]
|
||||
[reanimated/view
|
||||
{:style (style/max-limit-bar
|
||||
{:opacity-shared-value bar-opacity-shared-value
|
||||
:width limit-bar-width})}
|
||||
[rn/view {:style (style/max-limit-bar-background network-name)}]
|
||||
[dashed-line network-name]])]))))
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [networks container-style] :as params}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
[total-width
|
||||
set-total-width] (rn/use-state nil)
|
||||
on-layout (rn/use-callback #(let [width (oops/oget % "nativeEvent.layout.width")]
|
||||
(when (not= width total-width)
|
||||
(set-total-width width))))]
|
||||
(rn/use-unmount (fn []
|
||||
(doseq [[_ living-timeout] @timeouts]
|
||||
(js/clearTimeout living-timeout))))
|
||||
[{:keys [networks container-style theme] :as params}]
|
||||
(reagent/with-let [total-width (reagent/atom nil)]
|
||||
[rn/view
|
||||
{:accessibility-label :network-routing
|
||||
:style (style/container container-style theme)
|
||||
:on-layout on-layout}
|
||||
(when total-width
|
||||
:on-layout #(reset! total-width (oops/oget % "nativeEvent.layout.width"))}
|
||||
(when @total-width
|
||||
^{:key (str "network-routing-" (count networks))}
|
||||
[network-routing-bars (assoc params :total-width total-width)])]))
|
||||
[:f> f-network-routing-bars (assoc params :total-width @total-width)])]
|
||||
(finally
|
||||
(doseq [[_ living-timeout] @timeouts]
|
||||
(js/clearTimeout living-timeout)))))
|
||||
|
||||
(def view (schema/instrument #'view-internal network-routing-schema/?schema))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal network-routing-schema/?schema)))
|
||||
|
||||
@@ -14,5 +14,6 @@
|
||||
[:networks {:optional true}
|
||||
[:maybe [:sequential [:map [:source [:maybe :schema.common/image-source]]]]]]
|
||||
[:customization-color {:optional true} [:maybe :schema.common/customization-color]]
|
||||
[:value {:optional true} [:maybe :string]]]]]
|
||||
[:value {:optional true} [:maybe :string]]
|
||||
[:theme :schema.common/theme]]]]
|
||||
:any])
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[quo.foundations.common :as common]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]))
|
||||
|
||||
(defn fiat-format
|
||||
@@ -74,8 +75,7 @@
|
||||
[token-name-text theme text]])
|
||||
|
||||
(defn input-section
|
||||
[{:keys [on-change-text value value-internal set-value-internal on-selection-change
|
||||
on-token-press]}]
|
||||
[{:keys [on-change-text value value-atom on-selection-change on-token-press]}]
|
||||
(let [input-ref (atom nil)
|
||||
set-ref #(reset! input-ref %)
|
||||
focus-input #(when-let [ref ^js @input-ref]
|
||||
@@ -83,7 +83,7 @@
|
||||
controlled-input? (some? value)
|
||||
handle-on-change-text (fn [v]
|
||||
(when-not controlled-input?
|
||||
(set-value-internal v))
|
||||
(reset! value-atom v))
|
||||
(when on-change-text
|
||||
(on-change-text v)))
|
||||
handle-selection-change (fn [^js e]
|
||||
@@ -117,43 +117,41 @@
|
||||
:on-selection-change handle-selection-change
|
||||
:selection (clj->js selection)}
|
||||
controlled-input? (assoc :value value)
|
||||
(not controlled-input?) (assoc :default-value value-internal))]]
|
||||
(not controlled-input?) (assoc :default-value @value-atom))]]
|
||||
[token-label
|
||||
{:theme theme
|
||||
:text (if crypto? token currency)
|
||||
:value (if controlled-input? value value-internal)}]])))
|
||||
:value (if controlled-input? value @value-atom)}]])))
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [container-style value on-swap] :as props}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
width (:width (rn/get-window))
|
||||
[value-internal set-value-internal] (rn/use-state nil)
|
||||
[crypto? set-crypto] (rn/use-state true)
|
||||
handle-on-swap (rn/use-callback
|
||||
(fn []
|
||||
(set-crypto (not crypto?))
|
||||
(when on-swap (on-swap (not crypto?))))
|
||||
[crypto? on-swap])]
|
||||
[rn/view {:style (merge (style/main-container width) container-style)}
|
||||
[rn/view {:style style/amount-container}
|
||||
[input-section
|
||||
(assoc props
|
||||
:value-internal value-internal
|
||||
:set-value-internal set-value-internal
|
||||
:crypto? crypto?)]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press handle-on-swap
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[divider-line/view {:container-style (style/divider theme)}]
|
||||
[data-info
|
||||
(assoc props
|
||||
:theme theme
|
||||
:crypto? crypto?
|
||||
:amount (or value value-internal))]]))
|
||||
[]
|
||||
(let [width (:width (rn/get-window))
|
||||
value-atom (reagent/atom nil)
|
||||
crypto? (reagent/atom true)]
|
||||
(fn [{:keys [theme container-style value on-swap] :as props}]
|
||||
(let [handle-on-swap (fn []
|
||||
(swap! crypto? not)
|
||||
(when on-swap (on-swap @crypto?)))]
|
||||
[rn/view {:style (merge (style/main-container width) container-style)}
|
||||
[rn/view {:style style/amount-container}
|
||||
[input-section
|
||||
(assoc props
|
||||
:value-atom value-atom
|
||||
:crypto? @crypto?)]
|
||||
[button/button
|
||||
{:icon true
|
||||
:icon-only? true
|
||||
:size 32
|
||||
:on-press handle-on-swap
|
||||
:type :outline
|
||||
:accessibility-label :reorder}
|
||||
:i/reorder]]
|
||||
[divider-line/view {:container-style (style/divider theme)}]
|
||||
[data-info
|
||||
(assoc props
|
||||
:crypto? @crypto?
|
||||
:amount (or value @value-atom))]]))))
|
||||
|
||||
(def view (schema/instrument #'view-internal component-schema/?schema))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
[:blur? {:optional true} [:maybe :boolean]]
|
||||
[:on-press {:optional true} [:maybe fn?]]
|
||||
[:state {:optional true} [:maybe [:= :disabled]]]
|
||||
[:theme :schema.common/theme]
|
||||
[:second-tag-prefix {:optional true} [:maybe :keyword]]
|
||||
[:third-tag-prefix {:optional true} [:maybe :keyword]]
|
||||
[:fourth-tag-prefix {:optional true} [:maybe :keyword]]
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.hole-view :as hole-view]
|
||||
[reagent.core :as reagent]
|
||||
[schema.core :as schema]
|
||||
[utils.i18n :as i18n]))
|
||||
|
||||
@@ -99,37 +100,39 @@
|
||||
[context-tag/view (merge props {:size 24 :blur? blur?})]])
|
||||
|
||||
(defn- view-internal
|
||||
[{:keys [state blur? first-tag second-tag third-tag fourth-tag on-press
|
||||
second-tag-prefix third-tag-prefix fourth-tag-prefix]
|
||||
:as props}]
|
||||
(let [theme (quo.theme/use-theme-value)
|
||||
[pressed?
|
||||
set-pressed] (rn/use-state false)
|
||||
on-press-in (rn/use-callback #(set-pressed true))
|
||||
on-press-out (rn/use-callback #(set-pressed false))]
|
||||
[rn/pressable
|
||||
{:style (style/wallet-activity-container {:pressed? pressed?
|
||||
:theme theme
|
||||
:blur? blur?})
|
||||
:accessibility-label :wallet-activity
|
||||
:disabled (= state :disabled)
|
||||
:on-press on-press
|
||||
:on-press-in on-press-in
|
||||
:on-press-out on-press-out}
|
||||
[rn/view
|
||||
{:style {:flex-direction :row}}
|
||||
[transaction-icon-view props]
|
||||
[rn/view
|
||||
{:style style/content-container}
|
||||
[transaction-header props]
|
||||
[rn/view {:style style/content-line}
|
||||
(when first-tag [prop-tag first-tag blur?])
|
||||
(when second-tag-prefix [prop-text second-tag-prefix theme])
|
||||
(when second-tag [prop-tag second-tag blur?])]
|
||||
[rn/view {:style style/content-line}
|
||||
(when third-tag-prefix [prop-text third-tag-prefix theme])
|
||||
(when third-tag [prop-tag third-tag blur?])
|
||||
(when fourth-tag-prefix [prop-text fourth-tag-prefix theme])
|
||||
(when fourth-tag [prop-tag fourth-tag blur?])]]]]))
|
||||
[_]
|
||||
(let [pressed? (reagent/atom false)]
|
||||
(fn
|
||||
[{:keys [state theme blur?
|
||||
on-press
|
||||
first-tag second-tag third-tag fourth-tag
|
||||
second-tag-prefix third-tag-prefix fourth-tag-prefix]
|
||||
:as props}]
|
||||
[rn/pressable
|
||||
{:style (style/wallet-activity-container {:pressed? @pressed?
|
||||
:theme theme
|
||||
:blur? blur?})
|
||||
:accessibility-label :wallet-activity
|
||||
:disabled (= state :disabled)
|
||||
:on-press on-press
|
||||
:on-press-in (fn [] (reset! pressed? true))
|
||||
:on-press-out (fn [] (reset! pressed? false))}
|
||||
[rn/view
|
||||
{:style {:flex-direction :row}}
|
||||
[transaction-icon-view props]
|
||||
[rn/view
|
||||
{:style style/content-container}
|
||||
[transaction-header props]
|
||||
[rn/view {:style style/content-line}
|
||||
(when first-tag [prop-tag first-tag blur?])
|
||||
(when second-tag-prefix [prop-text second-tag-prefix theme])
|
||||
(when second-tag [prop-tag second-tag blur?])]
|
||||
[rn/view {:style style/content-line}
|
||||
(when third-tag-prefix [prop-text third-tag-prefix theme])
|
||||
(when third-tag [prop-tag third-tag blur?])
|
||||
(when fourth-tag-prefix [prop-text fourth-tag-prefix theme])
|
||||
(when fourth-tag [prop-tag fourth-tag blur?])]]]])))
|
||||
|
||||
(def view (schema/instrument #'view-internal component-schema/?schema))
|
||||
(def view
|
||||
(quo.theme/with-theme
|
||||
(schema/instrument #'view-internal component-schema/?schema)))
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
quo.components.community.channel-action.view
|
||||
quo.components.community.channel-actions.view
|
||||
quo.components.community.community-card-view
|
||||
quo.components.community.community-detail-token-gating.view
|
||||
quo.components.community.community-list-view
|
||||
quo.components.community.community-stat.view
|
||||
quo.components.community.community-view
|
||||
@@ -225,7 +224,6 @@
|
||||
|
||||
;;;; Community
|
||||
(def community-card-view-item quo.components.community.community-card-view/view)
|
||||
(def community-detail-token-gating quo.components.community.community-detail-token-gating.view/view)
|
||||
(def communities-membership-list-item
|
||||
quo.components.community.community-list-view/communities-membership-list-item)
|
||||
(def community-stats-column quo.components.community.community-view/community-stats-column)
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
quo.components.calendar.calendar.component-spec
|
||||
quo.components.calendar.calendar.month-picker.component-spec
|
||||
quo.components.colors.color-picker.component-spec
|
||||
quo.components.community.community-detail-token-gating.component-spec
|
||||
quo.components.community.community-stat.component-spec
|
||||
quo.components.counter.collectible-counter.component-spec
|
||||
quo.components.counter.counter.component-spec
|
||||
|
||||
@@ -10,10 +10,7 @@
|
||||
(def ui-themed
|
||||
{:no-funds
|
||||
{:light (js/require "../resources/images/ui2/no-funds-light.png")
|
||||
:dark (js/require "../resources/images/ui2/no-funds-dark.png")}
|
||||
:no-contacts-to-chat
|
||||
{:light (js/require "../resources/images/ui2/no-contacts-to-chat-light.png")
|
||||
:dark (js/require "../resources/images/ui2/no-contacts-to-chat-dark.png")}})
|
||||
:dark (js/require "../resources/images/ui2/no-funds-dark.png")}})
|
||||
|
||||
(defn get-themed-image
|
||||
[k theme]
|
||||
|
||||
@@ -226,3 +226,7 @@
|
||||
(defn open-url [link] (.openURL ^js linking link))
|
||||
|
||||
(def set-status-bar-style react-native/StatusBar.setBarStyle)
|
||||
|
||||
(defn sharing
|
||||
[content]
|
||||
(.share (.-Share ^js react-native) (clj->js content)))
|
||||
|
||||
@@ -4,5 +4,9 @@
|
||||
|
||||
(defn open
|
||||
([options]
|
||||
(open options #() #()))
|
||||
([options on-success on-error]
|
||||
(-> ^js react-native-share
|
||||
(.open (clj->js options)))))
|
||||
(.open (clj->js options))
|
||||
(.then on-success)
|
||||
(.catch on-error))))
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
(defn contacts-section-header
|
||||
[{:keys [title]}]
|
||||
(let [theme (quo.theme/use-theme-value)]
|
||||
[quo/divider-label {:container-style (style/contacts-section-header theme)}
|
||||
[quo/divider-label {:container-style {:background-color (style/contacts-section-header theme)}}
|
||||
title]))
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn contact-list-item
|
||||
[{:keys [on-press on-long-press accessory allow-multiple-presses? disabled?]}
|
||||
[{:keys [on-press on-long-press accessory allow-multiple-presses?]}
|
||||
{:keys [primary-name secondary-name public-key compressed-key ens-verified added?]}
|
||||
theme]
|
||||
(let [photo-path (rf/sub [:chats/photo-path public-key])
|
||||
@@ -24,5 +24,4 @@
|
||||
:contact? added?
|
||||
:on-press on-press
|
||||
:on-long-press on-long-press
|
||||
:accessory accessory
|
||||
:disabled? disabled?}]))
|
||||
:accessory accessory}]))
|
||||
|
||||
@@ -40,15 +40,13 @@
|
||||
params: sequence - A positional sequence of zero or more arguments.
|
||||
|
||||
on-success/on-error: function/vector (optional) - When a function, it will be
|
||||
called with the transformed response and id (request-id) as the argument.
|
||||
When a vector, it is expected to be a valid re-frame event vector, and the event
|
||||
will be dispatched with the transformed response and id conj'ed at the end.
|
||||
called with the transformed response as the sole argument. When a vector, it
|
||||
is expected to be a valid re-frame event vector, and the event will be
|
||||
dispatched with the transformed response conj'ed at the end.
|
||||
|
||||
js-response: boolean - When non-nil, the successful response will not be
|
||||
recursively converted to Clojure data structures. Default: nil.
|
||||
|
||||
id: (optional) - id passed while making the RPC call will be returned in response
|
||||
|
||||
number-of-retries: integer - The maximum number of retries in case of failure.
|
||||
Default: nil.
|
||||
|
||||
@@ -58,14 +56,14 @@
|
||||
Note that on-error is optional, but if not provided, a default implementation
|
||||
will be used.
|
||||
"
|
||||
[{:keys [method params on-success on-error js-response id] :as arg}]
|
||||
[{:keys [method params on-success on-error js-response] :as arg}]
|
||||
(let [params (or params [])
|
||||
on-error (or on-error
|
||||
(on-error-retry call arg)
|
||||
#(log/warn :json-rpc/error method :error % :params params))]
|
||||
(native-module/call-private-rpc
|
||||
(transforms/clj->json {:jsonrpc "2.0"
|
||||
:id (or id 1)
|
||||
:id 1
|
||||
:method method
|
||||
:params params})
|
||||
(fn [raw-response]
|
||||
@@ -81,13 +79,12 @@
|
||||
(rf/dispatch (conj on-error error))
|
||||
(on-error error)))
|
||||
(when on-success
|
||||
(let [result (if js-response
|
||||
(.-result response-js)
|
||||
(transforms/js->clj (.-result response-js)))
|
||||
request-id (.-id response-js)]
|
||||
(let [result (if js-response
|
||||
(.-result response-js)
|
||||
(transforms/js->clj (.-result response-js)))]
|
||||
(if (vector? on-success)
|
||||
(rf/dispatch (conj on-success result request-id))
|
||||
(on-success result request-id)))))))))))
|
||||
(rf/dispatch (conj on-success result))
|
||||
(on-success result)))))))))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:json-rpc/call
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
[react-native.cameraroll :as cameraroll]
|
||||
[react-native.fs :as fs]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.share :as share]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def config
|
||||
@@ -14,12 +15,10 @@
|
||||
(blob/fetch uri
|
||||
config
|
||||
(fn [downloaded-url]
|
||||
(rf/dispatch [:open-share
|
||||
{:options {:url (str (when platform/android? "file://")
|
||||
downloaded-url)
|
||||
:isNewTask true}
|
||||
:on-success #(fs/unlink downloaded-url)
|
||||
:on-error #(fs/unlink downloaded-url)}])))))
|
||||
(share/open {:url (str (when platform/android? "file://") downloaded-url)
|
||||
:isNewTask true}
|
||||
#(fs/unlink downloaded-url)
|
||||
#(fs/unlink downloaded-url))))))
|
||||
|
||||
(rf/reg-fx :effects.lightbox/save-image-to-gallery
|
||||
(fn [[uri on-success]]
|
||||
|
||||
@@ -100,7 +100,7 @@
|
||||
ens?
|
||||
(assoc-in [:route-params :ens-name] fragment)
|
||||
|
||||
(and (= handler :community) compressed-key?)
|
||||
(and (or (= handler :community) (= handler :community-chat)) compressed-key?)
|
||||
(assoc-in [:route-params :community-id] fragment)
|
||||
|
||||
(and equal-end-of-base64url (= handler :community) (:community-data route-params))
|
||||
@@ -119,13 +119,6 @@
|
||||
(re-find constants/regx-starts-with-uuid (:community-data route-params)))
|
||||
(assoc-in [:route-params :community-channel-id] (:community-data route-params))
|
||||
|
||||
(and fragment
|
||||
(= handler :community-chat)
|
||||
(:community-data route-params)
|
||||
(string? (:community-data route-params))
|
||||
(not (re-find constants/regx-starts-with-uuid (:community-data route-params))))
|
||||
(assoc-in [:route-params :community-encoded-data?] true)
|
||||
|
||||
(and equal-end-of-base64url (= handler :user) (:user-data route-params))
|
||||
(update-in [:route-params :user-data] #(str % equal-end-of-base64url))
|
||||
|
||||
@@ -210,10 +203,6 @@
|
||||
(cb {:type :private-chat
|
||||
:error :invalid-chat-id})))))
|
||||
|
||||
(defn parse-shared-url
|
||||
[uri]
|
||||
(re-frame/dispatch [:shared-urls/parse-shared-url uri]))
|
||||
|
||||
(defn match-community-channel-async
|
||||
[{:keys [community-channel-id community-id]} cb]
|
||||
(if (validators/valid-compressed-key? community-id)
|
||||
@@ -318,10 +307,9 @@
|
||||
(and (= handler :community-chat) (:community-channel-id route-params) (:community-id route-params))
|
||||
(match-community-channel-async route-params cb)
|
||||
|
||||
(and (= handler :community-chat)
|
||||
(:community-encoded-data? route-params)
|
||||
(:community-id route-params))
|
||||
(parse-shared-url uri)
|
||||
(and (= handler :community-chat) (:community-id route-params))
|
||||
(cb {:type :community
|
||||
:community-id (:community-id route-params)})
|
||||
|
||||
;; NOTE: removed in `match-uri`, might need this in the future
|
||||
(= handler :wallet-account)
|
||||
|
||||
@@ -42,14 +42,12 @@
|
||||
[:community-chat
|
||||
{:community-data
|
||||
"G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM="
|
||||
:community-encoded-data? true
|
||||
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||
|
||||
"status-app://cc/G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM=#zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"
|
||||
[:community-chat
|
||||
{:community-data
|
||||
"G54AAKwObLdpiGjXnckYzRcOSq0QQAS_CURGfqVU42ceGHCObstUIknTTZDOKF3E8y2MSicncpO7fTskXnoACiPKeejvjtLTGWNxUhlT7fyQS7Jrr33UVHluxv_PLjV2ePGw5GQ33innzeK34pInIgUGs5RjdQifMVmURalxxQKwiuoY5zwIjixWWRHqjHM="
|
||||
:community-encoded-data? true
|
||||
:community-id "zQ3shYSHp7GoiXaauJMnDcjwU2yNjdzpXLosAWapPS4CFxc11"}]
|
||||
|
||||
"https://status.app/cc/c432709e-fc73-440d-bb67-cb3a0929dfda#zQ3shZL6dXiFCbDyxnXxwQa9v8QFC2q19subFtyxd7kVszMVo"
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
(ns status-im.common.shared-urls.data-store
|
||||
(:require
|
||||
[clojure.set :as set]))
|
||||
|
||||
(defn <-rpc
|
||||
[{:keys [community channel contact]}]
|
||||
{:community (set/rename-keys
|
||||
community
|
||||
{:communityId :community-id
|
||||
:displayName :display-name
|
||||
:membersCount :members-count
|
||||
:tagIndices :tag-indices})
|
||||
:channel (set/rename-keys
|
||||
channel
|
||||
{:displayName :display-name
|
||||
:channelUuid :channel-uuid})
|
||||
:contact (set/rename-keys
|
||||
contact
|
||||
{:displayName :display-name
|
||||
:publicKey :public-key})})
|
||||
@@ -1,33 +0,0 @@
|
||||
(ns status-im.common.shared-urls.events
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.common.shared-urls.data-store :as data-store]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn parse-shared-url-success
|
||||
[url response]
|
||||
(let [parsed-data (data-store/<-rpc response)
|
||||
cb #(rf/dispatch [:universal-links/match-value url %])]
|
||||
(cond
|
||||
(:channel parsed-data)
|
||||
(cb {:type :community-chat
|
||||
:chat-id (str (get-in parsed-data [:community :community-id])
|
||||
(get-in parsed-data [:channel :channel-uuid]))
|
||||
:community-id (get-in parsed-data [:community :community-id])})
|
||||
|
||||
(:community parsed-data)
|
||||
(cb {:type :community :community-id (get-in parsed-data [:community :community-id])}))))
|
||||
|
||||
(defn parse-shared-url
|
||||
[_ [uri]]
|
||||
(let [url (string/replace uri #"status-app:/" "https://status.app")]
|
||||
{:json-rpc/call
|
||||
[{:method "wakuext_parseSharedURL"
|
||||
:params [url]
|
||||
:on-success #(parse-shared-url-success url %)
|
||||
:on-error (fn [err]
|
||||
(log/error "failed to parse shared url" {:error err :url url}))}]}))
|
||||
|
||||
(re-frame/reg-event-fx :shared-urls/parse-shared-url parse-shared-url)
|
||||
@@ -18,8 +18,8 @@
|
||||
[rn/view
|
||||
[quo/text
|
||||
{:accessibility-label :sync-code-generated
|
||||
:weight :semi-bold
|
||||
:size :heading-2
|
||||
:weight :bold
|
||||
:size :heading-1
|
||||
:style {:margin-bottom 4}}
|
||||
(i18n/label :t/enter-password)]
|
||||
[rn/view
|
||||
|
||||
@@ -61,4 +61,4 @@
|
||||
(->> (rf/sub [:toasts])
|
||||
:ordered
|
||||
(into [rn/view {:style (style/outmost-transparent-container)}]
|
||||
(map #(with-meta [f-container %] {:key %})))))
|
||||
(map #(with-meta [:f> f-container %] {:key %})))))
|
||||
|
||||
@@ -116,16 +116,14 @@
|
||||
(log/debug "universal-links: no url")))
|
||||
|
||||
(rf/defn on-handle
|
||||
{:events [:universal-links/match-value]}
|
||||
[cofx url {:keys [type chat-id community-id] :as data}]
|
||||
{:events [::match-value]}
|
||||
[cofx url {:keys [type chat-id] :as data}]
|
||||
(case type
|
||||
:group-chat (handle-group-chat cofx data)
|
||||
:private-chat (handle-private-chat cofx data)
|
||||
:community-requests (handle-community-requests cofx data)
|
||||
:community (communities.events/navigate-to-community-overview cofx [community-id])
|
||||
:community-chat (communities.events/navigate-to-community-chat cofx
|
||||
[chat-id :pop-to-root
|
||||
community-id])
|
||||
:community (communities.events/navigate-to-serialized-community cofx data)
|
||||
:community-chat {:dispatch [:communities/navigate-to-community-chat chat-id :pop-to-root]}
|
||||
:contact (handle-view-profile cofx data)
|
||||
:browser (handle-browse cofx data)
|
||||
:eip681 (handle-eip681 cofx data)
|
||||
@@ -138,7 +136,7 @@
|
||||
{:router/handle-uri {:chain (chain/chain-keyword db)
|
||||
:chats (:chats db)
|
||||
:uri url
|
||||
:cb #(re-frame/dispatch [:universal-links/match-value url %])}})
|
||||
:cb #(re-frame/dispatch [::match-value url %])}})
|
||||
|
||||
(rf/defn store-url-for-later
|
||||
"Store the url in the db to be processed on login"
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[react-native.config :as react-native-config]
|
||||
[status-im.constants :as constants]
|
||||
[utils.ens.core :as utils.ens]
|
||||
[utils.ethereum.chain :as chain]))
|
||||
|
||||
@@ -60,7 +59,6 @@
|
||||
(def swap-enabled? (enabled? (get-config :SWAP_ENABLED "0")))
|
||||
(def stickers-test-enabled? (enabled? (get-config :STICKERS_TEST_ENABLED "0")))
|
||||
(def local-pairing-mode-enabled? (enabled? (get-config :LOCAL_PAIRING_ENABLED "1")))
|
||||
(def show-not-implemented-features? (enabled? (get-config :SHOW_NOT_IMPLEMENTED_FEATURES "0")))
|
||||
|
||||
;; CONFIG VALUES
|
||||
(def log-level (string/upper-case (get-config :LOG_LEVEL "")))
|
||||
@@ -71,18 +69,6 @@
|
||||
; currently not supported in status-go
|
||||
(def enable-remove-profile-picture? false)
|
||||
|
||||
(defn env-variable->int
|
||||
[env-var-name default-value]
|
||||
(js/parseInt (get-config env-var-name default-value)))
|
||||
|
||||
(def delete-message-for-me-undo-time-limit-ms
|
||||
(env-variable->int :DELETE_MESSAGE_FOR_ME_UNDO_TIME_LIMIT
|
||||
constants/delete-message-for-me-undo-time-limit-ms))
|
||||
|
||||
(def delete-message-undo-time-limit-ms
|
||||
(env-variable->int :DELETE_MESSAGE_UNDO_TIME_LIMIT
|
||||
constants/delete-message-undo-time-limit-ms))
|
||||
|
||||
(def verify-transaction-chain-id (js/parseInt (get-config :VERIFY_TRANSACTION_CHAIN_ID "1")))
|
||||
(def verify-transaction-url
|
||||
(if (= :mainnet (chain/chain-id->chain-keyword verify-transaction-chain-id))
|
||||
|
||||
@@ -448,8 +448,6 @@
|
||||
(def ^:const optimism-short-name "opt")
|
||||
(def ^:const arbitrum-short-name "arb1")
|
||||
|
||||
(def ^:const default-multichain-address-prefix "eth:opt:arb1:")
|
||||
|
||||
(def ^:const mainnet-abbreviated-name "Eth.")
|
||||
(def ^:const optimism-abbreviated-name "Opt.")
|
||||
(def ^:const arbitrum-abbreviated-name "Arb1.")
|
||||
|
||||
@@ -101,7 +101,6 @@
|
||||
{:keys [primary-name public-key]} (when one-contact-selected?
|
||||
(rf/sub [:contacts/contact-by-identity
|
||||
(first selected-contacts)]))]
|
||||
(rn/use-unmount #(rf/dispatch [:group-chat/clear-contacts]))
|
||||
[rn/view {:flex 1}
|
||||
[rn/view {:padding-horizontal 20}
|
||||
[quo/button
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.share :as share]
|
||||
[status-im.common.contact-list-item.view :as contact-list-item]
|
||||
[status-im.common.contact-list.view :as contact-list]
|
||||
[status-im.common.home.actions.view :as actions]
|
||||
@@ -121,7 +122,7 @@
|
||||
[:show-bottom-sheet {:content chat.actions.view/new-chat}])
|
||||
:accessibility-label :new-chat-button}
|
||||
:card-props
|
||||
{:on-press #(rf/dispatch [:open-share {:options {:url profile-link}}])
|
||||
{:on-press #(share/open {:url profile-link})
|
||||
:banner (resources/get-image :invite-friends)
|
||||
:title (i18n/label :t/invite-friends-to-status)
|
||||
:description (i18n/label :t/share-invite-link)}})
|
||||
|
||||
@@ -41,13 +41,8 @@
|
||||
|
||||
(defn f-send-button
|
||||
[props state animations window-height images? btn-opacity z-index edit]
|
||||
(let [{:keys [text-value]} state
|
||||
profile-customization-color (rf/sub [:profile/customization-color])
|
||||
{:keys [chat-id chat-type]
|
||||
chat-color :color} (rf/sub [:chats/current-chat-chat-view])
|
||||
contact-customization-color (when (= chat-type constants/one-to-one-chat-type)
|
||||
(rf/sub [:contacts/contact-customization-color-by-address
|
||||
chat-id]))]
|
||||
(let [{:keys [text-value]} state
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
(rn/use-effect (fn []
|
||||
;; Handle send button opacity animation and z-index when input content changes
|
||||
(if (or (seq @text-value) images?)
|
||||
@@ -65,7 +60,7 @@
|
||||
[quo/button
|
||||
{:icon-only? true
|
||||
:size 32
|
||||
:customization-color (or contact-customization-color chat-color profile-customization-color)
|
||||
:customization-color customization-color
|
||||
:accessibility-label :send-message-button
|
||||
:on-press #(send-message props state animations window-height edit)}
|
||||
:i/arrow-up]]))
|
||||
|
||||
@@ -8,13 +8,13 @@
|
||||
:margin-bottom (when-not community? 12)})
|
||||
|
||||
(def community-tag-container
|
||||
{:margin-horizontal 20
|
||||
:margin-top 4
|
||||
:margin-bottom 12})
|
||||
{:margin-horizontal 20 :margin-top 4 :margin-bottom 12})
|
||||
|
||||
(def no-pinned-messages-container
|
||||
{:justify-content :center
|
||||
:align-items :center})
|
||||
:align-items :center
|
||||
:margin 12
|
||||
:margin-bottom (when platform/android? 12)})
|
||||
|
||||
(def list-footer
|
||||
{:height (when platform/android? 12)})
|
||||
|
||||
@@ -59,15 +59,12 @@
|
||||
:channel-name (:chat-name current-chat)}])]
|
||||
(if (pos? (count pinned))
|
||||
[rn/flat-list
|
||||
{:data pinned
|
||||
:render-data (assoc render-data
|
||||
:disable-message-long-press?
|
||||
disable-message-long-press?)
|
||||
:render-fn message-render-fn
|
||||
:footer [rn/view {:style style/list-footer}]
|
||||
:content-container-style {:padding-top 8}
|
||||
:key-fn list-key-fn
|
||||
:separator [quo/separator {:style {:margin-vertical 8}}]}]
|
||||
{:data pinned
|
||||
:render-data (assoc render-data :disable-message-long-press? disable-message-long-press?)
|
||||
:render-fn message-render-fn
|
||||
:footer [rn/view {:style style/list-footer}]
|
||||
:key-fn list-key-fn
|
||||
:separator [quo/separator {:style {:margin-vertical 8}}]}]
|
||||
[empty-pinned-messages-state
|
||||
{:theme theme}])]))
|
||||
|
||||
|
||||
@@ -29,15 +29,11 @@
|
||||
|
||||
(defn pinned-message
|
||||
[{:keys [from quoted-message timestamp-str]}]
|
||||
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity from])
|
||||
one-to-one-chat? (rf/sub [:chats/current-chat-one-to-one?])
|
||||
current-chat-color (rf/sub [:chats/current-chat-color])
|
||||
contact-customization-color (rf/sub [:contacts/contact-customization-color-by-address from])]
|
||||
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity from])
|
||||
customization-color (rf/sub [:profile/customization-color])]
|
||||
[quo/system-message
|
||||
{:type :pinned
|
||||
:pinned-by primary-name
|
||||
:customization-color (if one-to-one-chat?
|
||||
contact-customization-color
|
||||
current-chat-color)
|
||||
:customization-color customization-color
|
||||
:child [reply/quoted-message quoted-message false true]
|
||||
:timestamp timestamp-str}]))
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.messages.drawers.view :as drawers]
|
||||
[utils.re-frame :as rf]))
|
||||
@@ -55,7 +54,7 @@
|
||||
(defn- view-internal
|
||||
[{:keys [message-id chat-id pinned-by preview? theme]} user-message-content]
|
||||
(let [reactions (rf/sub [:chats/message-reactions message-id chat-id])]
|
||||
[rn/view {:style {:padding-bottom 12}}
|
||||
[:<>
|
||||
(when (seq reactions)
|
||||
[quo/react
|
||||
{:container-style {:margin-left 44
|
||||
|
||||
@@ -16,17 +16,16 @@
|
||||
(assoc :margin-top 4)))
|
||||
|
||||
(defn user-message-content
|
||||
[{:keys [outgoing outgoing-status six-reactions? window-scale small-screen? in-pinned-view?]}]
|
||||
[{:keys [outgoing outgoing-status six-reactions? window-scale small-screen?]}]
|
||||
{:border-radius 16
|
||||
:padding-horizontal 8
|
||||
:padding-top (if in-pinned-view? 8 4)
|
||||
:padding-bottom (if in-pinned-view?
|
||||
5
|
||||
(when (or small-screen?
|
||||
(and
|
||||
(> 3 window-scale)
|
||||
six-reactions?))
|
||||
(* message-padding-scaling-ratio window-scale)))
|
||||
:padding-top 4
|
||||
:padding-bottom (if (or small-screen?
|
||||
(and
|
||||
(> 3 window-scale)
|
||||
six-reactions?))
|
||||
(* message-padding-scaling-ratio window-scale)
|
||||
4)
|
||||
:opacity (if (and outgoing (= outgoing-status :sending))
|
||||
0.5
|
||||
1)})
|
||||
|
||||
@@ -79,17 +79,16 @@
|
||||
|
||||
(defn system-message-contact-request
|
||||
[{:keys [chat-id timestamp-str from]} type]
|
||||
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity chat-id])
|
||||
{:keys [images]
|
||||
contact-customization-color
|
||||
:customization-color} (rf/sub [:contacts/contact-by-address chat-id])
|
||||
photo-path (when (seq images) (rf/sub [:chats/photo-path chat-id]))
|
||||
public-key (rf/sub [:profile/public-key])]
|
||||
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity chat-id])
|
||||
contact (rf/sub [:contacts/contact-by-address chat-id])
|
||||
photo-path (when (seq (:images contact)) (rf/sub [:chats/photo-path chat-id]))
|
||||
customization-color (rf/sub [:profile/customization-color])
|
||||
public-key (rf/sub [:profile/public-key])]
|
||||
[quo/system-message
|
||||
{:type type
|
||||
:timestamp timestamp-str
|
||||
:display-name primary-name
|
||||
:customization-color contact-customization-color
|
||||
:customization-color customization-color
|
||||
:photo-path photo-path
|
||||
:incoming? (not= public-key from)}]))
|
||||
|
||||
@@ -152,7 +151,7 @@
|
||||
[]
|
||||
(let [show-delivery-state? (reagent/atom false)]
|
||||
(fn [{:keys [message-data context keyboard-shown? show-reactions? in-reaction-and-action-menu?
|
||||
show-user-info? preview? in-pinned-view? theme]}]
|
||||
show-user-info? preview? theme]}]
|
||||
(let [{:keys [content-type quoted-message content outgoing outgoing-status pinned-by pinned
|
||||
last-in-group? message-id chat-id]} message-data
|
||||
{:keys [disable-message-long-press?]} context
|
||||
@@ -195,8 +194,7 @@
|
||||
:outgoing-status outgoing-status
|
||||
:small-screen? rn/small-screen?
|
||||
:window-scale window-scale
|
||||
:six-reactions? six-reactions?
|
||||
:in-pinned-view? in-pinned-view?})
|
||||
:six-reactions? six-reactions?})
|
||||
:on-press (fn []
|
||||
(if (and platform/ios? keyboard-shown?)
|
||||
(do
|
||||
@@ -260,7 +258,7 @@
|
||||
|
||||
(when @show-delivery-state?
|
||||
[status/status outgoing-status])])]
|
||||
(when (and show-reactions? (seq reactions))
|
||||
(when show-reactions?
|
||||
[reactions/message-reactions-row (assoc message-data :preview? preview?)
|
||||
[rn/view {:pointer-events :none}
|
||||
[user-message-content-internal
|
||||
@@ -338,5 +336,4 @@
|
||||
{:message-data message-data
|
||||
:context context
|
||||
:keyboard-shown? keyboard-shown?
|
||||
:show-reactions? true
|
||||
:in-pinned-view? in-pinned-view?}])]))
|
||||
:show-reactions? true}])]))
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
[react-native.gesture :as gesture]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.contact-list-item.view :as contact-list-item]
|
||||
[status-im.config :as config]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.composer.reply.view :as reply]
|
||||
[status-im.contexts.chat.messenger.messages.drawers.style :as style]
|
||||
@@ -141,7 +140,7 @@
|
||||
(rf/dispatch
|
||||
[:hide-bottom-sheet])
|
||||
(rf/dispatch [:chat.ui/delete-message-for-me message-data
|
||||
config/delete-message-for-me-undo-time-limit-ms]))
|
||||
constants/delete-message-for-me-undo-time-limit-ms]))
|
||||
|
||||
:label (i18n/label :t/delete-for-me)
|
||||
:icon :i/delete
|
||||
@@ -156,7 +155,7 @@
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch [:chat.ui/delete-message message-data
|
||||
config/delete-message-undo-time-limit-ms]))
|
||||
constants/delete-message-undo-time-limit-ms]))
|
||||
:label (i18n/label :t/delete-for-everyone)
|
||||
:icon :i/delete
|
||||
:id :delete-for-all}])))
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
(ns status-im.contexts.chat.messenger.messages.list.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[quo.foundations.shadows :as shadows]
|
||||
[quo.theme :as quo.theme]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.contexts.chat.messenger.messages.constants :as messages.constants]))
|
||||
|
||||
@@ -25,12 +23,10 @@
|
||||
[bottom theme top-margin]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:bottom bottom}
|
||||
(merge
|
||||
(shadows/get 2 (quo.theme/get-theme) :inverted)
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
|
||||
:padding-horizontal 20
|
||||
:border-radius 20
|
||||
:margin-top top-margin})))
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-95 theme)
|
||||
:padding-horizontal 20
|
||||
:border-radius 20
|
||||
:margin-top top-margin}))
|
||||
|
||||
(defn header-image
|
||||
[scale top left theme]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns status-im.contexts.chat.messenger.messages.list.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.ui.screens.chat.group :as chat.group]
|
||||
[oops.core :as oops]
|
||||
[quo.core :as quo]
|
||||
@@ -113,24 +112,19 @@
|
||||
[rn/view {:style {:height height}}]))
|
||||
|
||||
(defn list-footer-avatar
|
||||
[{:keys [distance-from-list-top display-name online? profile-picture theme group-chat color
|
||||
emoji chat-type chat-name last-message]}]
|
||||
(let [scale (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[0 (if (seq last-message) messages.constants/header-container-top-margin 0)]
|
||||
[1 0.4]
|
||||
messages.constants/default-extrapolation-option)
|
||||
top (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[0 (if (seq last-message) messages.constants/header-container-top-margin 0)]
|
||||
[-44 -12]
|
||||
messages.constants/default-extrapolation-option)
|
||||
left (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[0 (if (seq last-message) messages.constants/header-container-top-margin 0)]
|
||||
[16 -8]
|
||||
messages.constants/default-extrapolation-option)
|
||||
community-channel? (= chat-type constants/community-chat-type)]
|
||||
[{:keys [distance-from-list-top display-name online? profile-picture theme group-chat color]}]
|
||||
(let [scale (reanimated/interpolate distance-from-list-top
|
||||
[0 messages.constants/header-container-top-margin]
|
||||
[1 0.4]
|
||||
messages.constants/default-extrapolation-option)
|
||||
top (reanimated/interpolate distance-from-list-top
|
||||
[0 messages.constants/header-container-top-margin]
|
||||
[-44 -12]
|
||||
messages.constants/default-extrapolation-option)
|
||||
left (reanimated/interpolate distance-from-list-top
|
||||
[0 messages.constants/header-container-top-margin]
|
||||
[16 -8]
|
||||
messages.constants/default-extrapolation-option)]
|
||||
[reanimated/view
|
||||
{:style (style/header-image scale top left theme)}
|
||||
(if group-chat
|
||||
@@ -138,10 +132,7 @@
|
||||
{:customization-color color
|
||||
:size :size-80
|
||||
:picture profile-picture
|
||||
:emoji (when (and (not (string/blank? emoji))
|
||||
community-channel?)
|
||||
(string/trim emoji))
|
||||
:chat-name chat-name}]
|
||||
:override-theme :dark}]
|
||||
[quo/user-avatar
|
||||
{:full-name display-name
|
||||
:online? online?
|
||||
@@ -149,17 +140,15 @@
|
||||
:size :big}])]))
|
||||
|
||||
(defn chat-display-name
|
||||
[{:keys [distance-from-list-top display-name contact theme last-message]}]
|
||||
(let [top (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[0 (if (seq last-message) messages.constants/header-container-top-margin 0)]
|
||||
[0 -35]
|
||||
messages.constants/default-extrapolation-option)
|
||||
left (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[0 (if (seq last-message) messages.constants/header-container-top-margin 0)]
|
||||
[0 40]
|
||||
messages.constants/default-extrapolation-option)]
|
||||
[{:keys [distance-from-list-top display-name contact theme]}]
|
||||
(let [top (reanimated/interpolate distance-from-list-top
|
||||
[0 messages.constants/header-container-top-margin]
|
||||
[0 -35]
|
||||
messages.constants/default-extrapolation-option)
|
||||
left (reanimated/interpolate distance-from-list-top
|
||||
[0 messages.constants/header-container-top-margin]
|
||||
[0 40]
|
||||
messages.constants/default-extrapolation-option)]
|
||||
[reanimated/view
|
||||
{:style (style/user-name-container top left)}
|
||||
[rn/view
|
||||
@@ -206,55 +195,54 @@
|
||||
muted?)))}]}]))
|
||||
|
||||
(defn bio-and-actions
|
||||
[{:keys [distance-from-list-top bio chat-id customization-color last-message description]}]
|
||||
(let [has-bio (seq (or bio description))
|
||||
[{:keys [distance-from-list-top bio chat-id customization-color]}]
|
||||
(let [has-bio (seq bio)
|
||||
top (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[0 (if (seq last-message) messages.constants/header-container-top-margin 0)]
|
||||
[0 messages.constants/header-container-top-margin]
|
||||
[(if has-bio 8 16) (if has-bio -28 -20)]
|
||||
messages.constants/default-extrapolation-option)]
|
||||
[reanimated/view
|
||||
{:style (style/bio-and-actions top)}
|
||||
(when has-bio
|
||||
[quo/text (or bio description)])
|
||||
[quo/text bio])
|
||||
[actions chat-id customization-color]]))
|
||||
|
||||
(defn footer-component
|
||||
[{:keys [chat distance-from-list-top theme customization-color]}]
|
||||
(let [{:keys [chat-id chat-name emoji chat-type
|
||||
group-chat color description
|
||||
last-message]} chat
|
||||
display-name (cond
|
||||
(= chat-type constants/one-to-one-chat-type)
|
||||
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
|
||||
(= chat-type constants/community-chat-type)
|
||||
(str "# " chat-name)
|
||||
:else (str emoji chat-name))
|
||||
{:keys [bio]} (rf/sub [:contacts/contact-by-identity chat-id])
|
||||
online? (rf/sub [:visibility-status-updates/online? chat-id])
|
||||
contact (when-not group-chat
|
||||
(rf/sub [:contacts/contact-by-address chat-id]))
|
||||
photo-path (rf/sub [:chats/photo-path chat-id])
|
||||
top-margin (+ (safe-area/get-top)
|
||||
messages.constants/top-bar-height
|
||||
messages.constants/header-container-top-margin
|
||||
32)
|
||||
background-color (colors/theme-colors
|
||||
(colors/resolve-color customization-color theme 20)
|
||||
(colors/resolve-color customization-color theme 40)
|
||||
theme)
|
||||
bottom (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[0 messages.constants/header-container-top-margin]
|
||||
[32 -4]
|
||||
messages.constants/default-extrapolation-option)
|
||||
background-opacity (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[messages.constants/header-container-top-margin
|
||||
(+ messages.constants/header-animation-distance
|
||||
messages.constants/header-container-top-margin)]
|
||||
[1 0]
|
||||
messages.constants/default-extrapolation-option)]
|
||||
group-chat color]} chat
|
||||
display-name (cond
|
||||
(= chat-type constants/one-to-one-chat-type)
|
||||
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
|
||||
(= chat-type constants/community-chat-type)
|
||||
(str (when emoji (str emoji " ")) "# " chat-name)
|
||||
:else (str emoji chat-name))
|
||||
{:keys [bio]} (rf/sub [:contacts/contact-by-identity chat-id])
|
||||
online? (rf/sub [:visibility-status-updates/online? chat-id])
|
||||
contact (when-not group-chat
|
||||
(rf/sub [:contacts/contact-by-address chat-id]))
|
||||
photo-path (rf/sub [:chats/photo-path chat-id])
|
||||
top-margin (+ (safe-area/get-top)
|
||||
messages.constants/top-bar-height
|
||||
messages.constants/header-container-top-margin
|
||||
32)
|
||||
background-color (colors/theme-colors
|
||||
(colors/resolve-color customization-color theme 20)
|
||||
(colors/resolve-color customization-color theme 40)
|
||||
theme)
|
||||
bottom (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[0 messages.constants/header-container-top-margin]
|
||||
[32 -4]
|
||||
messages.constants/default-extrapolation-option)
|
||||
background-opacity (reanimated/interpolate
|
||||
distance-from-list-top
|
||||
[messages.constants/header-container-top-margin
|
||||
(+ messages.constants/header-animation-distance
|
||||
messages.constants/header-container-top-margin)]
|
||||
[1 0]
|
||||
messages.constants/default-extrapolation-option)]
|
||||
[:<>
|
||||
[reanimated/view
|
||||
{:style (style/background-container background-color background-opacity top-margin)}]
|
||||
@@ -266,25 +254,18 @@
|
||||
:theme theme
|
||||
:profile-picture photo-path
|
||||
:group-chat group-chat
|
||||
:color color
|
||||
:emoji emoji
|
||||
:chat-type chat-type
|
||||
:chat-name chat-name
|
||||
:last-message last-message}]
|
||||
:color color}]
|
||||
[chat-display-name
|
||||
{:distance-from-list-top distance-from-list-top
|
||||
:display-name display-name
|
||||
:theme theme
|
||||
:contact contact
|
||||
:group-chat group-chat
|
||||
:last-message last-message}]
|
||||
:group-chat group-chat}]
|
||||
[bio-and-actions
|
||||
{:distance-from-list-top distance-from-list-top
|
||||
:bio bio
|
||||
:chat-id chat-id
|
||||
:customization-color customization-color
|
||||
:description description
|
||||
:last-message last-message}]]]))
|
||||
:customization-color customization-color}]]]))
|
||||
|
||||
(defn list-footer
|
||||
[props]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
(ns status-im.contexts.chat.messenger.messages.navigation.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
[re-frame.db]
|
||||
@@ -29,7 +28,7 @@
|
||||
[:contacts/contact-two-names-by-identity
|
||||
chat-id]))
|
||||
(= chat-type constants/community-chat-type)
|
||||
(str "# " chat-name)
|
||||
(str (when emoji (str emoji " ")) "# " chat-name)
|
||||
:else (str emoji chat-name))
|
||||
online? (when-not group-chat (rf/sub [:visibility-status-updates/online? chat-id]))
|
||||
photo-path (when-not group-chat (rf/sub [:chats/photo-path chat-id]))
|
||||
@@ -54,10 +53,7 @@
|
||||
{:customization-color color
|
||||
:size :size-32
|
||||
:picture photo-path
|
||||
:override-theme :dark
|
||||
:emoji (when-not (string/blank? emoji)
|
||||
(string/trim emoji))
|
||||
:chat-name chat-name}]
|
||||
:override-theme :dark}]
|
||||
[quo/user-avatar
|
||||
{:full-name display-name
|
||||
:online? online?
|
||||
@@ -115,29 +111,27 @@
|
||||
|
||||
(defn view
|
||||
[{:keys [distance-from-list-top chat-screen-layout-calculations-complete?]}]
|
||||
(let [{:keys [chat-id chat-type last-message]
|
||||
:as chat} (rf/sub [:chats/current-chat-chat-view])
|
||||
all-loaded? (reanimated/use-shared-value false)
|
||||
all-loaded-sub (rf/sub [:chats/all-loaded? chat-id])
|
||||
top-insets (safe-area/get-top)
|
||||
top-bar-height messages.constants/top-bar-height
|
||||
navigation-view-height (+ top-bar-height top-insets)
|
||||
navigation-buttons-opacity (worklets/navigation-buttons-complete-opacity
|
||||
chat-screen-layout-calculations-complete?)
|
||||
reached-threshold? (messages.worklets/use-messages-scrolled-to-threshold
|
||||
distance-from-list-top
|
||||
top-bar-height)
|
||||
button-background (if reached-threshold? :photo :blur)]
|
||||
(let [{:keys [chat-id chat-type] :as chat} (rf/sub [:chats/current-chat-chat-view])
|
||||
all-loaded? (reanimated/use-shared-value false)
|
||||
all-loaded-sub (rf/sub [:chats/all-loaded? chat-id])
|
||||
top-insets (safe-area/get-top)
|
||||
top-bar-height messages.constants/top-bar-height
|
||||
navigation-view-height (+ top-bar-height top-insets)
|
||||
navigation-buttons-opacity (worklets/navigation-buttons-complete-opacity
|
||||
chat-screen-layout-calculations-complete?)
|
||||
reached-threshold? (messages.worklets/use-messages-scrolled-to-threshold
|
||||
distance-from-list-top
|
||||
top-bar-height)
|
||||
button-background (if reached-threshold? :photo :blur)]
|
||||
(rn/use-effect (fn [] (reanimated/set-shared-value all-loaded? all-loaded-sub))
|
||||
[all-loaded-sub])
|
||||
[rn/view
|
||||
{:style (style/navigation-view navigation-view-height messages.constants/pinned-banner-height)}
|
||||
(when (seq last-message)
|
||||
[animated-background-and-pinned-banner
|
||||
{:chat-id chat-id
|
||||
:navigation-view-height navigation-view-height
|
||||
:distance-from-list-top distance-from-list-top
|
||||
:all-loaded? all-loaded?}])
|
||||
[animated-background-and-pinned-banner
|
||||
{:chat-id chat-id
|
||||
:navigation-view-height navigation-view-height
|
||||
:distance-from-list-top distance-from-list-top
|
||||
:all-loaded? all-loaded?}]
|
||||
[rn/view {:style (style/header-container top-insets top-bar-height)}
|
||||
[reanimated/view {:style (style/button-animation-container navigation-buttons-opacity)}
|
||||
[quo/button
|
||||
|
||||
@@ -130,9 +130,6 @@
|
||||
[cofx chat-id]
|
||||
(navigation/show-bottom-sheet
|
||||
cofx
|
||||
{:padding-bottom-override 21
|
||||
:content (fn [] [pinned-messages-menu/view
|
||||
{:chat-id chat-id
|
||||
:disable-message-long-press? (not= :chat
|
||||
(get-in cofx
|
||||
[:db :view-id]))}])}))
|
||||
{:content (fn [] [pinned-messages-menu/view
|
||||
{:chat-id chat-id
|
||||
:disable-message-long-press? (not= :chat (get-in cofx [:db :view-id]))}])}))
|
||||
|
||||
@@ -31,5 +31,5 @@
|
||||
|
||||
(def divider
|
||||
{:padding-horizontal 20
|
||||
:margin-top 12
|
||||
:margin-top 16
|
||||
:margin-bottom 8})
|
||||
|
||||
@@ -53,8 +53,7 @@
|
||||
[{:keys [title]}]
|
||||
(when-not (= title no-title)
|
||||
[quo/divider-label
|
||||
{:container-style style/divider
|
||||
:tight? false}
|
||||
{:container-style style/divider}
|
||||
title]))
|
||||
|
||||
(defn key-fn
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
[bottom-inset]
|
||||
{:left 0
|
||||
:right 0
|
||||
:height (+ bottom-inset (if platform/ios? 51 85))
|
||||
:height (+ bottom-inset (if platform/ios? 65 85))
|
||||
:position :absolute
|
||||
:bottom 0})
|
||||
|
||||
|
||||
@@ -73,25 +73,19 @@
|
||||
|
||||
(defn check-permissions-to-join-for-selection
|
||||
[{:keys [db]} [community-id addresses]]
|
||||
(let [request-id (rand-int 10000000)]
|
||||
(if (empty? addresses)
|
||||
;; When there are no addresses we can't just check permissions, otherwise
|
||||
;; status-go will consider all possible addresses and the user will see the
|
||||
;; incorrect highest permission role.
|
||||
{:db (update db :communities/permissions-checks-for-selection dissoc community-id)}
|
||||
{:db (update-in db
|
||||
[:communities/permissions-checks-for-selection community-id]
|
||||
assoc
|
||||
:checking? true
|
||||
:latest-request-id request-id)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method :wakuext_checkPermissionsToJoinCommunity
|
||||
:params [{:communityId community-id :addresses addresses}]
|
||||
:id request-id
|
||||
:on-success [:communities/check-permissions-to-join-during-selection-success
|
||||
community-id]
|
||||
:on-error [:communities/check-permissions-to-join-during-selection-failure
|
||||
community-id addresses]}]]]})))
|
||||
(if (empty? addresses)
|
||||
;; When there are no addresses we can't just check permissions, otherwise
|
||||
;; status-go will consider all possible addresses and the user will see the
|
||||
;; incorrect highest permission role.
|
||||
{:db (update db :communities/permissions-checks-for-selection dissoc community-id)}
|
||||
{:db (assoc-in db [:communities/permissions-checks-for-selection community-id :checking?] true)
|
||||
:fx [[:json-rpc/call
|
||||
[{:method :wakuext_checkPermissionsToJoinCommunity
|
||||
:params [{:communityId community-id :addresses addresses}]
|
||||
:on-success [:communities/check-permissions-to-join-during-selection-success
|
||||
community-id]
|
||||
:on-error [:communities/check-permissions-to-join-during-selection-failure
|
||||
community-id addresses]}]]]}))
|
||||
|
||||
;; This event should be used to check permissions temporarily because it won't
|
||||
;; mutate the state `:communities/permissions-check` (used by many other
|
||||
@@ -100,14 +94,12 @@
|
||||
check-permissions-to-join-for-selection)
|
||||
|
||||
(rf/reg-event-fx :communities/check-permissions-to-join-during-selection-success
|
||||
(fn [{:keys [db]} [community-id result request-id]]
|
||||
(when (= (get-in db [:communities/permissions-checks-for-selection community-id :latest-request-id])
|
||||
request-id)
|
||||
{:db (assoc-in db
|
||||
[:communities/permissions-checks-for-selection community-id]
|
||||
{:checking? false
|
||||
:based-on-client-selection? true
|
||||
:check result})})))
|
||||
(fn [{:keys [db]} [community-id result]]
|
||||
{:db (assoc-in db
|
||||
[:communities/permissions-checks-for-selection community-id]
|
||||
{:checking? false
|
||||
:based-on-client-selection? true
|
||||
:check result})}))
|
||||
|
||||
(rf/reg-event-fx :communities/check-permissions-to-join-during-selection-failure
|
||||
(fn [_ [community-id addresses error]]
|
||||
|
||||
@@ -112,14 +112,12 @@
|
||||
|
||||
(defn actions
|
||||
[{:keys [locked? chat-id community-id]} inside-chat? hide-view-members?]
|
||||
(let [{:keys [muted muted-till chat-type]} (rf/sub [:chats/chat-by-id chat-id])
|
||||
{:keys [token-gated?]} (rf/sub [:chats/community-chat-by-id community-id chat-id])]
|
||||
(let [{:keys [muted muted-till chat-type]} (rf/sub [:chats/chat-by-id chat-id])]
|
||||
(cond
|
||||
locked?
|
||||
[quo/action-drawer
|
||||
[[(action-invite-people)
|
||||
(when token-gated?
|
||||
(action-token-requirements))
|
||||
(action-token-requirements)
|
||||
(action-qr-code chat-id)
|
||||
(action-share chat-id)]]]
|
||||
|
||||
@@ -137,8 +135,7 @@
|
||||
(and inside-chat? (not locked?))
|
||||
[quo/action-drawer
|
||||
[[(action-view-members-and-details community-id chat-id)
|
||||
(when token-gated?
|
||||
(action-token-requirements))
|
||||
(action-token-requirements)
|
||||
(action-mark-as-read)
|
||||
(action-toggle-muted chat-id muted muted-till chat-type)
|
||||
(action-notification-settings)
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
(h/test "joined options - Token Gated"
|
||||
(h/setup-subs {:communities/my-pending-request-to-join nil
|
||||
:communities/community {:joined true
|
||||
:role-permissions? true}})
|
||||
:token-permissions []}})
|
||||
(h/render [options/community-options-bottom-sheet {:id "test"}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/view-members))
|
||||
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
|
||||
@@ -52,7 +52,7 @@
|
||||
(h/test "admin options - Token Gated"
|
||||
(h/setup-subs {:communities/my-pending-request-to-join nil
|
||||
:communities/community {:admin true
|
||||
:role-permissions? true}})
|
||||
:token-permissions []}})
|
||||
(h/render [options/community-options-bottom-sheet {:id "test"}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/view-members))
|
||||
(h/is-truthy (h/get-by-translation-text :t/view-community-rules))
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
(h/test "request sent options - Token Gated"
|
||||
(h/setup-subs {:communities/my-pending-request-to-join "mock-id"
|
||||
:communities/community {:role-permissions? true}})
|
||||
:communities/community {:token-permissions []}})
|
||||
(h/render [options/community-options-bottom-sheet {:id "test"}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
|
||||
(h/is-truthy (h/get-by-translation-text :t/view-token-gating))
|
||||
@@ -97,7 +97,7 @@
|
||||
(h/test "banned options - Token Gated"
|
||||
(h/setup-subs {:communities/my-pending-request-to-join nil
|
||||
:communities/community {:banList 100
|
||||
:role-permissions? true}})
|
||||
:token-permissions []}})
|
||||
(h/render [options/community-options-bottom-sheet {:id "test"}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
|
||||
(h/is-truthy (h/get-by-translation-text :t/view-token-gating))
|
||||
@@ -107,7 +107,7 @@
|
||||
(h/test "banned options - Token Gated"
|
||||
(h/setup-subs {:communities/my-pending-request-to-join nil
|
||||
:communities/community {:banList 100
|
||||
:role-permissions? true}})
|
||||
:token-permissions []}})
|
||||
(h/render [options/community-options-bottom-sheet {:id "test"}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/invite-people-from-contacts))
|
||||
(h/is-truthy (h/get-by-translation-text :t/view-token-gating))
|
||||
@@ -118,6 +118,6 @@
|
||||
(h/setup-subs {:communities/my-pending-request-to-join nil
|
||||
:communities/community {:joined true
|
||||
:muted true
|
||||
:role-permissions? true}})
|
||||
:token-permissions []}})
|
||||
(h/render [options/community-options-bottom-sheet {:id "test"}])
|
||||
(h/is-truthy (h/get-by-translation-text :t/unmute-community))))
|
||||
|
||||
@@ -180,16 +180,16 @@
|
||||
|
||||
(defn get-context-drawers
|
||||
[{:keys [id]}]
|
||||
(let [{:keys [role-permissions? admin joined
|
||||
(let [{:keys [token-permissions admin joined
|
||||
muted banList muted-till color
|
||||
intro-message]} (rf/sub [:communities/community id])
|
||||
request-id (rf/sub [:communities/my-pending-request-to-join id])]
|
||||
(cond
|
||||
admin (owner-options id role-permissions? muted muted-till intro-message)
|
||||
joined (joined-options id role-permissions? muted muted-till color intro-message)
|
||||
request-id (join-request-sent-options id role-permissions? request-id intro-message)
|
||||
banList (banned-options id role-permissions? intro-message)
|
||||
:else (not-joined-options id role-permissions? request-id intro-message))))
|
||||
admin (owner-options id token-permissions muted muted-till intro-message)
|
||||
joined (joined-options id token-permissions muted muted-till color intro-message)
|
||||
request-id (join-request-sent-options id token-permissions request-id intro-message)
|
||||
banList (banned-options id token-permissions intro-message)
|
||||
:else (not-joined-options id token-permissions request-id intro-message))))
|
||||
|
||||
(defn community-options-bottom-sheet
|
||||
[id]
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
(ns status-im.contexts.communities.actions.invite-contacts.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
|
||||
(def contact-selection-heading
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :flex-end
|
||||
:margin-top 24
|
||||
:margin-bottom 16})
|
||||
|
||||
(def chat-button
|
||||
{:position :absolute
|
||||
:bottom (safe-area/get-bottom)
|
||||
:left 20
|
||||
:right 20})
|
||||
|
||||
(defn no-contacts
|
||||
[]
|
||||
{:margin-bottom (+ 96 (safe-area/get-bottom))
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(def context-tag
|
||||
{:align-self :flex-start
|
||||
:margin-top -8
|
||||
:margin-bottom 12})
|
||||
|
||||
(def no-contacts-text
|
||||
{:margin-bottom 2
|
||||
:margin-top 12})
|
||||
|
||||
(def no-contacts-button-container
|
||||
{:margin-top 20
|
||||
:margin-bottom 12})
|
||||
|
||||
(defn section-list-container-style
|
||||
[theme]
|
||||
{:padding-bottom 70
|
||||
:background-color (colors/theme-colors colors/white
|
||||
colors/neutral-95
|
||||
theme)})
|
||||
|
||||
(defn invite-to-community-text
|
||||
[theme]
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white theme)})
|
||||
@@ -1,141 +0,0 @@
|
||||
(ns status-im.contexts.communities.actions.invite-contacts.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.resources :as resources]
|
||||
[quo.theme]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.share :as share]
|
||||
[status-im.common.contact-list-item.view :as contact-list-item]
|
||||
[status-im.common.contact-list.view :as contact-list]
|
||||
[status-im.contexts.communities.actions.invite-contacts.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- no-contacts-view
|
||||
[{:keys [theme id]}]
|
||||
(let [customization-color (rf/sub [:profile/customization-color])
|
||||
{:keys [universal-profile-url]} (rf/sub [:profile/profile])
|
||||
on-press-share-community (rn/use-callback
|
||||
#(rf/dispatch [:communities/share-community-url-with-data
|
||||
id]))
|
||||
on-press-share-profile (rn/use-callback #(share/open {:url universal-profile-url})
|
||||
[universal-profile-url])]
|
||||
[rn/view
|
||||
{:style (style/no-contacts)}
|
||||
[rn/image {:source (resources/get-themed-image :no-contacts-to-chat theme)}]
|
||||
[quo/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-1
|
||||
:style style/no-contacts-text}
|
||||
(i18n/label :t/you-have-no-contacts)]
|
||||
[quo/text
|
||||
{:weight :regular
|
||||
:size :paragraph-2}
|
||||
(i18n/label :t/dont-yell-at-me)]
|
||||
[quo/button
|
||||
{:customization-color customization-color
|
||||
:theme theme
|
||||
:type :primary
|
||||
:size 32
|
||||
:container-style style/no-contacts-button-container
|
||||
:on-press on-press-share-community}
|
||||
(i18n/label :t/send-community-link)]
|
||||
[quo/button
|
||||
{:customization-color customization-color
|
||||
:theme theme
|
||||
:type :grey
|
||||
:size 32
|
||||
:on-press on-press-share-profile}
|
||||
(i18n/label :t/invite-friends-to-status)]]))
|
||||
|
||||
(defn- contact-item
|
||||
[{:keys [public-key]
|
||||
:as item}]
|
||||
(let [user-selected? (rf/sub [:is-contact-selected? public-key])
|
||||
{:keys [id]} (rf/sub [:get-screen-params])
|
||||
community-members-keys (set (keys (rf/sub [:communities/community-members id])))
|
||||
community-member? (boolean (community-members-keys public-key))
|
||||
on-toggle (fn []
|
||||
(when-not community-member?
|
||||
(if user-selected?
|
||||
(rf/dispatch [:deselect-contact public-key])
|
||||
(rf/dispatch [:select-contact public-key]))))]
|
||||
[contact-list-item/contact-list-item
|
||||
{:on-press on-toggle
|
||||
:allow-multiple-presses? true
|
||||
:accessory {:type :checkbox
|
||||
:disabled? community-member?
|
||||
:checked? (or community-member? user-selected?)
|
||||
:on-check on-toggle}
|
||||
:disabled? community-member?}
|
||||
item]))
|
||||
|
||||
(defn view-internal
|
||||
[{:keys [theme]}]
|
||||
(fn []
|
||||
(rn/use-unmount #(rf/dispatch [:group-chat/clear-contacts]))
|
||||
(let [customization-color (rf/sub [:profile/customization-color])
|
||||
{:keys [id]} (rf/sub [:get-screen-params])
|
||||
contacts (rf/sub [:contacts/filtered-active-sections])
|
||||
selected (rf/sub [:group/selected-contacts])
|
||||
{:keys [name images]} (rf/sub [:communities/community id])
|
||||
selected-contacts-count (count selected)
|
||||
on-press (fn []
|
||||
(rf/dispatch [:communities/share-community-confirmation-pressed
|
||||
selected id])
|
||||
(rf/dispatch [:navigate-back])
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:type :positive
|
||||
:theme theme
|
||||
:text (if (= 1 selected-contacts-count)
|
||||
(i18n/label :t/one-user-was-invited)
|
||||
(i18n/label
|
||||
:t/n-users-were-invited
|
||||
{:count selected-contacts-count}))}]))
|
||||
{window-height :height} (rn/get-window)]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[rn/view {:style {:padding-horizontal 20}}
|
||||
[quo/button
|
||||
{:type :grey
|
||||
:size 32
|
||||
:icon-only? true
|
||||
:on-press #(rf/dispatch [:navigate-back])}
|
||||
:i/close]
|
||||
[rn/view {:style style/contact-selection-heading}
|
||||
[quo/text
|
||||
{:weight :semi-bold
|
||||
:size :heading-1
|
||||
:style (style/invite-to-community-text theme)}
|
||||
(i18n/label :t/invite-to-community)]]
|
||||
[quo/context-tag
|
||||
{:type :community
|
||||
:size 24
|
||||
:community-logo (:thumbnail images)
|
||||
:community-name name
|
||||
:container-style style/context-tag}]]
|
||||
(if (empty? contacts)
|
||||
[no-contacts-view
|
||||
{:theme theme
|
||||
:id id}]
|
||||
[:<>
|
||||
[gesture/section-list
|
||||
{:key-fn :public-key
|
||||
:sticky-section-headers-enabled true
|
||||
:sections contacts
|
||||
:render-section-header-fn contact-list/contacts-section-header
|
||||
:content-container-style (style/section-list-container-style theme)
|
||||
:render-fn contact-item
|
||||
:style {:height window-height}}]
|
||||
(when (pos? selected-contacts-count)
|
||||
[quo/button
|
||||
{:type :primary
|
||||
:accessibility-label :next-button
|
||||
:customization-color customization-color
|
||||
:container-style style/chat-button
|
||||
:on-press on-press}
|
||||
(if (= 1 selected-contacts-count)
|
||||
(i18n/label :t/invite-1-user)
|
||||
(i18n/label :t/invite-n-users {:count selected-contacts-count}))])])])))
|
||||
|
||||
(def view (quo.theme/with-theme view-internal))
|
||||
@@ -0,0 +1,5 @@
|
||||
(ns status-im.contexts.communities.actions.permissions-sheet.style)
|
||||
|
||||
(def container
|
||||
{:flex 1
|
||||
:padding-horizontal 20})
|
||||
@@ -1,12 +1,38 @@
|
||||
(ns status-im.contexts.communities.actions.permissions-sheet.view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[status-im.contexts.communities.actions.permissions-sheet.style :as style]
|
||||
[status-im.contexts.communities.utils :as communities.utils]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn- role-text
|
||||
[role]
|
||||
(i18n/label
|
||||
(communities.utils/role->translation-key role
|
||||
:t/token-master)))
|
||||
|
||||
(defn- permission-view
|
||||
[{:keys [tokens role satisfied?]}]
|
||||
(when (seq tokens)
|
||||
^{:key role}
|
||||
[rn/view {:style {:margin-bottom 20}}
|
||||
[quo/text {:weight :medium}
|
||||
(if satisfied?
|
||||
(i18n/label :t/you-eligible-to-join-as {:role (role-text role)})
|
||||
(i18n/label :t/you-not-eligible-to-join-as {:role (role-text role)}))]
|
||||
[quo/text {:size :paragraph-2 :style {:padding-bottom 8}}
|
||||
(if satisfied?
|
||||
(i18n/label :t/you-hodl)
|
||||
(i18n/label :t/you-must-hold))]
|
||||
[quo/token-requirement-list
|
||||
{:tokens tokens
|
||||
:container-style {:padding-horizontal 20}}]]))
|
||||
|
||||
(defn view
|
||||
[id]
|
||||
(let [permissions (rf/sub [:community/token-permissions id])]
|
||||
[gesture/scroll-view
|
||||
[quo/community-detail-token-gating {:permissions permissions}]
|
||||
]))
|
||||
[gesture/scroll-view {:style style/container}
|
||||
(map permission-view permissions)]))
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
(ns status-im.contexts.communities.events
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[legacy.status-im.data-store.chats :as data-store.chats]
|
||||
[legacy.status-im.data-store.communities :as data-store.communities]
|
||||
[legacy.status-im.mailserver.core :as mailserver]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.share :as share]
|
||||
[schema.core :as schema]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.messages.link-preview.events :as link-preview.events]
|
||||
@@ -11,9 +14,9 @@
|
||||
status-im.contexts.communities.actions.airdrop-addresses.events
|
||||
status-im.contexts.communities.actions.community-options.events
|
||||
status-im.contexts.communities.actions.leave.events
|
||||
[status-im.contexts.communities.utils :as utils]
|
||||
[status-im.navigation.events :as navigation]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn handle-community
|
||||
@@ -149,83 +152,43 @@
|
||||
:on-success #(rf/dispatch [:communities/fetched-collapsed-categories-success %])
|
||||
:on-error #(log/error "failed to fetch collapsed community categories" %)}]}))
|
||||
|
||||
(defn update-previous-permission-addresses
|
||||
[{:keys [db]} [community-id]]
|
||||
(when community-id
|
||||
(let [accounts (utils/sorted-non-watch-only-accounts db)
|
||||
selected-permission-addresses (get-in db
|
||||
[:communities community-id
|
||||
:selected-permission-addresses])
|
||||
selected-accounts (filter #(contains? selected-permission-addresses (:address %))
|
||||
accounts)
|
||||
current-airdrop-address (get-in db [:communities community-id :airdrop-address])
|
||||
share-all-addresses? (get-in db [:communities community-id :share-all-addresses?])]
|
||||
{:db (update-in db
|
||||
[:communities community-id]
|
||||
assoc
|
||||
:previous-share-all-addresses? share-all-addresses?
|
||||
:previous-permission-addresses selected-permission-addresses
|
||||
:airdrop-address (if (contains? selected-permission-addresses
|
||||
current-airdrop-address)
|
||||
current-airdrop-address
|
||||
(:address (first selected-accounts))))})))
|
||||
(rf/reg-event-fx :communities/get-community-channel-share-data
|
||||
(fn [_ [chat-id on-success]]
|
||||
(let [{:keys [community-id channel-id]} (data-store.chats/decode-chat-id chat-id)]
|
||||
{:json-rpc/call
|
||||
[{:method "wakuext_shareCommunityChannelURLWithData"
|
||||
:params [{:CommunityID community-id :ChannelID channel-id}]
|
||||
:on-success on-success
|
||||
:on-error (fn [err]
|
||||
(log/error "failed to retrieve community channel url with data"
|
||||
{:error err
|
||||
:chat-id chat-id
|
||||
:event :communities/get-community-channel-share-data}))}]})))
|
||||
|
||||
(rf/reg-event-fx :communities/update-previous-permission-addresses
|
||||
update-previous-permission-addresses)
|
||||
(rf/reg-event-fx :communities/share-community-channel-url-with-data
|
||||
(fn [_ [chat-id]]
|
||||
(let [title (i18n/label :t/channel-on-status)
|
||||
on-success (fn [url]
|
||||
(share/open
|
||||
(if platform/ios?
|
||||
{:activityItemSources [{:placeholderItem {:type "text"
|
||||
:content title}
|
||||
:item {:default {:type "url"
|
||||
:content url}}
|
||||
:linkMetadata {:title title}}]}
|
||||
{:title title
|
||||
:subject title
|
||||
:message url
|
||||
:url url
|
||||
:isNewTask true})))]
|
||||
{:fx [[:dispatch [:communities/get-community-channel-share-data chat-id on-success]]]})))
|
||||
|
||||
(defn toggle-selected-permission-address
|
||||
[{:keys [db]} [address community-id]]
|
||||
(let [selected-permission-addresses
|
||||
(get-in db [:communities community-id :selected-permission-addresses])
|
||||
updated-selected-permission-addresses
|
||||
(if (contains? selected-permission-addresses address)
|
||||
(disj selected-permission-addresses address)
|
||||
(conj selected-permission-addresses address))]
|
||||
{:db (assoc-in db
|
||||
[:communities community-id :selected-permission-addresses]
|
||||
updated-selected-permission-addresses)
|
||||
:fx [(when community-id
|
||||
[:dispatch
|
||||
[:communities/check-permissions-to-join-community community-id
|
||||
updated-selected-permission-addresses :based-on-client-selection]])]}))
|
||||
|
||||
(rf/reg-event-fx :communities/toggle-selected-permission-address
|
||||
toggle-selected-permission-address)
|
||||
|
||||
(defn toggle-share-all-addresses
|
||||
[{:keys [db]} [community-id]]
|
||||
(let [share-all-addresses? (get-in db [:communities community-id :share-all-addresses?])
|
||||
next-share-all-addresses? (not share-all-addresses?)
|
||||
accounts (utils/sorted-non-watch-only-accounts db)
|
||||
addresses (set (map :address accounts))]
|
||||
{:db (update-in db
|
||||
[:communities community-id]
|
||||
assoc
|
||||
:share-all-addresses? next-share-all-addresses?
|
||||
:selected-permission-addresses addresses)
|
||||
:fx [(when (and community-id next-share-all-addresses?)
|
||||
[:dispatch
|
||||
[:communities/check-permissions-to-join-community community-id
|
||||
addresses :based-on-client-selection]])]}))
|
||||
|
||||
(rf/reg-event-fx :communities/toggle-share-all-addresses
|
||||
toggle-share-all-addresses)
|
||||
|
||||
(rf/reg-event-fx :communities/reset-selected-permission-addresses
|
||||
(fn [{:keys [db]} [community-id]]
|
||||
(when community-id
|
||||
{:db (update-in db
|
||||
[:communities community-id]
|
||||
assoc
|
||||
:selected-permission-addresses
|
||||
(get-in db [:communities community-id :previous-permission-addresses])
|
||||
:share-all-addresses?
|
||||
(get-in db [:communities community-id :previous-share-all-addresses?]))
|
||||
:fx [[:dispatch [:communities/check-permissions-to-join-community community-id]]]})))
|
||||
|
||||
(rf/reg-event-fx :communities/set-airdrop-address
|
||||
(fn [{:keys [db]} [address community-id]]
|
||||
{:db (assoc-in db [:communities community-id :airdrop-address] address)}))
|
||||
(rf/reg-event-fx :communities/share-community-channel-url-qr-code
|
||||
(fn [_ [chat-id]]
|
||||
(let [on-success #(rf/dispatch [:open-modal :share-community-channel
|
||||
{:chat-id chat-id
|
||||
:url %}])]
|
||||
{:fx [[:dispatch [:communities/get-community-channel-share-data chat-id on-success]]]})))
|
||||
|
||||
(defn community-fetched
|
||||
[{:keys [db]} [community-id community]]
|
||||
@@ -325,8 +288,8 @@
|
||||
|
||||
(rf/reg-event-fx :chat.ui/spectate-community spectate-community)
|
||||
|
||||
(defn navigate-to-serialized-community
|
||||
[community-id]
|
||||
(rf/defn navigate-to-serialized-community
|
||||
[_ {:keys [community-id]}]
|
||||
{:serialization/deserialize-and-compress-key
|
||||
{:serialized-key community-id
|
||||
:on-success #(rf/dispatch [:communities/navigate-to-community-overview %])
|
||||
@@ -334,30 +297,27 @@
|
||||
:error %
|
||||
:community-id community-id})}})
|
||||
|
||||
(rf/defn navigate-to-community-overview
|
||||
[{:keys [db] :as cofx} [community-id]]
|
||||
(let [current-view-id (:view-id db)]
|
||||
(if (string/starts-with? community-id constants/serialization-key)
|
||||
(navigate-to-serialized-community community-id)
|
||||
(rf/merge
|
||||
cofx
|
||||
{:fx [[:dispatch
|
||||
[:communities/fetch-community
|
||||
{:community-id community-id
|
||||
:update-last-opened-at? true}]]
|
||||
[:dispatch [:navigate-to :community-overview community-id]]
|
||||
(when (get-in db [:communities community-id :joined])
|
||||
[:dispatch
|
||||
[:activity-center.notifications/dismiss-community-overview community-id]])]}
|
||||
(when-not (or (= current-view-id :shell) (= current-view-id :communities-stack))
|
||||
(navigation/pop-to-root :shell-stack))))))
|
||||
(rf/reg-event-fx :communities/navigate-to-community-overview
|
||||
(fn [{:keys [db] :as cofx} [deserialized-key]]
|
||||
(let [current-view-id (:view-id db)]
|
||||
(if (string/starts-with? deserialized-key constants/serialization-key)
|
||||
(navigate-to-serialized-community cofx deserialized-key)
|
||||
(rf/merge
|
||||
cofx
|
||||
{:fx [[:dispatch
|
||||
[:communities/fetch-community
|
||||
{:community-id deserialized-key
|
||||
:update-last-opened-at? true}]]
|
||||
[:dispatch [:navigate-to :community-overview deserialized-key]]
|
||||
(when (get-in db [:communities deserialized-key :joined])
|
||||
[:dispatch
|
||||
[:activity-center.notifications/dismiss-community-overview deserialized-key]])]}
|
||||
(when-not (or (= current-view-id :shell) (= current-view-id :communities-stack))
|
||||
(navigation/pop-to-root :shell-stack)))))))
|
||||
|
||||
(rf/reg-event-fx :communities/navigate-to-community-overview navigate-to-community-overview)
|
||||
|
||||
(defn navigate-to-community-chat
|
||||
[{:keys [db]} [chat-id pop-to-root? community-id]]
|
||||
(let [community-id (or community-id (get-in db [:chats chat-id :community-id]))]
|
||||
(merge
|
||||
(rf/reg-event-fx :communities/navigate-to-community-chat
|
||||
(fn [{:keys [db]} [chat-id pop-to-root?]]
|
||||
(let [{:keys [community-id]} (get-in db [:chats chat-id])]
|
||||
{:fx [(when community-id
|
||||
[:dispatch
|
||||
[:communities/fetch-community
|
||||
@@ -365,11 +325,7 @@
|
||||
:update-last-opened-at? true}]])
|
||||
(if pop-to-root?
|
||||
[:dispatch [:chat/pop-to-root-and-navigate-to-chat chat-id]]
|
||||
[:dispatch [:chat/navigate-to-chat chat-id]])]}
|
||||
(when-not (get-in db [:chats chat-id :community-id])
|
||||
{:db (assoc-in db [:chats chat-id :community-id] community-id)}))))
|
||||
|
||||
(rf/reg-event-fx :communities/navigate-to-community-chat navigate-to-community-chat)
|
||||
[:dispatch [:chat/navigate-to-chat chat-id]])]})))
|
||||
|
||||
(defn get-revealed-accounts
|
||||
[{:keys [db]} [community-id on-success]]
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
(def community-tag-container
|
||||
{:padding-horizontal screen-horizontal-padding
|
||||
:margin-horizontal (- screen-horizontal-padding)
|
||||
:margin-bottom 16})
|
||||
:margin-bottom 20})
|
||||
|
||||
(def community-content-container
|
||||
{:padding-horizontal screen-horizontal-padding})
|
||||
@@ -64,5 +64,4 @@
|
||||
{:border-radius 16
|
||||
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80)
|
||||
:border-width 1
|
||||
:padding-top 10
|
||||
:margin-bottom 106})
|
||||
:padding-top 10})
|
||||
|
||||
@@ -38,9 +38,8 @@
|
||||
{:keys [name emoji muted? id mentions-count unread-messages? on-press locked? color] :as chat}]
|
||||
(let [sheet-content [actions/chat-actions
|
||||
(assoc chat
|
||||
:community-id community-id
|
||||
:chat-type constants/community-chat-type
|
||||
:chat-id (str community-id id))
|
||||
:chat-type constants/community-chat-type
|
||||
:chat-id (str community-id id))
|
||||
false]
|
||||
notification (cond
|
||||
muted? :mute
|
||||
@@ -162,7 +161,7 @@
|
||||
(i18n/label :t/you-eligible-to-join-as {:role highest-role-text})
|
||||
(i18n/label :t/you-not-eligible-to-join))]
|
||||
[info-button]]
|
||||
[quo/text {:style {:padding-horizontal 12 :padding-bottom 6} :size :paragraph-2}
|
||||
[quo/text {:style {:padding-horizontal 12 :padding-bottom 18} :size :paragraph-2}
|
||||
(if can-request-access?
|
||||
(i18n/label :t/you-hodl)
|
||||
(i18n/label :t/you-must-hold))]
|
||||
@@ -176,7 +175,7 @@
|
||||
#(rf/dispatch [:open-modal :community-requests-to-join {:id id}]))
|
||||
:accessibility-label :join-community-button
|
||||
:customization-color color
|
||||
:container-style {:margin-horizontal 12 :margin-top 8 :margin-bottom 12}
|
||||
:container-style {:margin-horizontal 12 :margin-top 12 :margin-bottom 12}
|
||||
:disabled? (not can-request-access?)
|
||||
:icon-left (if can-request-access? :i/unlocked :i/locked)}
|
||||
(i18n/label :t/request-to-join)]])))
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
(ns status-im.contexts.communities.sharing.events
|
||||
(:require [legacy.status-im.data-store.chats :as data-store.chats]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.share :as share]
|
||||
[taoensso.timbre :as log]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :communities/invite-people-pressed
|
||||
(fn [{:keys [db]} [id]]
|
||||
{:db (assoc db :communities/community-id-input id)
|
||||
:fx [[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:open-modal :invite-people-community {:id id}]]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/share-community-pressed
|
||||
(fn [{:keys [db]} [id]]
|
||||
{:db (assoc db :communities/community-id-input id)
|
||||
:fx [[:dispatch [:hide-bottom-sheet]]
|
||||
[:dispatch [:open-modal :legacy-invite-people-community {:id id}]]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/share-community-confirmation-pressed
|
||||
(fn [_ [users-public-keys community-id]]
|
||||
{:fx [[:json-rpc/call
|
||||
[{:method "wakuext_shareCommunity"
|
||||
:params [{:communityId community-id
|
||||
:users users-public-keys}]
|
||||
:js-response true
|
||||
:on-success [:sanitize-messages-and-process-response]
|
||||
:on-error (fn [err]
|
||||
(log/error {:message "failed to share community"
|
||||
:community-id community-id
|
||||
:err err}))}]]]}))
|
||||
|
||||
(rf/reg-event-fx :communities/share-community-channel-url-qr-code
|
||||
(fn [_ [chat-id]]
|
||||
(let [on-success #(rf/dispatch [:open-modal :share-community-channel
|
||||
{:chat-id chat-id
|
||||
:url %}])]
|
||||
{:fx [[:dispatch [:communities/get-community-channel-share-data chat-id on-success]]]})))
|
||||
|
||||
(rf/reg-event-fx :communities/share-community-channel-url-with-data
|
||||
(fn [_ [chat-id]]
|
||||
(let [title (i18n/label :t/channel-on-status)
|
||||
on-success (fn [url]
|
||||
(rf/dispatch [:open-share
|
||||
{:options (if platform/ios?
|
||||
{:activityItemSources
|
||||
[{:placeholderItem {:type :text
|
||||
:content title}
|
||||
:item {:default {:type :url
|
||||
:content url}}
|
||||
:linkMetadata {:title title}}]}
|
||||
{:title title
|
||||
:subject title
|
||||
:message url
|
||||
:url url
|
||||
:isNewTask true})}]))]
|
||||
{:fx [[:dispatch [:communities/get-community-channel-share-data chat-id on-success]]]})))
|
||||
|
||||
(rf/reg-event-fx :communities/get-community-channel-share-data
|
||||
(fn [_ [chat-id on-success]]
|
||||
(let [{:keys [community-id channel-id]} (data-store.chats/decode-chat-id chat-id)]
|
||||
{:json-rpc/call
|
||||
[{:method "wakuext_shareCommunityChannelURLWithData"
|
||||
:params [{:CommunityID community-id :ChannelID channel-id}]
|
||||
:on-success on-success
|
||||
:on-error (fn [err]
|
||||
(log/error "failed to retrieve community channel url with data"
|
||||
{:error err
|
||||
:chat-id chat-id
|
||||
:event :communities/get-community-channel-share-data}))}]})))
|
||||
|
||||
(rf/reg-event-fx :communities/get-community-share-data
|
||||
(fn [_ [community-id on-success]]
|
||||
{:json-rpc/call
|
||||
[{:method "wakuext_shareCommunityURLWithData"
|
||||
:params [community-id]
|
||||
:on-success on-success
|
||||
:on-error (fn [err]
|
||||
(log/error "failed to retrieve community url with data"
|
||||
{:error err
|
||||
:community-id community-id
|
||||
:event :communities/get-community-share-data}))}]}))
|
||||
|
||||
(rf/reg-event-fx :communities/share-community-channel-url-with-data
|
||||
(fn [_ [chat-id]]
|
||||
(let [title (i18n/label :t/channel-on-status)
|
||||
on-success (fn [url]
|
||||
(share/open
|
||||
(if platform/ios?
|
||||
{:activityItemSources [{:placeholderItem {:type "text"
|
||||
:content title}
|
||||
:item {:default {:type "url"
|
||||
:content url}}
|
||||
:linkMetadata {:title title}}]}
|
||||
{:title title
|
||||
:subject title
|
||||
:message url
|
||||
:url url
|
||||
:isNewTask true})))]
|
||||
{:fx [[:dispatch [:communities/get-community-channel-share-data chat-id on-success]]]})))
|
||||
@@ -49,13 +49,12 @@
|
||||
[:screen/onboarding.enter-seed-phrase
|
||||
:screen/onboarding.new-to-status]])}]
|
||||
[rn/view {:style style/space-between-suboptions}]
|
||||
(when config/show-not-implemented-features?
|
||||
[quo/small-option-card
|
||||
{:variant :icon
|
||||
:title (i18n/label :t/use-keycard)
|
||||
:subtitle (i18n/label :t/use-keycard-subtitle)
|
||||
:image (resources/get-image :use-keycard)
|
||||
:on-press #(js/alert "TODO: to be implemented")}])]]))
|
||||
[quo/small-option-card
|
||||
{:variant :icon
|
||||
:title (i18n/label :t/use-keycard)
|
||||
:subtitle (i18n/label :t/use-keycard-subtitle)
|
||||
:image (resources/get-image :use-keycard)
|
||||
:on-press #(js/alert "TODO: to be implemented")}]]]))
|
||||
|
||||
(defn getting-started-doc
|
||||
[]
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
(ns status-im.contexts.preview.quo.community.community-detail-token-gating
|
||||
(:require [quo.core :as quo]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.resources :as resources]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
(def descriptor
|
||||
[{:key :role
|
||||
:type :select
|
||||
:options [{:key :one-role}
|
||||
{:key :two-roles}
|
||||
{:key :three-roles}
|
||||
{:key :four-roles}]}])
|
||||
|
||||
(def roles
|
||||
{:member
|
||||
{:role 2
|
||||
:role-text "Member"
|
||||
:satisfied? true
|
||||
:tokens
|
||||
[[{:symbol "ETH" :sufficient? true :collectible? false :loading? false :amount 0.8 :img-src nil}]
|
||||
[{:symbol "ETH" :sufficient? false :collectible? false :loading? false :amount 1 :img-src nil}
|
||||
{:symbol "STT" :sufficient? false :collectible? false :loading? false :amount 10 :img-src nil}]]}
|
||||
:admin
|
||||
{:role 1
|
||||
:role-text "Admin"
|
||||
:satisfied? true
|
||||
:tokens
|
||||
[[{:symbol "ETH" :sufficient? true :collectible? false :loading? false :amount 2 :img-src nil}]]}
|
||||
:token-master
|
||||
{:role 5
|
||||
:role-text "Token Master"
|
||||
:satisfied? true
|
||||
:tokens
|
||||
[[{:symbol "TMANI"
|
||||
:sufficient? true
|
||||
:collectible? true
|
||||
:loading? false
|
||||
:amount nil
|
||||
:img-src (resources/mock-images :collectible1)}]]}
|
||||
:token-owner
|
||||
{:role 6
|
||||
:role-text "Token Owner"
|
||||
:satisfied? true
|
||||
:tokens
|
||||
[[{:symbol "TOANI"
|
||||
:sufficient? true
|
||||
:collectible? true
|
||||
:loading? false
|
||||
:amount nil
|
||||
:img-src (resources/mock-images :collectible)}]]}})
|
||||
|
||||
(def permissions
|
||||
{:one-role [(:member roles)]
|
||||
:two-roles [(:admin roles) (:member roles)]
|
||||
:three-roles [(:token-master roles) (:admin roles) (:member roles)]
|
||||
:four-roles [(:token-owner roles) (:token-master roles) (:admin roles) (:member roles)]})
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:role :one-role})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor
|
||||
:blur? (:blur? @state)
|
||||
:show-blur-background? true}
|
||||
[quo/community-detail-token-gating {:permissions ((:role @state) permissions)}]])))
|
||||
@@ -39,8 +39,6 @@
|
||||
channel-actions]
|
||||
[status-im.contexts.preview.quo.community.community-card-view :as
|
||||
community-card]
|
||||
[status-im.contexts.preview.quo.community.community-detail-token-gating :as
|
||||
community-detail-token-gating]
|
||||
[status-im.contexts.preview.quo.community.community-membership-list-view
|
||||
:as community-membership-list-view]
|
||||
[status-im.contexts.preview.quo.community.community-stat :as community-stat]
|
||||
@@ -262,8 +260,6 @@
|
||||
:component color/view}]
|
||||
:community [{:name :community-card-view
|
||||
:component community-card/view}
|
||||
{:name :community-detail-token-gating
|
||||
:component community-detail-token-gating/view}
|
||||
{:name :community-membership-list-view
|
||||
:component community-membership-list-view/view}
|
||||
{:name :community-stat
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
(ns status-im.contexts.preview.quo.wallet.network-link
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.preview.quo.preview :as preview]))
|
||||
|
||||
@@ -24,21 +23,17 @@
|
||||
:options networks}
|
||||
{:key :destination
|
||||
:type :select
|
||||
:options networks}
|
||||
{:key :width
|
||||
:type :number}])
|
||||
:options networks}])
|
||||
|
||||
(defn view
|
||||
[]
|
||||
(let [state (reagent/atom {:shape :linear
|
||||
:source :ethereum
|
||||
:destination :optimism
|
||||
:width 63})]
|
||||
:destination :optimism})]
|
||||
(fn []
|
||||
[preview/preview-container
|
||||
{:state state
|
||||
:descriptor descriptor
|
||||
:component-container-style {:padding-top 40
|
||||
:align-items :center}}
|
||||
[rn/view {:style {:width (max (:width @state) 63)}}
|
||||
[quo/network-link @state]]])))
|
||||
[quo/network-link @state]])))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user