diff --git a/nix/deps/clojure/deps.json b/nix/deps/clojure/deps.json index 8a769e3c01..249a8011c8 100644 --- a/nix/deps/clojure/deps.json +++ b/nix/deps/clojure/deps.json @@ -12,6 +12,19 @@ } }, + { + "path": "bidi/bidi/2.1.6/bidi-2.1.6", + "host": "https://repo.clojars.org", + "pom": { + "sha1": "179b6a4d499f6830d8bf8ae030d82d8a49f61924", + "sha256": "1g3pzsal938f9s5xvfbkjplmprry33j0nc9x106z41jzzgqry37h" + }, + "jar": { + "sha1": "e17fa1c05ff99e99543c6d5328e293e933e15e06", + "sha256": "1gld043c5qz7v9bp5s61vf1s5f8f1pbda9nzwqhy893dpm8xv0qb" + } + }, + { "path": "binaryage/env-config/0.2.2/env-config-0.2.2", "host": "https://repo.clojars.org", @@ -78,15 +91,15 @@ }, { - "path": "cljsjs/react/16.13.0-0/react-16.13.0-0", + "path": "cljsjs/react-dom-server/16.13.0-0/react-dom-server-16.13.0-0", "host": "https://repo.clojars.org", "pom": { - "sha1": "66011033045a6aaa778c01ed308675fa008817f0", - "sha256": "1j17bw4vmi26782v84znxnrx1qpi0wm6agbpczds0gb5f9nr2myv" + "sha1": "320f6487531caf52b15ef10d43129b80c40f7c35", + "sha256": "1l9s4akd1s06xcx0r38h6xf82bcr0ypmaw6xnvdrmll19a3g9ilc" }, "jar": { - "sha1": "b72f3f9a69ec4039ac57597859ea4b5d1cfcd113", - "sha256": "1dp4pi9jphncifa56kqj6sri8vwl62ia1xy3ii70fba1mdjij63s" + "sha1": "4d400ae4f66687286170eb691aa8e642fe87aa47", + "sha256": "0fzwd6hfb2rx85pr6fsr2r4x76a90wgnjgnv23jzfn1vw6znch07" } }, @@ -104,15 +117,15 @@ }, { - "path": "cljsjs/react-dom-server/16.13.0-0/react-dom-server-16.13.0-0", + "path": "cljsjs/react/16.13.0-0/react-16.13.0-0", "host": "https://repo.clojars.org", "pom": { - "sha1": "320f6487531caf52b15ef10d43129b80c40f7c35", - "sha256": "1l9s4akd1s06xcx0r38h6xf82bcr0ypmaw6xnvdrmll19a3g9ilc" + "sha1": "66011033045a6aaa778c01ed308675fa008817f0", + "sha256": "1j17bw4vmi26782v84znxnrx1qpi0wm6agbpczds0gb5f9nr2myv" }, "jar": { - "sha1": "4d400ae4f66687286170eb691aa8e642fe87aa47", - "sha256": "0fzwd6hfb2rx85pr6fsr2r4x76a90wgnjgnv23jzfn1vw6znch07" + "sha1": "b72f3f9a69ec4039ac57597859ea4b5d1cfcd113", + "sha256": "1dp4pi9jphncifa56kqj6sri8vwl62ia1xy3ii70fba1mdjij63s" } }, @@ -246,19 +259,6 @@ } }, - { - "path": "com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1", - "host": "https://repo1.maven.org/maven2", - "pom": { - "sha1": "5e902aae26ac5c36f6420f689f43333129dd69e2", - "sha256": "10vzlnl8vbjv2jqf818wdb7kgy9c6qjka7fjmmi3vdpg1mcn6pv6" - }, - "jar": { - "sha1": "c9ad4a0850ab676c5c64461a05ca524cdfff59f1", - "sha256": "170rflxnqnah0265ik2aylmxkshyqbf2zas9bp2l32xqj9l6jsaf" - } - }, - { "path": "com/google/elemental2/elemental2-core/1.0.0-RC1/elemental2-core-1.0.0-RC1", "host": "https://repo1.maven.org/maven2", @@ -390,54 +390,15 @@ }, { - "path": "commons-codec/commons-codec/1.10/commons-codec-1.10", + "path": "com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1", "host": "https://repo1.maven.org/maven2", "pom": { - "sha1": "44b9477418d2942d45550f7e7c66c16262062d0e", - "sha256": "1yscxabk7i59vgfjg7c1y3prj39h1d8prnwgxbisc4ni29qdpf5x" + "sha1": "5e902aae26ac5c36f6420f689f43333129dd69e2", + "sha256": "10vzlnl8vbjv2jqf818wdb7kgy9c6qjka7fjmmi3vdpg1mcn6pv6" }, "jar": { - "sha1": "4b95f4897fa13f2cd904aee711aeafc0c5295cd8", - "sha256": "0scm6321zz76dc3bs8sy2qyami755lz4lq5455gl67bi9slxyha2" - } - }, - - { - "path": "commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4", - "host": "https://repo1.maven.org/maven2", - "pom": { - "sha1": "65112009d674333c1acfafb4e198ff250d710764", - "sha256": "007nyd66fqp3fbrmnsbfp1fpkhmr2lk33qmkp3salqld3xd7qlc8" - }, - "jar": { - "sha1": "f95188e3d372e20e7328706c37ef366e5d7859b0", - "sha256": "1xyyl54sfxsdcwxdyq6b0azmr31b4dwqns850jjkw9a9dwrh5v54" - } - }, - - { - "path": "commons-io/commons-io/2.6/commons-io-2.6", - "host": "https://repo1.maven.org/maven2", - "pom": { - "sha1": "5060835593e5b6ed18c82fc2e782f0a3c30a00b1", - "sha256": "0q4a6fp6xkyd86ikymkyv2plhf9vj8aqvggxg9d1yad2jcw8c8qc" - }, - "jar": { - "sha1": "815893df5f31da2ece4040fe0a12fd44b577afaf", - "sha256": "04v5fg53jl9gbn6pyz3l7kbpxv0xjzyasnw6yd1a3hhacq2d6xzq" - } - }, - - { - "path": "compojure/compojure/1.5.2/compojure-1.5.2", - "host": "https://repo.clojars.org", - "pom": { - "sha1": "9e8da477b6682094d56802cb155291a2acb829bd", - "sha256": "036z64iprypccz03iq7lqxvw99xjh4xlsfmfwbs37pmhfnfmbdnx" - }, - "jar": { - "sha1": "0b5258d0616ffc5f64c2b6d95f09de56d24df439", - "sha256": "1s2k05lwnlm9a66mxnsss437i9gp70dny8y2rlfkl090s6mdqsaf" + "sha1": "c9ad4a0850ab676c5c64461a05ca524cdfff59f1", + "sha256": "170rflxnqnah0265ik2aylmxkshyqbf2zas9bp2l32xqj9l6jsaf" } }, @@ -519,6 +480,58 @@ } }, + { + "path": "commons-codec/commons-codec/1.10/commons-codec-1.10", + "host": "https://repo1.maven.org/maven2", + "pom": { + "sha1": "44b9477418d2942d45550f7e7c66c16262062d0e", + "sha256": "1yscxabk7i59vgfjg7c1y3prj39h1d8prnwgxbisc4ni29qdpf5x" + }, + "jar": { + "sha1": "4b95f4897fa13f2cd904aee711aeafc0c5295cd8", + "sha256": "0scm6321zz76dc3bs8sy2qyami755lz4lq5455gl67bi9slxyha2" + } + }, + + { + "path": "commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4", + "host": "https://repo1.maven.org/maven2", + "pom": { + "sha1": "65112009d674333c1acfafb4e198ff250d710764", + "sha256": "007nyd66fqp3fbrmnsbfp1fpkhmr2lk33qmkp3salqld3xd7qlc8" + }, + "jar": { + "sha1": "f95188e3d372e20e7328706c37ef366e5d7859b0", + "sha256": "1xyyl54sfxsdcwxdyq6b0azmr31b4dwqns850jjkw9a9dwrh5v54" + } + }, + + { + "path": "commons-io/commons-io/2.6/commons-io-2.6", + "host": "https://repo1.maven.org/maven2", + "pom": { + "sha1": "5060835593e5b6ed18c82fc2e782f0a3c30a00b1", + "sha256": "0q4a6fp6xkyd86ikymkyv2plhf9vj8aqvggxg9d1yad2jcw8c8qc" + }, + "jar": { + "sha1": "815893df5f31da2ece4040fe0a12fd44b577afaf", + "sha256": "04v5fg53jl9gbn6pyz3l7kbpxv0xjzyasnw6yd1a3hhacq2d6xzq" + } + }, + + { + "path": "compojure/compojure/1.5.2/compojure-1.5.2", + "host": "https://repo.clojars.org", + "pom": { + "sha1": "9e8da477b6682094d56802cb155291a2acb829bd", + "sha256": "036z64iprypccz03iq7lqxvw99xjh4xlsfmfwbs37pmhfnfmbdnx" + }, + "jar": { + "sha1": "0b5258d0616ffc5f64c2b6d95f09de56d24df439", + "sha256": "1s2k05lwnlm9a66mxnsss437i9gp70dny8y2rlfkl090s6mdqsaf" + } + }, + { "path": "crypto-equality/crypto-equality/1.0.0/crypto-equality-1.0.0", "host": "https://repo.clojars.org", @@ -922,19 +935,6 @@ } }, - { - "path": "org/clojure/google-closure-library/0.0-20191016-6ae1f72f/google-closure-library-0.0-20191016-6ae1f72f", - "host": "https://repo1.maven.org/maven2", - "pom": { - "sha1": "dea94d117aa88d75e281f877914454f79df06bf2", - "sha256": "1nysls9ywj3b3zvlfwy68kayx47r4bacidmq1vx8w4h043l9kxrr" - }, - "jar": { - "sha1": "6025affb7181cd40418600864f58eed1ea80055d", - "sha256": "0w6waii2qps7vp3nzbj5nai809xdq26ss0cabl4wz1s8fc6js6qw" - } - }, - { "path": "org/clojure/google-closure-library-third-party/0.0-20191016-6ae1f72f/google-closure-library-third-party-0.0-20191016-6ae1f72f", "host": "https://repo1.maven.org/maven2", @@ -948,6 +948,19 @@ } }, + { + "path": "org/clojure/google-closure-library/0.0-20191016-6ae1f72f/google-closure-library-0.0-20191016-6ae1f72f", + "host": "https://repo1.maven.org/maven2", + "pom": { + "sha1": "dea94d117aa88d75e281f877914454f79df06bf2", + "sha256": "1nysls9ywj3b3zvlfwy68kayx47r4bacidmq1vx8w4h043l9kxrr" + }, + "jar": { + "sha1": "6025affb7181cd40418600864f58eed1ea80055d", + "sha256": "0w6waii2qps7vp3nzbj5nai809xdq26ss0cabl4wz1s8fc6js6qw" + } + }, + { "path": "org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176", "host": "https://repo1.maven.org/maven2", @@ -974,19 +987,6 @@ } }, - { - "path": "org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0", - "host": "https://repo1.maven.org/maven2", - "pom": { - "sha1": "fa72b6392b31762b55e0dc3de1c220ecdc6bb8a7", - "sha256": "1yg46a9zbga7rsrhwdv877hh60hcbyaykn37r3i50icxmgqcylq4" - }, - "jar": { - "sha1": "d2fb65426c7998647fb1fb3db1fb5b222ab91df6", - "sha256": "0mj1xi3v03fzcw1smpayvbvbgly2p3ysbgfz7jgfdhmxi4gl6gs6" - } - }, - { "path": "org/clojure/tools.analyzer.jvm/1.0.0/tools.analyzer.jvm-1.0.0", "host": "https://repo1.maven.org/maven2", @@ -1000,6 +1000,19 @@ } }, + { + "path": "org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0", + "host": "https://repo1.maven.org/maven2", + "pom": { + "sha1": "fa72b6392b31762b55e0dc3de1c220ecdc6bb8a7", + "sha256": "1yg46a9zbga7rsrhwdv877hh60hcbyaykn37r3i50icxmgqcylq4" + }, + "jar": { + "sha1": "d2fb65426c7998647fb1fb3db1fb5b222ab91df6", + "sha256": "0mj1xi3v03fzcw1smpayvbvbgly2p3ysbgfz7jgfdhmxi4gl6gs6" + } + }, + { "path": "org/clojure/tools.cli/1.0.194/tools.cli-1.0.194", "host": "https://repo1.maven.org/maven2", @@ -1195,6 +1208,19 @@ } }, + { + "path": "prismatic/schema/1.1.7/schema-1.1.7", + "host": "https://repo.clojars.org", + "pom": { + "sha1": "d5bb7edbd1830e6400705c2b5797ced1737fb208", + "sha256": "0bmnmx53kjlcxx477wm7xvcnaf2vi95rr164xi49611kfbhh2dsd" + }, + "jar": { + "sha1": "289b571f1cbab59aef436fc0af56e7efc5322685", + "sha256": "01zc13qhkyghhr4s1if9agbgz38gvrg8x62gn1g8fjll9nq7aca9" + } + }, + { "path": "quoin/quoin/0.1.2/quoin-0.1.2", "host": "https://repo.clojars.org", @@ -1208,19 +1234,6 @@ } }, - { - "path": "reagent/reagent/0.10.0/reagent-0.10.0", - "host": "https://repo.clojars.org", - "pom": { - "sha1": "0ced0db04eaf77ec3dfa7a3f56cc022fe2814d8b", - "sha256": "15cqnfwkzxia6bdjq1kism72jf66zdpldk0925313z41ynkqfr8r" - }, - "jar": { - "sha1": "1a88fae22cd0f7f66bb181aa520da264a82f6942", - "sha256": "0vdvm75rpcq9kx2sp0jd2lsa70fv2xymy1g55ss972s85p5j50bm" - } - }, - { "path": "re-com/re-com/2.8.0/re-com-2.8.0", "host": "https://repo.clojars.org", @@ -1234,19 +1247,6 @@ } }, - { - "path": "refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0", - "host": "https://repo.clojars.org", - "pom": { - "sha1": "0bce30b420249ba7e4b90cbb3e046b4bb5416389", - "sha256": "0zmg5qc8d55pry7832isiwd2q237znfjqjpxchd2hvlpalh5qnva" - }, - "jar": { - "sha1": "6bc3441afc94f7ca024e41a864ca75e05df7e207", - "sha256": "0w8hax99y98l53mixxzx2ja0vcnhjv8dnsaz1zj3vqk775ns5w6i" - } - }, - { "path": "re-frame/re-frame/0.12.0/re-frame-0.12.0", "host": "https://repo.clojars.org", @@ -1286,6 +1286,32 @@ } }, + { + "path": "reagent/reagent/0.10.0/reagent-0.10.0", + "host": "https://repo.clojars.org", + "pom": { + "sha1": "0ced0db04eaf77ec3dfa7a3f56cc022fe2814d8b", + "sha256": "15cqnfwkzxia6bdjq1kism72jf66zdpldk0925313z41ynkqfr8r" + }, + "jar": { + "sha1": "1a88fae22cd0f7f66bb181aa520da264a82f6942", + "sha256": "0vdvm75rpcq9kx2sp0jd2lsa70fv2xymy1g55ss972s85p5j50bm" + } + }, + + { + "path": "refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0", + "host": "https://repo.clojars.org", + "pom": { + "sha1": "0bce30b420249ba7e4b90cbb3e046b4bb5416389", + "sha256": "0zmg5qc8d55pry7832isiwd2q237znfjqjpxchd2hvlpalh5qnva" + }, + "jar": { + "sha1": "6bc3441afc94f7ca024e41a864ca75e05df7e207", + "sha256": "0w8hax99y98l53mixxzx2ja0vcnhjv8dnsaz1zj3vqk775ns5w6i" + } + }, + { "path": "ring-cors/ring-cors/0.1.8/ring-cors-0.1.8", "host": "https://repo.clojars.org", diff --git a/nix/deps/clojure/deps.list b/nix/deps/clojure/deps.list index 872e2803dc..b53486be6b 100644 --- a/nix/deps/clojure/deps.list +++ b/nix/deps/clojure/deps.list @@ -1,12 +1,13 @@ args4j/args4j/2.0.26/args4j-2.0.26.jar +bidi/bidi/2.1.6/bidi-2.1.6.jar binaryage/env-config/0.2.2/env-config-0.2.2.jar binaryage/oops/0.7.0/oops-0.7.0.jar cider/cider-nrepl/0.24.0/cider-nrepl-0.24.0.jar cider/piggieback/0.4.1/piggieback-0.4.1.jar cljs-bean/cljs-bean/1.3.0/cljs-bean-1.3.0.jar -cljsjs/react/16.13.0-0/react-16.13.0-0.jar -cljsjs/react-dom/16.13.0-0/react-dom-16.13.0-0.jar cljsjs/react-dom-server/16.13.0-0/react-dom-server-16.13.0-0.jar +cljsjs/react-dom/16.13.0-0/react-dom-16.13.0-0.jar +cljsjs/react/16.13.0-0/react-16.13.0-0.jar clout/clout/2.1.2/clout-2.1.2.jar com/andrewmcveigh/cljs-time/0.5.2/cljs-time-0.5.2.jar com/bhauman/cljs-test-display/0.1.1/cljs-test-display-0.1.1.jar @@ -17,7 +18,6 @@ com/cognitect/transit-js/0.8.846/transit-js-0.8.846.jar com/fasterxml/jackson/core/jackson-core/2.8.7/jackson-core-2.8.7.jar com/google/code/findbugs/jsr305/3.0.1/jsr305-3.0.1.jar com/google/code/gson/gson/2.7/gson-2.7.jar -com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar com/google/elemental2/elemental2-core/1.0.0-RC1/elemental2-core-1.0.0-RC1.jar com/google/errorprone/error_prone_annotations/2.3.1/error_prone_annotations-2.3.1.jar com/google/guava/guava/25.1-jre/guava-25.1-jre.jar @@ -28,16 +28,17 @@ com/google/jsinterop/base/1.0.0/base-1.0.0.jar com/google/jsinterop/jsinterop-annotations/1.0.2/jsinterop-annotations-1.0.2.jar com/google/protobuf/protobuf-java/3.11.1/protobuf-java-3.11.1.jar com/google/re2j/re2j/1.3/re2j-1.3.jar -commons-codec/commons-codec/1.10/commons-codec-1.10.jar -commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4.jar -commons-io/commons-io/2.6/commons-io-2.6.jar -compojure/compojure/1.5.2/compojure-1.5.2.jar +com/googlecode/json-simple/json-simple/1.1.1/json-simple-1.1.1.jar com/taoensso/encore/2.105.0/encore-2.105.0.jar com/taoensso/timbre/4.10.0/timbre-4.10.0.jar com/taoensso/truss/1.5.0/truss-1.5.0.jar com/taoensso/tufte/2.1.0/tufte-2.1.0.jar com/wsscode/pathom/2.2.31/pathom-2.2.31.jar com/wsscode/spec-inspec/1.0.0-alpha2/spec-inspec-1.0.0-alpha2.jar +commons-codec/commons-codec/1.10/commons-codec-1.10.jar +commons-fileupload/commons-fileupload/1.4/commons-fileupload-1.4.jar +commons-io/commons-io/2.6/commons-io-2.6.jar +compojure/compojure/1.5.2/compojure-1.5.2.jar crypto-equality/crypto-equality/1.0.0/crypto-equality-1.0.0.jar crypto-random/crypto-random/1.2.0/crypto-random-1.2.0.jar day8/re-frame/test/0.1.5/test-0.1.5.jar @@ -69,12 +70,12 @@ org/clojure/core.rrb-vector/0.1.1/core.rrb-vector-0.1.1.jar org/clojure/core.specs.alpha/0.2.44/core.specs.alpha-0.2.44.jar org/clojure/data.json/1.0.0/data.json-1.0.0.jar org/clojure/data.priority-map/0.0.7/data.priority-map-0.0.7.jar -org/clojure/google-closure-library/0.0-20191016-6ae1f72f/google-closure-library-0.0-20191016-6ae1f72f.jar org/clojure/google-closure-library-third-party/0.0-20191016-6ae1f72f/google-closure-library-third-party-0.0-20191016-6ae1f72f.jar +org/clojure/google-closure-library/0.0-20191016-6ae1f72f/google-closure-library-0.0-20191016-6ae1f72f.jar org/clojure/spec.alpha/0.2.176/spec.alpha-0.2.176.jar org/clojure/test.check/1.0.0/test.check-1.0.0.jar -org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0.jar org/clojure/tools.analyzer.jvm/1.0.0/tools.analyzer.jvm-1.0.0.jar +org/clojure/tools.analyzer/1.0.0/tools.analyzer-1.0.0.jar org/clojure/tools.cli/1.0.194/tools.cli-1.0.194.jar org/clojure/tools.logging/0.4.1/tools.logging-0.4.1.jar org/clojure/tools.macro/0.1.5/tools.macro-0.1.5.jar @@ -90,13 +91,14 @@ org/msgpack/msgpack/0.6.12/msgpack-0.6.12.jar org/ow2/asm/asm/5.2/asm-5.2.jar org/wildfly/client/wildfly-client-config/1.0.1.Final/wildfly-client-config-1.0.1.Final.jar org/wildfly/common/wildfly-common/1.5.2.Final/wildfly-common-1.5.2.Final.jar +prismatic/schema/1.1.7/schema-1.1.7.jar quoin/quoin/0.1.2/quoin-0.1.2.jar -reagent/reagent/0.10.0/reagent-0.10.0.jar re-com/re-com/2.8.0/re-com-2.8.0.jar -refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0.jar re-frame/re-frame/0.12.0/re-frame-0.12.0.jar re-frisk-remote/re-frisk-remote/1.3.1/re-frisk-remote-1.3.1.jar re-frisk/sente/1.15.0/sente-1.15.0.jar +reagent/reagent/0.10.0/reagent-0.10.0.jar +refactor-nrepl/refactor-nrepl/2.5.0/refactor-nrepl-2.5.0.jar ring-cors/ring-cors/0.1.8/ring-cors-0.1.8.jar ring/ring-codec/1.1.2/ring-codec-1.1.2.jar ring/ring-core/1.8.1/ring-core-1.8.1.jar diff --git a/shadow-cljs.edn b/shadow-cljs.edn index e6538004ed..312e6d39a5 100644 --- a/shadow-cljs.edn +++ b/shadow-cljs.edn @@ -17,6 +17,8 @@ [cider/cider-nrepl "0.24.0"] [cider/piggieback "0.4.1"] [re-frisk-remote "1.3.1"] + ;; routing + [bidi "2.1.6"] ;; test dependencies [day8.re-frame/test "0.1.5"] [com.taoensso/tufte "2.1.0"]] diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index 3fe7700032..f6858a51f3 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -29,7 +29,6 @@ [status-im.multiaccounts.update.core :as multiaccounts.update] [status-im.pairing.core :as pairing] [status-im.privacy-policy.core :as privacy-policy] - [status-im.qr-scanner.core :as qr-scanner] [status-im.signals.core :as signals] [status-im.stickers.core :as stickers] [status-im.transport.core :as transport] @@ -344,25 +343,6 @@ (fn [cofx [_ qr-code-data _]] (browser/handle-canceled-qr-code cofx (:data qr-code-data)))) -;; qr-scanner module - -(handlers/register-handler-fx - :qr-scanner.ui/scan-qr-code-pressed - (fn [cofx [_ opts]] - (qr-scanner/scan-qr-code cofx opts))) - -(handlers/register-handler-fx - :qr-scanner.callback/scan-qr-code-success - (fn [cofx [_ opts data]] - (qr-scanner/set-qr-code cofx opts data))) - -(handlers/register-handler-fx - :qr-scanner.callback/scan-qr-code-cancel - (fn [cofx [_ opts]] - (fx/merge cofx - (qr-scanner/set-qr-code-cancel opts) - (navigation/navigate-back)))) - ;; privacy-policy module (handlers/register-handler-fx diff --git a/src/status_im/qr_scanner/core.cljs b/src/status_im/qr_scanner/core.cljs index 014bd6f751..1c71f51ce2 100644 --- a/src/status_im/qr_scanner/core.cljs +++ b/src/status_im/qr_scanner/core.cljs @@ -1,10 +1,16 @@ (ns status-im.qr-scanner.core (:require [re-frame.core :as re-frame] [status-im.i18n :as i18n] + [status-im.chat.models :as chat] + [status-im.router.core :as router] + [status-im.navigation :as navigation] [status-im.utils.utils :as utils] + [status-im.ethereum.core :as ethereum] + [status-im.ui.screens.add-new.new-chat.db :as new-chat.db] [status-im.utils.fx :as fx])) (fx/defn scan-qr-code + {:events [::scan-code]} [_ opts] {:request-permissions-fx {:permissions [:camera] @@ -16,11 +22,73 @@ 50))}}) (fx/defn set-qr-code + {:events [:qr-scanner.callback/scan-qr-code-success]} [{:keys [db]} opts data] (when-let [handler (:handler opts)] {:dispatch [handler data opts]})) (fx/defn set-qr-code-cancel - [_ opts] - (when-let [handler (:cancel-handler opts)] - {:dispatch [handler opts]})) + {:events [:qr-scanner.callback/scan-qr-code-cancel]} + [cofx opts] + (fx/merge cofx + (navigation/navigate-back) + (when-let [handler (:cancel-handler opts)] + (fn [] {:dispatch [handler opts]})))) + +(fx/defn handle-browse [cofx {:keys [url]}] + (fx/merge cofx + {:browser/show-browser-selection url} + (navigation/navigate-back))) + +(fx/defn handle-private-chat [{:keys [db] :as cofx} {:keys [chat-id]}] + (if-not (new-chat.db/own-public-key? db chat-id) + (chat/start-chat cofx chat-id) + {:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code) + :content (i18n/label :t/can-not-add-yourself)}})) + +(fx/defn handle-public-chat [cofx {:keys [topic]}] + (when (seq topic) + (chat/start-public-chat cofx topic {}))) + +(fx/defn handle-view-profile + [{:keys [db] :as cofx} {:keys [public-key]}] + (let [own (new-chat.db/own-public-key? db public-key)] + (cond + (and public-key own) + (navigation/navigate-to-cofx cofx :tabs {:screen :profile-stack + :params {:screen :my-profile}}) + + (and public-key (not own)) + (navigation/navigate-to-cofx (assoc-in cofx [:db :contacts/identity] public-key) + :tabs + {:screen :chat-stack + :params {:screen :profile}}) + + :else + {:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code) + :content (i18n/label :t/ens-name-not-found) + :on-dismiss #(re-frame/dispatch [:navigate-to :home])}}))) + +(fx/defn handle-eip681 [cofx data] + (fx/merge cofx + {:dispatch [:wallet/parse-eip681-uri-and-resolve-ens data]} + (navigation/navigate-to-cofx :tabs {:screen :wallet}))) + +(fx/defn match-scan + {:events [::match-scanned-value]} + [cofx {:keys [type] :as data}] + (case type + :public-chat (handle-public-chat cofx data) + :private-chat (handle-private-chat cofx data) + :contact (handle-view-profile cofx data) + :browser (handle-browse cofx data) + :eip681 (handle-eip681 cofx data) + {:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code) + :on-dismiss #(re-frame/dispatch [:navigate-to :home])}})) + +(fx/defn on-scan + {:events [::on-scan-success]} + [{:keys [db]} uri] + {::router/handle-uri {:chain (ethereum/chain-keyword db) + :uri uri + :cb #(re-frame/dispatch [::match-scanned-value %])}}) diff --git a/src/status_im/router/core.cljs b/src/status_im/router/core.cljs new file mode 100644 index 0000000000..a95da9e526 --- /dev/null +++ b/src/status_im/router/core.cljs @@ -0,0 +1,180 @@ +(ns status-im.router.core + (:require [re-frame.core :as re-frame] + [clojure.string :as string] + [bidi.bidi :as bidi] + [taoensso.timbre :as log] + [status-im.ui.screens.add-new.new-public-chat.db :as public-chat.db] + [status-im.utils.security :as security] + [status-im.ethereum.eip681 :as eip681] + [status-im.ethereum.ens :as ens] + [status-im.ethereum.resolver :as resolver] + [status-im.ethereum.stateofus :as stateofus] + [cljs.spec.alpha :as spec] + [status-im.ethereum.core :as ethereum])) + +(def ethereum-scheme "ethereum:") + +(def uri-schemes ["status-im://" "status-im:"]) + +(def web-prefixes ["https://" "http://" "https://www." "http://wwww."]) + +(def web2-domain "join.status.im") + +(def web-urls (map #(str % web2-domain "/") web-prefixes)) + +(def handled-schemes (set (into uri-schemes web-urls))) + +(def browser-extractor {[#"(.*)" :domain] {"" :browser + "/" :browser}}) + +(def eip-extractor {#{[:prefix "-" :address] + [:address]} + {#{["@" :chain-id] ""} + {#{["/" :function] ""} + :ethereum}}}) + +(def routes ["" {handled-schemes {["" :chat-id] :public-chat + "chat" {["/public/" :chat-id] :public-chat} + "b/" browser-extractor + "browser/" browser-extractor + ["p/" :chat-id] :private-chat + ["u/" :user-id] :user + ["user/" :user-id] :user + ["referral/" :referrer] :referrals} + ethereum-scheme eip-extractor}]) + +(defn match-uri [uri] + (assoc (bidi/match-route routes uri) :uri uri)) + +(defn- ens-name-parse [contact-identity] + (when (string? contact-identity) + (string/lower-case + (if (ens/is-valid-eth-name? contact-identity) + contact-identity + (stateofus/subdomain contact-identity))))) + +(defn resolve-public-key + [{:keys [chain contact-identity cb]}] + (let [registry (get ens/ens-registries chain) + ens-name (ens-name-parse contact-identity)] + (resolver/pubkey registry ens-name cb))) + +(defn match-contact-async + [chain {:keys [user-id]} callback] + (let [public-key? (and (string? user-id) + (string/starts-with? user-id "0x")) + valid-key (and (spec/valid? :global/public-key user-id) + (not= user-id ens/default-key))] + (cond + (and public-key? valid-key) + (callback {:type :contact + :public-key user-id}) + + (and (not public-key?) (string? user-id)) + (let [registry (get ens/ens-registries chain) + ens-name (ens-name-parse user-id) + on-success #(match-contact-async chain {:user-id %} callback)] + (resolver/pubkey registry ens-name on-success)) + + :else + (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-private-chat-async [chain {:keys [chat-id]} cb] + (match-contact-async chain + {:user-id chat-id} + (fn [{:keys [public-key]}] + (if public-key + (cb {:type :private-chat + :chat-id public-key}) + (cb {:type :private-chat + :error :invalid-chat-id}))))) + +(defn match-browser [uri {:keys [domain]}] + ;; NOTE: We rebuild domain from original URI and matched domain + (let [domain (->> (string/split uri domain) + second + (str domain))] + (if (security/safe-link? domain) + {:type :browser + :url domain} + {:type :browser + :error :unsafe-link}))) + +;; NOTE(Ferossgp): Better to handle eip681 also with router instead of regexp. +(defn match-eip681 [uri] + (if-let [message (eip681/parse-uri uri)] + (let [{:keys [paths ens-names]} + (reduce (fn [acc path] + (let [address (get-in message path)] + (if (ens/is-valid-eth-name? address) + (-> acc + (update :paths conj path) + (update :ens-names conj address)) + acc))) + {:paths [] :ens-names []} + [[:address] [:function-arguments :address]])] + (if (empty? ens-names) + ;; if there are no ens-names, we dispatch request-uri-parsed immediately + {:type :eip681 + :message message + :uri uri} + {:type :eip681 + :uri uri + :message message + :paths paths + :ens-names ens-names})) + {:type :eip681 + :uri uri + :error :cannot-parse})) + +(defn address->eip681 [address] + (match-eip681 (str ethereum-scheme address))) + +(defn match-referral [{:keys [referrer]}] + {:type :referrals + :referrer referrer}) + +(defn handle-uri [chain uri cb] + (let [{:keys [handler route-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)) + + (= handler :ethereum) + (cb (match-eip681 uri)) + + (= handler :user) + (match-contact-async chain route-params cb) + + (= handler :private-chat) + (match-private-chat-async chain route-params cb) + + (spec/valid? :global/public-key uri) + (match-contact-async chain {:user-id uri} cb) + + (= handler :referrals) + (cb (match-referral route-params)) + + (ethereum/address? uri) + (cb (address->eip681 uri)) + + :else + (cb {:type :undefined + :data uri})))) + +(re-frame/reg-fx + ::handle-uri + (fn [{:keys [chain uri cb]}] + (handle-uri chain uri cb))) diff --git a/src/status_im/router/core_test.cljs b/src/status_im/router/core_test.cljs new file mode 100644 index 0000000000..55033bfb86 --- /dev/null +++ b/src/status_im/router/core_test.cljs @@ -0,0 +1,52 @@ +(ns status-im.router.core-test + (:require [status-im.router.core :as router] + [cljs.test :refer [deftest are] :include-macros true])) + +(def public-key "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073") + +(deftest parse-uris + (are [uri expected] (= (router/match-uri uri) {:handler (first expected) + :route-params (second expected) + :uri uri}) + + "status-im://status" [:public-chat {:chat-id "status"}] + + "status-im://u/statuse2e" [:user {:user-id "statuse2e"}] + + (str "status-im://user/" public-key) [:user {:user-id public-key}] + + "status-im://b/www.cryptokitties.co" [:browser {:domain "www.cryptokitties.c"}] + + "https://join.status.im/status" [:public-chat {:chat-id "status"}] + + "https://join.status.im/u/statuse2e" [:user {:user-id "statuse2e"}] + + (str "https://join.status.im/user/" public-key) [:user {:user-id public-key}] + + ;; Last char removed by: https://github.com/juxt/bidi/issues/104 + "https://join.status.im/b/www.cryptokitties.co" [:browser {:domain "www.cryptokitties.c"}] + + "https://join.status.im/b/https://www.google.com/" [:browser {:domain "https://www.google.co"}] + + "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" [:ethereum {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}] + + "ethereum:pay-0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" [:ethereum {:prefix "pay" + :address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}] + "ethereum:foo-0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" [:ethereum {:prefix "foo" + :address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}] + + ;; FIXME: Should handle only first line + "ethereum:foo-state-of-us.eth" [:ethereum {:prefix "foo-state-of" + :address "us.eth"}] + + "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7@42" [:ethereum {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" + :chain-id "42"}] + + "ethereum:0x0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7/transfer?address=0x12345&uint256=1" [:ethereum {:address "0x0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" + :function "transfer"}] + + "ethereum:0x0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7?value=2.014e18&gas=10&gasLimit=21000&gasPrice=50" [:ethereum {:address "0x0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7"}] + + "ethereum:0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7@1/transfer?uint256=1" [:ethereum {:address "0x89205a3a3b2a69de6dbf7f01ed13b2108b2c43e7" + :chain-id "1" + :function "transfer"}])) diff --git a/src/status_im/ui/screens/add_new/new_chat/events.cljs b/src/status_im/ui/screens/add_new/new_chat/events.cljs index 614c75e9b7..5c71722b58 100644 --- a/src/status_im/ui/screens/add_new/new_chat/events.cljs +++ b/src/status_im/ui/screens/add_new/new_chat/events.cljs @@ -2,7 +2,6 @@ (:require [clojure.string :as string] [re-frame.core :as re-frame] [status-im.ethereum.core :as ethereum] - [status-im.utils.universal-links.core :as ul] [status-im.ethereum.ens :as ens] [status-im.ethereum.resolver :as resolver] [status-im.ui.screens.add-new.new-chat.db :as db] @@ -14,6 +13,7 @@ [status-im.chat.models :as chat] [status-im.i18n :as i18n] [status-im.contact.core :as contact] + [status-im.router.core :as router] [status-im.navigation :as navigation])) (defn- ens-name-parse [contact-identity] @@ -79,30 +79,30 @@ :yourself (i18n/label :t/can-not-add-yourself))) -(fx/defn qr-code-scanned - {:events [:contact/qr-code-scanned]} - [{:keys [db] :as cofx} contact-identity {:keys [new-contact?] :as opts}] - (let [public-key? (and (string? contact-identity) - (string/starts-with? contact-identity "0x")) - validation-result (db/validate-pub-key db contact-identity)] - (cond - (and public-key? (not (some? validation-result))) +(fx/defn qr-code-handled + {:events [::qr-code-handled]} + [{:keys [db] :as cofx} {:keys [type public-key chat-id data]} {:keys [new-contact?] :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? (fx/merge cofx - (contact/add-contact contact-identity) + (contact/add-contact chat-key) (navigation/navigate-to-cofx :contacts-list {})) - (chat/start-chat cofx contact-identity)) - - (and (string? contact-identity) (ul/match-url contact-identity ul/profile-regex)) - (qr-code-scanned cofx (ul/match-url contact-identity ul/profile-regex) opts) - - (and (not public-key?) (string? contact-identity)) - (let [chain (ethereum/chain-keyword db)] - {:resolve-public-key {:chain chain - :contact-identity contact-identity - :cb #(re-frame/dispatch [:contact/qr-code-scanned % opts])}}) - - :else + (chat/start-chat cofx chat-key)) {:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code) :content (get-validation-label validation-result) :on-dismiss #(re-frame/dispatch [:navigate-to :home])}}))) + +(fx/defn qr-code-scanned + {:events [:contact/qr-code-scanned]} + [{:keys [db]} data opts] + {::router/handle-uri {:chain (ethereum/chain-keyword db) + :uri data + :cb #(re-frame/dispatch [::qr-code-handled % opts])}}) diff --git a/src/status_im/ui/screens/add_new/new_chat/views.cljs b/src/status_im/ui/screens/add_new/new_chat/views.cljs index fee8d40f00..1185140972 100644 --- a/src/status_im/ui/screens/add_new/new_chat/views.cljs +++ b/src/status_im/ui/screens/add_new/new_chat/views.cljs @@ -7,6 +7,7 @@ [status-im.ui.components.icons.vector-icons :as vector-icons] [quo.core :as quo] [status-im.utils.gfycat.core :as gfycat] + [status-im.qr-scanner.core :as qr-scanner] [status-im.ui.components.list.views :as list] [status-im.ui.components.react :as react] [status-im.ui.components.topbar :as topbar] @@ -67,7 +68,7 @@ :modal? true :accessories [{:icon :qr :accessibility-label :scan-contact-code-button - :handler #(re-frame/dispatch [:qr-scanner.ui/scan-qr-code-pressed + :handler #(re-frame/dispatch [::qr-scanner/scan-code {:title (i18n/label :t/new-contact) :handler :contact/qr-code-scanned}])}]}] [react/view {:flex-direction :row @@ -115,7 +116,7 @@ :modal? true :accessories [{:icon :qr :accessibility-label :scan-contact-code-button - :handler #(re-frame/dispatch [:qr-scanner.ui/scan-qr-code-pressed + :handler #(re-frame/dispatch [::qr-scanner/scan-code {:title (i18n/label :t/new-contact) :handler :contact/qr-code-scanned :new-contact? true}])}]}] diff --git a/src/status_im/ui/screens/bootnodes_settings/edit_bootnode/views.cljs b/src/status_im/ui/screens/bootnodes_settings/edit_bootnode/views.cljs index 3f7e2a6f8b..d623bcff7c 100644 --- a/src/status_im/ui/screens/bootnodes_settings/edit_bootnode/views.cljs +++ b/src/status_im/ui/screens/bootnodes_settings/edit_bootnode/views.cljs @@ -5,6 +5,7 @@ [status-im.ui.components.react :as react] [status-im.ui.components.toolbar :as toolbar] [quo.core :as quo] + [status-im.qr-scanner.core :as qr-scanner] [status-im.ui.components.topbar :as topbar] [status-im.ui.screens.bootnodes-settings.edit-bootnode.styles :as @@ -55,7 +56,7 @@ {:format (i18n/label :t/bootnode-format)})) :bottom-value 0 :after {:icon :main-icons/qr - :on-press #(re-frame/dispatch [:qr-scanner.ui/scan-qr-code-pressed + :on-press #(re-frame/dispatch [::qr-scanner/scan-code {:title (i18n/label :t/add-bootnode) :handler :bootnodes.callback/qr-code-scanned}])}})]] (when id diff --git a/src/status_im/ui/screens/home/sheet/views.cljs b/src/status_im/ui/screens/home/sheet/views.cljs index 1f0dc187cb..23b7458d04 100644 --- a/src/status_im/ui/screens/home/sheet/views.cljs +++ b/src/status_im/ui/screens/home/sheet/views.cljs @@ -1,6 +1,7 @@ (ns status-im.ui.screens.home.sheet.views (:require [re-frame.core :as re-frame] [status-im.ui.components.react :as react] + [status-im.qr-scanner.core :as qr-scanner] [quo.core :as quo] [status-im.i18n :as i18n] [status-im.utils.config :as config] @@ -12,6 +13,20 @@ (defn add-new-view [] [react/view + [react/view {:style {:flex-direction :row + :padding-left 16 + :padding-right 8 + :justify-content :space-between + :align-items :center}} + [quo/text {:size :large + :weight :bold} + (i18n/label :t/open-home)] + [quo/button {:type :icon + :theme :icon + :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) diff --git a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/views.cljs b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/views.cljs index d5c1821746..e8bb011eee 100644 --- a/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/views.cljs +++ b/src/status_im/ui/screens/offline_messaging_settings/edit_mailserver/views.cljs @@ -6,6 +6,7 @@ [status-im.ui.components.toolbar :as toolbar] [status-im.ui.screens.offline-messaging-settings.edit-mailserver.styles :as styles] [clojure.string :as string] + [status-im.qr-scanner.core :as qr-scanner] [quo.core :as quo] [status-im.ui.components.topbar :as topbar])) @@ -61,7 +62,7 @@ (i18n/label :t/invalid-format {:format (i18n/label :t/mailserver-format)})) :after {:icon :main-icons/qr - :on-press #(re-frame/dispatch [:qr-scanner.ui/scan-qr-code-pressed + :on-press #(re-frame/dispatch [::qr-scanner/scan-code {:title (i18n/label :t/add-mailserver) :handler :mailserver.callback/qr-code-scanned}])}}]] (when (and id diff --git a/src/status_im/ui/screens/profile/contact/views.cljs b/src/status_im/ui/screens/profile/contact/views.cljs index a0fe9e0ebd..dc8b5ca61b 100644 --- a/src/status_im/ui/screens/profile/contact/views.cljs +++ b/src/status_im/ui/screens/profile/contact/views.cljs @@ -113,6 +113,7 @@ [react/view {:padding-top 12} (for [{:keys [label subtext accessibility-label icon action disabled?]} (actions contact)] + ^{:key label} (when label [quo/list-item {:theme :accent :title label diff --git a/src/status_im/ui/screens/wallet/accounts/views.cljs b/src/status_im/ui/screens/wallet/accounts/views.cljs index 4aedabc29b..4fda567394 100644 --- a/src/status_im/ui/screens/wallet/accounts/views.cljs +++ b/src/status_im/ui/screens/wallet/accounts/views.cljs @@ -10,7 +10,7 @@ [status-im.ui.components.react :as react] [status-im.ui.screens.wallet.accounts.sheets :as sheets] [status-im.ui.screens.wallet.accounts.styles :as styles] - [status-im.utils.utils :as utils.utils] + [status-im.qr-scanner.core :as qr-scanner] [status-im.wallet.utils :as wallet.utils] [status-im.keycard.login :as keycard.login]) (:require-macros [status-im.utils.views :as views])) @@ -91,20 +91,6 @@ :key-fn :name :render-fn (render-asset (:code currency))}])) -(defn- request-camera-permissions [] - (let [options {:handler :wallet.send/qr-scanner-result}] - (re-frame/dispatch - [:request-permissions - {:permissions [:camera] - :on-allowed - #(re-frame/dispatch [:wallet.send/qr-scanner-allowed options]) - :on-denied - #(utils.utils/set-timeout - (fn [] - (utils.utils/show-popup (i18n/label :t/error) - (i18n/label :t/camera-access-error))) - 50)}]))) - (views/defview send-button [] (views/letsubs [account [:multiaccount/default-account]] [react/view styles/send-button-container @@ -187,7 +173,9 @@ [quo/animated-header {:extended-header total-value :use-insets true - :right-accessories [{:on-press #(request-camera-permissions) + :right-accessories [{:on-press #(re-frame/dispatch + [::qr-scanner/scan-code + {:handler :wallet.send/qr-scanner-result}]) :icon :main-icons/qr :accessibility-label :accounts-qr-code} {:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet diff --git a/src/status_im/ui/screens/wallet/add_new/views.cljs b/src/status_im/ui/screens/wallet/add_new/views.cljs index b55e1c3757..566e8b32a6 100644 --- a/src/status_im/ui/screens/wallet/add_new/views.cljs +++ b/src/status_im/ui/screens/wallet/add_new/views.cljs @@ -10,7 +10,6 @@ [status-im.multiaccounts.db :as multiaccounts.db] [status-im.ui.components.toolbar :as toolbar] [status-im.ui.components.topbar :as topbar] - [status-im.utils.utils :as utils.utils] [status-im.ui.components.icons.vector-icons :as icons] [status-im.ui.screens.wallet.account-settings.views :as account-settings] [status-im.ethereum.core :as ethereum] @@ -19,32 +18,19 @@ [quo.core :as quo] [status-im.ui.components.bottom-panel.views :as bottom-panel])) -(defn- request-camera-permissions [] - (let [options {:handler :wallet.add-new/qr-scanner-result}] - (re-frame/dispatch - [:request-permissions - {:permissions [:camera] - :on-allowed - #(re-frame/dispatch [:wallet.add-new/qr-scanner-allowed options]) - :on-denied - #(utils.utils/set-timeout - (fn [] - (utils.utils/show-popup (i18n/label :t/error) - (i18n/label :t/camera-access-error))) - 50)}]))) - (defn add-account-topbar [type] (let [title (case type :generate :t/generate-an-account - :watch :t/add-watch-account - :seed :t/add-seed-account - :key :t/add-private-key-account + :watch :t/add-watch-account + :seed :t/add-seed-account + :key :t/add-private-key-account "")] [topbar/topbar (merge {:title title} (when (= type :watch) {:accessories [{:icon :qr - :handler #(request-camera-permissions)}]}))])) + :handler #(re-frame/dispatch [:wallet.add-new/qr-scanner + {:handler :wallet.add-new/qr-scanner-result}])}]}))])) (defn common-settings [account] [react/view {:margin-horizontal 16} diff --git a/src/status_im/ui/screens/wallet/send/sheets.cljs b/src/status_im/ui/screens/wallet/send/sheets.cljs index b284b5e487..c97a006cf2 100644 --- a/src/status_im/ui/screens/wallet/send/sheets.cljs +++ b/src/status_im/ui/screens/wallet/send/sheets.cljs @@ -6,8 +6,7 @@ [quo.core :as quo] [status-im.ui.components.chat-icon.screen :as chat-icon] [status-im.ui.components.list.views :as list] - [status-im.ui.screens.wallet.accounts.views :as wallet.accounts] - [status-im.utils.utils :as utils.utils])) + [status-im.ui.screens.wallet.accounts.views :as wallet.accounts])) (views/defview assets [address] (views/letsubs [{:keys [tokens]} [:wallet/visible-assets-with-values address] @@ -34,21 +33,6 @@ :key-fn :address :render-fn (render-account field event)}])) -(defn- request-camera-permissions [] - (let [options {:handler :wallet.send/qr-scanner-result - :cancel-handler :wallet.send/qr-scanner-cancel - :modal-opened? true}] - (re-frame/dispatch - [:request-permissions - {:permissions [:camera] - :on-allowed #(re-frame/dispatch [:wallet.send/qr-scanner-allowed options]) - :on-denied - #(utils.utils/set-timeout - (fn [] - (utils.utils/show-popup (i18n/label :t/error) - (i18n/label :t/camera-access-error))) - 50)}]))) - (defn show-accounts-list [] (re-frame/dispatch [:bottom-sheet/hide]) (js/setTimeout #(re-frame/dispatch [:bottom-sheet/show-sheet @@ -66,7 +50,9 @@ :icon :main-icons/qr :theme :accent :accessibility-label :chose-recipient-scan-qr - :on-press request-camera-permissions} + :on-press #(re-frame/dispatch [:wallet.send/qr-scanner {:handler :wallet.send/qr-scanner-result + :cancel-handler :wallet.send/qr-scanner-cancel + :modal-opened? true}])} {:title (i18n/label :t/recipient-code) :icon :main-icons/address :theme :accent diff --git a/src/status_im/utils/universal_links/core.cljs b/src/status_im/utils/universal_links/core.cljs index c33d9e445f..6bfdd42188 100644 --- a/src/status_im/utils/universal_links/core.cljs +++ b/src/status_im/utils/universal_links/core.cljs @@ -1,14 +1,12 @@ (ns status-im.utils.universal-links.core - (:require [cljs.spec.alpha :as spec] - [clojure.string :as string] - [goog.string :as gstring] + (:require [goog.string :as gstring] [re-frame.core :as re-frame] [status-im.multiaccounts.model :as multiaccounts.model] [status-im.chat.models :as chat] [status-im.constants :as constants] - [status-im.ethereum.ens :as ens] + [status-im.router.core :as router] + [status-im.i18n :as i18n] [status-im.ethereum.core :as ethereum] - [status-im.utils.security :as security] [status-im.ui.components.react :as react] [status-im.ui.screens.add-new.new-chat.db :as new-chat.db] [status-im.navigation :as navigation] @@ -20,12 +18,6 @@ ;; TODO(yenda) investigate why `handle-universal-link` event is ;; dispatched 7 times for the same link -(def private-chat-regex #".*/chat/private/(.*)$") -(def public-chat-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:chat/public/([a-z0-9\-]+)$|([a-z0-9\-]+))$") -(def profile-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:u/(0x.*)$|u/(.*)$|user/(.*))$") -(def browse-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:b/(.*)$|browse/(.*))$") -(def referral-link-regex #"(?:https?://join\.)?status[.-]im(?::/)?/(?:referral/(.*))$") - ;; domains should be without the trailing slash (def domains {:external "https://join.status.im" :internal "status-im:/"}) @@ -40,17 +32,6 @@ (get domains domain-type) param)) -(defn match-url [url regex] - (some->> url - (re-matches regex) - rest - reverse - (remove nil?) - first)) - -(defn is-request-url? [url] - (string/starts-with? url "ethereum:")) - (defn universal-link? [url] (boolean (re-matches constants/regx-universal-link url))) @@ -59,52 +40,45 @@ (boolean (re-matches constants/regx-deep-link url))) -(fx/defn handle-browse [cofx url] +(fx/defn handle-browse [cofx {:keys [url]}] (log/info "universal-links: handling browse" url) - (when (security/safe-link? url) - {:browser/show-browser-selection url})) + {:browser/show-browser-selection url}) -(fx/defn handle-private-chat [cofx chat-id] +(fx/defn handle-private-chat [{:keys [db] :as cofx} {:keys [chat-id]}] (log/info "universal-links: handling private chat" chat-id) - (chat/start-chat cofx chat-id)) + (when chat-id + (if-not (new-chat.db/own-public-key? db chat-id) + (chat/start-chat cofx chat-id) + {:utils/show-popup {:title (i18n/label :t/unable-to-read-this-code) + :content (i18n/label :t/can-not-add-yourself)}}))) -(fx/defn handle-public-chat [cofx public-chat] - (log/info "universal-links: handling public chat" public-chat) - (chat/start-public-chat cofx public-chat {})) +(fx/defn handle-public-chat [cofx {:keys [topic]}] + (log/info "universal-links: handling public chat" topic) + (when (seq topic) + (chat/start-public-chat cofx topic {}))) (fx/defn handle-view-profile - [{:keys [db] :as cofx} {:keys [public-key ens-name]}] - (log/info "universal-links: handling view profile" (or ens-name public-key)) + [{:keys [db] :as cofx} {:keys [public-key]}] + (log/info "universal-links: handling view profile" public-key) (cond (and public-key (new-chat.db/own-public-key? db public-key)) - (navigation/navigate-to-cofx cofx :my-profile nil) + (navigation/navigate-to-cofx cofx :tabs {:screen :profile-stack}) public-key - (navigation/navigate-to-cofx (assoc-in cofx [:db :contacts/identity] public-key) :profile nil) + (navigation/navigate-to-cofx (assoc-in cofx [:db :contacts/identity] public-key) + :tabs + {:screen :chat-stack + :params {:screen :profile}}))) - ens-name - (let [chain (ethereum/chain-keyword db)] - {:resolve-public-key {:chain chain - :contact-identity ens-name - :cb (fn [pub-key] - (cond - (and pub-key (new-chat.db/own-public-key? db pub-key)) - (re-frame/dispatch [:navigate-to :my-profile]) - - pub-key - (re-frame/dispatch [:chat.ui/show-profile pub-key]) - - :else - (log/info "universal-link: no pub-key for ens-name " ens-name)))}}))) - -(fx/defn handle-referrer-url [_ referrer] - {::acquisition/check-referrer referrer}) - -(fx/defn handle-eip681 [cofx url] +(fx/defn handle-eip681 [cofx data] (fx/merge cofx - (choose-recipient/parse-eip681-uri-and-resolve-ens url) + (choose-recipient/parse-eip681-uri-and-resolve-ens data) (navigation/navigate-to-cofx :wallet nil))) +(fx/defn handle-referrer-url [_ {:keys [referrer]}] + ;; TODO: Use only for testing + {::acquisition/check-referrer referrer}) + (defn handle-not-found [full-url] (log/info "universal-links: no handler for " full-url)) @@ -115,35 +89,24 @@ (re-frame/dispatch [:handle-universal-link url]) (log/debug "universal-links: no url"))) +(fx/defn on-handle + {:events [::match-value]} + [cofx url {:keys [type] :as data}] + (case type + :public-chat (handle-public-chat cofx data) + :private-chat (handle-private-chat cofx data) + :contact (handle-view-profile cofx data) + :browser (handle-browse cofx data) + :eip681 (handle-eip681 cofx data) + :referrals (handle-referrer-url cofx data) + (handle-not-found url))) + (fx/defn route-url "Match a url against a list of routes and handle accordingly" - [cofx url] - (cond - - (match-url url referral-link-regex) - (handle-referrer-url cofx (match-url url referral-link-regex)) - - (match-url url private-chat-regex) - (handle-private-chat cofx (match-url url private-chat-regex)) - - (spec/valid? :global/public-key (match-url url profile-regex)) - (handle-view-profile cofx {:public-key (match-url url profile-regex)}) - - (or (ens/valid-eth-name-prefix? (match-url url profile-regex)) - (ens/is-valid-eth-name? (match-url url profile-regex))) - (handle-view-profile cofx {:ens-name (match-url url profile-regex)}) - - (match-url url browse-regex) - (handle-browse cofx (match-url url browse-regex)) - - (is-request-url? url) - (handle-eip681 cofx url) - - ;; This needs to stay last, as it's a bit of a catch-all regex - (match-url url public-chat-regex) - (handle-public-chat cofx (match-url url public-chat-regex)) - - :else (handle-not-found url))) + [{:keys [db]} url] + {::router/handle-uri {:chain (ethereum/chain-keyword db) + :uri url + :cb #(re-frame/dispatch [::match-value url %])}}) (fx/defn store-url-for-later "Store the url in the db to be processed on login" diff --git a/src/status_im/utils/universal_links/core_test.cljs b/src/status_im/utils/universal_links/core_test.cljs index ea11fffb26..04207667a6 100644 --- a/src/status_im/utils/universal_links/core_test.cljs +++ b/src/status_im/utils/universal_links/core_test.cljs @@ -3,6 +3,7 @@ [status-im.utils.gfycat.core :as gfycat] [status-im.utils.identicon :as identicon] [re-frame.core :as re-frame] + [status-im.router.core :as router] [status-im.utils.universal-links.core :as links])) (deftest handle-url-test @@ -18,54 +19,10 @@ (testing "it clears the url" (is (nil? (get-in (links/handle-url {:db db} "some-url") [:db :universal-links/url])))) - (testing "a public chat link" - (testing "it joins the chat, short version" - (is (get-in (links/handle-url {:db db} "status-im://status") - [:db :chats "status"]))) - (testing "it joins the chat, short version, https" - (is (get-in (links/handle-url {:db db} "https://join.status.im/status") - [:db :chats "status"]))) - (testing "it joins the chat" - (is (get-in (links/handle-url {:db db} "status-im://chat/public/status") - [:db :chats "status"])))) - (testing "a browse dapp link" - (testing "it open the dapps short version" - (is - (= "www.cryptokitties.co" - (:browser/show-browser-selection (links/handle-url {:db db} "status-im://b/www.cryptokitties.co"))))) - (testing "it open the dapps short version, https" - (is - (= "www.cryptokitties.co" - (:browser/show-browser-selection (links/handle-url {:db db} "https://join.status.im/b/www.cryptokitties.co"))))) - (testing "it open the dapps" - (is - (= "www.cryptokitties.co" - (:browser/show-browser-selection (links/handle-url {:db db} "status-im://browse/www.cryptokitties.co")))))) - (testing "a user profile link" - (testing "it loads the profile, short version" - (let [actual (links/handle-url {:db db} "status-im://u/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")] - (is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity]))))) - (testing "it loads the profile, short version https" - (let [actual (links/handle-url {:db db} "https://join.status.im/u/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")] - (is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity]))))) - (testing "it loads the profile" - (let [actual (links/handle-url {:db db} "status-im://user/0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073")] - (is (= "0x04fbce10971e1cd7253b98c7b7e54de3729ca57ce41a2bfb0d1c4e0a26f72c4b6913c3487fa1b4bb86125770f1743fb4459da05c1cbe31d938814cfaf36e252073" (get-in actual [:db :contacts/identity])))))) - (testing "Handle a custom string as a an profile link with ens-name" - (is (= (get-in (links/handle-url {:db db} "status-im://u/CONTACTCODE") - [:resolve-public-key :contact-identity]) - "CONTACTCODE"))) - (testing "Handle a custom string as a an profile link with ens-name, http" + (testing "Handle a custom string" (is (= (get-in (links/handle-url {:db db} "https://join.status.im/u/statuse2e") - [:resolve-public-key :contact-identity]) - "statuse2e"))) - (testing "Handle a custom string as a an profile link with ens-name" - (is (= (get-in (links/handle-url {:db db} "status-im://user/CONTACTCODE") - [:resolve-public-key :contact-identity]) - "CONTACTCODE"))) - (testing "a not found url" - (testing "it does nothing" - (is (nil? (links/handle-url {:db db} "status-im://blah/not-existing"))))))))) + [::router/handle-uri :uri]) + "https://join.status.im/u/statuse2e"))))))) (deftest url-event-listener (testing "the url is not nil" diff --git a/src/status_im/wallet/choose_recipient/core.cljs b/src/status_im/wallet/choose_recipient/core.cljs index 7c1ffb81bc..771f775bdb 100644 --- a/src/status_im/wallet/choose_recipient/core.cljs +++ b/src/status_im/wallet/choose_recipient/core.cljs @@ -8,10 +8,14 @@ [status-im.i18n :as i18n] [status-im.utils.money :as money] [status-im.utils.fx :as fx] + [status-im.router.core :as router] + [status-im.qr-scanner.core :as qr-scaner] + [status-im.ui.components.bottom-sheet.core :as bottom-sheet] [status-im.navigation :as navigation] [clojure.string :as string] [status-im.ethereum.stateofus :as stateofus])) +;; FIXME(Ferossgp): Should be part of QR scanner not wallet (fx/defn toggle-flashlight {:events [:wallet/toggle-flashlight]} [{:keys [db]}] @@ -107,43 +111,42 @@ {:data uri :chain current-chain-id})})))) {:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})}))) +(fx/defn qr-scanner-allowed + {:events [:wallet.send/qr-scanner]} + [{:keys [db] :as cofx} options] + (fx/merge cofx + (when (:modal-opened? options) + {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] true)}) + (bottom-sheet/hide-bottom-sheet) + (qr-scaner/scan-qr-code options))) + (fx/defn qr-scanner-cancel {:events [:wallet.send/qr-scanner-cancel]} [{db :db} _] {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] false)}) (fx/defn parse-eip681-uri-and-resolve-ens - [{db :db :as cofx} uri] - (if-let [message (eip681/parse-uri uri)] + {:events [:wallet/parse-eip681-uri-and-resolve-ens]} + [{db :db :as cofx} {:keys [message uri paths ens-names error]}] + (if-not error ;; first we get a vector of ens-names to resolve and a vector of paths of ;; these names - (let [{:keys [paths ens-names]} - (reduce (fn [acc path] - (let [address (get-in message path)] - (if (ens/is-valid-eth-name? address) - (-> acc - (update :paths conj path) - (update :ens-names conj address)) - acc))) - {:paths [] :ens-names []} - [[:address] [:function-arguments :address]])] - (println "message" message) - (if (empty? ens-names) - ;; if there are no ens-names, we dispatch request-uri-parsed immediately - (request-uri-parsed cofx message uri) - {::resolve-addresses - {:registry (get ens/ens-registries (ethereum/chain-keyword db)) - :ens-names ens-names - :callback - (fn [addresses] - (re-frame/dispatch - [:wallet/request-uri-parsed - ;; we replace ens-names at their path in the message by their - ;; actual address - (reduce (fn [message [path address]] - (assoc-in message path address)) - message - (map vector paths addresses)) uri]))}})) + (if (empty? ens-names) + ;; if there are no ens-names, we dispatch request-uri-parsed immediately + (request-uri-parsed cofx message uri) + {::resolve-addresses + {:registry (get ens/ens-registries (ethereum/chain-keyword db)) + :ens-names ens-names + :callback + (fn [addresses] + (re-frame/dispatch + [:wallet/request-uri-parsed + ;; we replace ens-names at their path in the message by their + ;; actual address + (reduce (fn [message [path address]] + (assoc-in message path address)) + message + (map vector paths addresses)) uri]))}}) {:ui/show-error (i18n/label :t/wallet-invalid-address {:data uri})})) (fx/defn qr-scanner-result @@ -151,7 +154,7 @@ [cofx data _] (fx/merge cofx (navigation/navigate-back) - (parse-eip681-uri-and-resolve-ens data) + (parse-eip681-uri-and-resolve-ens (router/match-eip681 data)) (fn [{:keys [db]}] (when (get-in db [:wallet/prepare-transaction :modal-opened?]) {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] false)})))) diff --git a/src/status_im/wallet/core.cljs b/src/status_im/wallet/core.cljs index 29b6d4798f..bf51793410 100644 --- a/src/status_im/wallet/core.cljs +++ b/src/status_im/wallet/core.cljs @@ -2,6 +2,7 @@ (:require [re-frame.core :as re-frame] [status-im.multiaccounts.update.core :as multiaccounts.update] [status-im.constants :as constants] + [status-im.qr-scanner.core :as qr-scaner] [status-im.waku.core :as waku] [status-im.ethereum.core :as ethereum] [status-im.ethereum.eip55 :as eip55] @@ -548,21 +549,12 @@ :amount amount :from-command? true})}) -(fx/defn qr-scanner-allowed - {:events [:wallet.send/qr-scanner-allowed]} - [{:keys [db] :as cofx} options] - (fx/merge cofx - (when (:modal-opened? options) - {:db (assoc-in db [:wallet/prepare-transaction :modal-opened?] true)}) - (bottom-sheet/hide-bottom-sheet) - (navigation/navigate-to-cofx :qr-scanner options))) - (fx/defn view-only-qr-scanner-allowed - {:events [:wallet.add-new/qr-scanner-allowed]} + {:events [:wallet.add-new/qr-scanner]} [{:keys [db] :as cofx} options] (fx/merge cofx {:db (update-in db [:add-account] dissoc :address)} - (navigation/navigate-to-cofx :qr-scanner options))) + (qr-scaner/scan-qr-code options))) (fx/defn wallet-send-set-symbol {:events [:wallet.send/set-symbol]} diff --git a/translations/en.json b/translations/en.json index 6b4af57096..302dbb8610 100644 --- a/translations/en.json +++ b/translations/en.json @@ -413,6 +413,7 @@ "ens-username-connected-with-different-key": "Continuing will require a transaction to connect the username with your current chat key.", "ens-username-owned-continue": "Continuing will connect this username with your chat key.", "ens-username-taken": "Username already taken :(", + "ens-name-not-found": "Cannot resolve ENS name", "enter-12-words": "Enter the 12 words of your seed phrase, separated by single spaces", "enter-a-private-key": "Enter a private key", "enter-a-seed-phrase": "Enter a seed phrase", @@ -785,6 +786,7 @@ "okay": "Okay", "on": "On", "open": "Open", + "open-home": "Open...", "open-dapp": "Open ÐApp", "open-dapp-store": "Discover ÐApps", "open-nfc-settings": "Open NFC settings",