Compare commits

...
Author SHA1 Message Date
Omar Basem d433285acb selectable-input 2023-05-04 10:26:51 +04:00
Omar Basem eb16f4b6c4 revert podfile.lock 2023-05-04 09:17:53 +04:00
Omar Basem 9268060aa9 review 2023-05-04 09:16:53 +04:00
Omar Basem 7ab9e7abd0 review 2023-05-04 09:16:52 +04:00
Omar Basem 2430bde3d5 review 2023-05-04 09:16:52 +04:00
Omar Basem 739556f2b4 review 2023-05-04 09:16:52 +04:00
Omar Basem f4ac7a4c51 lint 2023-05-04 09:16:51 +04:00
Omar Basem 36fac66eac feat: mentions new design
review

lint

review

udpates

updates

updates

udpates

updates

updates

lint

updates

composer shell button

updates

updates

updates

updates

updates

updates

updates

updates

updates

updates

updates

updates

updates
2023-05-04 09:16:51 +04:00
Alexander 4774b0f5e5 Fix for mention text overlaying message text when mention is added during message editing (Android) (#15778) 2023-05-03 18:26:37 +02:00
Siddarth Kumar 6aa38de7c7 set checked for communities disclaimer explicitly (#15804) 2023-05-03 21:24:19 +05:30
Omar Basem a973976123 New composer - add audio comp (#15790)
* feat: composer - add audio comp
2023-05-03 09:54:23 +04:00
Ajay Sivan 03aac0e4ce fix: quo2 title-input component selection style fix for android (#15717) 2023-05-02 17:01:09 +05:30
Siddarth Kumar fac368521b (fix) modify disclaimer component for on tap UX (#15757) 2023-05-02 15:55:49 +05:30
Omar Basem 51b9253734 revert podfile.lock (#15791)
* revert podfile.lock
2023-05-02 09:27:47 +04:00
Omar Basem 08e6b8164e feat: composer - edit message (#15772)
* feat: new composer - edit message
2023-05-01 20:39:07 +04:00
Parvesh Monu 9a8354f783 Improve dissmiss all overlays (#15773) 2023-04-28 20:52:34 +05:30
Churikova Tetiana 6c0c742676 e2e: align with new communities / cleanup 2023-04-28 13:56:31 +02:00
flexsurfer e0ed2a250b clean old code, remove public chat, implement drawers for home screens (#15766) 2023-04-28 13:42:38 +02:00
jakub 2f988fcd47 nix: disable sandboxing for xcodewrapper
Otherwise we see weird errors like this:
```
/nix/store/g0jijpgcb4q54zbvz5p8yvxcnb6lshnk-stdenv-darwin/setup: line 1391: /nix/store/sja8sqq4y5s9ijkb97i3pi2jrhsy40cz-xcode-wrapper-14.3/bin/xcodebuild: Operation not permitted
We require xcodebuild version: 14.3
error: builder for '/nix/store/d1dji0ywl851wgj9vv58ibpm32gq3wsm-xcode-wrapper-14.3.drv' failed with exit code 1;
       last 2 log lines:
       > /nix/store/g0jijpgcb4q54zbvz5p8yvxcnb6lshnk-stdenv-darwin/setup: line 1391: /nix/store/sja8sqq4y5s9ijkb97i3pi2jrhsy40cz-xcode-wrapper-14.3/bin/xcodebuild: Operation not permitted
       > We require xcodebuild version: 14.3
```
Related to: https://github.com/NixOS/nixpkgs/pull/228696

Signed-off-by: Jakub Sokołowski <jakub@status.im>
2023-04-28 11:24:16 +02:00
frank ee71117111 remove unused code relate to old text-input component (#15765)
* remove unused code relate to old text-input component

* removed tow lines
2023-04-28 09:37:13 +08:00
Omar Basem 3e9d5dde54 Reimplement composer: add reply (#15736)
* feat: add composer reply
2023-04-27 20:20:00 +04:00
Siddarth Kumar 2eed30be8f (chore) : Improve QR code quo2 component (#15755)
This PR adds the ability to :

- Generate a QR by passing any url.
- See different error correction levels.
- Shows the media server url for that specific QR code.
- Moved media server URI generation logic to `image_server.cljs`
2023-04-27 19:25:49 +05:30
Parvesh Monu 8e49a06dbe fix UI freeze issue (#15761) 2023-04-27 17:26:33 +05:30
Roman Volosovskyi fb326bbf4e [#15741] Fix error on tapping pinned message 2023-04-27 10:23:16 +02:00
Jamie Caprani 52c6687608 feat: add identifiers screen to onboarding-flow (#15684) 2023-04-26 21:26:32 -07:00
frank cfefef6b75 fix [#15616] Sometimes mentions list does not appear after typing @ in chat input filed (#15622) 2023-04-27 11:37:01 +08:00
flexsurfer e6ba40ac17 fix quo hotreload (#15760) 2023-04-26 18:14:58 +02:00
flexsurfer efbf93f6e2 move status native module (#15749) 2023-04-26 18:14:14 +02:00
Mohamed Javid 6eb2029c51 Show "Kicked from community" notification in Activity Center (#15734)
* [Feature] Implement Community Kicked notification

* Status Go Update
2023-04-26 19:56:33 +05:30
Parvesh Monu 55bab9454a fix status bar font color (#15744) 2023-04-26 19:35:51 +05:30
flexsurferandChurikova Tetiana 0ca6ee3934 Request to join community screen is not scrollable on Android #15748 (#15750)
Co-authored-by: Churikova Tetiana <tatiana@status.im>
2023-04-26 13:33:00 +02:00
Parvesh Monu 0649c66dde fix device theme change listener in ios (#15724) 2023-04-26 16:41:11 +05:30
Roman Volosovskyi 1b0374a156 [#15655] Resolve messages with markdown on Jump To screen 2023-04-26 11:55:45 +02:00
182 changed files with 2105 additions and 3888 deletions
+5 -5
View File
@@ -12,11 +12,11 @@ status-im.chat.models.message-content/actions
status-im.chat.models.message-content/blank-string
status-im.chat.models.message-content/sorted-ranges
status-im.ethereum.mnemonic/words->passphrase
status-im.native-module.core/listener
status-im.native-module.core/multiaccount-reset
status-im.native-module.core/extract-group-membership-signatures
status-im.native-module.core/sign-group-membership
status-im.native-module.core/update-mailservers
native-module.core/listener
native-module.core/multiaccount-reset
native-module.core/extract-group-membership-signatures
native-module.core/sign-group-membership
native-module.core/update-mailservers
status-im.ethereum.abi-spec/bytes-to-hex
status-im.android.core/init
status-im.chat.models.message/transport-keys
@@ -8,6 +8,9 @@ assert stdenv.isDarwin;
stdenv.mkDerivation {
name = "xcode-wrapper-${version}${if allowHigher then "-plus" else ""}";
# Fix 'xcodebuild: Operation not permitted' when 'sandbox=relaxed' is used.
# https://github.com/NixOS/nixpkgs/pull/228696
__noChroot = stdenv.isDarwin;
buildCommand = ''
mkdir -p $out/bin
cd $out/bin
Binary file not shown.

After

Width:  |  Height:  |  Size: 528 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 759 B

After

Width:  |  Height:  |  Size: 913 B

+2 -2
View File
@@ -18,11 +18,11 @@ export function stackOpacity (stackId, selectedStackId) {
);
}
export function stackPointer (stackId, selectedStackId) {
export function stackZIndex (stackId, selectedStackId) {
return useDerivedValue(
function () {
'worklet'
return selectedStackId.value == stackId ? "auto" : "none";
return selectedStackId.value == stackId ? 10 : 9;
}
);
}
@@ -1,19 +1,19 @@
(ns status-im.native-module.core
(ns native-module.core
(:require ["react-native" :as react-native]
[re-frame.core :as re-frame]
[status-im2.utils.validators :as validators]
[status-im.utils.platform :as platform]
[status-im.utils.react-native :as react-native-utils]
[status-im.utils.types :as types]
[utils.validators :as validators]
[taoensso.timbre :as log]
[status-im2.constants :as constants]))
[react-native.platform :as platform]
[react-native.core :as rn]
[utils.transforms :as types]))
(defn status
[]
(when (exists? (.-NativeModules react-native))
(.-Status ^js (.-NativeModules react-native))))
(def adjust-resize 16)
(defn init
[handler]
(.addListener ^js rn/device-event-emitter "gethEvent" #(handler (.-jsonEvent ^js %))))
(defn clear-web-data
[]
@@ -72,15 +72,6 @@
accounts-data
chat-key)))
(defn login
"NOTE: beware, the password has to be sha3 hashed"
[key-uid account-data hashed-password]
(log/debug "[native-module] login")
(clear-web-data)
(init-keystore
key-uid
#(.login ^js (status) account-data hashed-password)))
(defn login-with-config
"NOTE: beware, the password has to be sha3 hashed"
[key-uid account-data hashed-password config]
@@ -123,11 +114,6 @@
(clear-web-data)
(.logout ^js (status)))
(defonce listener
(.addListener ^js react-native-utils/device-event-emitter
"gethEvent"
#(re-frame/dispatch [:signals/signal-received (.-jsonEvent ^js %)])))
(defn multiaccount-load-account
"NOTE: beware, the password has to be sha3 hashed
@@ -141,14 +127,6 @@
:password hashed-password})
callback))
(defn multiaccount-reset
"TODO: this function is not used anywhere
if usage isn't planned, remove"
[callback]
(log/debug "[native-module] multiaccount-reset")
(.multiAccountReset ^js (status)
callback))
(defn multiaccount-derive-addresses
"NOTE: this should be named derive-accounts
this only derive addresses, they still need to be stored
@@ -298,43 +276,13 @@
:key key})
(.deserializeAndCompressKey ^js (status) key callback))
(defn public-key->compressed-key
"Provides public key to status-go and gets back a compressed key via serialization"
[public-key callback]
(let [serialization-key constants/serialization-key
multi-code-prefix constants/multi-code-prefix
multi-code-key (str multi-code-prefix (subs public-key 2))]
(log/info "[native-module] Serializing public key"
{:fn :public-key->compressed-key
:public-key public-key
:multi-code-key multi-code-key})
(.multiformatSerializePublicKey ^js (status) multi-code-key serialization-key callback)))
(defn compressed-key->public-key
"Provides compressed key to status-go and gets back the uncompressed public key via deserialization"
[public-key callback]
(let [deserialization-key constants/deserialization-key]
(log/info "[native-module] Deserializing compressed key"
{:fn :compressed-key->public-key
:public-key public-key})
(.multiformatDeserializePublicKey ^js (status) public-key deserialization-key callback)))
(defn decompress-public-key
"Provides compressed key to status-go and gets back the uncompressed public key"
[public-key callback]
(log/info "[native-module] Decompressing public key"
{:fn :decompress-public-key
[public-key deserialization-key callback]
(log/info "[native-module] Deserializing compressed key"
{:fn :compressed-key->public-key
:public-key public-key})
(.decompressPublicKey ^js (status) public-key callback))
(defn compress-public-key
"Provides a public key to status-go and gets back a 33bit compressed key back"
[public-key callback]
(log/info "[native-module] Compressing public key"
{:fn :compress-public-key
:public-key public-key})
(.compressPublicKey ^js (status) public-key callback))
(.multiformatDeserializePublicKey ^js (status) public-key deserialization-key callback))
(defn hash-typed-data
"used for keycard"
@@ -388,11 +336,6 @@
(log/debug "[native-module] send-logs")
(.sendLogs ^js (status) dbJson js-logs callback))
(defn add-peer
[enode on-result]
(log/debug "[native-module] add-peer")
(.addPeer ^js (status) enode on-result))
(defn close-application
[]
(log/debug "[native-module] close-application")
@@ -408,11 +351,6 @@
(log/debug "[native-module] app-state-change")
(.appStateChange ^js (status) state))
(defn stop-local-notifications
[]
(log/debug "[native-module] stop-local-notifications")
(.stopLocalNotifications ^js (status)))
(defn start-local-notifications
[]
(log/debug "[native-module] start-local-notifications")
@@ -433,26 +371,11 @@
:build-id (.-buildId status)
:device-id (.-deviceId status)}))
(defn extract-group-membership-signatures
[signature-pairs callback]
(log/debug "[native-module] extract-group-membership-signatures")
(.extractGroupMembershipSignatures ^js (status) signature-pairs callback))
(defn sign-group-membership
[content callback]
(log/debug "[native-module] sign-group-membership")
(.signGroupMembership ^js (status) content callback))
(defn get-node-config
[callback]
(log/debug "[native-module] get-node-config")
(.getNodeConfig ^js (status) callback))
(defn update-mailservers
[enodes on-result]
(log/debug "[native-module] update-mailservers")
(.updateMailservers ^js (status) enodes on-result))
(defn toggle-webview-debug
[on]
(log/debug "[native-module] toggle-webview-debug" on)
@@ -483,12 +406,6 @@
(when (validators/valid-public-key? public-key)
(.generateAlias ^js (status) public-key)))
(defn generate-gfycat-async
"Generate a 3 words random name based on the user public-key, asynchronously"
[public-key callback]
(when (validators/valid-public-key? public-key)
(.generateAliasAsync ^js (status) public-key callback)))
(defn identicon
"Generate a icon based on a string, synchronously"
[seed]
@@ -500,11 +417,6 @@
(log/debug "[native-module] encode-transfer")
(.encodeTransfer ^js (status) to-norm amount-hex))
(defn encode-function-call
[method params]
(log/debug "[native-module] encode-function-call")
(.encodeFunctionCall ^js (status) method (types/clj->json params)))
(defn decode-parameters
[bytes-string types]
(log/debug "[native-module] decode-parameters")
@@ -555,11 +467,6 @@
(log/debug "[native-module] to-checksum-address")
(.toChecksumAddress ^js (status) address))
(defn identicon-async
"Generate a icon based on a string, asynchronously"
[seed callback]
(.identiconAsync ^js (status) seed callback))
(defn gfycat-identicon-async
"Generate an icon based on a string and 3 words random name asynchronously"
[seed callback]
@@ -585,16 +492,6 @@
(log/debug "[native-module] delete-imported-key")
(.deleteImportedKey ^js (status) key-uid address hashed-password callback))
(defn activate-keep-awake
[]
(log/debug "[native-module] activateKeepAwake")
(.activateKeepAwake ^js (status)))
(defn deactivate-keep-awake
[]
(log/debug "[native-module] deactivateKeepAwake")
(.deactivateKeepAwake ^js (status)))
(defn reset-keyboard-input
[input selection]
(log/debug "[native-module] resetKeyboardInput")
@@ -1,10 +1,10 @@
(ns status-im.native-module.core-test
(ns native-module.core-test
(:require [cljs.test :refer [deftest is testing]]
[status-im.native-module.core :as status]))
[native-module.core :as native-module]))
(deftest identicon-test
(testing "check if identicon test works"
(is
(=
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAjklEQVR4nOzXsQmAMBQGYRV3cUAdQwd0Gm2sJIWSBI6f+0oR8XjwSKYhhCE0htAYQmMITUzI/PXF49yv0vN12cYWP1L7/ZiJGEJjCE31xvm7bXptv5iJGEJjCE31WasVz1oPQ2gMoWlyuyvpfaN8i5mIITSG0BhCYwiNIeokZiKG0BhCYwiNITR3AAAA//+A3RtWaKqXgQAAAABJRU5ErkJggg=="
(status/identicon "a")))))
(native-module/identicon "a")))))
@@ -1,5 +1,6 @@
(ns quo2.components.inputs.title-input.style
(:require [quo2.foundations.colors :as colors]))
(:require [quo2.foundations.colors :as colors]
[react-native.platform :as platform]))
(defn get-focused-placeholder-color
[blur? override-theme]
@@ -28,9 +29,11 @@
(defn get-selection-color
[customization-color blur? override-theme]
(if blur?
(colors/theme-colors colors/neutral-100 colors/white override-theme)
(colors/custom-color customization-color (if (or (= :dark override-theme) colors/dark?) 60 50))))
(colors/alpha (if blur?
(colors/theme-colors colors/neutral-100 colors/white override-theme)
(colors/custom-color customization-color
(if (or (= :dark override-theme) colors/dark?) 60 50)))
(if platform/ios? 1 0.2)))
(def text-input-container {:flex 1})
@@ -154,12 +154,12 @@
ready-to-send? (reagent/atom false)
ready-to-lock? (reagent/atom false)
ready-to-delete? (reagent/atom false)
reviewing-audio? (reagent/atom false)
reviewing-audio? (reagent/atom (some? audio-file))
playing-audio? (reagent/atom false)
recording-length-ms (reagent/atom 0)
audio-current-time-ms (reagent/atom 0)
seeking-audio? (reagent/atom false)
force-show-controls? (reagent/atom false)
force-show-controls? (reagent/atom (some? audio-file))
clear-timeout (atom nil)
record-button-at-initial-position? (atom true)
record-button-is-animating? (atom false)
@@ -169,7 +169,7 @@
touch-active? (atom false)
recording-timer (atom nil)
playing-timer (atom nil)
output-file (atom nil)
output-file (atom audio-file)
reached-max-duration? (atom false)
touch-timestamp (atom nil)
disabled? (atom false)
@@ -512,10 +512,7 @@
(on-init reset-recorder))
(when audio-file
(let [filename (last (string/split audio-file "/"))]
(reload-player filename)
(reset! output-file audio-file)
(reset! reviewing-audio? true)
(reset! force-show-controls? true)))))
(reload-player filename)))))
[rn/view
{:style style/bar-container
:pointer-events :box-none}
@@ -5,15 +5,17 @@
[react-native.core :as rn]))
(defn view
[{:keys [checked? blur? on-change accessibility-label container-style]} label]
[rn/view
{:style (merge container-style (style/container blur?))}
[selectors/checkbox
{:accessibility-label accessibility-label
:blur? blur?
:checked? checked?
:on-change on-change}]
[text/text
{:size :paragraph-2
:style style/text}
label]])
[{:keys [checked? blur? accessibility-label container-style on-change]} label]
[rn/touchable-opacity
{:on-press on-change
:accessibility-label "disclaimer-touchable-opacity"}
[rn/view {:style (merge container-style (style/container blur?))}
[selectors/checkbox
{:accessibility-label accessibility-label
:blur? blur?
:checked? checked?
:on-change on-change}]
[text/text
{:size :paragraph-2
:style style/text}
label]]])
+2
View File
@@ -37,6 +37,8 @@
(def dismiss-keyboard! #(.dismiss keyboard))
(def device-event-emitter (.-DeviceEventEmitter ^js react-native))
(defn hide-splash-screen
[]
(.hide ^js (-> react-native .-NativeModules .-SplashScreen)))
-102
View File
@@ -1,102 +0,0 @@
(ns status-im.add-new.core
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.add-new.db :as db]
[status-im2.contexts.chat.events :as chat]
[status-im2.contexts.contacts.events :as contact]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.stateofus :as stateofus]
[utils.i18n :as i18n]
[status-im.router.core :as router]
[status-im.utils.db :as utils.db]
[utils.re-frame :as rf]
[status-im.utils.random :as random]
[status-im.utils.utils :as utils]
[status-im2.navigation.events :as navigation]))
(re-frame/reg-fx
:resolve-public-key
(fn [{:keys [chain-id contact-identity cb]}]
(let [ens-name (stateofus/ens-name-parse contact-identity)]
(ens/pubkey chain-id ens-name cb))))
;;NOTE we want to handle only last resolve
(def resolve-last-id (atom nil))
(rf/defn new-chat-set-new-identity
{:events [:new-chat/set-new-identity]}
[{db :db} new-identity-raw new-ens-name id]
(let [ens-error (and (= new-identity-raw "0x") (not (string/blank? new-ens-name)))]
(when (or (not id) (= id @resolve-last-id))
(if ens-error
{:db (assoc-in db [:contacts/new-identity :state] :error)}
(let [new-identity (utils/safe-trim new-identity-raw)
is-public-key? (and (string? new-identity)
(utils.db/valid-public-key? new-identity))
is-ens? (and (not is-public-key?)
(ens/valid-eth-name-prefix? new-identity))
error (db/validate-pub-key db new-identity)]
(reset! resolve-last-id nil)
(merge {:db (assoc db
:contacts/new-identity
{:public-key new-identity
:state (cond is-ens?
:searching
(and (string/blank? new-identity) (not new-ens-name))
:empty
error
:error
:else
:valid)
:error error
:ens-name (stateofus/ens-name-parse new-ens-name)})}
(when is-ens?
(reset! resolve-last-id (random/id))
{:resolve-public-key
{:chain-id (ethereum/chain-id db)
:contact-identity new-identity
:cb #(re-frame/dispatch [:new-chat/set-new-identity
%
new-identity
@resolve-last-id])}})))))))
(rf/defn clear-new-identity
{:events [::clear-new-identity ::new-chat-focus]}
[{:keys [db]}]
{:db (dissoc db :contacts/new-identity)})
(rf/defn qr-code-handled
{:events [::qr-code-handled]}
[{:keys [db] :as cofx} {:keys [type public-key chat-id data ens-name]}
{:keys [new-contact? nickname] :as opts}]
(let [public-key? (and (string? data)
(string/starts-with? data "0x"))
chat-key (cond
(= type :private-chat) chat-id
(= type :contact) public-key
(and (= type :undefined)
public-key?)
data)
validation-result (db/validate-pub-key db chat-key)]
(if-not validation-result
(if new-contact?
(rf/merge cofx
(contact/send-contact-request chat-key)
(navigation/navigate-to :contacts-list {}))
(chat/start-chat cofx chat-key ens-name))
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (case validation-result
:invalid
(i18n/label :t/use-valid-contact-code)
:yourself
(i18n/label :t/can-not-add-yourself))
:on-dismiss #(re-frame/dispatch [:pop-to-root :shell-stack])}})))
(rf/defn qr-code-scanned
{:events [:contact/qr-code-scanned]}
[{:keys [db]} data opts]
{::router/handle-uri {:chain (ethereum/chain-keyword db)
:chats (get db :chats)
:uri data
:cb #(re-frame/dispatch [::qr-code-handled % opts])}})
-30
View File
@@ -1,30 +0,0 @@
(ns status-im.add-new.db
(:require [cljs.spec.alpha :as spec]
[status-im.ethereum.ens :as ens]
[status-im2.utils.validators :as validators]))
(defn own-public-key?
[{:keys [multiaccount]} public-key]
(= (:public-key multiaccount) public-key))
(defn validate-pub-key
[db public-key]
(cond
(or (not (validators/valid-public-key? public-key))
(= public-key ens/default-key))
:invalid
(own-public-key? db public-key)
:yourself))
(spec/def ::name (spec/and string? not-empty))
(spec/def ::topic
(spec/and string?
not-empty
(partial re-matches #"[a-z0-9\-]+")))
(defn valid-topic?
[topic]
(and topic
(spec/valid? ::topic topic)
(not (validators/valid-public-key? topic))))
-4
View File
@@ -1,7 +1,6 @@
(ns status-im.bottom-sheet.sheets
(:require [utils.re-frame :as rf]
[status-im.ui.screens.about-app.views :as about-app]
[status-im.ui.screens.home.sheet.views :as home.sheet]
[status-im.ui.screens.keycard.views :as keycard]
[status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[status-im.ui.screens.multiaccounts.key-storage.views :as key-storage]
@@ -27,9 +26,6 @@
(= view :mobile-network-offline)
(merge mobile-network-settings/offline-sheet)
(= view :add-new)
(merge home.sheet/add-new)
(= view :keycard.login/more)
(merge keycard/more-sheet)
+3 -3
View File
@@ -13,7 +13,7 @@
[status-im.ethereum.ens :as ens]
[utils.i18n :as i18n]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.signing.core :as signing]
[status-im.ui.components.list-selection :as list-selection]
[utils.re-frame :as rf]
@@ -537,7 +537,7 @@
(re-frame/reg-fx
:browser/call-rpc
(fn [[payload callback]]
(status/call-rpc
(native-module/call-rpc
(types/clj->json payload)
(fn [response]
(if (= "" response)
@@ -559,7 +559,7 @@
(re-frame/reg-fx
:browser/clear-web-data
(fn []
(status/clear-web-data)))
(native-module/clear-web-data)))
(defn share-link
[url]
-35
View File
@@ -1,35 +0,0 @@
(ns status-im.chat.models
(:require [utils.i18n :as i18n]
[re-frame.core :as re-frame]
[utils.re-frame :as rf]
[taoensso.timbre :as log]
[status-im.add-new.db :as new-public-chat.db]
[status-im.data-store.chats :as chats-store]))
;; OLD
(rf/defn handle-public-chat-created
{:events [::public-chat-created]}
[{:keys [db]} chat-id response]
{:db (-> db
(assoc-in [:chats chat-id] (chats-store/<-rpc (first (:chats response))))
(update :chats-home-list conj chat-id))
:dispatch [:chat/navigate-to-chat chat-id]})
(rf/defn create-public-chat-go
[_ chat-id]
{:json-rpc/call [{:method "wakuext_createPublicChat"
:params [{:id chat-id}]
:on-success #(re-frame/dispatch [::public-chat-created chat-id %])
:on-error #(log/error "failed to create public chat" chat-id %)}]})
(rf/defn start-public-chat
"Starts a new public chat"
{:events [:chat.ui/start-public-chat]}
[cofx topic]
(if (new-public-chat.db/valid-topic? topic)
(create-public-chat-go
cofx
topic)
{:utils/show-popup {:title (i18n/label :t/cant-open-public-chat)
:content (i18n/label :t/invalid-public-chat-topic)}}))
+44 -39
View File
@@ -6,12 +6,12 @@
[status-im.chat.models.mentions :as mentions]
[status-im.chat.models.message :as chat.message]
[status-im.chat.models.message-content :as message-content]
[status-im2.config :as config]
[status-im2.constants :as constants]
[utils.re-frame :as rf]
[utils.i18n :as i18n]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]
[status-im.ui.screens.chat.components.input :as input]))
[taoensso.timbre :as log]))
(defn text->emoji
"Replaces emojis in a specified `text`"
@@ -51,11 +51,17 @@
(let [current-chat-id (or chat-id (:current-chat-id db))]
{:db (assoc-in db [:chat/inputs current-chat-id :input-maximized?] maximized?)}))
(rf/defn set-input-refocus
{:events [:chat.ui/set-input-refocus]}
[{db :db} refocus? chat-id]
(rf/defn set-input-focused
{:events [:chat.ui/set-input-focused]}
[{db :db} focused? chat-id]
(let [current-chat-id (or chat-id (:current-chat-id db))]
{:db (assoc-in db [:chat/inputs current-chat-id :input-refocus?] refocus?)}))
{:db (assoc-in db [:chat/inputs current-chat-id :focused?] focused?)}))
(rf/defn set-input-audio
{:events [:chat.ui/set-input-audio]}
[{db :db} audio chat-id]
(let [current-chat-id (or chat-id (:current-chat-id db))]
{:db (assoc-in db [:chat/inputs current-chat-id :audio] audio)}))
(rf/defn select-mention
{:events [:chat.ui/select-mention]}
@@ -98,15 +104,15 @@
[{:keys [db] :as cofx} message]
(let [current-chat-id (:current-chat-id db)
text (get-in message [:content :text])]
(rf/merge cofx
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))}
(input/set-input-text text current-chat-id))))
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))
:dispatch (when-not config/new-composer-enabled?
[:mention/to-input-field text current-chat-id])}))
(rf/defn show-contact-request-input
"Sets reference to previous chat message and focuses on input"
@@ -181,7 +187,8 @@
[{:keys [db] :as cofx}]
(let [current-chat-id (:current-chat-id db)]
(rf/merge cofx
{:set-text-input-value [current-chat-id ""]}
(when-not config/new-composer-enabled?
{:set-text-input-value [current-chat-id ""]})
(clean-input current-chat-id)
(mentions/clear-mentions))))
@@ -225,22 +232,21 @@
(rf/defn send-edited-message
[{:keys [db] :as cofx} text {:keys [message-id quoted-message chat-id]}]
(let [pinned-message (get-in db [:pin-messages chat-id message-id])]
(rf/merge
cofx
{:json-rpc/call [{:method "wakuext_editMessage"
:params [{:id message-id
:text text
:content-type (if (message-content/emoji-only-content?
{:text text :response-to quoted-message})
constants/content-type-emoji
constants/content-type-text)}]
:js-response true
:on-error #(log/error "failed to edit message " %)
:on-success (fn [result]
(re-frame/dispatch [:sanitize-messages-and-process-response
result]))}]}
(cancel-message-edit))))
(rf/merge
cofx
{:json-rpc/call [{:method "wakuext_editMessage"
:params [{:id message-id
:text text
:content-type (if (message-content/emoji-only-content?
{:text text :response-to quoted-message})
constants/content-type-emoji
constants/content-type-text)}]
:js-response true
:on-error #(log/error "failed to edit message " %)
:on-success (fn [result]
(re-frame/dispatch [:sanitize-messages-and-process-response
result]))}]}
(cancel-message-edit)))
(rf/defn send-current-message
"Sends message from current chat input"
@@ -276,13 +282,12 @@
{:events [:contacts/send-contact-request]}
[{:keys [db] :as cofx} public-key message]
(rf/merge cofx
{:chat.ui/clear-inputs nil
:chat.ui/clear-inputs-old nil
:json-rpc/call [{:method "wakuext_sendContactRequest"
:js-response true
:params [{:id public-key :message message}]
:on-error #(log/warn "failed to send a contact request" %)
:on-success #(re-frame/dispatch [:transport/message-sent %])}]}
{:chat.ui/clear-inputs nil
:json-rpc/call [{:method "wakuext_sendContactRequest"
:js-response true
:params [{:id public-key :message message}]
:on-error #(log/warn "failed to send a contact request" %)
:on-success #(re-frame/dispatch [:transport/message-sent %])}]}
(mentions/clear-mentions)
(clean-input (:current-chat-id db))))
+56 -81
View File
@@ -3,10 +3,10 @@
[quo.react :as react]
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[status-im2.config :as config]
[utils.re-frame :as rf]
[status-im.utils.platform :as platform]
[taoensso.timbre :as log]
[status-im.native-module.core :as status]))
[native-module.core :as native-module]))
(defn- transfer-input-segments
[segments]
@@ -56,8 +56,8 @@
:ensVerified :ens-verified
:added :added?
:displayName :display-name
:searchedText :searched-text
})))
:searchedText :searched-text})))
{}
mentionable-users))
(defn- transfer-mention-result
@@ -81,6 +81,19 @@
(log/error "[mentions] on-error"
{:context context
:error error}))
(rf/defn to-input-field
{:events [:mention/to-input-field]}
[_ text chat-id]
(let [params [chat-id text]
method "wakuext_chatMentionToInputField"]
(log/debug "[mentions] to-input-field" {:params params})
{:json-rpc/call [{:method method
:params params
:on-success #(rf/dispatch [:mention/on-to-input-field-success %])
:on-error #(rf/dispatch [:mention/on-error
{:method method
:params params} %])}]}))
(rf/defn on-to-input-field-success
{:events [:mention/on-to-input-field-success]}
[{:keys [db]} result]
@@ -91,38 +104,29 @@
(assoc-in [:chats/mentions chat-id :mentions] state)
(assoc-in [:chat/inputs-with-mentions chat-id] input-segments))}))
(rf/defn on-text-input
{:events [:mention/on-text-input]}
[{:keys [db]} {:keys [previous-text start end] :as args}]
(let [previous-text
;; NOTE(rasom): on iOS `previous-text` contains entire input's text. To
;; get only removed part of text we have cut it.
(if platform/android?
previous-text
(subs previous-text start end))
chat-id (:current-chat-id db)
state (merge args {:previous-text previous-text})
state (set/rename-keys state
{:previous-text :PreviousText
:new-text :NewText
:start :Start
:end :End})
params [chat-id state]
method "wakuext_chatMentionOnTextInput"]
(log/debug "[mentions] on-text-input" {:params params})
(rf/defn on-change-text
{:events [:mention/on-change-text]}
[{:keys [db]} text]
(let [chat-id (:current-chat-id db)
params [chat-id text]
method "wakuext_chatMentionOnChangeText"]
(log/debug "[mentions] on-change-text" {:params params})
{:json-rpc/call [{:method method
:params [chat-id state]
:on-success #(rf/dispatch [:mention/on-text-input-success %])
:params params
:on-success #(rf/dispatch [:mention/on-change-text-success %])
:on-error #(rf/dispatch [:mention/on-error
{:method method
:params params} %])}]}))
(rf/defn on-text-input-success
{:events [:mention/on-text-input-success]}
(rf/defn on-change-text-success
{:events [:mention/on-change-text-success]}
[{:keys [db]} result]
(log/debug "[mentions] on-text-input-success" {:result result})
(let [{:keys [state chat-id]} (transfer-mention-result result)]
{:db (assoc-in db [:chats/mentions chat-id :mentions] state)}))
(let [{:keys [state chat-id mentionable-users input-segments]} (transfer-mention-result result)]
{:db (-> db
(assoc-in [:chats/mention-suggestions chat-id] mentionable-users)
(assoc-in [:chats/mentions chat-id :mentions] state)
(assoc-in [:chat/inputs-with-mentions chat-id] input-segments))}))
(rf/defn recheck-at-idxs
[{:keys [db]} public-key]
@@ -164,27 +168,20 @@
cursor (+ at-sign-idx (count primary-name) 2)]
(rf/merge
cofx
{:db (-> db
(assoc-in [:chats/mention-suggestions chat-id] nil))
:set-text-input-value [chat-id new-text text-input-ref]
:dispatch [:chat.ui/set-chat-input-text new-text chat-id]}
;; NOTE(rasom): Some keyboards do not react on selection property passed to
;; text input (specifically Samsung keyboard with predictive text set on).
;; In this case, if the user continues typing after the programmatic change,
;; the new text is added to the last known cursor position before
;; programmatic change. By calling `reset-text-input-cursor` we force the
;; keyboard's cursor position to be changed before the next input.
(reset-text-input-cursor text-input-ref cursor)
;; NOTE(roman): on-text-input event is not dispatched when we change input
;; programmatically, so we have to call `on-text-input` manually
(on-text-input
(let [match-len (count match)
start (inc at-sign-idx)
end (+ start match-len)]
{:new-text match
:previous-text searched-text
:start start
:end end}))
(let [common {:db (-> db
(assoc-in [:chats/mention-suggestions chat-id] nil))
:dispatch [:chat.ui/set-chat-input-text new-text chat-id]}
extra (if (not config/new-composer-enabled?)
;; NOTE(rasom): Some keyboards do not react on selection property passed to
;; text input (specifically Samsung keyboard with predictive text set on).
;; In this case, if the user continues typing after the programmatic change,
;; the new text is added to the last known cursor position before
;; programmatic change. By calling `reset-text-input-cursor` we force the
;; keyboard's cursor position to be changed before the next input.
{:set-text-input-value [chat-id new-text text-input-ref]
:reset-text-input-cursor (reset-text-input-cursor text-input-ref cursor)}
{})]
(merge common extra))
(recheck-at-idxs public-key))))
(rf/defn clear-suggestions
@@ -220,7 +217,7 @@
(when text
(log/debug "[mentions] check-selection" {:params params})
{:json-rpc/call [{:method method
:params [chat-id text start end]
:params params
:on-success #(rf/dispatch [:mention/on-handle-selection-change-success %])
:on-error #(rf/dispatch [:mention/on-error
{:method method
@@ -230,38 +227,16 @@
{:events [:mention/on-handle-selection-change-success]}
[{:keys [db]} result]
(log/debug "[mentions] on-check-selection-success" {:result result})
(let [{:keys [state chat-id]} (transfer-mention-result result)]
{:db (assoc-in db [:chats/mentions chat-id :mentions] (rename-state state))}))
(re-frame/reg-fx
::reset-text-input-cursor
(fn [[ref cursor]]
(when ref
(status/reset-keyboard-input
(rn/find-node-handle (react/current-ref ref))
cursor))))
(rf/defn calculate-suggestions
{:events [:mention/calculate-suggestions]}
[{:keys [db]}]
(let [chat-id (:current-chat-id db)
text (get-in db [:chat/inputs chat-id :input-text])
params [chat-id text]
method "wakuext_chatMentionCalculateSuggestions"]
(log/debug "[mentions] calculate-suggestions" {:params params})
{:json-rpc/call [{:method method
:params [chat-id text]
:on-success #(rf/dispatch [:mention/on-calculate-suggestions-success %])
:on-error #(rf/dispatch [:mention/on-error
{:method method
:params params} %])}]}))
(rf/defn on-calculate-suggestions-success
{:events [:mention/on-calculate-suggestions-success]}
[{:keys [db]} result]
(log/debug "[mentions] on-calculate-suggestions-success" {:result result})
(let [{:keys [state chat-id mentionable-users input-segments]} (transfer-mention-result result)]
{:db (-> db
(assoc-in [:chats/mention-suggestions chat-id] mentionable-users)
(assoc-in [:chats/mentions chat-id :mentions] state)
(assoc-in [:chat/inputs-with-mentions chat-id] input-segments))}))
(re-frame/reg-fx
::reset-text-input-cursor
(fn [[ref cursor]]
(when ref
(native-module/reset-keyboard-input
(rn/find-node-handle (react/current-ref ref))
cursor))))
+1 -1
View File
@@ -505,7 +505,7 @@
(handle-response response-js)))
(rf/defn open-create-community
{:events [::open-create-community]}
{:events [:legacy-only-for-e2e/open-create-community]}
[{:keys [db] :as cofx}]
(rf/merge cofx
{:db (assoc db :communities/create {:membership constants/community-no-membership-access})}
+1 -6
View File
@@ -9,8 +9,7 @@
(defn rpc->type
[{:keys [chat-type name] :as chat}]
(cond
(or (= constants/public-chat-type chat-type)
(= constants/profile-chat-type chat-type)
(or (= constants/profile-chat-type chat-type)
(= constants/timeline-chat-type chat-type))
(assoc chat
:chat-name (str "#" name)
@@ -39,10 +38,6 @@
(defn- unmarshal-members
[{:keys [members chat-type] :as chat}]
(cond
(= constants/public-chat-type chat-type) (assoc chat
:contacts #{}
:admins #{}
:members-joined #{})
(= constants/private-group-chat-type chat-type) (merge chat
(reduce members-reducer
{:admins #{}
+5 -5
View File
@@ -1,23 +1,23 @@
(ns status-im.ethereum.core
(:require [clojure.string :as string]
[status-im.ethereum.eip55 :as eip55]
[status-im.native-module.core :as status]))
[native-module.core :as native-module]))
(defn sha3
[s]
(when s
(status/sha3 (str s))))
(native-module/sha3 (str s))))
(defn utf8-to-hex
[s]
(let [hex (status/utf8-to-hex (str s))]
(let [hex (native-module/utf8-to-hex (str s))]
(if (empty? hex)
nil
hex)))
(defn hex-to-utf8
[s]
(let [utf8 (status/hex-to-utf8 s)]
(let [utf8 (native-module/hex-to-utf8 s)]
(if (empty? utf8)
nil
utf8)))
@@ -118,7 +118,7 @@
(defn address?
[s]
(when s
(status/address? s)))
(native-module/address? s)))
(defn network->chain-id
[network]
+3 -3
View File
@@ -5,7 +5,7 @@
e.g. 0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"
(:require [clojure.string :as string]
[status-im.native-module.core :as status]))
[native-module.core :as native-module]))
(def hex-prefix "0x")
@@ -13,7 +13,7 @@
"Converts an arbitrary case address to one with correct checksum case."
[address]
(when address
(status/to-checksum-address
(native-module/to-checksum-address
(if (string/starts-with? address hex-prefix)
address
(str hex-prefix address)))))
@@ -21,4 +21,4 @@
(defn valid-address-checksum?
"Checks address checksum validity."
[address]
(status/check-address-checksum address))
(native-module/check-address-checksum address))
+2 -2
View File
@@ -1,6 +1,6 @@
(ns status-im.ethereum.encode
(:require [status-im.native-module.core :as status]))
(:require [native-module.core :as native-module]))
(defn uint
[x]
(str "0x" (status/number-to-hex x)))
(str "0x" (native-module/number-to-hex x)))
+2 -2
View File
@@ -1,6 +1,6 @@
(ns status-im.ethereum.ens
(:require [clojure.string :as string]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im2.common.json-rpc.events :as json-rpc]))
;; this is the addresses of ens registries for the different networks
@@ -66,7 +66,7 @@
:params [chain-id ens-name]
:on-success
;;NOTE: returns a timestamp in s and we want ms
#(cb (* (js/Number (status/hex-to-number %)) 1000))}))
#(cb (* (js/Number (native-module/hex-to-number %)) 1000))}))
(defn register-prepare-tx
[chain-id from ens-name pubkey cb]
+10 -4
View File
@@ -7,7 +7,6 @@
status-im.bootnodes.core
status-im.browser.core
status-im.browser.permissions
status-im.chat.models
status-im.chat.models.images
status-im.chat.models.input
status-im.chat.models.loading
@@ -30,7 +29,7 @@
status-im.multiaccounts.logout.core
[status-im.multiaccounts.model :as multiaccounts.model]
status-im.multiaccounts.update.core
[status-im.native-module.core :as status]
[native-module.core :as native-module]
status-im.network.net-info
status-im.pairing.core
status-im.profile.core
@@ -60,6 +59,9 @@
status-im2.contexts.onboarding.events
status-im.chat.models.gaps
[status-im2.navigation.events :as navigation]
[status-im2.common.theme.core :as theme]
[react-native.core :as rn]
[react-native.platform :as platform]
status-im2.contexts.chat.home.events))
(re-frame/reg-fx
@@ -85,12 +87,16 @@
(re-frame/reg-fx
:ui/close-application
(fn [_]
(status/close-application)))
(native-module/close-application)))
(re-frame/reg-fx
::app-state-change-fx
(fn [state]
(status/app-state-change state)))
(when (and platform/ios? (= state "active"))
;; Change the app theme if the ios device theme was updated when the app was in the background
;; https://github.com/status-im/status-mobile/issues/15708
(theme/change-device-theme (rn/get-color-scheme)))
(native-module/app-state-change state)))
(re-frame/reg-fx
:ui/listen-to-window-dimensions-change
-15
View File
@@ -2,21 +2,6 @@
(:require [re-frame.core :as re-frame]
[status-im.utils.http :as http]))
(re-frame/reg-fx
:http-get
(fn [{:keys [url response-validator on-success on-error timeout-ms]}]
(let [opts {:valid-response? response-validator
:timeout-ms timeout-ms}]
(http/get url on-success on-error opts))))
(re-frame/reg-fx
:http-get-n
(fn [calls]
(doseq [{:keys [url response-validator on-success on-error timeout-ms]} calls]
(let [opts {:valid-response? response-validator
:timeout-ms timeout-ms}]
(http/get url on-success on-error opts)))))
(re-frame/reg-fx
:http-post
(fn [{:keys [url data response-validator on-success on-error timeout-ms opts]}]
+1 -1
View File
@@ -125,7 +125,7 @@
(rf-test/wait-for ; wait for login
[::transport/messenger-started]
(assert-messenger-started)
(rf/dispatch-sync [:status-im.communities.core/open-create-community])
(rf/dispatch-sync [:legacy-only-for-e2e/open-create-community])
(doseq [[k v] (dissoc community :membership)]
(rf/dispatch-sync [:status-im.communities.core/create-field k v]))
(rf/dispatch [:status-im.communities.core/create-confirmation-pressed])
+2 -2
View File
@@ -3,7 +3,7 @@
["react-native" :refer (BackHandler)]
[re-frame.core :as re-frame]
[status-im.keycard.card :as card]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.utils.types :as types]
[taoensso.timbre :as log]))
@@ -202,7 +202,7 @@
(re-frame/reg-fx
:keycard/generate-name-and-photo
(fn [{:keys [public-key on-success]}]
(status/gfycat-identicon-async
(native-module/gfycat-identicon-async
public-key
(fn [whisper-name photo-path]
(re-frame/dispatch
+5 -5
View File
@@ -4,7 +4,7 @@
[clojure.string :as string]
[status-im.ethereum.core :as ethereum]
[status-im.keycard.keycard :as keycard]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.utils.platform :as platform]
[status-im.utils.types :as types]
[taoensso.timbre :as log]))
@@ -296,7 +296,7 @@
(defn save-multiaccount-and-login
[{:keys [key-uid multiaccount-data password settings node-config accounts-data chat-key]}]
(status/save-multiaccount-and-login-with-keycard
(native-module/save-multiaccount-and-login-with-keycard
key-uid
(types/clj->json multiaccount-data)
password
@@ -307,15 +307,15 @@
(defn login
[args]
(status/login-with-keycard args))
(native-module/login-with-keycard args))
(defn send-transaction-with-signature
[{:keys [transaction signature on-completed]}]
(status/send-transaction-with-signature transaction signature on-completed))
(native-module/send-transaction-with-signature transaction signature on-completed))
(defn delete-multiaccount-before-migration
[{:keys [key-uid on-success on-error]}]
(status/delete-multiaccount
(native-module/delete-multiaccount
key-uid
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
+3 -3
View File
@@ -10,7 +10,7 @@
status-im.keycard.fx
[status-im.multiaccounts.create.core :as multiaccounts.create]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.popover.core :as popover]
[utils.re-frame :as rf]
[utils.datetime :as datetime]
@@ -250,14 +250,14 @@
(re-frame/reg-fx
::finish-migration
(fn [[account settings password encryption-pass login-params]]
(status/convert-to-keycard-account
(native-module/convert-to-keycard-account
account
settings
password
encryption-pass
#(let [{:keys [error]} (types/json->clj %)]
(if (string/blank? error)
(status/login-with-keycard login-params)
(native-module/login-with-keycard login-params)
(throw
(js/Error.
"Please shake the phone to report this error and restart the app. Migration failed unexpectedly.")))))))
+15 -15
View File
@@ -7,7 +7,7 @@
[utils.i18n :as i18n]
[status-im.keycard.keycard :as keycard]
[status-im.multiaccounts.create.core :as multiaccounts.create]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.node.core :as node]
[status-im.utils.types :as types]
[status-im.utils.utils :as utils]
@@ -249,14 +249,14 @@
[{:keys [password on-success]}]
(when (and (not @initialization)
(not @derived-acc))
(status/multiaccount-import-mnemonic
(native-module/multiaccount-import-mnemonic
"night fortune spider version version armed amused winner matter tonight cave flag"
nil
(fn [result]
(let [{:keys [id] :as root-data}
(multiaccounts.create/normalize-multiaccount-data-keys
(types/json->clj result))]
(status-im.native-module.core/multiaccount-derive-addresses
(native-module.core/multiaccount-derive-addresses
id
[constants/path-wallet-root
constants/path-eip1581
@@ -266,7 +266,7 @@
(let [derived-data (multiaccounts.create/normalize-derived-data-keys
(types/json->clj result))
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
(status/gfycat-identicon-async
(native-module/gfycat-identicon-async
public-key
(fn [name photo-path]
(let [derived-data-extended
@@ -294,7 +294,7 @@
(if delete-multiaccount?
(fn [on-deletion-success]
(js/alert "OH SHEET")
(status/delete-multiaccount
(native-module/delete-multiaccount
key-uid
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
@@ -304,7 +304,7 @@
(fn [cb] (cb)))]
(deletion-wrapper
(fn []
(status/multiaccount-store-derived
(native-module/multiaccount-store-derived
id
(:key-uid response)
[constants/path-wallet-root
@@ -398,14 +398,14 @@
path-num (inc (get-in @re-frame.db/app-db
[:multiaccount :latest-derived-path]))
path (str "m/" path-num)]
(status/multiaccount-load-account
(native-module/multiaccount-load-account
wallet-root-address
hashed-password
(fn [value]
(let [{:keys [id error]} (types/json->clj value)]
(if error
(re-frame/dispatch [::new-account-error :password-error error])
(status/multiaccount-derive-addresses
(native-module/multiaccount-derive-addresses
id
[path]
(fn [derived]
@@ -413,7 +413,7 @@
(if (some (fn [a] (= derived-address (get a :address))) accounts)
(re-frame/dispatch [::new-account-error :account-error
(i18n/label :t/account-exists-title)])
(status/multiaccount-store-derived
(native-module/multiaccount-store-derived
id
key-uid
[path]
@@ -436,7 +436,7 @@
(swap! state assoc-in
[:application-info :key-uid]
(:key-uid keys))
(status/multiaccount-store-derived
(native-module/multiaccount-store-derived
id
(:key-uid keys)
[constants/path-wallet-root
@@ -473,7 +473,7 @@
{:account address
:password password
:data (or data (str "0x" hash))})]
(status/sign-message
(native-module/sign-message
params
(fn [res]
(let [signature (-> res
@@ -481,7 +481,7 @@
:result
ethereum/normalized-hex)]
(on-success signature)))))
(status/sign-typed-data
(native-module/sign-typed-data
data
address
password
@@ -498,7 +498,7 @@
(defn save-multiaccount-and-login
[{:keys [key-uid multiaccount-data password settings node-config accounts-data]}]
(status/save-account-and-login
(native-module/save-account-and-login
key-uid
(types/clj->json multiaccount-data)
password
@@ -508,11 +508,11 @@
(defn login
[{:keys [key-uid multiaccount-data password]}]
(status/login-with-config key-uid multiaccount-data password node/login-node-config))
(native-module/login-with-config key-uid multiaccount-data password node/login-node-config))
(defn send-transaction-with-signature
[{:keys [transaction on-completed]}]
(status/send-transaction transaction account-password on-completed))
(native-module/send-transaction transaction account-password on-completed))
(defn delete-multiaccount-before-migration
[{:keys [on-success]}]
@@ -3,7 +3,7 @@
[quo.design-system.colors :as colors]
[re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.popover.core :as popover]
[utils.re-frame :as rf]
[status-im.utils.keychain.core :as keychain]
@@ -17,7 +17,7 @@
;;; android blacklist based on device info:
(def deviceinfo (status/get-device-model-info))
(def deviceinfo (native-module/get-device-model-info))
;; {:model ?
;; :brand "Xiaomi"
+2 -1
View File
@@ -4,7 +4,7 @@
[re-frame.core :as re-frame]
[status-im.bottom-sheet.events :as bottom-sheet]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.native-module.core :as native-module]
[native-module.core :as native-module]
[utils.re-frame :as rf]
[quo2.foundations.colors :as colors]
[status-im2.constants :as constants]
@@ -150,6 +150,7 @@
(re-frame/dispatch [:change-shell-status-bar-style
(if (shell.animation/home-stack-open?) status-bar-theme :light)])
(when reload-ui?
(rf/dispatch [:dissmiss-all-overlays])
(hot-reload/reload)
(when-not (= view-id :shell-stack)
(re-frame/dispatch [:change-shell-nav-bar-color nav-bar-color]))))))
+5 -5
View File
@@ -6,7 +6,7 @@
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.eip55 :as eip55]
[utils.i18n :as i18n]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.node.core :as node]
[status-im2.config :as config]
[utils.re-frame :as rf]
@@ -44,7 +44,7 @@
(re-frame/reg-fx
::store-multiaccount
(fn [[id key-uid hashed-password callback]]
(status/multiaccount-store-derived
(native-module/multiaccount-store-derived
id
key-uid
[constants/path-wallet-root
@@ -69,7 +69,7 @@
(fn [result]
(let [derived-data (normalize-derived-data-keys (types/json->clj result))
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
(status/gfycat-identicon-async
(native-module/gfycat-identicon-async
public-key
(fn [name identicon]
(let [derived-whisper (derived-data constants/path-whisper-keyword)
@@ -81,7 +81,7 @@
(re-frame/reg-fx
:multiaccount-generate-and-derive-addresses
(fn []
(status/multiaccount-generate-and-derive-addresses
(native-module/multiaccount-generate-and-derive-addresses
5
12
[constants/path-whisper
@@ -127,7 +127,7 @@
(re-frame/reg-fx
::save-account-and-login
(fn [[key-uid multiaccount-data hashed-password settings config accounts-data]]
(status/save-account-and-login
(native-module/save-account-and-login
key-uid
multiaccount-data
hashed-password
@@ -11,7 +11,7 @@
[status-im.multiaccounts.logout.core :as multiaccounts.logout]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.multiaccounts.recover.core :as multiaccounts.recover]
[status-im.native-module.core :as native-module]
[native-module.core :as native-module]
[status-im.popover.core :as popover]
[utils.re-frame :as rf]
[status-im.utils.types :as types]
+6 -6
View File
@@ -20,7 +20,7 @@
[status-im.mobile-sync-settings.core :as mobile-network]
[status-im.multiaccounts.biometric.core :as biometric]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.node.core :as node]
[status-im.notifications.core :as notifications]
[status-im.popover.core :as popover]
@@ -58,22 +58,22 @@
(re-frame/reg-fx
::login
(fn [[key-uid account-data hashed-password]]
(status/login-with-config key-uid account-data hashed-password node/login-node-config)))
(native-module/login-with-config key-uid account-data hashed-password node/login-node-config)))
(re-frame/reg-fx
::export-db
(fn [[key-uid account-data hashed-password callback]]
(status/export-db key-uid account-data hashed-password callback)))
(native-module/export-db key-uid account-data hashed-password callback)))
(re-frame/reg-fx
::import-db
(fn [[key-uid account-data hashed-password]]
(status/import-db key-uid account-data hashed-password)))
(native-module/import-db key-uid account-data hashed-password)))
(re-frame/reg-fx
::enable-local-notifications
(fn []
(status/start-local-notifications)))
(native-module/start-local-notifications)))
(re-frame/reg-fx
::initialize-wallet-connect
@@ -363,7 +363,7 @@
(rf/defn get-node-config
[_]
(status/get-node-config #(re-frame/dispatch [::get-node-config-callback %])))
(native-module/get-node-config #(re-frame/dispatch [::get-node-config-callback %])))
(rf/defn redirect-to-root
"Decides which root should be initialised depending on user and app state"
+2 -3
View File
@@ -2,7 +2,7 @@
(:require [re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.notifications.core :as notifications]
[utils.re-frame :as rf]
[status-im.utils.keychain.core :as keychain]
@@ -16,7 +16,6 @@
(rf/merge cofx
{:set-root :progress
:chat.ui/clear-inputs nil
:chat.ui/clear-inputs-old nil
:shell/reset-bottom-tabs nil
:hide-popover nil
::logout nil
@@ -62,4 +61,4 @@
(re-frame/reg-fx
::logout
(fn []
(status/logout)))
(native-module/logout)))
@@ -9,7 +9,7 @@
[status-im.keycard.nfc :as nfc]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.multiaccounts.create.core :as multiaccounts.create]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.popover.core :as popover]
[utils.re-frame :as rf]
[status-im.utils.types :as types]
@@ -89,14 +89,14 @@
::import-multiaccount
(fn [{:keys [passphrase password success-event]}]
(log/debug "[recover] ::import-multiaccount")
(status/multiaccount-import-mnemonic
(native-module/multiaccount-import-mnemonic
passphrase
password
(fn [result]
(let [{:keys [id] :as root-data}
(multiaccounts.create/normalize-multiaccount-data-keys
(types/json->clj result))]
(status-im.native-module.core/multiaccount-derive-addresses
(native-module.core/multiaccount-derive-addresses
id
[constants/path-wallet-root
constants/path-eip1581
@@ -106,7 +106,7 @@
(let [derived-data (multiaccounts.create/normalize-derived-data-keys
(types/json->clj result))
public-key (get-in derived-data [constants/path-whisper-keyword :public-key])]
(status/gfycat-identicon-async
(native-module/gfycat-identicon-async
public-key
(fn [name identicon]
(let [derived-data-extended
@@ -2,7 +2,7 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.ethereum.core :as ethereum]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.popover.core :as popover]
[utils.re-frame :as rf]
[status-im.utils.keychain.core :as keychain]
@@ -59,7 +59,7 @@
(re-frame/reg-fx
::change-db-password
(fn [[key-uid {:keys [current-password new-password]}]]
(status/reset-password
(native-module/reset-password
key-uid
(ethereum/sha3 (security/safe-unmask-data current-password))
(ethereum/sha3 (security/safe-unmask-data new-password))
@@ -88,9 +88,9 @@
::validate-current-password-and-reset
(fn [{:keys [address current-password] :as form-vals}]
(let [hashed-pass (ethereum/sha3 (security/safe-unmask-data current-password))]
(status/verify address
hashed-pass
(partial handle-verification form-vals)))))
(native-module/verify address
hashed-pass
(partial handle-verification form-vals)))))
(rf/defn reset
{:events [::reset]}
+2 -2
View File
@@ -2,7 +2,7 @@
(:require ["@react-native-community/netinfo" :default net-info]
[re-frame.core :as re-frame]
[status-im.mobile-sync-settings.core :as mobile-network]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[utils.re-frame :as rf]
[status-im.wallet.core :as wallet]
[taoensso.timbre :as log]))
@@ -59,4 +59,4 @@
(re-frame/reg-fx
:network/notify-status-go
(fn [[network-type expensive?]]
(status/connection-change network-type expensive?)))
(native-module/connection-change network-type expensive?)))
+2 -2
View File
@@ -1,6 +1,6 @@
(ns status-im.node.core
(:require [re-frame.core :as re-frame]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im2.config :as config]
[utils.re-frame :as rf]
[status-im.utils.platform :as utils.platform]
@@ -221,4 +221,4 @@ app-db"
(re-frame/reg-fx
::prepare-new-config
(fn [[key-uid config callback]]
(status/prepare-dir-and-update-config key-uid config callback)))
(native-module/prepare-dir-and-update-config key-uid config callback)))
+3 -3
View File
@@ -11,9 +11,9 @@
[status-im.notifications.android :as pn-android]
[utils.re-frame :as rf]
[status-im.utils.money :as money]
[status-im.utils.react-native :as react-native-utils]
[status-im.utils.types :as types]
[status-im.utils.utils :as utils]))
[status-im.utils.utils :as utils]
[react-native.core :as rn]))
(def default-erc20-token
{:symbol :ERC20
@@ -56,7 +56,7 @@
(fn [notification]
(handle-notification-press {:userInfo (bean/bean (.getData ^js
notification))})))
(.addListener ^js react-native-utils/device-event-emitter
(.addListener ^js rn/device-event-emitter
notification-event-android
(fn [^js data]
(when (and data (.-dataJSON data))
+6 -15
View File
@@ -1,7 +1,5 @@
(ns status-im.qr-scanner.core
(:require [re-frame.core :as re-frame]
[status-im.add-new.db :as new-chat.db]
[status-im.chat.models :as chat]
[status-im.ethereum.core :as ethereum]
[status-im.group-chats.core :as group-chats]
[utils.i18n :as i18n]
@@ -43,25 +41,24 @@
{:browser/show-browser-selection url}
(navigation/navigate-back)))
(defn own-public-key?
[{:keys [multiaccount]} public-key]
(= (:public-key multiaccount) public-key))
(rf/defn handle-private-chat
[{:keys [db] :as cofx} {:keys [chat-id]}]
(if-not (new-chat.db/own-public-key? db chat-id)
(if-not (own-public-key? db chat-id)
{:dispatch [:chat.ui/start-chat chat-id]}
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (i18n/label :t/can-not-add-yourself)}}))
(rf/defn handle-public-chat
[cofx {:keys [topic]}]
(when (seq topic)
(chat/start-public-chat cofx topic)))
(rf/defn handle-group-chat
[cofx params]
(group-chats/create-from-link cofx params))
(rf/defn handle-view-profile
[{:keys [db] :as cofx} {:keys [public-key ens-name]}]
(let [own (new-chat.db/own-public-key? db public-key)]
(let [own (own-public-key? db public-key)]
(cond
(and public-key own)
(rf/merge cofx
@@ -85,11 +82,6 @@
(navigation/change-tab :wallet-stack)
(navigation/pop-to-root :shell-stack)))
(rf/defn handle-wallet-connect
{:events [::handle-wallet-connect-uri]}
[cofx data]
{:dispatch [:wallet-connect/pair data]})
(rf/defn handle-local-pairing
{:events [::handle-local-pairing-uri]}
[_ data]
@@ -99,7 +91,6 @@
{:events [::match-scanned-value]}
[cofx {:keys [type] :as data}]
(case type
:public-chat (handle-public-chat cofx data)
:group-chat (handle-group-chat cofx data)
:private-chat (handle-private-chat cofx data)
:contact (handle-view-profile cofx data)
@@ -65,11 +65,3 @@
k
(get ui k))
k)))
(def reactions-old
{:love (js/require "../resources/images/reactions/love.png")
:angry (js/require "../resources/images/reactions/angry.png")
:sad (js/require "../resources/images/reactions/sad.png")
:laugh (js/require "../resources/images/reactions/laugh.png")
:thumbs-up (js/require "../resources/images/reactions/thumbs-up.png")
:thumbs-down (js/require "../resources/images/reactions/thumbs-down.png")})
+5 -19
View File
@@ -2,16 +2,15 @@
(:require [bidi.bidi :as bidi]
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.add-new.db :as public-chat.db]
[status-im2.contexts.chat.events :as chat.events]
[status-im2.constants :as constants]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.eip681 :as eip681]
[status-im.ethereum.ens :as ens]
[status-im.utils.types :as types]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.ethereum.stateofus :as stateofus]
[status-im2.utils.validators :as validators]
[utils.validators :as validators]
[status-im.utils.http :as http]
[status-im.utils.wallet-connect :as wallet-connect]
[taoensso.timbre :as log]
@@ -21,8 +20,6 @@
(def uri-schemes ["status-im://" "status-im:"])
(def wallet-connect-scheme "wc:")
(def web-prefixes ["https://" "http://" "https://www." "http://wwww."])
(def web2-domain "join.status.im")
@@ -48,9 +45,7 @@
(def routes
[""
{handled-schemes {["" :chat-id] :public-chat
"chat" {["/public/" :chat-id] :public-chat}
"b/" browser-extractor
{handled-schemes {"b/" browser-extractor
"browser/" browser-extractor
["p/" :chat-id] :private-chat
["cr/" :community-id] :community-requests
@@ -83,8 +78,9 @@
:ens-name ens-name})
valid-compressed-key?
(status/compressed-key->public-key
(native-module/compressed-key->public-key
user-id
constants/deserialization-key
(fn [response]
(let [{:keys [error]} (types/json->clj response)]
(when-not error
@@ -106,14 +102,6 @@
(callback {:type :contact
:error :not-found}))))
(defn match-public-chat
[{:keys [chat-id]}]
(if (public-chat.db/valid-topic? chat-id)
{:type :public-chat
:topic chat-id}
{:type :public-chat
:error :invalid-topic}))
(defn match-group-chat
[chats {:strs [a a1 a2]}]
(let [[admin-pk encoded-chat-name chat-id] [a a1 a2]
@@ -224,8 +212,6 @@
(let [{:keys [handler route-params query-params]} (match-uri uri)]
(log/info "[router] uri " uri " matched " handler " with " route-params)
(cond
(= handler :public-chat)
(cb (match-public-chat route-params))
(= handler :browser)
(cb (match-browser uri route-params))
-6
View File
@@ -18,9 +18,6 @@
:query-params (when (= 3 (count expected)) (last expected))
:uri uri})
"status-im://status"
[:public-chat {:chat-id "status"}]
"status-im://u/statuse2e"
[:user {:user-id "statuse2e"}]
@@ -36,9 +33,6 @@
(str "https://join.status.im/g/args?a=" public-key "&a1=" chat-name-url "&a2=" chat-id)
[:group-chat {:params "arg"} {"a" public-key "a1" chat-name "a2" chat-id}]
"https://join.status.im/status"
[:public-chat {:chat-id "status"}]
"https://join.status.im/u/statuse2e"
[:user {:user-id "statuse2e"}]
+22 -22
View File
@@ -9,7 +9,7 @@
[utils.i18n :as i18n]
[status-im.keycard.card :as keycard.card]
[status-im.keycard.common :as keycard.common]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.signing.eip1559 :as eip1559]
[status-im.signing.keycard :as signing.keycard]
[utils.re-frame :as rf]
@@ -26,9 +26,9 @@
(re-frame/reg-fx
:signing/send-transaction-fx
(fn [{:keys [tx-obj hashed-password cb]}]
(status/send-transaction (types/clj->json tx-obj)
hashed-password
cb)))
(native-module/send-transaction (types/clj->json tx-obj)
hashed-password
cb)))
(re-frame/reg-fx
:signing/show-transaction-error
@@ -43,21 +43,21 @@
(re-frame/reg-fx
:signing.fx/sign-message
(fn [{:keys [params on-completed]}]
(status/sign-message (types/clj->json params)
on-completed)))
(native-module/sign-message (types/clj->json params)
on-completed)))
(re-frame/reg-fx
:signing.fx/recover-message
(fn [{:keys [params on-completed]}]
(status/recover-message (types/clj->json params)
on-completed)))
(native-module/recover-message (types/clj->json params)
on-completed)))
(re-frame/reg-fx
:signing.fx/sign-typed-data
(fn [{:keys [v4 data account on-completed hashed-password]}]
(if v4
(status/sign-typed-data-v4 data account hashed-password on-completed)
(status/sign-typed-data data account hashed-password on-completed))))
(native-module/sign-typed-data-v4 data account hashed-password on-completed)
(native-module/sign-typed-data data account hashed-password on-completed))))
(defn get-contact
[db to]
@@ -109,18 +109,18 @@
(sign-message cofx)
(let [tx-obj-to-send (merge tx-obj
(when gas
{:gas (str "0x" (status/number-to-hex gas))})
{:gas (str "0x" (native-module/number-to-hex gas))})
(when gasPrice
{:gasPrice (str "0x" (status/number-to-hex gasPrice))})
{:gasPrice (str "0x" (native-module/number-to-hex gasPrice))})
(when nonce
{:nonce (str "0x" (status/number-to-hex nonce))})
{:nonce (str "0x" (native-module/number-to-hex nonce))})
(when maxPriorityFeePerGas
{:maxPriorityFeePerGas (str "0x"
(status/number-to-hex
(native-module/number-to-hex
(js/parseInt maxPriorityFeePerGas)))})
(when maxFeePerGas
{:maxFeePerGas (str "0x"
(status/number-to-hex
(native-module/number-to-hex
(js/parseInt maxFeePerGas)))}))]
(when-not in-progress?
{:db (update db :signing/sign assoc :error nil :in-progress? true)
@@ -184,7 +184,7 @@
(let [{:keys [symbol decimals] :as token} (tokens/address->token (:wallet/all-tokens db) to)]
(when (and token data (string? data))
(when-let [type (get-method-type data)]
(let [[address value _] (status/decode-parameters
(let [[address value _] (native-module/decode-parameters
(str "0x" (subs data 10))
(if (= type :approve-and-call)
["address" "uint256" "bytes"]
@@ -476,7 +476,7 @@
{:events [:wallet.ui/sign-transaction-button-clicked-from-chat]}
[{:keys [db] :as cofx} {:keys [to amount from token]}]
(let [{:keys [symbol address]} token
amount-hex (str "0x" (status/number-to-hex amount))
amount-hex (str "0x" (native-module/number-to-hex amount))
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
from-address (:address from)
identity (:current-chat-id db)
@@ -495,7 +495,7 @@
:from from-address
:chat-id identity
:command? true
:data (status/encode-transfer to-norm amount-hex)})}))
:data (native-module/encode-transfer to-norm amount-hex)})}))
{:db db
:json-rpc/call
[{:method "wakuext_requestAddressForTransaction"
@@ -512,7 +512,7 @@
[{:keys [db] :as cofx} {:keys [amount from token]}]
(let [{:keys [request-parameters chat-id]} (:wallet/prepare-transaction db)
{:keys [symbol address]} token
amount-hex (str "0x" (status/number-to-hex amount))
amount-hex (str "0x" (native-module/number-to-hex amount))
to-norm (:address request-parameters)
from-address (:address from)]
(rf/merge cofx
@@ -532,13 +532,13 @@
:command? true
:message-id (:id request-parameters)
:chat-id chat-id
:data (status/encode-transfer to-norm amount-hex)})})))))
:data (native-module/encode-transfer to-norm amount-hex)})})))))
(rf/defn sign-transaction-button-clicked
{:events [:wallet.ui/sign-transaction-button-clicked]}
[{:keys [db] :as cofx} {:keys [to amount from token gas gasPrice maxFeePerGas maxPriorityFeePerGas]}]
(let [{:keys [symbol address]} token
amount-hex (str "0x" (status/number-to-hex amount))
amount-hex (str "0x" (native-module/number-to-hex amount))
to-norm (ethereum/normalized-hex (if (string? to) to (:address to)))
from-address (:address from)]
(rf/merge cofx
@@ -558,7 +558,7 @@
{:to to-norm
:value amount-hex}
{:to (ethereum/normalized-hex address)
:data (status/encode-transfer to-norm amount-hex)}))}))))
:data (native-module/encode-transfer to-norm amount-hex)}))}))))
(re-frame/reg-fx
:signing/get-transaction-by-hash-fx
+4 -4
View File
@@ -1,15 +1,15 @@
(ns status-im.signing.core-test
(:require [cljs.test :refer-macros [deftest is testing]]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.signing.core :as signing]))
(deftest signing-test
(testing "showing sheet"
(let [to "0x2f88d65f3cb52605a54a833ae118fb1363acccd2"
contract "0xc55cf4b03948d7ebc8b9e8bad92643703811d162"
amount1-hex (str "0x" (status/number-to-hex "10000000000000000000"))
amount2-hex (str "0x" (status/number-to-hex "100000000000000000000"))
data (status/encode-transfer to amount2-hex)
amount1-hex (str "0x" (native-module/number-to-hex "10000000000000000000"))
amount2-hex (str "0x" (native-module/number-to-hex "100000000000000000000"))
data (native-module/encode-transfer to amount2-hex)
first-tx {:tx-obj {:to to
:from nil
:value amount1-hex}}
+9 -9
View File
@@ -1,7 +1,7 @@
(ns status-im.signing.keycard
(:require [re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[utils.re-frame :as rf]
[status-im.utils.types :as types]
[taoensso.timbre :as log]))
@@ -9,19 +9,19 @@
(re-frame/reg-fx
::hash-transaction
(fn [{:keys [transaction on-completed]}]
(status/hash-transaction (types/clj->json transaction) on-completed)))
(native-module/hash-transaction (types/clj->json transaction) on-completed)))
(re-frame/reg-fx
::hash-message
(fn [{:keys [message on-completed]}]
(status/hash-message message on-completed)))
(native-module/hash-message message on-completed)))
(re-frame/reg-fx
::hash-typed-data
(fn [{:keys [v4 data on-completed]}]
(if v4
(status/hash-typed-data-v4 data on-completed)
(status/hash-typed-data data on-completed))))
(native-module/hash-typed-data-v4 data on-completed)
(native-module/hash-typed-data data on-completed))))
(defn prepare-transaction
[{:keys [gas gasPrice data nonce tx-obj] :as params}]
@@ -37,17 +37,17 @@
maxPriorityFeePerGas
(assoc :maxPriorityFeePerGas
(str "0x"
(status/number-to-hex
(native-module/number-to-hex
(js/parseInt maxPriorityFeePerGas))))
maxFeePerGas
(assoc :maxFeePerGas
(str "0x"
(status/number-to-hex
(native-module/number-to-hex
(js/parseInt maxFeePerGas))))
gas
(assoc :gas (str "0x" (status/number-to-hex gas)))
(assoc :gas (str "0x" (native-module/number-to-hex gas)))
gasPrice
(assoc :gasPrice (str "0x" (status/number-to-hex gasPrice)))
(assoc :gasPrice (str "0x" (native-module/number-to-hex gasPrice)))
data
(assoc :data data)
nonce
@@ -1,362 +0,0 @@
(ns status-im.ui.screens.add-new.new-chat.views
(:require
[clojure.string :as string]
[quo.core :as quo]
[quo.design-system.colors :as colors]
[quo.platform :as platform]
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ethereum.ens :as ens]
[utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.qr-scanner.core :as qr-scanner]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.chat.photos :as photos]
[status-im2.utils.validators :as validators]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.identicon :as identicon]
[status-im.utils.utils :as utils]
[utils.debounce :as debounce])
(:require-macros [status-im.utils.views :as views]))
(defn- render-row
[row]
[quo/list-item
{:title (:primary-name row)
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo row)]
:on-press #(re-frame/dispatch [:chat.ui/start-chat
(:public-key row)])}])
(defn- icon-wrapper
[color icon]
[react/view
{:style {:width 32
:height 32
:border-radius 25
:align-items :center
:justify-content :center
:background-color color}}
icon])
(defn- input-icon
[state new-contact? entered-nickname blocked?]
(let [icon (if new-contact? :main-icons/add :main-icons/arrow-right)]
(cond
(= state :searching)
[icon-wrapper colors/gray
[react/activity-indicator {:color colors/white-persist}]]
(and (= state :valid) (not blocked?))
[react/touchable-highlight
{:on-press #(debounce/dispatch-and-chill [:contact.ui/contact-code-submitted new-contact?
entered-nickname]
3000)}
[icon-wrapper colors/blue
[icons/icon icon {:color colors/white-persist}]]]
:else
[icon-wrapper colors/gray
[icons/icon icon {:color colors/white-persist}]])))
(defn get-validation-label
[value]
(case value
:invalid
(i18n/label :t/profile-not-found)
:yourself
(i18n/label :t/can-not-add-yourself)))
(defn search-contacts
[filter-text {:keys [name alias nickname]}]
(or
(string/includes? (string/lower-case (str name)) filter-text)
(string/includes? (string/lower-case (str alias)) filter-text)
(when nickname
(string/includes? (string/lower-case (str nickname)) filter-text))))
(defn filter-contacts
[filter-text contacts]
(let [lower-filter-text (string/lower-case filter-text)]
(if filter-text
(filter (partial search-contacts lower-filter-text) contacts)
contacts)))
(defn is-public-key?
[k]
(and
(string? k)
(string/starts-with? k "0x")))
(defn is-valid-username?
[username]
(let [is-chat-key? (and (is-public-key? username)
(= (count username) 132))
is-ens? (ens/valid-eth-name-prefix? username)]
(or is-chat-key? is-ens?)))
(defn translate-anim
[translate-y-value translate-y-anim-value]
(animation/start
(animation/timing translate-y-anim-value
{:toValue translate-y-value
:duration 200
:useNativeDriver true})))
(views/defview new-chat
[]
(views/letsubs [contacts [:contacts/active]
{:keys [state ens-name public-key error]} [:contacts/new-identity]
search-value (reagent/atom "")
account @(re-frame/subscribe [:multiaccount])
on-share #(re-frame/dispatch
[:show-popover
{:view :share-chat-key
:address (account :public-key)
:ens-name (account :preferred-name)}])
my-profile-button-anim-y (animation/create-value 0)
keyboard-show-listener (atom nil)
keyboard-hide-listener (atom nil)
on-keyboard-show (fn []
;; 42 is the bottom position so we
;; translate it by 32 pts to leave 10 as
;; margin
(translate-anim 32
my-profile-button-anim-y))
on-keyboard-hide (fn []
(translate-anim 0
my-profile-button-anim-y))
keyboard-show-event (if platform/android?
"keyboardDidShow"
"keyboardWillShow")
keyboard-hide-event (if platform/android?
"keyboardDidHide"
"keyboardWillHide")]
{:component-did-mount
(fn [_]
(reset! keyboard-show-listener (.addListener react/keyboard keyboard-show-event on-keyboard-show))
(reset! keyboard-hide-listener (.addListener react/keyboard
keyboard-hide-event
on-keyboard-hide)))
:component-will-unmount
(fn []
(some-> ^js @keyboard-show-listener
.remove)
(some-> ^js @keyboard-hide-listener
.remove))}
[kb-presentation/keyboard-avoiding-view {:style {:flex 1}}
[react/view {:style {:flex 1}}
[topbar/topbar
{:title (i18n/label :t/new-chat)
:modal? true
:right-accessories
[{:icon :qr
:accessibility-label :scan-contact-code-button
:on-press #(re-frame/dispatch [::qr-scanner/scan-code
{:title (i18n/label :t/new-chat)
:handler :contact/qr-code-scanned}])}]}]
[react/view
{:flex-direction :row
:padding 16}
[react/view {:flex 1}
[quo/text-input
{:on-change-text
#(do
(reset! search-value %)
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :empty])
(debounce/debounce-and-dispatch [:contacts/set-new-identity %] 600))
:on-submit-editing
#(when (= state :valid)
(debounce/dispatch-and-chill [:contact.ui/contact-code-submitted false nil] 3000))
:placeholder (i18n/label :t/enter-contact-code)
:show-cancel false
:accessibility-label :enter-contact-code-input
:auto-capitalize :none
:return-key-type :go
:monospace true
:auto-correct false}]]]
[react/scroll-view
{:style {:flex 1}
:keyboard-dismiss-mode :on-drag
:keyboard-should-persist-taps :handled}
[react/view
(when (and
(= (count contacts) 0)
(= @search-value ""))
{:flex 1})
(if (and
(= (count contacts) 0)
(= @search-value ""))
[react/view
{:flex 1
:align-items :center
:padding-horizontal 58
:padding-top 160}
[quo/text
{:size :base
:align :center
:color :secondary}
(i18n/label :t/you-dont-have-contacts-invite-friends)]
[invite/button]]
[list/flat-list
{:data (filter-contacts @search-value contacts)
:key-fn :address
:render-fn render-row}])]
(when-not (= @search-value "")
[react/view
[quo/text
{:style {:margin-horizontal 16
:margin-vertical 14}
:size :base
:align :left
:color :secondary}
(i18n/label :t/non-contacts)]
(when (and (= state :searching)
(is-valid-username? @search-value))
[rn/activity-indicator
{:color colors/gray
:size (if platform/android? :large :small)}])
(if (= state :valid)
[quo/list-item
(merge
{:title (or ens-name (gfycat/generate-gfy public-key))
:subtitle (if ens-name
(gfycat/generate-gfy public-key)
(utils/get-shortened-address public-key))
:icon [chat-icon/contact-icon-contacts-tab
(identicon/identicon public-key)]
:on-press #(do
(debounce/dispatch-and-chill [:contact.ui/contact-code-submitted false] 3000)
(re-frame/dispatch [:search/home-filter-changed nil]))}
(when ens-name {:subtitle-secondary public-key}))]
[quo/text
{:style {:margin-horizontal 16}
:size :base
:align :center
:color :secondary}
(if (is-valid-username? @search-value)
(when (= state :error)
(get-validation-label error))
(i18n/label :t/invalid-username-or-key))])])]
(when-not (and
(= (count contacts) 0)
(= @search-value ""))
[react/animated-view
{:style {:height 36
:width 124
:position :absolute
:bottom 42
:transform [{:translateY my-profile-button-anim-y}]
:align-self :center}}
[react/touchable-opacity
{:style {:padding-horizontal 2
:height 36
:width 124
:background-color colors/blue
:border-radius 18
:elevation 4
:shadow-offset {:width 0 :height 4}
:shadow-color "rgba(0, 34, 51, 0.16)"
:shadow-radius 4
:shadow-opacity 1}
:on-press on-share}
[react/view
{:style {:flex 1
:flex-direction :row
:align-items :center}}
[photos/photo
(multiaccounts/displayed-photo account)
{:size 32
:accessibility-label :current-account-photo}]
[quo/text
{:size :base
:weight :medium
:color :inverse
:style {:margin-left 6}}
(i18n/label :t/my-profile)]]]])]]))
(defn- nickname-input
[entered-nickname]
[quo/text-input
{:on-change-text #(reset! entered-nickname %)
:auto-capitalize :none
:max-length 32
:auto-focus false
:accessibility-label :nickname-input
:placeholder (i18n/label :t/add-nickname)
:return-key-type :done
:auto-correct false}])
(defn new-contact
[]
(let [entered-nickname (reagent/atom "")]
(fn []
(let [{:keys [state ens-name public-key error]} @(re-frame/subscribe [:contacts/new-identity])
blocked? (and
(validators/valid-public-key? (or public-key ""))
@(re-frame/subscribe [:contacts/contact-blocked?
public-key]))]
[react/view {:style {:flex 1}}
[topbar/topbar
{:title (i18n/label :t/new-contact)
:modal? true
:right-accessories
[{:icon :qr
:accessibility-label :scan-contact-code-button
:on-press #(re-frame/dispatch [::qr-scanner/scan-code
{:title (i18n/label :t/new-contact)
:handler :contact/qr-code-scanned
:new-contact? true
:nickname @entered-nickname}])}]}]
[react/view
{:flex-direction :row
:padding 16}
[react/view
{:flex 1
:padding-right 16}
[quo/text-input
{:on-change-text
#(do
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
(debounce/debounce-and-dispatch [:contacts/set-new-identity %] 600))
:on-submit-editing
#(when (= state :valid)
(debounce/dispatch-and-chill [:contact.ui/contact-code-submitted true @entered-nickname]
3000))
:placeholder (i18n/label :t/enter-contact-code)
:show-cancel false
:accessibility-label :enter-contact-code-input
:auto-capitalize :none
:return-key-type :go}]]
[react/view
{:justify-content :center
:align-items :center}
[input-icon state true @entered-nickname blocked?]]]
[react/view {:min-height 30 :justify-content :flex-end :margin-bottom 16}
[quo/text
{:style {:margin-horizontal 16}
:size :small
:align :center
:color :secondary}
(cond (= state :error)
(get-validation-label error)
(= state :valid)
(str (when ens-name (str ens-name " • "))
(utils/get-shortened-address public-key))
:else "")]]
[react/text {:style {:margin-horizontal 16 :color colors/gray}}
(i18n/label :t/nickname-description)]
[react/view {:padding 16}
[nickname-input entered-nickname]
[react/text
{:style {:align-self :flex-end
:margin-top 16
:color colors/gray}}
(str (count @entered-nickname) " / 32")]]]))))
@@ -1,50 +0,0 @@
(ns status-im.ui.screens.add-new.new-public-chat.view
(:require [quo.core :as quo]
[quo.design-system.colors :as colors]
[re-frame.core :as re-frame]
[status-im.add-new.db :as db]
[status-im.react-native.resources :as resources]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.react :as react]
[utils.i18n :as i18n])
(:require-macros [status-im.utils.views :as views]))
(defn- start-chat
[topic]
(re-frame/dispatch [:chat.ui/start-public-chat topic])
(re-frame/dispatch [:set :public-group-topic nil]))
(defn- hash-icon
[]
[icons/icon :main-icons/channel {:color colors/gray}])
(defn- chat-name-input
[topic error]
[quo/text-input
{:on-change-text #(re-frame/dispatch [:set :public-group-topic %])
:on-submit-editing #(when (db/valid-topic? topic) (start-chat topic))
:auto-capitalize :none
:auto-focus false
:accessibility-label :chat-name-input
:before {:component [hash-icon]}
;; Set default-value as otherwise it will
;; be erased in global `onWillBlur` handler
:default-value topic
:placeholder "chat-name"
:return-key-type :go
:auto-correct false
:error error}])
(views/defview new-public-chat
[]
(views/letsubs [topic [:public-group-topic]
error [:public-chat.new/topic-error-message]]
[react/scroll-view {:style {:flex 1}}
[react/view {:padding-horizontal 16}
[react/view {:align-items :center :padding-vertical 8}
[react/image
{:source (:new-chat-header resources/ui)
:style {:width 160 :height 160}}]]
[react/text {:style {:text-align :center :margin-bottom 16 :line-height 22}}
(i18n/label :t/public-chat-description)]
[chat-name-input topic error]]]))
@@ -41,8 +41,7 @@
(defn browser-options
[url account empty-tab name]
(fn []
(let [topic (http/topic-from-url url)
bookmarks @(re-frame/subscribe [:bookmarks/active])
(let [bookmarks @(re-frame/subscribe [:bookmarks/active])
permissions @(re-frame/subscribe [:dapps/permissions])
fav? (get bookmarks url)
connected? (some #{constants/dapp-permission-web3}
@@ -85,15 +84,6 @@
(js/setTimeout
#(browser/share-link url)
200))}]
[quo/list-item
{:icon [chat-icon/custom-icon-view-list
topic
(rand-nth colors/chat-colors)]
:accessibility-label :open-chat
:title (str "#" topic)
:subtitle (i18n/label :t/open-chat)
:on-press #(hide-sheet-and-dispatch [:chat.ui/start-public-chat topic])
:chevron true}]
[components/separator]])
(if connected?
[quo/list-item
@@ -1,157 +0,0 @@
(ns status-im.ui.screens.chat.components.accessory
(:require [cljs-bean.core :as bean]
[quo.animated :as animated]
[quo.design-system.colors :as colors]
[quo.platform :as platform]
[quo.react :as react]
[quo.react-native :as rn]
[reagent.core :as reagent]
[status-im.ui.components.tabbar.core :as tabbar]
[status-im.ui.screens.chat.components.hooks :refer [use-keyboard-dimension]]
[react-native.safe-area :as safe-area]))
(def duration 250)
(defn create-pan-responder
[y pan-active]
(when-not platform/android?
(js->clj
(.-panHandlers
^js
(.create
^js rn/pan-responder
#js
{:onPanResponderGrant (fn []
(animated/set-value pan-active 1))
:onPanResponderMove (fn [_ ^js state]
(animated/set-value y (.-moveY state)))
:onPanResponderRelease (fn []
(animated/set-value pan-active 0)
(js/setTimeout
#(animated/set-value y 0)
100))
:onPanResponderTerminate (fn []
(animated/set-value pan-active 0)
(js/setTimeout
#(animated/set-value y 0)
100))})))))
(def ios-view
(reagent/adapt-react-class
(react/memo
(fn [props]
(let [{on-update-inset :onUpdateInset
y :y
pan-state :panState
on-close :onClose
has-panel :hasPanel
children :children}
(bean/bean props)
{keyboard-height :height
keyboard-max-height :max-height
keyboard-end-position :end-position}
(use-keyboard-dimension)
bottom (safe-area/get-bottom)
{on-layout :on-layout
bar-height :height}
(rn/use-layout)
visible (or has-panel (pos? keyboard-height))
anim-visible (animated/use-value visible)
kb-on-screen (if platform/android? 0 (* -1 (- keyboard-height bottom (tabbar/get-height))))
panel-on-screen (* -1 (- keyboard-max-height bottom (tabbar/get-height)))
max-delta (min 0 (if has-panel panel-on-screen kb-on-screen))
panel-height (* -1 max-delta)
end-position (- keyboard-end-position (when has-panel keyboard-max-height))
delay (+ (/ (- keyboard-max-height panel-height)
(/ keyboard-max-height duration))
16)
drag-diff (animated/clamp (animated/sub y end-position) 0 keyboard-max-height)
animated-y (react/use-memo
(fn []
(animated/mix
(animated/with-timing-transition anim-visible
{:duration (- duration delay)
:easing (:keyboard animated/easings)})
0
panel-on-screen))
[panel-on-screen])
delta-y (animated/clamp (animated/add drag-diff animated-y) max-delta 0)
on-update (fn []
(when on-update-inset
(on-update-inset (+ bar-height panel-height))))
children (react/get-children children)]
(react/effect! on-update [panel-height bar-height])
(animated/code!
(fn []
(when has-panel
;; TODO: Check also velocity
(animated/cond* (animated/and* (animated/greater-or-eq drag-diff (* 0.6 panel-height))
(animated/not* pan-state))
[(animated/call* [] on-close)])))
[delta-y pan-state has-panel on-close])
(animated/code!
(fn []
(animated/delay
(animated/set anim-visible (if visible 1 0))
(if visible delay 0)))
[visible keyboard-max-height delay])
(reagent/as-element
[animated/view
{:style {:position :absolute
:left 0
:right 0
:background-color (:ui-background @colors/theme)
:bottom max-delta
:transform [{:translateY delta-y}]}}
[rn/view {:on-layout on-layout}
(first children)]
[rn/view
{:style {:flex 1
:height (when (pos? panel-height) panel-height)}}
(second children)]]))))))
(def android-view
(reagent/adapt-react-class
(react/memo
(fn [props]
(let [{on-update-inset :onUpdateInset
on-close :onClose
has-panel :hasPanel
children :children}
(bean/bean props)
{keyboard-max-height :max-height} (use-keyboard-dimension)
bottom (safe-area/get-bottom)
{on-layout :on-layout
bar-height :height}
(rn/use-layout)
visible has-panel
panel-on-screen (* -1 (- keyboard-max-height bottom (tabbar/get-height)))
max-delta (min 0 (if has-panel panel-on-screen 0))
panel-height (* -1 max-delta)
on-update (fn []
(when on-update-inset
(on-update-inset (+ bar-height panel-height))))
children (react/get-children children)]
(react/effect! on-update [panel-height bar-height])
(rn/use-back-handler
(fn []
(when visible
(on-close))
visible))
(reagent/as-element
[animated/view
{:style {:position :absolute
:left 0
:right 0
:bottom 0
:background-color (:ui-background @colors/theme)}}
[rn/view {:on-layout on-layout}
(first children)]
[rn/view
{:style {:flex 1
:height (when (pos? panel-height) panel-height)}}
(second children)]]))))))
(def view (if platform/android? android-view ios-view))
@@ -1,98 +0,0 @@
(ns status-im.ui.screens.chat.components.contact-request
(:require [clojure.string :as string]
[quo.core :as quo]
[quo.design-system.colors :as quo.colors]
[quo.react :as quo.react]
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[status-im.ethereum.stateofus :as stateofus]
[utils.i18n :as i18n]
[status-im.ui.screens.chat.components.style :as styles])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(def ^:private contact-request-symbol "↪ ")
(defn input-focus
[text-input-ref]
(some-> ^js (quo.react/current-ref text-input-ref)
.focus))
(defn format-author
[contact-name]
(let [author (if (or (= (aget contact-name 0) "@")
;; in case of replies
(= (aget contact-name 1) "@"))
(or (stateofus/username contact-name)
(subs contact-name 0 81))
contact-name)]
(i18n/label :contact-requesting-to {:author author})))
(defn format-contact-request-author
[from username current-public-key]
(or (and (= from current-public-key)
(str contact-request-symbol (i18n/label :t/You)))
(str contact-request-symbol (format-author username))))
(defn get-quoted-text-with-mentions
[parsed-text]
(string/join
(mapv (fn [{:keys [type literal children]}]
(cond
(= type "paragraph")
(get-quoted-text-with-mentions children)
(= type "mention")
@(re-frame/subscribe [:messages/resolve-mention literal])
(seq children)
(get-quoted-text-with-mentions children)
:else
literal))
parsed-text)))
(defn contact-request-message
[their-public-key]
(let [{:keys [input-text]} @(re-frame/subscribe [:chats/current-chat-input])]
[rn/view {:style {:flex-direction :row}}
[rn/view {:style (styles/contact-request-content)}
[quo/button
{:type :secondary
:weight :medium
:number-of-lines 1
:style {:line-height 18}
:on-press #(re-frame/dispatch [:chat.ui/cancel-contact-request])}
(i18n/label :t/cancel)]
[quo/button
{:type :secondary
:disabled (string/blank? input-text)
:weight :medium
:after :main-icons/send
:on-press #(re-frame/dispatch [:contacts/send-contact-request their-public-key input-text])
:style {:line-height 18}}
(i18n/label :t/send-request)]]]))
(defn focus-input-on-contact-request
[contact-request had-contact-request text-input-ref]
;;when we show contact-request we focus input
(when-not (= contact-request @had-contact-request)
(reset! had-contact-request contact-request)
(when contact-request
(js/setTimeout #(input-focus text-input-ref) 250))))
(defn contact-request-message-wrapper
[contact-request]
[rn/view
{:style {:padding-horizontal 15
:border-top-width 1
:border-top-color (:ui-01 @quo.colors/theme)
:padding-vertical 8}}
[contact-request-message contact-request]])
(defview contact-request-message-auto-focus-wrapper
[text-input-ref]
(letsubs [had-reply (atom nil)
contact-request @(re-frame/subscribe [:chats/sending-contact-request])]
{:component-did-mount #(focus-input-on-contact-request contact-request had-reply text-input-ref)}
(when contact-request
[contact-request-message-wrapper contact-request])))
@@ -1,59 +0,0 @@
(ns status-im.ui.screens.chat.components.edit
(:require [quo.components.animated.pressable :as pressable]
[quo.core :as quo]
[quo.design-system.colors :as quo.colors]
[quo.react :as quo.react]
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.screens.chat.components.style :as styles]))
(defn input-focus
[text-input-ref]
(some-> ^js (quo.react/current-ref text-input-ref)
.focus))
(defn edit-message
[]
[rn/view {:style {:flex-direction :row}}
[rn/view {}
[icons/icon :tiny-icons/tiny-edit {:container-style {:margin-top 5}}]]
[rn/view {:style (styles/reply-content)}
[quo/text
{:weight :medium
:number-of-lines 1}
(i18n/label :t/editing-message)]]
[rn/view
[pressable/pressable
{:on-press #(re-frame/dispatch [:chat.ui/cancel-message-edit])
:accessibility-label :cancel-message-reply}
[icons/icon :main-icons/close-circle
{:container-style (styles/close-button)
:color (:icon-02 @quo.colors/theme)}]]]])
(defn focus-input-on-edit
[edit had-edit text-input-ref]
;;when we show edit we focus input
(when-not (= edit @had-edit)
(reset! had-edit edit)
(when edit
(js/setTimeout #(input-focus text-input-ref) 250))))
(defn edit-message-wrapper
[edit]
[rn/view
{:style {:padding-horizontal 15
:border-top-width 1
:border-top-color (:ui-01 @quo.colors/theme)
:padding-vertical 8}}
[edit-message edit]])
(defn edit-message-auto-focus-wrapper
[text-input-ref]
(let [had-edit (atom nil)]
(fn []
(let [edit @(re-frame/subscribe [:chats/edit-message])]
(focus-input-on-edit edit had-edit text-input-ref)
(when edit
[edit-message-wrapper])))))
@@ -1,50 +0,0 @@
(ns status-im.ui.screens.chat.components.hooks
(:require [quo.platform :as platform]
[quo.react :as react]
[quo.react-native :refer [use-window-dimensions] :as rn]
[react-native.safe-area :as safe-area]))
(def ^:private keyboard-change-event (if platform/android? "keyboardDidShow" "keyboardWillChangeFrame"))
(def default-kb-height (if platform/ios? 258 272))
(def min-duration 100)
(defn use-keyboard-dimension
[]
(let [{:keys [height]} (use-window-dimensions)
bottom (safe-area/get-bottom)
keyboard-listener (atom nil)
keyboard (react/state
{:height 0
:duration min-duration
:end-position height
:max-height (+ (if platform/ios? bottom 0) default-kb-height)})]
(react/effect!
(fn []
(letfn
[(dimensions-change [evt]
(swap! keyboard assoc :end-position (-> ^js evt .-window .-height)))
(keyboard-dimensions [evt]
(let [duration (.-duration ^js evt)
easing (.-easing ^js evt)
screen-y (-> ^js evt .-endCoordinates .-screenY)
new-height (- height screen-y)]
(when-not (= new-height (:height @keyboard))
(when (and duration easing platform/ios?)
(rn/configure-next
#js
{:duration (max min-duration duration)
:update #js
{:duration (max min-duration duration)
:type (-> ^js rn/layout-animation .-Types (aget easing))}})))
(reset! keyboard {:height new-height
:end-position screen-y
:duration (max min-duration duration)
:max-height (max new-height (:max-height @keyboard))})))]
(.addEventListener rn/dimensions "change" dimensions-change)
(reset! keyboard-listener (.addListener rn/keyboard keyboard-change-event keyboard-dimensions))
(fn []
(.removeEventListener rn/dimensions "change" dimensions-change)
(some-> ^js @keyboard-listener
.remove)))))
@keyboard))
@@ -1,428 +0,0 @@
(ns status-im.ui.screens.chat.components.input
(:require [clojure.string :as string]
[quo.components.animated.pressable :as pressable]
[quo.components.list.item :as list-item]
[quo.components.text :as text]
[quo.design-system.colors :as colors]
[quo.platform :as platform]
[quo.react :as quo.react]
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im2.constants :as chat.constants]
[utils.i18n :as i18n]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.list.views :as list]
[status-im.ui.screens.chat.components.reply :as reply]
[status-im.ui.screens.chat.components.style :as styles]
[status-im.ui.screens.chat.photos :as photos]
[utils.re-frame :as rf]
[status-im.utils.utils :as utils.utils]))
(defn input-focus
[text-input-ref]
(some-> ^js (quo.react/current-ref text-input-ref)
.focus))
(def panel->icons
{:extensions :main-icons/commands
:images :main-icons/photo})
(defn touchable-icon
[{:keys [panel active set-active accessibility-label]}]
[pressable/pressable
{:type :scale
:accessibility-label accessibility-label
:on-press #(set-active (when-not (= active panel) panel))}
[rn/view {:style (styles/touchable-icon)}
[icons/icon
(panel->icons panel)
(styles/icon (= active panel))]]])
(defn touchable-stickers-icon
[{:keys [panel active set-active accessibility-label input-focus]}]
[pressable/pressable
{:type :scale
:accessibility-label accessibility-label
:on-press #(if (= active panel)
(input-focus)
(set-active panel))}
[rn/view {:style (styles/in-input-touchable-icon)}
(if (= active panel)
[icons/icon :main-icons/keyboard (styles/icon false)]
[icons/icon :main-icons/stickers (styles/icon false)])]])
;; TODO(Ferossgp): Move this into audio panel.
;; Instead of not changing panel we can show a placeholder with no permission
(defn- request-record-audio-permission
[set-active panel]
(re-frame/dispatch
[:request-permissions
{:permissions [:record-audio]
:on-allowed
#(set-active panel)
:on-denied
#(utils.utils/set-timeout
(fn []
(utils.utils/show-popup
(i18n/label :t/audio-recorder-error)
(i18n/label :t/audio-recorder-permissions-error)))
50)}]))
(defn touchable-audio-icon
[{:keys [panel active set-active accessibility-label input-focus]}]
[pressable/pressable
{:type :scale
:accessibility-label accessibility-label
:on-press #(if (= active panel)
(input-focus)
(request-record-audio-permission set-active panel))}
[rn/view {:style (styles/in-input-touchable-icon)}
(if (= active panel)
[icons/icon :main-icons/keyboard (styles/icon false)]
[icons/icon :main-icons/speech (styles/icon false)])]])
(defn send-button
[on-send contact-request]
[rn/touchable-opacity {:on-press-in on-send}
[rn/view {:style (styles/send-message-button)}
(when-not contact-request
[icons/icon :main-icons/arrow-up
{:container-style (styles/send-message-container contact-request)
:accessibility-label :send-message-button
:color (styles/send-icon-color)}])]])
(defn on-selection-change
[timeout-id last-text-change args]
(let [selection (.-selection ^js (.-nativeEvent ^js args))
start (.-start selection)
end (.-end selection)]
;; NOTE(rasom): on iOS we do not dispatch this event immediately
;; because it is needed only in case if selection is changed without
;; typing. Timeout might be canceled on `on-change`.
(when platform/ios?
(reset!
timeout-id
(utils.utils/set-timeout
#(re-frame/dispatch [:mention/on-selection-change
{:start start
:end end}])
50)))
;; NOTE(rasom): on Android we dispatch event only in case if there
;; was no text changes during last 50ms. `on-selection-change` is
;; dispatched after `on-change`, that's why there is no another way
;; to know whether selection was changed without typing.
(when (and platform/android?
(or (not @last-text-change)
(< 50 (- (js/Date.now) @last-text-change))))
(re-frame/dispatch [:mention/on-selection-change
{:start start
:end end}]))))
(defonce input-texts (atom {}))
(defonce mentions-enabled (reagent/atom {}))
(defonce chat-input-key (reagent/atom 1))
(re-frame/reg-fx
:chat.ui/clear-inputs-old
(fn []
(reset! input-texts {})
(reset! mentions-enabled {})
(reset! chat-input-key 1)))
(defn force-text-input-update!
"force-text-input-update! forces the
input to re-render, necessary when we are setting value"
[]
(swap! chat-input-key inc))
(defn show-send
[{:keys [actions-ref send-ref sticker-ref]}]
(when actions-ref
(quo.react/set-native-props actions-ref #js {:width 0 :left -88}))
(quo.react/set-native-props send-ref #js {:width nil :right nil})
(when sticker-ref
(quo.react/set-native-props sticker-ref #js {:width 0 :right -100})))
(defn hide-send
[{:keys [actions-ref send-ref sticker-ref]}]
(when actions-ref
(quo.react/set-native-props actions-ref #js {:width nil :left nil}))
(quo.react/set-native-props send-ref #js {:width 0 :right -100})
(when sticker-ref
(quo.react/set-native-props sticker-ref #js {:width nil :right nil})))
(defn reset-input
[refs chat-id]
(some-> ^js (quo.react/current-ref (:text-input-ref refs))
.clear)
(swap! mentions-enabled update :render not)
(swap! input-texts dissoc chat-id))
(defn clear-input
[chat-id refs]
(hide-send refs)
(if (get @mentions-enabled chat-id)
(do
(swap! mentions-enabled dissoc chat-id)
;;we need this timeout, because if we clear text input and first index was a mention object with
;;blue color,
;;after clearing text will be typed with this blue color, so we render white text first and then
;;clear it
(js/setTimeout #(reset-input refs chat-id) 50))
(reset-input refs chat-id)))
(defn on-text-change
[val chat-id]
(swap! input-texts assoc chat-id val)
;;we still store it in app-db for mentions, we don't have reactions in views
(re-frame/dispatch [:chat.ui/set-chat-input-text val]))
(defn on-change
[last-text-change timeout-id refs chat-id sending-image args]
(let [text (.-text ^js (.-nativeEvent ^js args))
prev-text (get @input-texts chat-id)]
(when (and (seq prev-text) (empty? text) (not sending-image))
(hide-send refs))
(when (and (empty? prev-text) (seq text))
(show-send refs))
(when (and (not (get @mentions-enabled chat-id)) (string/index-of text "@"))
(swap! mentions-enabled assoc chat-id true))
;; NOTE(rasom): on iOS `on-selection-change` is canceled in case if it
;; happens during typing because it is not needed for mention
;; suggestions calculation
(when (and platform/ios? @timeout-id)
(utils.utils/clear-timeout @timeout-id))
(when platform/android?
(reset! last-text-change (js/Date.now)))
(on-text-change text chat-id)
;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`,
;; that's why mention suggestions are calculated on `on-change`
(when platform/ios?
(re-frame/dispatch [:mention/calculate-suggestions]))))
(rf/defn set-input-text
"Set input text for current-chat. Takes db and input text and cofx
as arguments and returns new fx. Always clear all validation messages."
{:events [:chat.ui.input/set-chat-input-text]}
[{:keys [db]} text chat-id]
(let [params [chat-id text]
method "wakuext_chatMentionToInputField"]
{:json-rpc/call [{:method method
:params params
:on-success #(rf/dispatch [:mention/on-to-input-field-success %])
:on-error #(rf/dispatch [:mention/on-error
{:method method
:params params} %])}]}))
(defn on-text-input
[chat-id args]
(let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event)
previous-text (.-previousText ^js native-event)
range (.-range ^js native-event)
start (.-start ^js range)
end (.-end ^js range)]
(when (and (not (get @mentions-enabled chat-id)) (string/index-of text "@"))
(swap! mentions-enabled assoc chat-id true))
(re-frame/dispatch
[:mention/on-text-input
{:new-text text
:previous-text previous-text
:start start
:end end}])
;; NOTE(rasom): on Android `on-text-input` is dispatched after
;; `on-change`, that's why mention suggestions are calculated
;; on `on-change`
(when platform/android?
(re-frame/dispatch [:mention/calculate-suggestions]))))
(defn text-input
[{:keys [set-active-panel refs chat-id sending-image]}]
(let [cooldown-enabled? @(re-frame/subscribe [:chats/current-chat-cooldown-enabled?])
timeout-id (atom nil)
last-text-change (atom nil)
mentions-enabled (get @mentions-enabled chat-id)
contact-request @(re-frame/subscribe [:chats/sending-contact-request])]
[rn/text-input
{:style (styles/text-input contact-request)
:ref (:text-input-ref refs)
:max-font-size-multiplier 1
:accessibility-label :chat-message-input
:text-align-vertical :center
:multiline true
:editable (not cooldown-enabled?)
:blur-on-submit false
:auto-focus false
:on-focus #(set-active-panel nil)
:max-length chat.constants/max-text-size
:placeholder-text-color (:text-02 @colors/theme)
:placeholder (if cooldown-enabled?
(i18n/label :cooldown/text-input-disabled)
(i18n/label :t/type-a-message))
:underline-color-android :transparent
:auto-capitalize :sentences
:on-selection-change (partial on-selection-change
timeout-id
last-text-change)
:on-change
(partial on-change last-text-change timeout-id refs chat-id sending-image)
:on-text-input (partial on-text-input chat-id)}
(if mentions-enabled
(for [[idx [type text]] (map-indexed
(fn [idx item]
[idx item])
@(re-frame/subscribe [:chat/input-with-mentions]))]
^{:key (str idx "_" type "_" text)}
[rn/text (when (= type :mention) {:style {:color "#0DA4C9"}})
text])
(get @input-texts chat-id))]))
(defn mention-item
[[public-key {:keys [alias name nickname] :as user}] _ _ text-input-ref]
(let [ens-name? (not= alias name)]
[list-item/list-item
(cond->
{:icon [photos/member-photo public-key]
:size :small
:text-size :small
:title
[text/text
{:weight :medium
:ellipsize-mode :tail
:number-of-lines 1
:size :small}
(if nickname
nickname
name)
(when nickname
[text/text
{:weight :regular
:color :secondary
:ellipsize-mode :tail
:size :small}
" "
(when ens-name?
"@")
name])]
:title-text-weight :medium
:on-press
(fn []
(re-frame/dispatch [:chat.ui/select-mention text-input-ref user]))}
ens-name?
(assoc :subtitle alias))]))
(def chat-toolbar-height (reagent/atom nil))
(defn autocomplete-mentions
[text-input-ref bottom]
(let [suggestions @(re-frame/subscribe [:chat/mention-suggestions])]
(when (seq suggestions)
(let [height (+ 16 (* 52 (min 4.5 (count suggestions))))]
[rn/view
{:style (styles/autocomplete-container bottom)
:accessibility-label :suggestions-list}
[rn/view
{:style {:height height}}
[list/flat-list
{:keyboard-should-persist-taps :always
:footer [rn/view {:style {:height 8}}]
:header [rn/view {:style {:height 8}}]
:data suggestions
:key-fn first
:render-data text-input-ref
:render-fn mention-item}]]]))))
(defn on-chat-toolbar-layout
[^js ev]
(reset! chat-toolbar-height (-> ev .-nativeEvent .-layout .-height)))
(defn send-image
[]
(let [sending-image @(re-frame/subscribe [:chats/sending-image])]
(when (seq sending-image)
[reply/send-image sending-image])))
(defn actions
[extensions image show-send actions-ref active-panel set-active-panel contact-request]
[rn/view
{:style (styles/actions-wrapper (and (not contact-request) show-send))
:ref actions-ref}
(when extensions
[touchable-icon
{:panel :extensions
:accessibility-label :show-extensions-icon
:active active-panel
:set-active set-active-panel}])
(when image
[touchable-icon
{:panel :images
:accessibility-label :show-photo-icon
:active active-panel
:set-active set-active-panel}])])
(defn chat-toolbar
[{:keys [chat-id]}]
(let [actions-ref (quo.react/create-ref)
send-ref (quo.react/create-ref)
sticker-ref (quo.react/create-ref)
toolbar-options (re-frame/subscribe [:chats/chat-toolbar])
show-send (seq (get @input-texts chat-id))]
(fn [{:keys [active-panel set-active-panel text-input-ref chat-id]}]
(let [;we want to control components on native level, so instead of RN state we set native props
;via reference
;we don't react on input text in this view, @input-texts below is a regular atom
refs {:actions-ref actions-ref
:send-ref send-ref
:sticker-ref sticker-ref
:text-input-ref text-input-ref}
{:keys [send stickers image extensions audio
sending-image]} @toolbar-options
show-send (or show-send sending-image)
contact-request @(re-frame/subscribe [:chats/sending-contact-request])]
[rn/view
{:style (styles/toolbar)
:on-layout on-chat-toolbar-layout}
;; EXTENSIONS and IMAGE buttons
[actions extensions image show-send actions-ref active-panel set-active-panel contact-request]
[rn/view {:style (styles/input-container contact-request)}
[send-image]
[rn/view {:style styles/input-row}
[text-input
{:chat-id chat-id
:sending-image sending-image
:refs refs
:set-active-panel set-active-panel}]
;; SEND button
[rn/view {:ref send-ref :style (when-not show-send {:width 0 :right -100})}
(when send
[send-button
#(do (clear-input chat-id refs)
(re-frame/dispatch [:chat.ui/send-current-message]))
contact-request])]
;; STICKERS and AUDIO buttons
(when-not @(re-frame/subscribe [:chats/edit-message])
[rn/view
{:style (merge {:flex-direction :row} (when show-send {:width 0 :right -100}))
:ref sticker-ref}
(when stickers
[touchable-stickers-icon
{:panel :stickers
:accessibility-label :show-stickers-icon
:active active-panel
:input-focus #(input-focus text-input-ref)
:set-active set-active-panel}])
(when audio
[touchable-audio-icon
{:panel :audio
:accessibility-label :show-audio-message-icon
:active active-panel
:input-focus #(input-focus text-input-ref)
:set-active set-active-panel}])])]]]))))
@@ -1,121 +0,0 @@
(ns status-im.ui.screens.chat.components.reply
(:require [clojure.string :as string]
[quo.components.animated.pressable :as pressable]
[quo.core :as quo]
[quo.design-system.colors :as quo.colors]
[quo.react :as quo.react]
[quo.react-native :as rn]
[re-frame.core :as re-frame]
[status-im.ethereum.stateofus :as stateofus]
[utils.i18n :as i18n]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.screens.chat.components.style :as styles]))
(def ^:private reply-symbol "↪ ")
(defn input-focus
[text-input-ref]
(some-> ^js (quo.react/current-ref text-input-ref)
.focus))
(defn format-author
[contact-name]
(let [author (if (or (= (aget contact-name 0) "@")
;; in case of replies
(= (aget contact-name 1) "@"))
(or (stateofus/username contact-name)
(subs contact-name 0 81))
contact-name)]
(i18n/label :replying-to {:author author})))
(defn format-reply-author
[from username current-public-key]
(or (and (= from current-public-key)
(str reply-symbol (i18n/label :t/You)))
(str reply-symbol (format-author username))))
(defn get-quoted-text-with-mentions
[parsed-text]
(string/join
(mapv (fn [{:keys [type literal children]}]
(cond
(= type "paragraph")
(get-quoted-text-with-mentions children)
(= type "mention")
@(re-frame/subscribe [:messages/resolve-mention literal])
(seq children)
(get-quoted-text-with-mentions children)
:else
literal))
parsed-text)))
(defn reply-message
[{:keys [from]}]
(let [contact-name @(re-frame/subscribe [:contacts/contact-name-by-identity from])
current-public-key @(re-frame/subscribe [:multiaccount/public-key])]
[rn/view {:style {:flex-direction :row}}
[rn/view {:style (styles/reply-content)}
[quo/text
{:weight :medium
:number-of-lines 1
:style {:line-height 18}}
(format-reply-author from contact-name current-public-key)]]
[rn/view
[pressable/pressable
{:on-press #(re-frame/dispatch [:chat.ui/cancel-message-reply])
:accessibility-label :cancel-message-reply}
[icons/icon :main-icons/close-circle
{:container-style (styles/close-button)
:color (:icon-02 @quo.colors/theme)}]]]]))
(defn send-image
[images]
[rn/view {:style (styles/reply-container-image)}
[rn/scroll-view
{:horizontal true
:style (styles/reply-content)}
(for [{:keys [uri]} (vals images)]
^{:key uri}
[rn/image
{:source {:uri uri}
:style {:width 56
:height 56
:border-radius 4
:margin-right 4}}])]
[rn/view
[pressable/pressable
{:on-press #(re-frame/dispatch [:chat.ui/cancel-sending-image])
:accessibility-label :cancel-send-image}
[icons/icon :main-icons/close-circle
{:container-style (styles/close-button)
:color quo.colors/white}]]]])
(defn focus-input-on-reply
[reply had-reply text-input-ref]
;;when we show reply we focus input
(when-not (= reply @had-reply)
(reset! had-reply reply)
(when reply
;; A setTimeout of 0 is necessary to ensure the statement is enqueued and will get executed ASAP.
(js/setTimeout #(input-focus text-input-ref) 0))))
(defn reply-message-wrapper
[reply]
[rn/view
{:style {:padding-horizontal 15
:border-top-width 1
:border-top-color (:ui-01 @quo.colors/theme)
:padding-vertical 8}}
[reply-message reply]])
(defn reply-message-auto-focus-wrapper
[text-input-ref]
(let [had-reply (atom nil)]
(fn []
(let [reply @(re-frame/subscribe [:chats/reply-message])]
(focus-input-on-reply reply had-reply text-input-ref)
(when reply
[reply-message-wrapper reply])))))
@@ -1,152 +0,0 @@
(ns status-im.ui.screens.chat.components.style
(:require [quo.design-system.colors :as colors]
[quo.design-system.typography :as typography]
[quo.platform :as platform]))
(defn toolbar
[]
{:min-height 52
:padding-vertical 8
:border-top-width 1
:border-top-color (:ui-01 @colors/theme)
:align-items :flex-end
:flex-direction :row})
(defn input-container
[contact-request]
{:background-color (:ui-01 @colors/theme)
:flex 1
:height (when contact-request 44)
:border-top-left-radius (if contact-request 8 16)
:border-top-right-radius (if contact-request 8 16)
:border-bottom-right-radius (if contact-request 8 4)
:border-bottom-left-radius (if contact-request 8 16)
:margin-horizontal 8})
(def input-row
{:flex-direction :row
:overflow :hidden
:align-items :flex-end})
(defn text-input-wrapper
[]
(merge {:flex-direction :row
:align-items :flex-start
:flex 1
:min-height 34
:max-height 144}
(when platform/ios?
{:padding-top 2})))
(defn text-input
[contact-request]
(merge typography/font-regular
typography/base
{:flex 1
:min-height 34
:max-height 144
:margin 0
:flex-shrink 1
:color (:text-01 @colors/theme)
:padding-horizontal 12}
(if platform/android?
{:padding-vertical 2}
{:padding-top (if contact-request 10 2)
:padding-bottom (if contact-request 5 6)})))
(defn actions-wrapper
[show-send]
(merge (when show-send
{:width 0 :left -88})
{:flex-direction :row
:padding-left 4
:min-height 34}))
(defn touchable-icon
[]
{:padding-horizontal 10
:padding-vertical 5
:justify-content :center
:align-items :center})
(defn in-input-touchable-icon
[]
{:padding-horizontal 6
:padding-vertical 5
:justify-content :center
:align-items :center})
(defn icon
[active]
{:color (if active
(:icon-04 @colors/theme)
(:icon-02 @colors/theme))})
(defn reply-container-image
[]
{:border-top-left-radius 14
:border-top-right-radius 14
:border-bottom-right-radius 4
:border-bottom-left-radius 14
:margin 2
:flex-direction :row
:background-color (:ui-03 @colors/theme)})
(defn reply-container
[]
{:flex-direction :row})
(defn reply-content
[]
{:padding-vertical 6
:padding-horizontal 10
:flex 1})
(defn quoted-message
[pin?]
(merge {:flex-direction :row
:align-items :center
:width "45%"}
(when-not pin?
{:position :absolute
:left 34
:top 3})))
(defn contact-request-content
[]
{:flex 1
:flex-direction :row
:justify-content :space-between})
(defn close-button
[]
{:margin-top 3})
(defn send-message-button
[]
{:margin-vertical 4
:margin-horizontal 5})
(defn send-message-container
[contact-request]
{:background-color (:interactive-01 @colors/theme)
:width 26
:height (if contact-request 44 26)
:border-radius (if contact-request 22 13)
:justify-content :center
:align-items :center})
(defn send-icon-color
[]
colors/white)
(defn autocomplete-container
[bottom]
{:position :absolute
:left 0
:right 0
:bottom bottom
:background-color (colors/get-color :ui-background)
:border-top-width 1
:border-top-color (colors/get-color :ui-01)
:z-index 3})
+1 -43
View File
@@ -4,10 +4,8 @@
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]
[status-im.ui.screens.chat.styles.message.sheets :as sheets.styles]
[status-im.utils.universal-links.utils :as universal-links]))
[status-im.ui.screens.chat.styles.message.sheets :as sheets.styles]))
(defn hide-sheet-and-dispatch
[event]
@@ -42,41 +40,6 @@
:icon :main-icons/delete
:on-press #(re-frame/dispatch [:chat.ui/show-remove-confirmation chat-id])}]]))
(defn public-chat-accents
[chat-id]
(let [link (universal-links/generate-link :public-chat :external chat-id)
message (i18n/label :t/share-public-chat-text {:link link})]
[react/view
[quo/list-item
{:theme :accent
:title (i18n/label :t/share-chat)
:accessibility-label :share-chat-button
:icon :main-icons/share
:on-press (fn []
(re-frame/dispatch [:bottom-sheet/hide-old])
;; https://github.com/facebook/react-native/pull/26839
(js/setTimeout
#(list-selection/open-share {:message message})
250))}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/mark-all-read)
:accessibility-label :mark-all-read-button
:icon :main-icons/check
:on-press #(hide-sheet-and-dispatch [:chat.ui/mark-all-read-pressed chat-id])}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/clear-history)
:accessibility-label :clear-history-button
:icon :main-icons/close
:on-press #(re-frame/dispatch [:chat.ui/show-clear-history-confirmation chat-id])}]
[quo/list-item
{:theme :negative
:title (i18n/label :t/delete-chat)
:accessibility-label :delete-chat-button
:icon :main-icons/delete
:on-press #(re-frame/dispatch [:chat.ui/show-remove-confirmation chat-id])}]]))
(defn community-chat-accents
[]
(fn [{:keys [chat-id group-chat chat-name color emoji]}]
@@ -150,11 +113,6 @@
[{:keys [chat-type chat-id]
:as current-chat}]
(cond
(#{constants/public-chat-type
constants/profile-chat-type
constants/timeline-chat-type}
chat-type)
[public-chat-accents chat-id]
(= chat-type constants/community-chat-type)
[community-chat-accents current-chat]
@@ -19,10 +19,10 @@
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.chat.photos :as photos]
[status-im.ui.screens.chat.sheets :as sheets]
[status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.utils.core :as utils]
[utils.datetime :as datetime]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[status-im.ui.screens.home.views.inner-item :as inner-item]))
(def request-cooldown-ms (* 24 60 60 1000))
@@ -1,183 +0,0 @@
(ns status-im.ui.screens.communities.views
(:require [quo.core :as quo]
[quo.design-system.colors :as quo.colors]
[status-im.communities.core :as communities]
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[status-im.ui.components.badge :as badge]
[status-im.ui.components.copyable-text :as copyable-text]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.communities.community :as community]
[status-im.ui.screens.communities.icon :as communities.icon]
[status-im.utils.core :as utils]
[utils.re-frame :as rf]))
(defn hide-sheet-and-dispatch
[event]
(rf/dispatch [:bottom-sheet/hide-old])
(rf/dispatch event))
(defn community-unviewed-count
[id]
(let [{:keys [unviewed-messages-count unviewed-mentions-count]} (rf/sub [:communities/unviewed-counts
id])]
(cond
(pos? unviewed-mentions-count)
[badge/message-counter unviewed-mentions-count]
(pos? unviewed-messages-count)
[react/view
{:style {:background-color quo.colors/blue
:border-radius 6
:margin-right 5
:margin-top 2
:width 12
:height 12}
:accessibility-label :unviewed-messages-public}])))
(defn community-home-list-item
[{:keys [id name last?] :as community}]
[react/touchable-opacity
{:style (merge {:height 64}
(when last?
{:border-bottom-color (quo.colors/get-color :ui-01)
:border-bottom-width 1}))
:on-press (fn []
(rf/dispatch [:communities/load-category-states id])
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community-overview id]))
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet-old
{:content (fn []
[community/community-actions community])}])}
[:<>
[react/view {:top 12 :left 16 :position :absolute}
[communities.icon/community-icon community]]
[react/view
{:style {:margin-left 72
:flex-direction :row
:flex 1}
:accessibility-label :chat-name-text}
[react/view
{:flex-direction :row
:flex 1
:padding-right 16
:align-items :center}
[quo/text
{:weight :medium
:accessibility-label :chat-name-text
:font-size 17
:ellipsize-mode :tail
:number-of-lines 1}
name]]
[react/view
{:flex-direction :row
:flex 1
:margin-right 15
:justify-content :flex-end
:align-items :center}
[community-unviewed-count id]]]]])
(defn community-list-item
[{:keys [id permissions members name description] :as community}]
(let [members-count (count members)
show-members-count? (not= (:access permissions) constants/community-no-membership-access)]
[quo/list-item
{:icon [communities.icon/community-icon community]
:title [react/view
{:flex-direction :row
:flex 1
:padding-right 16
:align-items :center}
[quo/text
{:weight :medium
:accessibility-label :community-name-text
:ellipsize-mode :tail
:number-of-lines 1}
(utils/truncate-str name 30)]]
:title-accessibility-label :community-name-text
:subtitle [react/view
[quo/text {:number-of-lines 1}
description]
[quo/text
{:number-of-lines 1
:color :secondary}
(if show-members-count?
(i18n/label-pluralize members-count
:t/community-members
{:count members-count})
(i18n/label :t/open-membership))]]
:on-press #(do
(rf/dispatch [:dismiss-keyboard])
(rf/dispatch [:navigate-to :community-overview id]))}]))
(defn communities-actions
[]
[:<>
[quo/list-item
{:theme :accent
:title (i18n/label :t/import-community)
:accessibility-label :community-import-community
:icon :main-icons/objects
:on-press #(hide-sheet-and-dispatch [:navigate-to :community-import])}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/create-community)
:accessibility-label :community-create-community
:icon :main-icons/add
:on-press #(hide-sheet-and-dispatch [::communities/open-create-community])}]])
(defn communities-list
[communities]
[list/section-list
{:content-container-style {:padding-vertical 8}
:key-fn :id
:keyboard-should-persist-taps :always
:sticky-section-headers-enabled false
:sections communities
:render-section-header-fn quo/list-index
:render-fn community-list-item}])
(defn communities
[]
(let [communities (rf/sub [:communities/section-list])]
[:<>
[topbar/topbar
{:title (i18n/label :t/communities)
:right-accessories
[{:icon :main-icons/more
:accessibility-label :chat-menu-button
:on-press
#(rf/dispatch [:bottom-sheet/show-sheet-old
{:content (fn []
[communities-actions])
:height 256}])}]}]
[communities-list communities]
[toolbar/toolbar
{:show-border? true
:center [quo/button
{:on-press #(rf/dispatch [::communities/open-create-community])
:type :secondary}
(i18n/label :t/create-community)]}]]))
(defn export-community
[]
(let [{:keys [community-key]} (rf/sub [:popover/popover])]
[react/view
{:style {:padding-top 16
:padding-horizontal 16}}
[quo/text
{:size :x-large
:align :center}
(i18n/label :t/community-private-key)]
[copyable-text/copyable-text-view
{:container-style {:padding-vertical 12}
:copied-text community-key}
[quo/text
{:number-of-lines 1
:ellipsize-mode :middle
:accessibility-label :chat-key
:monospace true}
community-key]]]))
@@ -11,8 +11,7 @@
:title (i18n/label :t/faq)
:accessibility-label :faq-button
:on-press
#(.openURL ^js react/linking
constants/faq)
#(.openURL ^js react/linking constants/faq)
:chevron true}
{:size :small
:title (i18n/label :t/glossary)
@@ -25,13 +24,6 @@
:accessibility-label :submit-bug-button
:on-press
#(re-frame/dispatch [:open-modal :bug-report])
:chevron true}
{:size :small
:title (i18n/label :t/request-feature)
:accessibility-label :request-a-feature-button
:on-press
#(re-frame/dispatch [:chat.ui/start-public-chat
"support"])
:chevron true}])
(defn help-center
@@ -1,7 +0,0 @@
(ns status-im.ui.screens.home.sheet.styles)
(def add-new-view-wrapper
{:style {:flex-direction :row
:padding-left 16
:padding-right 8
:justify-content :space-between
:align-items :center}})
@@ -1,62 +0,0 @@
(ns status-im.ui.screens.home.sheet.views
(:require [quo.core :as quo]
[utils.re-frame :as rf]
[utils.i18n :as i18n]
[status-im.qr-scanner.core :as qr-scanner]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.react :as rn]
[status-im2.config :as config]
[status-im.ui.screens.home.sheet.styles :as style]))
(defn- hide-sheet-and-dispatch
[event]
(rf/dispatch [:bottom-sheet/hide-old])
(rf/dispatch event))
(defn add-new-view
[]
[rn/view
[rn/view style/add-new-view-wrapper
[quo/text
{:size :large
:weight :bold}
(i18n/label :t/open-home)]
[quo/button
{:type :icon
:theme :icon
:accessibility-label :universal-qr-scanner
:on-press #(hide-sheet-and-dispatch
[::qr-scanner/scan-code
{:handler ::qr-scanner/on-scan-success}])}
:main-icons/qr]]
[quo/list-item
{:theme :accent
:title (i18n/label :t/start-new-chat)
:accessibility-label :start-1-1-chat-button
:icon :main-icons/one-on-one-chat
:on-press #(hide-sheet-and-dispatch [:open-modal :new-chat])}]
(when config/group-chat-enabled?
[quo/list-item
{:theme :accent
:title (i18n/label :t/start-group-chat)
:accessibility-label :start-group-chat-button
:icon :main-icons/group-chat
:on-press #(hide-sheet-and-dispatch [:contact.ui/start-group-chat-pressed])}])
[quo/list-item
{:theme :accent
:title (i18n/label :t/new-public-group-chat)
:accessibility-label :join-public-chat-button
:icon :main-icons/public-chat
:on-press #(hide-sheet-and-dispatch [:open-modal :new-public-chat])}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/communities-alpha)
:accessibility-label :communities-button
:icon :main-icons/communities
:on-press #(hide-sheet-and-dispatch [:navigate-to :communities])}]
[invite/list-item
{:accessibility-label :chats-menu-invite-friends-button}]])
;; Deprecated
(def add-new
{:content add-new-view})
-375
View File
@@ -1,375 +0,0 @@
(ns status-im.ui.screens.home.views
(:require
[quo.core :as quo]
[quo.design-system.colors :as colors]
[quo2.components.buttons.button :as quo2.button]
[quo2.components.markdown.text :as quo2.text]
[quo2.foundations.colors :as quo2.colors]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.add-new.db :as db]
[utils.i18n :as i18n]
[status-im.qr-scanner.core :as qr-scanner]
[status-im.react-native.resources :as resources]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.chat-icon.styles :as chat-icon.styles]
[status-im.ui.components.connectivity.view :as connectivity]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.components.react :as react]
[status-im.ui.components.search-input.view :as search-input]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.chat.sheets :as sheets]
[status-im.ui.screens.communities.views :as communities.views]
[status-im.ui.screens.home.styles :as styles]
[status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.utils.utils :as utils]
[utils.debounce :as debounce])
(:require-macros [status-im.utils.views :as views]))
(defn home-tooltip-view
[]
[react/view (styles/chat-tooltip)
[react/view
{:style {:width 66
:position :absolute
:top -6
:background-color colors/white
:align-items :center}}
[react/image
{:source (resources/get-image :empty-chats-header)
:style {:width 50 :height 50}}]]
[react/touchable-highlight
{:style {:position :absolute
:right 0
:top 0
:width 44
:height 44
:align-items :center
:justify-content :center}
:on-press #(re-frame/dispatch [:multiaccounts.ui/hide-home-tooltip])
:accessibility-label :hide-home-button}
[icons/icon :main-icons/close-circle {:color colors/gray}]]
[react/i18n-text {:style styles/no-chats-text :key :chat-and-transact}]
[react/view
{:align-items :center
:margin-top 8
:margin-bottom 12}
[invite/button]]])
(defn welcome-blank-page
[]
[react/view {:style {:flex 1 :flex-direction :row :align-items :center :justify-content :center}}
[react/i18n-text {:style styles/welcome-blank-text :key :welcome-blank-message}]])
(defonce search-active? (reagent/atom false))
(defn search-input-wrapper
[search-filter chats-empty]
[react/view
{:padding-horizontal 16
:padding-vertical 10}
[search-input/search-input
{:search-active? search-active?
:placeholder (i18n/label :t/search)
:border-radius 10
:search-filter search-filter
:before true
:on-cancel #(re-frame/dispatch [:search/home-filter-changed nil])
:on-blur (fn []
(when chats-empty
(re-frame/dispatch [:search/home-filter-changed nil]))
(re-frame/dispatch [:contacts/clear-new-identity]))
:on-focus (fn [search-filter]
(when-not search-filter
(re-frame/dispatch [:search/home-filter-changed ""])
(re-frame/dispatch [:contacts/clear-new-identity])))
:on-change (fn [text]
(re-frame/dispatch [:search/home-filter-changed text])
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
(debounce/debounce-and-dispatch [:contacts/set-new-identity text] 300))}]])
(defn search-input-wrapper-old
[search-filter chats-empty]
[react/view
{:padding-horizontal 16
:padding-vertical 10}
[search-input/search-input-old
{:search-active? search-active?
:search-filter search-filter
:on-cancel #(re-frame/dispatch [:search/home-filter-changed nil])
:on-blur (fn []
(when chats-empty
(re-frame/dispatch [:search/home-filter-changed nil]))
(re-frame/dispatch [:contacts/clear-new-identity]))
:on-focus (fn [search-filter]
(when-not search-filter
(re-frame/dispatch [:search/home-filter-changed ""])
(re-frame/dispatch [:contacts/clear-new-identity])))
:on-change (fn [text]
(re-frame/dispatch [:search/home-filter-changed text])
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
(debounce/debounce-and-dispatch [:new-chat/set-new-identity text] 300))}]])
(defn start-suggestion
[search-value]
(let [{:keys [state ens-name public-key compressed-key]}
@(re-frame/subscribe [:contacts/new-identity])
valid-private? (= state :valid)
valid-public? (db/valid-topic? search-value)]
(when (or valid-public? valid-private?)
[react/view
[quo/list-header (i18n/label :t/search-no-chat-found)]
(when valid-private?
[quo/list-item
{:theme :accent
:icon :main-icons/private-chat
:title (or ens-name
(utils/get-shortened-address
(or compressed-key public-key)))
:subtitle (i18n/label :t/join-new-private-chat)
:on-press (fn []
(debounce/dispatch-and-chill [:contact.ui/contact-code-submitted false] 3000)
(re-frame/dispatch [:search/home-filter-changed nil]))}])
(when valid-public?
[quo/list-item
{:theme :accent
:icon :main-icons/public-chat
:title (str "#" search-value)
:subtitle (i18n/label :t/join-new-public-chat)
:on-press (fn []
(re-frame/dispatch [:chat.ui/start-public-chat search-value])
(re-frame/dispatch [:set :public-group-topic nil])
(re-frame/dispatch [:search/home-filter-changed nil]))}])])))
(defn render-fn
[{:keys [chat-id] :as home-item}]
;; We use `chat-id` to distinguish communities from chats
(if chat-id
[inner-item/home-list-item
home-item
{:on-press (fn []
(re-frame/dispatch [:dismiss-keyboard])
(re-frame/dispatch [:chat/navigate-to-chat chat-id])
(re-frame/dispatch [:search/home-filter-changed nil]))
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
{:content (fn []
[sheets/actions home-item])}])}]
[communities.views/community-home-list-item home-item]))
(defn render-fn-old
[{:keys [chat-id] :as home-item}]
;; We use `chat-id` to distinguish communities from chats
(if chat-id
[inner-item/home-list-item-old
home-item
{:on-press (fn []
(re-frame/dispatch [:dismiss-keyboard])
(re-frame/dispatch [:chat/navigate-to-chat chat-id])
(re-frame/dispatch [:search/home-filter-changed nil]))
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet-old
{:content (fn []
[sheets/actions home-item])}])}]
[communities.views/community-home-list-item home-item]))
(defn chat-list-key-fn
[item]
(or (:chat-id item) (:id item)))
(defn get-item-layout
[_ index]
#js {:length 64 :offset (* 64 index) :index index})
(views/defview communities-and-chats
[]
(views/letsubs [{:keys [items search-filter]} [:home-items]
hide-home-tooltip? [:hide-home-tooltip?]]
(if (and (empty? items)
(empty? search-filter)
hide-home-tooltip?
(not @search-active?))
[welcome-blank-page]
[list/flat-list
{:key-fn chat-list-key-fn
:getItemLayout get-item-layout
:on-end-reached #(re-frame/dispatch [:chat/show-more-chats])
:keyboard-should-persist-taps :always
:data items
:render-fn render-fn
:header [:<>
(when (or (seq items) @search-active? (seq search-filter))
[search-input-wrapper search-filter (empty? items)])
(when (and (empty? items)
(or @search-active? (seq search-filter)))
[start-suggestion search-filter])]
:footer (if (and (not hide-home-tooltip?) (not @search-active?))
[home-tooltip-view]
[react/view {:height 68}])}])))
(views/defview communities-and-chats-old
[]
(views/letsubs [{:keys [items search-filter]} [:home-items]
hide-home-tooltip? [:hide-home-tooltip?]]
(if (and (empty? items)
(empty? search-filter)
hide-home-tooltip?
(not @search-active?))
[welcome-blank-page]
[list/flat-list
{:key-fn chat-list-key-fn
:getItemLayout get-item-layout
:on-end-reached #(re-frame/dispatch [:chat/show-more-chats])
:keyboard-should-persist-taps :always
:data items
:render-fn render-fn-old
:header [:<>
(when (or (seq items) @search-active? (seq search-filter))
[search-input-wrapper-old search-filter (empty? items)])
(when (and (empty? items)
(or @search-active? (seq search-filter)))
[start-suggestion search-filter])]
:footer (if (and (not hide-home-tooltip?) (not @search-active?))
[home-tooltip-view]
[react/view {:height 68}])}])))
(views/defview chats-list
[]
(views/letsubs [loading? [:chats/loading?]]
[:<>
[connectivity/loading-indicator]
(if loading?
[react/view {:flex 1 :align-items :center :justify-content :center}
[react/activity-indicator {:animating true}]]
[communities-and-chats])]))
(views/defview chats-list-old
[]
(views/letsubs [loading? [:chats/loading?]]
[:<>
[connectivity/loading-indicator]
(if loading?
[react/view {:flex 1 :align-items :center :justify-content :center}
[react/activity-indicator {:animating true}]]
[communities-and-chats-old])]))
(views/defview plus-button
[]
(views/letsubs [logging-in? [:multiaccounts/login]]
[components.plus-button/plus-button-old
{:on-press (when-not logging-in?
(fn []
(re-frame/dispatch [:group-chat/clear-contacts])
(re-frame/dispatch [:bottom-sheet/show-sheet-old :start-a-new-chat {}])))
:loading logging-in?
:accessibility-label :new-chat-button}]))
(views/defview plus-button-old
[]
(views/letsubs [logging-in? [:multiaccounts/login]]
[components.plus-button/plus-button-old
{:on-press (when-not logging-in?
(fn []
(re-frame/dispatch [:group-chat/clear-contacts])
(re-frame/dispatch [:bottom-sheet/show-sheet-old :start-a-new-chat {}])))
:loading logging-in?
:accessibility-label :new-chat-button}]))
(views/defview notifications-button
[]
(views/letsubs [notif-count [:activity-center/unread-count]]
[react/view
[quo2.button/button
{:type :grey
:size 32
:width 32
:style {:margin-left 12}
:accessibility-label :notifications-button
:on-press #(re-frame/dispatch [:activity-center/open])}
[icons/icon :main-icons/notification2
{:color (quo2.colors/theme-colors quo2.colors/neutral-100 quo2.colors/white)}]]
(when (pos? notif-count)
[react/view
{:style (merge (styles/counter-public-container) {:top 5 :right 5})
:pointer-events :none}
[react/view
{:style styles/counter-public
:accessibility-label :notifications-unread-badge}]])]))
(defn qr-button
[]
[quo2.button/button
{:type :grey
:accessibility-label "qr-button"
:size 32
:width 32
:style {:margin-left 12}
:on-press #(do
(re-frame/dispatch [::qr-scanner/scan-code
{:handler ::qr-scanner/on-scan-success}]))}
[icons/icon :main-icons/qr2
{:color (quo2.colors/theme-colors quo2.colors/neutral-100 quo2.colors/white)}]])
(defn scan-button
[]
[quo2.button/button
{:type :grey
:size 32
:width 32
:accessibility-label "scan-button"
:on-press #(do
(re-frame/dispatch [::qr-scanner/scan-code
{:handler ::qr-scanner/on-scan-success}]))}
[icons/icon :main-icons/scan2
{:color (quo2.colors/theme-colors quo2.colors/neutral-100 quo2.colors/white)}]])
(views/defview profile-button
[]
(views/letsubs [{:keys [public-key preferred-name emoji]} [:multiaccount]]
[react/view
[chat-icon.screen/emoji-chat-icon-view public-key false preferred-name emoji
{:size 28
:chat-icon chat-icon.styles/chat-icon-chat-list}]]))
(defn home
[]
[react/keyboard-avoiding-view
{:style {:flex 1
:background-color (quo2.colors/theme-colors quo2.colors/neutral-5
quo2.colors/neutral-95)}
:ignore-offset true}
[topbar/topbar
{:navigation :none
:use-insets true
:background (quo2.colors/theme-colors quo2.colors/neutral-5 quo2.colors/neutral-95)
:left-component [react/view {:flex-direction :row :margin-left 16}
[profile-button]]
:right-component [react/view {:flex-direction :row :margin-right 16}
[scan-button]
[qr-button]
[notifications-button]]
:border-bottom false}]
[react/view
{:flex-direction :row
:justify-content :space-between
:align-items :center
:margin-horizontal 16
:margin-top 15
:margin-bottom 8}
[quo2.text/text {:size :heading-1 :weight :semi-bold} (i18n/label :t/messages)]
[plus-button]]
[chats-list]])
(defn home-old
[]
[react/keyboard-avoiding-view
{:style {:flex 1}
:ignore-offset true}
[topbar/topbar
{:title (i18n/label :t/chat)
:navigation :none
:right-component [react/view {:flex-direction :row :margin-right 16}
[connectivity/connectivity-button]]}]
[chats-list-old]
[plus-button-old]])
@@ -2,7 +2,7 @@
(:require [re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ethereum.decode :as decode]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.ui.components.react :as react]
[status-im2.common.json-rpc.events :as json-rpc]
[utils.datetime :as datetime]))
@@ -36,7 +36,7 @@
(reset! latest-block res)
(get-block
(str "0x"
(status/number-to-hex
(native-module/number-to-hex
(last-loaded-block-number)))
(fn [res]
(reset! last-loaded-block res))))))]
@@ -7,7 +7,6 @@
[status-im.ui.components.animation :as anim]
[status-im.ui.components.react :as react]
[status-im.ui.screens.biometric.views :as biometric]
[status-im.ui.screens.communities.views :as communities]
[status-im.ui.screens.keycard.frozen-card.view :as frozen-card]
[status-im.ui.screens.keycard.views :as keycard.views]
[status-im.ui.screens.multiaccounts.key-storage.views :as multiaccounts.key-storage]
@@ -167,9 +166,6 @@
(= :blocked-card view)
[keycard.views/blocked-card-popover]
(= :export-community view)
[communities/export-community]
(= :seed-key-uid-mismatch view)
[multiaccounts.key-storage/seed-key-uid-mismatch-popover]
@@ -3,7 +3,7 @@
[re-frame.core :as re-frame]
[status-im.ethereum.core :as ethereum]
[utils.i18n :as i18n]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[utils.re-frame :as rf]
[status-im.utils.types :as types]
[taoensso.timbre :as log]
@@ -21,7 +21,7 @@
(-> masked-password
security/safe-unmask-data
ethereum/sha3)]
(status/verify
(native-module/verify
address
hashed-password
(fn [result]
@@ -29,7 +29,7 @@
(log/info "[delete-profile] verify-password" result error)
(if-not (safe-blank? error)
(callback :wrong-password nil)
(status/delete-multiaccount
(native-module/delete-multiaccount
key-uid
(fn [result]
(let [{:keys [error]} (types/json->clj result)]
+6 -31
View File
@@ -4,8 +4,6 @@
[utils.i18n :as i18n]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.screens.about-app.views :as about-app]
[status-im.ui.screens.add-new.new-chat.views :as new-chat]
[status-im.ui.screens.add-new.new-public-chat.view :as new-public-chat]
[status-im.ui.screens.advanced-settings.views :as advanced-settings]
[status-im.ui.screens.appearance.views :as appearance]
[status-im.ui.screens.backup-settings.view :as backup-settings]
@@ -30,7 +28,6 @@
[status-im.ui.screens.communities.reorder-categories :as reorder-categories]
[status-im.ui.screens.communities.requests-to-join :as requests-to-join]
[status-im.ui.screens.communities.select-category :as select-category]
[status-im.ui.screens.communities.views :as communities]
[status-im.ui.screens.contacts-list.views :as contacts-list]
[status-im.ui.screens.currency-settings.views :as currency-settings]
[status-im.ui.screens.dapps-permissions.views :as dapps-permissions]
@@ -277,13 +274,10 @@
:options {:insets {:top? true}}
;;TODO custom subtitle
:component group-chat/new-group}
{:name :communities
;;TODO custom
:options {:insets {:top? true}}
:component communities/communities}
{:name :community-import
:options {:topBar {:title {:text (i18n/label :t/import-community-title)}}
:insets {:top? true}}
:insets {:top? true
:bottom? true}}
:component communities.import/view}
{:name :community-edit
:options {:topBar {:title {:text (i18n/label :t/community-edit-title)}}
@@ -291,11 +285,13 @@
:component community.edit/edit}
{:name :community-create
:options {:topBar {:title {:text (i18n/label :t/new-community-title)}}
:insets {:top? true}}
:insets {:top? true
:bottom? true}}
:component communities.create/view}
{:name :community-membership
:options {:topBar {:title {:text (i18n/label :t/membership-title)}}
:insets {:top? true}}
:insets {:top? true
:bottom? true}}
:component membership/membership}
;;WALLET
@@ -576,20 +572,6 @@
;;MODALS
;[Chat] New Chat
{:name :new-chat
:on-focus [:contacts/new-chat-focus]
;;TODO accessories
:options {:insets {:top? true}}
:component new-chat/new-chat}
;[Chat] New Public chat
{:name :new-public-chat
:options {:topBar {:title {:text (i18n/label :t/new-public-group-chat)}}
:insets {:bottom? true
:top? true}}
:component new-public-chat/new-public-chat}
;[Chat] Link preview settings
{:name :link-preview-settings
:options {:topBar {:title {:text (i18n/label :t/chat-link-previews)}}
@@ -610,13 +592,6 @@
:options {:insets {:top? true}}
:component new-chat-aio/contact-selection-list}
;[Chat] New Public chat
{:name :new-public-chat
:options {:topBar {:title {:text (i18n/label :t/new-public-group-chat)}}
:insets {:bottom? true
:top? true}}
:component new-public-chat/new-public-chat}
;[Group chat] Add participants
{:name :add-participants-toggle-list
:on-focus [:group/add-participants-toggle-list]
@@ -141,33 +141,15 @@
(reset! last-text-change (js/Date.now)))
(on-text-change text chat-id)
;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`,
;; that's why mention suggestions are calculated on `on-change`
(when platform/ios?
(rf/dispatch [:mention/calculate-suggestions]))))
(rf/dispatch [:mention/on-change-text text])))
(defn on-text-input
[chat-id args]
(let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event)
previous-text (.-previousText ^js native-event)
range (.-range ^js native-event)
start (.-start ^js range)
end (.-end ^js range)]
(let [native-event (.-nativeEvent ^js args)
text (.-text ^js native-event)]
(when (and (not (get @mentions-enabled? chat-id)) (string/index-of text "@"))
(swap! mentions-enabled? assoc chat-id true))
(rf/dispatch
[:mention/on-text-input
{:new-text text
:previous-text previous-text
:start start
:end end}])
;; NOTE(rasom): on Android `on-text-input` is dispatched after
;; `on-change`, that's why mention suggestions are calculated
;; on `on-change`
(when platform/android?
(rf/dispatch [:mention/calculate-suggestions]))))
(swap! mentions-enabled? assoc chat-id true))))
(defn text-input-style
[chat-id]
+1 -12
View File
@@ -1,6 +1,5 @@
(ns status-im.utils.gfycat.core
(:require [re-frame.core :as re-frame]
[status-im.native-module.core :as native-module]))
(:require [native-module.core :as native-module]))
(def unknown-gfy "Unknown")
@@ -12,13 +11,3 @@
(native-module/generate-gfycat public-key)))
(def generate-gfy (memoize build-gfy))
(re-frame/reg-fx
:insert-gfycats
(fn [key-path-seq]
(for [key-path key-path-seq]
(let [public-key (first key-path)
path-for-gfycat (second key-path)]
(native-module/generate-gfycat-async public-key
#(re-frame/dispatch [:gfycat-generated path-for-gfycat
%]))))))
+1 -12
View File
@@ -1,15 +1,4 @@
(ns status-im.utils.identicon
(:require [re-frame.core :as re-frame]
[status-im.native-module.core :as native-module]))
(:require [native-module.core :as native-module]))
(def identicon (memoize native-module/identicon))
(def identicon-async native-module/identicon-async)
(re-frame/reg-fx
:insert-identicons
(fn [key-path-seq]
(for [key-path key-path-seq]
(let [public-key (first key-path)
path-for-identicon (second key-path)]
(identicon-async public-key #(re-frame/dispatch [:identicon-generated path-for-identicon %]))))))
+2 -2
View File
@@ -2,7 +2,7 @@
(:require ["react-native-keychain" :as react-native-keychain]
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[utils.re-frame :as rf]
[status-im.utils.platform :as platform]
[taoensso.timbre :as log]
@@ -63,7 +63,7 @@
;; Android only
(defn- device-not-rooted?
[callback]
(status/rooted-device? (fn [rooted?] (callback (not rooted?)))))
(native-module/rooted-device? (fn [rooted?] (callback (not rooted?)))))
;; Android only
(defn- secure-hardware-available?
+2 -2
View File
@@ -5,7 +5,7 @@
[react-native.mail :as react-native-mail]
[status-im.bottom-sheet.events :as bottom-sheet]
[utils.i18n :as i18n]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.transport.utils :as transport.utils]
[status-im.ui.components.react :as react]
[status-im.utils.build :as build]
@@ -20,7 +20,7 @@
(re-frame/reg-fx
:logs/archive-logs
(fn [[db-json callback-handler]]
(status/send-logs
(native-module/send-logs
db-json
(string/join "\n" (log/get-logs-queue))
#(re-frame/dispatch [callback-handler %]))))
-8
View File
@@ -1,8 +0,0 @@
(ns status-im.utils.react-native
(:require ["react-native" :as react-native]))
; Moved from status-im.ui.components.react(let's short for R), so status-im.native-module.core(short for
; N) don't need to have a dependency to R.
; We should keep N's dependencies as simple as possible, otherwise we may see issue like:
; Circular dependency detected: N -> R -> status-im.utils.utils -> status-im.ethereum.eip55 -> N
(def device-event-emitter (.-DeviceEventEmitter react-native))
+9 -15
View File
@@ -2,8 +2,6 @@
(:require [clojure.string :as string]
[goog.string :as gstring]
[re-frame.core :as re-frame]
[status-im.add-new.db :as new-chat.db]
[status-im.chat.models :as chat]
[status-im2.constants :as constants]
[status-im.ethereum.core :as ethereum]
[status-im.group-chats.core :as group-chats]
@@ -15,7 +13,7 @@
[status-im.wallet.choose-recipient.core :as choose-recipient]
[status-im2.navigation.events :as navigation]
[taoensso.timbre :as log]
[status-im.native-module.core :as status]))
[native-module.core :as native-module]))
;; TODO(yenda) investigate why `handle-universal-link` event is
;; dispatched 7 times for the same link
@@ -26,8 +24,7 @@
:internal "status-im:/"})
(def links
{:public-chat "%s/%s"
:private-chat "%s/p/%s"
{:private-chat "%s/p/%s"
:community-requests "%s/cr/%s"
:community "%s/c/%s"
:group-chat "%s/g/%s"
@@ -60,11 +57,15 @@
(log/info "universal-links: handling group" params)
(group-chats/create-from-link cofx params))
(defn own-public-key?
[{:keys [multiaccount]} public-key]
(= (:public-key multiaccount) public-key))
(rf/defn handle-private-chat
[{:keys [db] :as cofx} {:keys [chat-id]}]
(log/info "universal-links: handling private chat" chat-id)
(when chat-id
(if-not (new-chat.db/own-public-key? db chat-id)
(if-not (own-public-key? db chat-id)
{:dispatch [:chat.ui/start-chat chat-id]}
{:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code)
:content (i18n/label :t/can-not-add-yourself)}})))
@@ -88,7 +89,7 @@
(rf/defn handle-desktop-community
[cofx {:keys [community-id]}]
(status/deserialize-and-compress-key
(native-module/deserialize-and-compress-key
community-id
(fn [deserialized-key]
(rf/dispatch [:handle-navigation-to-desktop-community-from-mobile cofx (str deserialized-key)]))))
@@ -98,17 +99,11 @@
(log/info "universal-links: handling community chat" chat-id)
{:dispatch [:chat/navigate-to-chat chat-id]})
(rf/defn handle-public-chat
[cofx {:keys [topic]}]
(log/info "universal-links: handling public chat" topic)
(when (seq topic)
(chat/start-public-chat cofx topic)))
(rf/defn handle-view-profile
[{:keys [db] :as cofx} {:keys [public-key ens-name]}]
(log/info "universal-links: handling view profile" public-key)
(cond
(and public-key (new-chat.db/own-public-key? db public-key))
(and public-key (own-public-key? db public-key))
(rf/merge cofx
{:pop-to-root-fx :shell-stack}
(navigation/navigate-to :my-profile nil))
@@ -153,7 +148,6 @@
[cofx url {:keys [type] :as data}]
(case type
:group-chat (handle-group-chat cofx data)
:public-chat (handle-public-chat cofx data)
:private-chat (handle-private-chat cofx data)
:community-requests (handle-community-requests cofx data)
:community (handle-community cofx data)
@@ -8,8 +8,7 @@
:internal "status-im:/"})
(def links
{:public-chat "%s/%s"
:private-chat "%s/p/%s"
{:private-chat "%s/p/%s"
:user "%s/u/%s"
:browse "%s/b/%s"})
+8 -8
View File
@@ -14,7 +14,7 @@
[status-im.multiaccounts.core :as multiaccounts]
[status-im.multiaccounts.key-storage.core :as key-storage]
[status-im.multiaccounts.update.core :as multiaccounts.update]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im.ui.components.list-selection :as list-selection]
[utils.re-frame :as rf]
[status-im.utils.hex :as hex]
@@ -74,7 +74,7 @@
(let [{:keys [id error]} (types/json->clj value)]
(if error
(re-frame/dispatch [::new-account-error :password-error error])
(status/multiaccount-derive-addresses
(native-module/multiaccount-derive-addresses
id
[path]
(fn [derived]
@@ -82,7 +82,7 @@
(if (some #(= derived-address (get % :address)) accounts)
(re-frame/dispatch [::new-account-error :account-error
(i18n/label :t/account-exists-title)])
(status/multiaccount-store-derived
(native-module/multiaccount-store-derived
id
key-uid
[path]
@@ -110,7 +110,7 @@
(re-frame/dispatch [::new-account-error
(if (= error pass-error) :password-error :account-error)
error])
(status/multiaccount-store-account
(native-module/multiaccount-store-account
id
key-uid
hashed-password
@@ -119,7 +119,7 @@
(re-frame/reg-fx
::verify-password
(fn [{:keys [address hashed-password]}]
(status/verify
(native-module/verify
address
hashed-password
#(re-frame/dispatch [:wallet.accounts/add-new-account-password-verifyied % hashed-password]))))
@@ -128,7 +128,7 @@
::generate-account
(fn [{:keys [derivation-info hashed-password accounts key-uid]}]
(let [{:keys [address path]} derivation-info]
(status/multiaccount-load-account
(native-module/multiaccount-load-account
address
hashed-password
(derive-and-store-account key-uid path hashed-password :generated accounts)))))
@@ -136,7 +136,7 @@
(re-frame/reg-fx
::import-account-seed
(fn [{:keys [passphrase hashed-password accounts key-uid]}]
(status/multiaccount-import-mnemonic
(native-module/multiaccount-import-mnemonic
(mnemonic/sanitize-passphrase (security/unmask passphrase))
""
(derive-and-store-account key-uid constants/path-default-wallet hashed-password :seed accounts))))
@@ -144,7 +144,7 @@
(re-frame/reg-fx
::import-account-private-key
(fn [{:keys [private-key hashed-password key-uid]}]
(status/multiaccount-import-private-key
(native-module/multiaccount-import-private-key
(string/trim (security/unmask private-key))
(store-account key-uid constants/path-default-wallet hashed-password :key))))
@@ -433,15 +433,6 @@
(notification-actions item inside-chat?)
(destructive-actions item)]])
(defn public-chat-actions
[{:keys [chat-id] :as item} inside-chat?]
[quo/action-drawer
[[(group-details-entry chat-id)
(when inside-chat?
(add-members-entry))]
(notification-actions item inside-chat?)
(destructive-actions item)]])
(defn private-group-chat-actions
[item inside-chat?]
[quo/action-drawer
@@ -470,8 +461,6 @@
(case chat-type
constants/one-to-one-chat-type
[one-to-one-actions item inside-chat?]
constants/public-chat-type
[public-chat-actions item inside-chat?]
constants/private-group-chat-type
[private-group-chat-actions item inside-chat?]))
+2 -2
View File
@@ -2,7 +2,7 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[react-native.background-timer :as background-timer]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[taoensso.timbre :as log]
[utils.transforms :as transforms]))
@@ -29,7 +29,7 @@
on-error (or on-error
(on-error-retry call arg)
#(log/warn :json-rpc/error method :error % :params params))]
(status/call-private-rpc
(native-module/call-private-rpc
(transforms/clj->json {:jsonrpc "2.0"
:id 1
:method method
+19 -8
View File
@@ -1,18 +1,29 @@
(ns status-im2.common.theme.core
(:require [quo.theme :as quo]
[quo2.theme :as quo2]
[react-native.core :as rn]))
[utils.re-frame :as rf]
[oops.core :refer [oget]]
[react-native.core :as rn]
[react-native.platform :as platform]))
(def device-theme (atom (rn/get-color-scheme)))
;; Note - don't use value returned by change listener
;; https://github.com/facebook/react-native/issues/28525
(defn change-device-theme
[theme]
(when-not (= theme @device-theme)
(reset! device-theme theme)
(rf/dispatch [:system-theme-mode-changed (keyword theme)])))
;; Appearance change listener fires false events in ios when the app is in the background
;; So, we are ignoring those events and when the device returns form the background,
;; we are manually checking the device theme, in ::app-state-change-fx
;; https://github.com/status-im/status-mobile/issues/15708
(defn add-device-theme-change-listener
[callback]
(rn/appearance-add-change-listener #(let [theme (rn/get-color-scheme)]
(when-not (= theme @device-theme)
(reset! device-theme theme)
(callback (keyword theme))))))
[]
(rn/appearance-add-change-listener
#(when (or platform/android?
(not= (oget rn/app-state "currentState") "background"))
(change-device-theme (oget % "colorScheme")))))
(defn device-theme-dark?
[]
+8
View File
@@ -45,3 +45,11 @@
(update-in [:db :toasts] assoc :hide-toasts-timer-set true)
(assoc :dispatch-later [{:ms 500 :dispatch [:toasts/hide-with-check]}]))
effect))))
(rf/defn close-all-toasts
{:events [:toasts/close-all-toasts]}
[{:keys [db]}]
{:dispatch-n (reduce (fn [acc toast]
(conj acc [:toasts/close (key toast)]))
[]
(get-in db [:toasts :toasts]))})
+2
View File
@@ -158,3 +158,5 @@
["enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.waku.nodes.status.im"]})
(def default-kdf-iterations 3200)
(def ^:const new-composer-enabled? true)
@@ -0,0 +1,37 @@
(ns status-im2.contexts.activity-center.notification.community-kicked.view
(:require [quo2.core :as quo]
[status-im2.contexts.activity-center.notification.common.style :as common-style]
[status-im2.contexts.activity-center.notification.common.view :as common]
[utils.datetime :as datetime]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- swipeable
[{:keys [active-swipeable extra-fn]} child]
[common/swipeable
{:left-button common/swipe-button-read-or-unread
:left-on-press common/swipe-on-press-toggle-read
:right-button common/swipe-button-delete
:right-on-press common/swipe-on-press-delete
:active-swipeable active-swipeable
:extra-fn extra-fn}
child])
(defn view
[{:keys [notification set-swipeable-height] :as props}]
(let [{:keys [community-id read
timestamp]} notification
community (rf/sub [:communities/community community-id])
community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])]
[swipeable props
[quo/activity-log
{:title (i18n/label :t/community-kicked-heading)
:icon :i/placeholder
:on-layout set-swipeable-height
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [[quo/text {:style common-style/user-avatar-tag-text}
(i18n/label :t/community-kicked-body)]
[quo/context-tag common/tag-params {:uri community-image}
community-name]]}]]))
@@ -8,6 +8,7 @@
(def ^:const contact-request 5)
(def ^:const community-request 7)
(def ^:const admin 8)
(def ^:const community-kicked 9)
(def ^:const contact-verification 10)
(def ^:const all-supported
@@ -18,6 +19,7 @@
contact-request
community-request
admin
community-kicked
contact-verification})
;; TODO: Replace with correct enum values once status-go implements them.
@@ -29,4 +31,5 @@
it doesn't have a corresponding type in the backend. Think of the collection
as a composite key of actual types."
#{private-group-chat
community-request})
community-request
community-kicked})
@@ -14,6 +14,8 @@
[status-im2.contexts.activity-center.notification.reply.view :as reply]
[status-im2.contexts.activity-center.notification.community-request.view :as
community-request]
[status-im2.contexts.activity-center.notification.community-kicked.view :as
community-kicked]
[status-im2.contexts.activity-center.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]
@@ -203,6 +205,8 @@
types/community-request [community-request/view props]
types/community-kicked [community-kicked/view props]
nil)
:else
@@ -6,11 +6,12 @@
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.ens :as ens]
[status-im.ethereum.stateofus :as stateofus]
[status-im.native-module.core :as status]
[native-module.core :as native-module]
[status-im2.navigation.events :as navigation]
[status-im2.utils.validators :as validators]
[utils.validators :as validators]
[status-im2.contexts.contacts.events :as data-store.contacts]
[status-im.utils.utils :as utils]))
[status-im.utils.utils :as utils]
[status-im2.constants :as constants]))
(defn init-contact
"Create a new contact (persisted to app-db as [:contacts/new-identity]).
@@ -124,8 +125,9 @@
(re-frame/reg-fx
:contacts/decompress-public-key
(fn [{:keys [compressed-key on-success on-error]}]
(status/compressed-key->public-key
(native-module/compressed-key->public-key
compressed-key
constants/deserialization-key
(fn [resp]
(let [{:keys [error]} (types/json->clj resp)]
(if error
@@ -0,0 +1,20 @@
(ns status-im2.contexts.chat.actions.view
(:require [quo2.core :as quo]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn new-chat
[]
[quo/action-drawer
[[{:icon :i/new-message
:accessibility-label :start-a-new-chat
:label (i18n/label :t/new-chat)
:on-press (fn []
(rf/dispatch [:group-chat/clear-contacts])
(rf/dispatch [:open-modal :start-a-new-chat]))}
{:icon :i/add-user
:accessibility-label :add-a-contact
:label (i18n/label :t/add-a-contact)
:sub-label (i18n/label :t/enter-a-chat-key)
:add-divider? true
:on-press #(rf/dispatch [:open-modal :new-contact])}]]])
@@ -18,4 +18,17 @@
{:position :absolute
:right 0
:z-index z-index
:background-color (colors/theme-colors colors/white colors/neutral-95)}))
:background-color (colors/theme-colors colors/white colors/neutral-95)
:padding-vertical 3
:padding-left 2}))
(defn record-audio-container
[]
{:align-items :center
:background-color :transparent
:flex-direction :row
:position :absolute
:left -20
:right -20
:bottom 0
:height constants/composer-default-height})
@@ -14,8 +14,7 @@
[status-im2.contexts.chat.bottom-sheet-composer.actions.style :as style]))
(defn send-message
[{:keys [input-ref]}
{:keys [text-value focused? maximized?]}
[{:keys [text-value focused? maximized?]}
{:keys [height saved-height last-height opacity background-y container-opacity]}
window-height]
(reanimated/animate height constants/input-height)
@@ -33,13 +32,10 @@
(rf/dispatch [:chat.ui/set-chat-input-text nil])
(reset! maximized? false)
(reset! text-value "")
(when @input-ref
(.clear ^js @input-ref))
(messages.list/scroll-to-bottom))
(defn send-button
[props
{:keys [text-value] :as state}
[{:keys [text-value] :as state}
animations
window-height
images?]
@@ -64,17 +60,62 @@
{:icon true
:size 32
:accessibility-label :send-message-button
:on-press #(send-message props state animations window-height)}
:on-press #(send-message state animations window-height)}
:i/arrow-up]])]))])
(defn audio-button
[]
[quo/button
{:on-press #(js/alert "to be added")
:icon true
:type :outline
:size 32}
:i/audio])
[{:keys [record-permission? record-reset-fn]}
{:keys [recording? gesture-enabled?]}
{:keys [container-opacity]}]
(let [audio (rf/sub [:chats/sending-audio])]
[rn/view
{:style (style/record-audio-container)
:pointer-events :box-none}
[quo/record-audio
{:record-audio-permission-granted record-permission?
:on-init (fn [reset-fn]
(reset! record-reset-fn reset-fn))
:on-start-recording (fn []
(reset! recording? true)
(reset! gesture-enabled? false)
(reanimated/animate container-opacity 1))
:audio-file audio
:on-reviewing-audio (fn [file]
(rf/dispatch [:chat.ui/set-input-audio file]))
:on-send (fn [{:keys [file-path duration]}]
(reset! recording? false)
(reset! gesture-enabled? true)
(rf/dispatch [:chat/send-audio file-path duration])
(reanimated/animate container-opacity
constants/empty-opacity)
(rf/dispatch [:chat.ui/set-input-audio nil]))
:on-cancel (fn []
(when @recording?
(reset! recording? false)
(reset! gesture-enabled? true)
(reanimated/animate container-opacity
constants/empty-opacity)
(rf/dispatch [:chat.ui/set-input-audio nil])))
:on-check-audio-permissions (fn []
(permissions/permission-granted?
:record-audio
#(reset! record-permission? %)
#(reset! record-permission? false)))
:on-request-record-audio-permission (fn []
(rf/dispatch
[:request-permissions
{:permissions [:record-audio]
:on-allowed
#(reset! record-permission? true)
:on-denied
#(js/setTimeout
(fn []
(alert/show-popup
(i18n/label :t/audio-recorder-error)
(i18n/label
:t/audio-recorder-permissions-error)))
50)}]))}]]))
(defn camera-button
[]
@@ -88,17 +129,13 @@
(defn open-photo-selector
[{:keys [input-ref]}
{:keys [focused?]}
{:keys [height]}
insets]
(permissions/request-permissions
{:permissions [:read-external-storage :write-external-storage]
:on-allowed (fn []
(when platform/android?
(when @focused?
(rf/dispatch [:chat.ui/set-input-refocus true]))
(when @input-ref
(.blur ^js @input-ref)))
(when (and platform/android? @input-ref)
(.blur ^js @input-ref))
(rf/dispatch [:chat.ui/set-input-content-height
(reanimated/get-shared-value height)])
(rf/dispatch [:open-modal :photo-selector {:insets insets}]))
@@ -108,9 +145,9 @@
:t/external-storage-denied)))}))
(defn image-button
[props state animations insets]
[props animations insets]
[quo/button
{:on-press #(open-photo-selector props state animations insets)
{:on-press #(open-photo-selector props animations insets)
:icon true
:type :outline
:size 32
@@ -137,12 +174,14 @@
:i/format])
(defn view
[props state animations window-height insets images?]
[props state animations window-height insets images? audio]
[rn/view {:style style/actions-container}
[rn/view {:style {:flex-direction :row}}
[rn/view
{:style {:flex-direction :row
:display (if @(:recording? state) :none :flex)}}
[camera-button]
[image-button props state animations insets]
[image-button props animations insets]
[reaction-button]
[format-button]]
[send-button props state animations window-height images?]
[audio-button]])
[send-button state animations window-height images?]
[audio-button props state animations audio]])
@@ -17,6 +17,12 @@
(def ^:const images-container-height 76)
(def ^:const reply-container-height 32)
(def ^:const edit-container-height 32)
(def ^:const mentions-max-height 240)
(def ^:const extra-content-offset (if platform/ios? 6 0))
(def ^:const content-change-threshold 10)
@@ -0,0 +1,23 @@
(ns status-im2.contexts.chat.bottom-sheet-composer.edit.style)
(def container
{:flex-direction :row
:height 24})
(def content-container
{:flex 1
:flex-direction :row})
(def icon-container
{:position :absolute
:left 0
:bottom -4
:width 16
:height 16})
(def text-container
{:position :absolute
:left 24
:top 3
:flex-direction :row
:align-items :center})
@@ -0,0 +1,49 @@
(ns status-im2.contexts.chat.bottom-sheet-composer.edit.view
(:require
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
[utils.i18n :as i18n]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[re-frame.core :as rf]
[react-native.core :as rn]
[status-im2.contexts.chat.bottom-sheet-composer.edit.style :as style]))
(defn edit-message
[cancel]
[rn/view
{:style style/container
:accessibility-label :edit-message}
[rn/view {:style style/content-container}
[quo/icon
:i/connector-dotted
{:size 16
:color (colors/theme-colors colors/neutral-40 colors/neutral-60)
:container-style style/icon-container}]
[rn/view {:style style/text-container}
[quo/text
{:weight :medium
:size :paragraph-2}
(i18n/label :t/editing-message)]]]
[quo/button
{:width 24
:size 24
:accessibility-label :edit-cancel-button
:on-press (fn []
(cancel)
(rf/dispatch [:chat.ui/cancel-message-edit]))
:type :outline}
[quo/icon :i/close
{:size 16
:color (colors/theme-colors colors/neutral-100 colors/neutral-40)}]]])
(defn- f-view
[edit cancel]
(let [height (reanimated/use-shared-value (if edit constants/edit-container-height 0))]
(rn/use-effect #(reanimated/animate height (if edit constants/edit-container-height 0)) [edit])
[reanimated/view {:style (reanimated/apply-animations-to-style {:height height} {})}
(when edit [edit-message cancel])]))
(defn view
[edit cancel]
[:f> f-view edit cancel])
@@ -5,7 +5,6 @@
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
[status-im2.contexts.chat.bottom-sheet-composer.keyboard :as kb]
[utils.re-frame :as rf]
[utils.number :as utils.number]))
(defn reenter-screen-effect
@@ -29,13 +28,6 @@
(reanimated/set-shared-value saved-height max-height)
(reanimated/set-shared-value last-height max-height)))
(defn refocus-effect
[{:keys [input-ref]}
{:keys [input-refocus?]}]
(when (and input-refocus? @input-ref)
(.focus ^js @input-ref)
(rf/dispatch [:chat.ui/set-input-refocus false])))
(defn layout-effect
[{:keys [lock-layout?]}]
(when-not @lock-layout?
@@ -56,17 +48,53 @@
(reanimated/set-shared-value background-y 0)
(reanimated/animate opacity 1)))
(defn images-effect
(defn images-or-reply-effect
[{:keys [container-opacity]}
images?]
(when images?
{:keys [replying? sending-images? input-ref]}
images? reply?]
(when (or images? reply?)
(reanimated/animate container-opacity 1))
(when (and (not @sending-images?) images? @input-ref)
(.focus ^js @input-ref)
(reset! sending-images? true))
(when (and (not @replying?) reply? @input-ref)
(.focus ^js @input-ref)
(reset! replying? true))
(when-not images?
(reset! sending-images? false))
(when-not reply?
(reset! replying? false)))
(defn edit-effect
[{:keys [text-value saved-cursor-position]}
{:keys [editing? input-ref]}
edit]
(let [edit-text (get-in edit [:content :text])]
(when (and (not @editing?) edit @input-ref)
(.focus ^js @input-ref)
(reset! editing? true)
(reset! text-value edit-text)
(reset! saved-cursor-position (count edit-text)))
(when-not edit-text
(reset! editing? false))))
(defn audio-effect
[{:keys [recording? gesture-enabled?]}
{:keys [container-opacity]}
audio]
(when (and audio (not @recording?))
(reset! recording? true)
(reset! gesture-enabled? false)
(reanimated/animate container-opacity 1)))
(defn empty-effect
[{:keys [text-value maximized? focused?]}
{:keys [container-opacity]}
images?]
(when (and (empty? @text-value) (not images?) (not @maximized?) (not @focused?))
images?
reply?
audio]
(when
(and (empty? @text-value) (not images?) (not reply?) (not @maximized?) (not @focused?) (not audio))
(reanimated/animate-delay container-opacity constants/empty-opacity 200)))
(defn component-will-unmount
@@ -76,17 +104,19 @@
(.remove ^js @keyboard-frame-listener))
(defn initialize
[props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images?]
[props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images? reply?
edit audio]
(rn/use-effect
(fn []
(maximized-effect state animations dimensions chat-input)
(refocus-effect props chat-input)
(reenter-screen-effect state dimensions chat-input)
(layout-effect state)
(kb-default-height-effect state)
(background-effect state animations dimensions chat-input)
(images-effect animations images?)
(empty-effect state animations images?)
(images-or-reply-effect animations props images? reply?)
(edit-effect state props edit)
(audio-effect state animations audio)
(empty-effect state animations images? reply? audio)
(kb/add-kb-listeners props state animations dimensions keyboard-height)
#(component-will-unmount props))
[max-height]))
@@ -1,11 +1,12 @@
(ns status-im2.contexts.chat.bottom-sheet-composer.handlers
(:require [react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[oops.core :as oops]
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
[status-im2.contexts.chat.bottom-sheet-composer.keyboard :as kb]
[status-im2.contexts.chat.bottom-sheet-composer.utils :as utils]
[utils.re-frame :as rf]))
(:require
[react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[oops.core :as oops]
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
[status-im2.contexts.chat.bottom-sheet-composer.keyboard :as kb]
[status-im2.contexts.chat.bottom-sheet-composer.utils :as utils]
[utils.re-frame :as rf]))
(defn focus
[{:keys [input-ref] :as props}
@@ -14,6 +15,7 @@
:as animations}
{:keys [max-height] :as dimensions}]
(reset! focused? true)
(rf/dispatch [:chat.ui/set-input-focused true])
(reanimated/animate height (reanimated/get-shared-value last-height))
(reanimated/set-shared-value saved-height (reanimated/get-shared-value last-height))
(reanimated/animate container-opacity 1)
@@ -34,16 +36,18 @@
maximized?]}
{:keys [height saved-height last-height gradient-opacity container-opacity opacity background-y]}
{:keys [lines content-height max-height window-height]}
images]
images
reply]
(let [min-height (utils/get-min-height lines)
reopen-height (utils/calc-reopen-height text-value min-height content-height saved-height)]
(reset! focused? false)
(rf/dispatch [:chat.ui/set-input-focused false])
(reanimated/set-shared-value last-height reopen-height)
(reanimated/animate height min-height)
(reanimated/set-shared-value saved-height min-height)
(reanimated/animate opacity 0)
(js/setTimeout #(reanimated/set-shared-value background-y (- window-height)) 300)
(when (and (empty? @text-value) (empty? images))
(when (utils/empty-input? @text-value images reply nil)
(reanimated/animate container-opacity constants/empty-opacity))
(reanimated/animate gradient-opacity 0)
(reset! lock-selection? true)
@@ -67,7 +71,8 @@
(reanimated/animate height new-height)
(reanimated/set-shared-value saved-height new-height))
(when (= new-height max-height)
(reset! maximized? true))
(reset! maximized? true)
(rf/dispatch [:chat.ui/set-input-maximized true]))
(if (utils/show-background? saved-height max-height new-height)
(do
(reanimated/set-shared-value background-y 0)
@@ -79,10 +84,12 @@
(defn scroll
[event
{:keys [scroll-y]}
{:keys [gradient-z-index focused?]}
{:keys [gradient-opacity]}
{:keys [lines max-lines]}]
(let [y (oops/oget event "nativeEvent.contentOffset.y")]
(reset! scroll-y y)
(when (utils/show-top-gradient? y lines max-lines gradient-opacity focused?)
(reset! gradient-z-index 1)
(js/setTimeout #(reanimated/animate gradient-opacity 1) 0))
@@ -92,17 +99,22 @@
(defn change-text
[text
{:keys [input-ref]}
{:keys [text-value cursor-position]}]
{:keys [input-ref record-reset-fn]}
{:keys [text-value cursor-position recording?]}]
(reset! text-value text)
(reagent/next-tick #(when @input-ref
(.setNativeProps ^js @input-ref
(clj->js {:selection {:start @cursor-position
:end @cursor-position}}))))
(rf/dispatch [:chat.ui/set-chat-input-text text]))
(when @recording?
(@record-reset-fn)
(reset! recording? false))
(rf/dispatch [:chat.ui/set-chat-input-text text])
(rf/dispatch [:mention/on-change-text text]))
(defn selection-change
[event {:keys [lock-selection? cursor-position]}]
(println "selectionc ahnge")
(when-not @lock-selection?
(reset! cursor-position (oops/oget event "nativeEvent.selection.end"))))
@@ -0,0 +1,30 @@
(ns status-im2.contexts.chat.bottom-sheet-composer.mentions.style
(:require [quo2.foundations.colors :as colors]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]))
(defn shadow
[]
(if platform/ios?
{:shadow-radius (colors/theme-colors 30 50)
:shadow-opacity (colors/theme-colors 0.1 0.7)
:shadow-color colors/neutral-100
:shadow-offset {:width 0 :height (colors/theme-colors 8 12)}}
{:elevation 10}))
(defn container
[opacity bottom]
(reanimated/apply-animations-to-style
{:opacity opacity}
(merge
{:position :absolute
:bottom bottom
:left 8
:right 8
:border-radius 16
:z-index 4
:max-height constants/mentions-max-height
:background-color (colors/theme-colors colors/white colors/neutral-95)}
(shadow))))
@@ -0,0 +1,67 @@
(ns status-im2.contexts.chat.bottom-sheet-composer.mentions.view
(:require
[react-native.hooks :as hooks]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.contexts.chat.bottom-sheet-composer.utils :as utils]
[utils.re-frame :as rf]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[status-im2.common.contact-list-item.view :as contact-list-item]
[status-im2.contexts.chat.bottom-sheet-composer.mentions.style :as style]))
(defn update-cursor
[user {:keys [cursor-position input-ref]}]
(when platform/android?
(let [new-cursor-pos (+ (count (:primary-name user)) @cursor-position)]
(reset! cursor-position new-cursor-pos)
(reagent/next-tick #(when @input-ref
(.setNativeProps ^js @input-ref
(clj->js {:selection {:start new-cursor-pos
:end
new-cursor-pos}})))))))
(defn mention-item
[user _ _ render-data]
[contact-list-item/contact-list-item
{:on-press (fn []
(rf/dispatch [:chat.ui/select-mention nil user])
(update-cursor user render-data))}
user])
(defn- f-view
[suggestions-atom props state animations max-height cursor-pos]
(let [{:keys [keyboard-height]} (hooks/use-keyboard)
suggestions (rf/sub [:chat/mention-suggestions])
opacity (reanimated/use-shared-value (if (seq suggestions) 1 0))
size (count suggestions)
data {:keyboard-height keyboard-height
:insets (safe-area/get-insets)
:curr-height (reanimated/get-shared-value (:height animations))
:window-height (rf/sub [:dimensions/window-height])
:reply (rf/sub [:chats/reply-message])
:edit (rf/sub [:chats/edit-message])}
mentions-pos (utils/calc-suggestions-position cursor-pos max-height size state data)]
(rn/use-effect
(fn []
(if (seq suggestions)
(reset! suggestions-atom suggestions)
(js/setTimeout #(reset! suggestions-atom suggestions) 300))
(reanimated/animate opacity (if (seq suggestions) 1 0)))
[(seq suggestions)])
[reanimated/view
{:style (style/container opacity mentions-pos)}
[rn/flat-list
{:keyboard-should-persist-taps :always
:data (vals @suggestions-atom)
:key-fn :key
:render-fn mention-item
:render-data {:cursor-position (:cursor-position state)
:input-ref (:input-ref props)}
:accessibility-label :mentions-list}]]))
(defn view
[props state animations max-height cursor-pos]
(let [suggestions-atom (reagent/atom {})]
[:f> f-view suggestions-atom props state animations max-height cursor-pos]))

Some files were not shown because too many files have changed in this diff Show More