diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index cc5f6f072fb7..4254941dd844 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -21,6 +21,8 @@ + + diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 91b5e4874de3..20245645f0f6 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -318,6 +318,8 @@ PODS: - React-cxxreact (= 0.62.2) - React-jsi (= 0.62.2) - ReactCommon/callinvoker (= 0.62.2) + - ReactNativeAudioToolkit (2.0.3): + - React - ReactNativeDarkMode (0.2.2): - React - RNCClipboard (1.2.2): @@ -354,8 +356,8 @@ PODS: - SQLCipher/common (3.4.2) - SQLCipher/standard (3.4.2): - SQLCipher/common - - SSZipArchive (2.2.2) - - TOCropViewController (2.5.2) + - SSZipArchive (2.2.3) + - TOCropViewController (2.5.3) - TouchID (4.4.1): - React - Yoga (1.14.0) @@ -419,6 +421,7 @@ DEPENDENCIES: - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) - ReactCommon/callinvoker (from `../node_modules/react-native/ReactCommon`) - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - "ReactNativeAudioToolkit (from `../node_modules/@react-native-community/audio-toolkit`)" - ReactNativeDarkMode (from `../node_modules/react-native-dark-mode`) - "RNCClipboard (from `../node_modules/@react-native-community/clipboard`)" - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" @@ -437,11 +440,8 @@ DEPENDENCIES: - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) SPEC REPOS: - https://github.com/CocoaPods/Specs.git: - - boost-for-react-native - - SQLCipher - - SSZipArchive trunk: + - boost-for-react-native - CocoaAsyncSocket - CocoaLibEvent - Flipper @@ -452,6 +452,8 @@ SPEC REPOS: - Flipper-RSocket - FlipperKit - OpenSSL-Universal + - SQLCipher + - SSZipArchive - TOCropViewController - YogaKit @@ -524,6 +526,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/Libraries/Vibration" ReactCommon: :path: "../node_modules/react-native/ReactCommon" + ReactNativeAudioToolkit: + :path: "../node_modules/@react-native-community/audio-toolkit" ReactNativeDarkMode: :path: "../node_modules/react-native-dark-mode" RNCClipboard: @@ -599,6 +603,7 @@ SPEC CHECKSUMS: React-RCTText: fae545b10cfdb3d247c36c56f61a94cfd6dba41d React-RCTVibration: 4356114dbcba4ce66991096e51a66e61eda51256 ReactCommon: ed4e11d27609d571e7eee8b65548efc191116eb3 + ReactNativeAudioToolkit: de9610f323e855ac6574be8c99621f3d57c5df06 ReactNativeDarkMode: 0178ffca3b10f6a7c9f49d6f9810232b328fa949 RNCClipboard: 8148e21ac347c51fd6cd4b683389094c216bb543 RNCMaskedView: 71fc32d971f03b7f03d6ab6b86b730c4ee64f5b6 @@ -612,8 +617,8 @@ SPEC CHECKSUMS: RNScreens: ac02d0e4529f08ced69f5580d416f968a6ec3a1d RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f SQLCipher: f9fcf29b2e59ced7defc2a2bdd0ebe79b40d4990 - SSZipArchive: fa16b8cc4cdeceb698e5e5d9f67e9558532fbf23 - TOCropViewController: e9da34f484aedd4e5d5a8ab230ba217cfe16c729 + SSZipArchive: 62d4947b08730e4cda640473b0066d209ff033c9 + TOCropViewController: 20a14b6a7a098308bf369e7c8d700dc983a974e6 TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4 Yoga: 3ebccbdd559724312790e7742142d062476b698e YogaKit: f782866e155069a2cca2517aafea43200b01fd5a diff --git a/mobile/js_files/package.json b/mobile/js_files/package.json index a9b93143e138..077186466210 100644 --- a/mobile/js_files/package.json +++ b/mobile/js_files/package.json @@ -10,6 +10,7 @@ "app:android": "react-native run-android" }, "dependencies": { + "@react-native-community/audio-toolkit": "git+https://github.com/tbenr/react-native-audio-toolkit.git#v2.0.3-status", "@react-native-community/cameraroll": "^1.6.1", "@react-native-community/clipboard": "^1.2.2", "@react-native-community/hooks": "^2.5.1", diff --git a/mobile/js_files/yarn.lock b/mobile/js_files/yarn.lock index 6aee56001dd6..e13a841131d1 100644 --- a/mobile/js_files/yarn.lock +++ b/mobile/js_files/yarn.lock @@ -1207,6 +1207,14 @@ "@types/yargs" "^15.0.0" chalk "^3.0.0" +"@react-native-community/audio-toolkit@git+https://github.com/tbenr/react-native-audio-toolkit.git#v2.0.3-status": + version "2.0.3" + resolved "git+https://github.com/tbenr/react-native-audio-toolkit.git#df14bedfd70f0a02aaf9d1d6f0dd35ffe717299f" + dependencies: + async "^2.6.3" + eventemitter3 "^1.2.0" + lodash "^4.17.15" + "@react-native-community/cameraroll@^1.6.1": version "1.6.2" resolved "https://registry.yarnpkg.com/@react-native-community/cameraroll/-/cameraroll-1.6.2.tgz#a4dedcf8ba7bc938f805dd07dd43a275edb1f411" @@ -1821,7 +1829,7 @@ async-limiter@~1.0.0: resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async@^2.4.0: +async@^2.4.0, async@^2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== @@ -3245,6 +3253,11 @@ event-target-shim@^5.0.0, event-target-shim@^5.0.1: resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== +eventemitter3@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.2.0.tgz#1c86991d816ad1e504750e73874224ecf3bec508" + integrity sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg= + eventemitter3@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.2.tgz#2d3d48f9c346698fce83a85d7d664e98535df6e7" diff --git a/nix/deps/gradle/deps.json b/nix/deps/gradle/deps.json index 036f33690a18..375977b66b7e 100644 --- a/nix/deps/gradle/deps.json +++ b/nix/deps/gradle/deps.json @@ -5554,26 +5554,26 @@ }, { - "path": "com/google/auto/value/auto-value-annotations/1.7.2/auto-value-annotations-1.7.2", + "path": "com/google/auto/value/auto-value-annotations/1.7.3/auto-value-annotations-1.7.3", "host": "https://repo.maven.apache.org/maven2", "type": "jar", "pom": { - "sha1": "5aef9d8912438ba9c964822687e836a8eacdff42", - "sha256": "1v9w96cxqd9dnm1qxilizvdljzciqv24hsnbwqf1y355whmjnjfw" + "sha1": "fd25d76eeeec987053ac5c242476519e30204657", + "sha256": "0xl91j3zyxmqqmc4zj82s5xakdx6c4mz8hg9vmmxcnqbvs3l5ca4" }, "jar": { - "sha1": "7eec707327ec1663b9387c8671efb6808750e039", - "sha256": "1aw54c5ch164kawqmgqjl5ndds7qav2kkckvjnhh68d1calqsfc7" + "sha1": "59ce5ee6aea918f674229f1147da95fdf7f31ce6", + "sha256": "0gg3v68ms4wf0in56il4ly22vs7zmdnpx8qqgl70kr7vyzwr7cz0" } }, { - "path": "com/google/auto/value/auto-value-parent/1.7.2/auto-value-parent-1.7.2", + "path": "com/google/auto/value/auto-value-parent/1.7.3/auto-value-parent-1.7.3", "host": "https://repo.maven.apache.org/maven2", "type": "pom", "pom": { - "sha1": "c022e9c0ddc49607c8e5d68aee0c16392732eb1e", - "sha256": "0lmh29zyz0izw1cywdk5fs155smdvxk899bw6y9l1i8vkkk8s4yp" + "sha1": "2fa007c7efdcab57172ef5a6327d8ec488899b23", + "sha256": "1bdvfmch78pvknr646757lv5z3vj0wlphjwsjh0mb9qlw99g2i6l" } }, @@ -5790,16 +5790,16 @@ }, { - "path": "com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4", + "path": "com/google/errorprone/error_prone_annotations/2.4.0/error_prone_annotations-2.4.0", "host": "https://repo.maven.apache.org/maven2", "type": "jar", "pom": { - "sha1": "9a23fcb83bc8ed502506a8e6c648bf763dc5bcf9", - "sha256": "1vavpvwnawnfhw8lcnba1zv3w6c5zc8nm1kvc37wlz2g9f5769hk" + "sha1": "efece50811944f4b355130bc01f5eb2739d28e58", + "sha256": "0ks7330dr2ys6jb0zj3pgx8aadw7mj2d4n21117kv80f4vx4p9by" }, "jar": { - "sha1": "dac170e4594de319655ffb62f41cbd6dbb5e601e", - "sha256": "0b00bg90n9ni33x0mpyx4iffzrrcbyx58s0vw59nqq6fjzmddxxs" + "sha1": "32ecccc595e4e4d813a80ee9e3ab5813d65874eb", + "sha256": "0a5287bvcaaqvx6y90zn7bqnjwrxb26k1ps9w25jwrha4d40cajz" } }, @@ -5834,12 +5834,12 @@ }, { - "path": "com/google/errorprone/error_prone_parent/2.3.4/error_prone_parent-2.3.4", + "path": "com/google/errorprone/error_prone_parent/2.4.0/error_prone_parent-2.4.0", "host": "https://repo.maven.apache.org/maven2", "type": "pom", "pom": { - "sha1": "a9b9dd42d174a5f96d6c195525877fc6d0b2028a", - "sha256": "11i162j51sf2443ll9vs6j14lfcwknw59h6z1y7kklk0g91mnja0" + "sha1": "b9ca052d865d3ed214b61462960923998be720e8", + "sha256": "16l69qpwxaxk1qk18s15sadr3yykkj11rlp01p42lxfslk6s1pfy" } }, @@ -6182,16 +6182,16 @@ }, { - "path": "com/google/protobuf/protobuf-java/3.12.1/protobuf-java-3.12.1", + "path": "com/google/protobuf/protobuf-java/3.12.2/protobuf-java-3.12.2", "host": "https://repo.maven.apache.org/maven2", "type": "jar", "pom": { - "sha1": "9f534fa0cea834450a87bb99ca02e36695037e2b", - "sha256": "1hdlmkcrkh8li38zqzvjfcd2f2lvknvydnpc3rxmr0hsj6pimfsz" + "sha1": "da3bb9dce2a722503f0d3e4f3b5eea93f737ba48", + "sha256": "1ijicnm83gq33px9c5r4man0n2zw6axrxsqw0jnm1miixyjz08cv" }, "jar": { - "sha1": "48e4a0c3bf6750e6c4efa40a9f13defa869a2f57", - "sha256": "0b55fvlykjf14r01z4aymlrw4a35jklkkpvwm1zmyjybhz7mbq7w" + "sha1": "f0029524002295154c6b546d4e6bd1cfc5081874", + "sha256": "186a1lgmcfr3iml7bfxk9gnbsafyxmriqfyglvkwa85d7gwvx1dk" } }, @@ -6216,12 +6216,12 @@ }, { - "path": "com/google/protobuf/protobuf-parent/3.12.1/protobuf-parent-3.12.1", + "path": "com/google/protobuf/protobuf-parent/3.12.2/protobuf-parent-3.12.2", "host": "https://repo.maven.apache.org/maven2", "type": "pom", "pom": { - "sha1": "63dbda33bf785fe89f47c99c18a7a68688794276", - "sha256": "1d7dsw32p6s69ffn7py229ndg6qrf0hrw6y6cxxjyq9xczf42338" + "sha1": "f5b5d4cb5e6d512f2fac5d2b08e599644a53c087", + "sha256": "0md51xi5af8yi9l1dpqbmysrvlll05zpvmalag6p4f6fykwcry05" } }, @@ -6420,16 +6420,16 @@ }, { - "path": "com/squareup/okio/okio/2.7.0-alpha.lockfree.1/okio-2.7.0-alpha.lockfree.1", + "path": "com/squareup/okio/okio/2.7.0-alpha.lockfree.2/okio-2.7.0-alpha.lockfree.2", "host": "https://repo.maven.apache.org/maven2", "type": "jar", "pom": { - "sha1": "93f841606965109787a468e49a38c3e1031599e0", - "sha256": "1nnjv05r7x044ryh0dnsvib6220wqjbbxv3xxq68qjvq22yzq2nn" + "sha1": "c3e3eca5d192679ca91729b81992f0564e964b68", + "sha256": "11bp2yxj5k04cxrjamf1pbxkm1ghhv83z47f0blgl05mwgd1xpl0" }, "jar": { - "sha1": "a025f03782f6c1aec46c151da0c0add297010f61", - "sha256": "0s7k48i95qqpqixs46xibzd7gw74d1a74m5m4939crjwjz4gkn86" + "sha1": "1b89666c085f2f7bbcc02e90b9f3b7e035314218", + "sha256": "06bimqyial008vxfn32bw3d4hx3d65022v6ahgvb78ipij2a3im9" } }, @@ -6540,12 +6540,12 @@ }, { - "path": "com/sun/xml/bind/jaxb-bom-ext/3.0.0-M3/jaxb-bom-ext-3.0.0-M3", + "path": "com/sun/xml/bind/jaxb-bom-ext/3.0.0-M4/jaxb-bom-ext-3.0.0-M4", "host": "https://repo.maven.apache.org/maven2", "type": "pom", "pom": { - "sha1": "87660d0b2d3e743e8768ca35067798087429b69e", - "sha256": "0j4d162d4dmafi36pnx453k6sifrczjra52rnyyyqnm08ilv1df3" + "sha1": "f6b46b0e806dac58917a43223782b2aed39ea652", + "sha256": "1cnjk3dxw3qk8sp716qklk6jcfbg5ryg6fqgfgah180pll9slldq" } }, @@ -6560,12 +6560,12 @@ }, { - "path": "com/sun/xml/bind/mvn/jaxb-parent/3.0.0-M3/jaxb-parent-3.0.0-M3", + "path": "com/sun/xml/bind/mvn/jaxb-parent/3.0.0-M4/jaxb-parent-3.0.0-M4", "host": "https://repo.maven.apache.org/maven2", "type": "pom", "pom": { - "sha1": "6f7a9a57584c760ade0ea1254867799389dc5ea9", - "sha256": "0gakrwa5yzhgaz26sj6h0lfiwgbd9cjfxh2zznlqh1jq2ak7kyhh" + "sha1": "1bacfd08abc2072018ec7c78e34cca867cea5548", + "sha256": "03k0i5wgizmx5r0f53djlfw7i9plb28qas796mr8vnp2rjy51a13" } }, @@ -6590,12 +6590,12 @@ }, { - "path": "com/sun/xml/bind/mvn/jaxb-txw-parent/3.0.0-M3/jaxb-txw-parent-3.0.0-M3", + "path": "com/sun/xml/bind/mvn/jaxb-txw-parent/3.0.0-M4/jaxb-txw-parent-3.0.0-M4", "host": "https://repo.maven.apache.org/maven2", "type": "pom", "pom": { - "sha1": "c43f6d76e67507998c870bea97a4fb57b3dee903", - "sha256": "1lshn5izj3zp25whyv43dbinm73kf5lx64kkhvnkfvqjm0mmdlq4" + "sha1": "a796032f4a0117ba47401b9e3233df8d1779c0f3", + "sha256": "161nir0qk32pz7jnd8ljz9d37qbg28x20jfbwx6nhpk4n3492fkq" } }, @@ -8002,16 +8002,16 @@ }, { - "path": "org/checkerframework/checker-qual/3.4.0/checker-qual-3.4.0", + "path": "org/checkerframework/checker-qual/3.4.1/checker-qual-3.4.1", "host": "https://repo.maven.apache.org/maven2", "type": "jar", "pom": { - "sha1": "ec1663cd82fd24839d5eb2b5de8dd9dca47b3f78", - "sha256": "0cs0vn3ka4vkn21c84lwv7kfqblq14kq4my1c9zavq71k5vvwibd" + "sha1": "48f9d7fe1e9df19b41d95388fed313dacddcea69", + "sha256": "0x4k1glx55qppc9cnri07va54fd20wg3hmgvj4s7rdrgjg8c0wc1" }, "jar": { - "sha1": "36830784bdefda6dcf8fc217e0416d8291bfe7fa", - "sha256": "1hjsmh708hym8b2kvkfcv5hbk7j746gf5f1926wr26vaq0p90aia" + "sha1": "b3df2bf4d7d258e5aa192c3ac6f7f84688046262", + "sha256": "0zjha61sasdfyscmll51cjcnzxgqzqcmkq7w1yfdchh58s3wirdw" } }, @@ -8280,12 +8280,12 @@ }, { - "path": "org/glassfish/jaxb/jaxb-bom/3.0.0-M3/jaxb-bom-3.0.0-M3", + "path": "org/glassfish/jaxb/jaxb-bom/3.0.0-M4/jaxb-bom-3.0.0-M4", "host": "https://repo.maven.apache.org/maven2", "type": "pom", "pom": { - "sha1": "4599efca8af86d90de8505c3f9f561e748cdf680", - "sha256": "1qfhsc7gz7w1xpkwfbli9yzm31vln3m5wxhwrg70l91f76i1sr3b" + "sha1": "eaa73c4a5fba23d9f3da8e95428bec55a722eabf", + "sha256": "1vqn88lq4x0y1n8h669myg5h6laizr53jwngmhjb1lipxz6gxcpl" } }, @@ -8304,16 +8304,16 @@ }, { - "path": "org/glassfish/jaxb/jaxb-core/3.0.0-M3/jaxb-core-3.0.0-M3", + "path": "org/glassfish/jaxb/jaxb-core/3.0.0-M4/jaxb-core-3.0.0-M4", "host": "https://repo.maven.apache.org/maven2", "type": "jar", "pom": { - "sha1": "7bfd3d071e95e2a1ac7d76a717d5a0140bd2fc9f", - "sha256": "1j1dbbdsrgd2y8nxayrb18p2k7g89pwk54jbplhyy18px0h1gjaw" + "sha1": "e669c8c7c0cd75d3201ee3538588f7304b8dac8b", + "sha256": "0h8mvvbj743vvmyrvwmqpsf7qc1fl1l6vq19mwxpmvs0pisp0y9y" }, "jar": { - "sha1": "b40a6d72c0c8aea8538f58f8f1a370dde74991d3", - "sha256": "0ag58wfvg0gwqg0rxyqj1j8siymz5nqaqpcpkx95nn5n6d1wzn5y" + "sha1": "47d4d84d0861122c71a4cdf71fc6c0b66d4a13f1", + "sha256": "193bkzs93cz6zl3n7q8qy1n9c9bm5lkcrmg66sbb3qk1rlrnw485" } }, @@ -8346,16 +8346,16 @@ }, { - "path": "org/glassfish/jaxb/txw2/3.0.0-M3/txw2-3.0.0-M3", + "path": "org/glassfish/jaxb/txw2/3.0.0-M4/txw2-3.0.0-M4", "host": "https://repo.maven.apache.org/maven2", "type": "jar", "pom": { - "sha1": "3515e65f22e70651ec40652995d58d4639ab282f", - "sha256": "0n4zril9pk56a8jwaxpjhw44kdjmadnavz3dmds7g0hgmyblgrb0" + "sha1": "b5633883ac1e877537f805434c63254ee148d5c9", + "sha256": "0yvarhya3dxa3mhxv8cvrk1phnpa6l65grfanrvmj7ix160w1ilf" }, "jar": { - "sha1": "402cd8ef4b6fb5b659da98dbf58647b97815b31e", - "sha256": "1ybrhsjacr13dp8g9b1hrl6rpn4p277vinzr1vmyv1fhf2ikgac8" + "sha1": "fef146e275c3f85b82977848df2573bcfe168b3b", + "sha256": "19a2q7cg16a093v337l7iyf7yl3rx87b8rvl0ynwhpmgvxd6qr2k" } }, diff --git a/nix/deps/gradle/deps.urls b/nix/deps/gradle/deps.urls index 04f577153749..15a6ecab7c6d 100644 --- a/nix/deps/gradle/deps.urls +++ b/nix/deps/gradle/deps.urls @@ -395,8 +395,8 @@ https://repo.maven.apache.org/maven2/com/googlecode/java-diff-utils/diffutils/1. https://repo.maven.apache.org/maven2/com/googlecode/json-simple/json-simple/1.1/json-simple-1.1.pom https://repo.maven.apache.org/maven2/com/googlecode/juniversalchardet/juniversalchardet/1.0.3/juniversalchardet-1.0.3.pom https://repo.maven.apache.org/maven2/com/google/auto/auto-parent/3/auto-parent-3.pom -https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.7.2/auto-value-annotations-1.7.2.pom -https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.7.2/auto-value-parent-1.7.2.pom +https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.7.3/auto-value-annotations-1.7.3.pom +https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-parent/1.7.3/auto-value-parent-1.7.3.pom https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value/1.5.2/auto-value-1.5.2.pom https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/1.3.9/jsr305-1.3.9.pom https://repo.maven.apache.org/maven2/com/google/code/findbugs/jsr305/2.0.1/jsr305-2.0.1.pom @@ -413,11 +413,11 @@ https://repo.maven.apache.org/maven2/com/google/code/gson/gson/2.8.5/gson-2.8.5. https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.0.18/error_prone_annotations-2.0.18.pom https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.2.0/error_prone_annotations-2.2.0.pom https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.3.1/error_prone_annotations-2.3.1.pom -https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.3.4/error_prone_annotations-2.3.4.pom +https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_annotations/2.4.0/error_prone_annotations-2.4.0.pom https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.0.18/error_prone_parent-2.0.18.pom https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.2.0/error_prone_parent-2.2.0.pom https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.3.1/error_prone_parent-2.3.1.pom -https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.3.4/error_prone_parent-2.3.4.pom +https://repo.maven.apache.org/maven2/com/google/errorprone/error_prone_parent/2.4.0/error_prone_parent-2.4.0.pom https://repo.maven.apache.org/maven2/com/google/google/1/google-1.pom https://repo.maven.apache.org/maven2/com/google/guava/failureaccess/1.0.1/failureaccess-1.0.1.pom https://repo.maven.apache.org/maven2/com/google/guava/guava-parent/17.0/guava-parent-17.0.pom @@ -445,10 +445,10 @@ https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java-util/3.4. https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/2.5.0/protobuf-java-2.5.0.pom https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.0.0/protobuf-java-3.0.0.pom https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.4.0/protobuf-java-3.4.0.pom -https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.12.1/protobuf-java-3.12.1.pom +https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-java/3.12.2/protobuf-java-3.12.2.pom https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.0.0/protobuf-parent-3.0.0.pom https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.4.0/protobuf-parent-3.4.0.pom -https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.12.1/protobuf-parent-3.12.1.pom +https://repo.maven.apache.org/maven2/com/google/protobuf/protobuf-parent/3.12.2/protobuf-parent-3.12.2.pom https://repo.maven.apache.org/maven2/com/google/truth/truth-parent/1.0.1/truth-parent-1.0.1.pom https://repo.maven.apache.org/maven2/com/google/truth/truth/1.0.1/truth-1.0.1.pom https://repo.maven.apache.org/maven2/com/google/zxing/core/3.3.3/core-3.3.3.pom @@ -464,7 +464,7 @@ https://repo.maven.apache.org/maven2/com/squareup/okhttp3/parent/3.12.1/parent-3 https://repo.maven.apache.org/maven2/com/squareup/okio/okio-parent/1.15.0/okio-parent-1.15.0.pom https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.15.0/okio-1.15.0.pom https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.6.0/okio-2.6.0.pom -https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.7.0-alpha.lockfree.1/okio-2.7.0-alpha.lockfree.1.pom +https://repo.maven.apache.org/maven2/com/squareup/okio/okio/2.7.0-alpha.lockfree.2/okio-2.7.0-alpha.lockfree.2.pom https://repo.maven.apache.org/maven2/com/sun/activation/all/1.2.0/all-1.2.0.pom https://repo.maven.apache.org/maven2/com/sun/activation/all/2.0.0-RC3/all-2.0.0-RC3.pom https://repo.maven.apache.org/maven2/com/sun/activation/jakarta.activation/2.0.0-RC3/jakarta.activation-2.0.0-RC3.pom @@ -474,12 +474,12 @@ https://repo.maven.apache.org/maven2/com/sun/istack/istack-commons-runtime/4.0.0 https://repo.maven.apache.org/maven2/com/sun/istack/istack-commons/2.21/istack-commons-2.21.pom https://repo.maven.apache.org/maven2/com/sun/istack/istack-commons/4.0.0-M3/istack-commons-4.0.0-M3.pom https://repo.maven.apache.org/maven2/com/sun/xml/bind/jaxb-bom-ext/2.2.11/jaxb-bom-ext-2.2.11.pom -https://repo.maven.apache.org/maven2/com/sun/xml/bind/jaxb-bom-ext/3.0.0-M3/jaxb-bom-ext-3.0.0-M3.pom +https://repo.maven.apache.org/maven2/com/sun/xml/bind/jaxb-bom-ext/3.0.0-M4/jaxb-bom-ext-3.0.0-M4.pom https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-parent/2.2.11/jaxb-parent-2.2.11.pom -https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-parent/3.0.0-M3/jaxb-parent-3.0.0-M3.pom +https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-parent/3.0.0-M4/jaxb-parent-3.0.0-M4.pom https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-runtime-parent/2.2.11/jaxb-runtime-parent-2.2.11.pom https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-txw-parent/2.2.11/jaxb-txw-parent-2.2.11.pom -https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-txw-parent/3.0.0-M3/jaxb-txw-parent-3.0.0-M3.pom +https://repo.maven.apache.org/maven2/com/sun/xml/bind/mvn/jaxb-txw-parent/3.0.0-M4/jaxb-txw-parent-3.0.0-M4.pom https://repo.maven.apache.org/maven2/com/sun/xml/fastinfoset/FastInfoset/1.2.13/FastInfoset-1.2.13.pom https://repo.maven.apache.org/maven2/com/sun/xml/fastinfoset/FastInfoset/2.0.0-M2/FastInfoset-2.0.0-M2.pom https://repo.maven.apache.org/maven2/com/sun/xml/fastinfoset/fastinfoset-project/1.2.13/fastinfoset-project-1.2.13.pom @@ -595,7 +595,7 @@ https://repo.maven.apache.org/maven2/org/bouncycastle/bcprov-jdk15on/1.56/bcprov https://repo.maven.apache.org/maven2/org/bouncycastle/bcprov-jdk15on/1.60/bcprov-jdk15on-1.60.pom https://repo.maven.apache.org/maven2/org/checkerframework/checker-compat-qual/2.5.5/checker-compat-qual-2.5.5.pom https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/2.5.2/checker-qual-2.5.2.pom -https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.4.0/checker-qual-3.4.0.pom +https://repo.maven.apache.org/maven2/org/checkerframework/checker-qual/3.4.1/checker-qual-3.4.1.pom https://repo.maven.apache.org/maven2/org/codehaus/codehaus-parent/4/codehaus-parent-4.pom https://repo.maven.apache.org/maven2/org/codehaus/groovy/groovy-all/2.4.15/groovy-all-2.4.15.pom https://repo.maven.apache.org/maven2/org/codehaus/mojo/animal-sniffer-annotations/1.14/animal-sniffer-annotations-1.14.pom @@ -618,12 +618,12 @@ https://repo.maven.apache.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.4/ecj-4 https://repo.maven.apache.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.5.1/ecj-4.5.1.pom https://repo.maven.apache.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.6.1/ecj-4.6.1.pom https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-bom/2.2.11/jaxb-bom-2.2.11.pom -https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-bom/3.0.0-M3/jaxb-bom-3.0.0-M3.pom +https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-bom/3.0.0-M4/jaxb-bom-3.0.0-M4.pom https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-core/2.2.11/jaxb-core-2.2.11.pom -https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-core/3.0.0-M3/jaxb-core-3.0.0-M3.pom +https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-core/3.0.0-M4/jaxb-core-3.0.0-M4.pom https://repo.maven.apache.org/maven2/org/glassfish/jaxb/jaxb-runtime/2.2.11/jaxb-runtime-2.2.11.pom https://repo.maven.apache.org/maven2/org/glassfish/jaxb/txw2/2.2.11/txw2-2.2.11.pom -https://repo.maven.apache.org/maven2/org/glassfish/jaxb/txw2/3.0.0-M3/txw2-3.0.0-M3.pom +https://repo.maven.apache.org/maven2/org/glassfish/jaxb/txw2/3.0.0-M4/txw2-3.0.0-M4.pom https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-core/2.2/hamcrest-core-2.2.pom https://repo.maven.apache.org/maven2/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom diff --git a/nix/deps/gradle/proj.list b/nix/deps/gradle/proj.list index 8b3dde7b6b65..2ae73c9bb7ed 100644 --- a/nix/deps/gradle/proj.list +++ b/nix/deps/gradle/proj.list @@ -1,6 +1,7 @@ app react-native-background-timer react-native-camera +react-native-community_audio-toolkit react-native-community_cameraroll react-native-community_clipboard react-native-community_masked-view diff --git a/src/status_im/chat/models/input.cljs b/src/status_im/chat/models/input.cljs index 56eb62a89c6c..4719e1df6a2e 100644 --- a/src/status_im/chat/models/input.cljs +++ b/src/status_im/chat/models/input.cljs @@ -126,6 +126,14 @@ :image-path (string/replace image-path #"file://" "") :text "Update to latest version to see a nice image here!"}))))) +(fx/defn send-audio-message + [cofx audio-path current-chat-id] + (when-not (string/blank? audio-path) + (chat.message/send-message cofx {:chat-id current-chat-id + :content-type constants/content-type-audio + :audio-path audio-path + :text "Update to latest version to listen to an audio here!"}))) + (fx/defn send-sticker-message [cofx {:keys [hash pack]} current-chat-id] (when-not (string/blank? hash) diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 9ff808aa087a..fab0c1d06594 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -14,6 +14,7 @@ (def content-type-command 5) (def content-type-system-text 6) (def content-type-image 7) +(def content-type-audio 8) (def message-type-one-to-one 1) (def message-type-public-group 2) diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index a14ec8d98117..cfd30b0b504b 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -575,6 +575,11 @@ {}) (chat.input/send-sticker-message sticker current-chat-id)))) +(handlers/register-handler-fx + :chat/send-audio + (fn [{{:keys [current-chat-id]} :db :as cofx} [_ audio-path]] + (chat.input/send-audio-message cofx audio-path current-chat-id))) + (handlers/register-handler-fx :chat/disable-cooldown (fn [cofx _] diff --git a/src/status_im/transport/message/protocol.cljs b/src/status_im/transport/message/protocol.cljs index eb5a5c697750..233178f4b0a9 100644 --- a/src/status_im/transport/message/protocol.cljs +++ b/src/status_im/transport/message/protocol.cljs @@ -10,6 +10,7 @@ response-to ens-name image-path + audio-path message-type sticker content-type] @@ -22,6 +23,7 @@ :responseTo response-to :ensName ens-name :imagePath image-path + :audioPath audio-path :sticker sticker :contentType content-type}] :on-success diff --git a/src/status_im/ui/components/permissions.cljs b/src/status_im/ui/components/permissions.cljs index cb85e584018c..74ce8bc21933 100644 --- a/src/status_im/ui/components/permissions.cljs +++ b/src/status_im/ui/components/permissions.cljs @@ -5,7 +5,8 @@ (def permissions-map {:read-external-storage "android.permission.READ_EXTERNAL_STORAGE" :write-external-storage "android.permission.WRITE_EXTERNAL_STORAGE" - :camera "android.permission.CAMERA"}) + :camera "android.permission.CAMERA" + :record-audio "android.permission.RECORD_AUDIO"}) (defn all-granted? [permissions] (let [permission-vals (distinct (vals permissions))] diff --git a/src/status_im/ui/screens/chat/audio_message/views.cljs b/src/status_im/ui/screens/chat/audio_message/views.cljs new file mode 100644 index 000000000000..9c24bac28895 --- /dev/null +++ b/src/status_im/ui/screens/chat/audio_message/views.cljs @@ -0,0 +1,364 @@ +(ns status-im.ui.screens.chat.audio-message.views + (:require-macros [status-im.utils.views :refer [defview letsubs]]) + (:require [clojure.string :as string] + [reagent.core :as reagent] + [status-im.ui.components.react :as react] + [status-im.utils.platform :as platform] + [re-frame.core :as re-frame] + [status-im.i18n :as i18n] + [status-im.ui.components.button :as button] + [status-im.ui.components.colors :as colors] + [status-im.ui.components.animation :as anim] + [status-im.ui.components.icons.vector-icons :as icons] + [status-im.utils.utils :as utils.utils] + [status-im.utils.fs :as fs] + ["@react-native-community/audio-toolkit" :refer (Player Recorder MediaStates)])) + +;; get mediastates from react module +(defonce PLAYING (.-PLAYING ^js MediaStates)) +(defonce PAUSED (.-PAUSED ^js MediaStates)) +(defonce RECORDING (.-RECORDING ^js MediaStates)) +(defonce PREPARED (.-PREPARED ^js MediaStates)) +(defonce IDLE (.-IDLE ^js MediaStates)) +(defonce ERROR (.-ERROR ^js MediaStates)) +(defonce DESTROYED (.-DESTROYED ^js MediaStates)) + +;; panel management +(defn- request-record-audio-permissions [] + (re-frame/dispatch + [:request-permissions + {:permissions [:record-audio] + :on-allowed + #(re-frame/dispatch [:chat.ui/set-chat-ui-props + {:input-bottom-sheet :audio-message}]) + :on-denied + #(utils.utils/set-timeout + (fn [] + (utils.utils/show-popup (i18n/label :t/error) + (i18n/label "you have to give permission to send audio messages"))) + 50)}])) + +(defn input-button [audio-message-showing?] + [react/touchable-highlight + {:on-press + (fn [_] + (if audio-message-showing? + (re-frame/dispatch [:chat.ui/set-chat-ui-props + {:input-bottom-sheet nil}]) + (request-record-audio-permissions)) + (when-not platform/desktop? (js/setTimeout #(react/dismiss-keyboard!) 100))) + :accessibility-label :show-audio-message-icon} + [icons/icon + :main-icons/warning + {:container-style {:margin 14 :margin-right 6} + :color (if audio-message-showing? colors/blue colors/gray)}]]) + +(defn show-panel-anim + [bottom-anim-value alpha-value] + (anim/start + (anim/parallel + [(anim/spring bottom-anim-value {:toValue 0 + :useNativeDriver true}) + (anim/timing alpha-value {:toValue 1 + :duration 500 + :useNativeDriver true})]))) + +;; --- AUDIO stuff + +(def base-filename "am.") + +(defonce recorder-ref (atom nil)) +(defonce player-ref (atom nil)) +(def default-rec-options {:filename (str base-filename "aac") + :bitrate 32000 + :channels 1 + :sampleRate 22050 + :quality "medium" ; ios only + :meteringInterval 50}) + +(defonce state-cb (atom #())) +(defonce record-ended-cb (atom #())) +(defonce meter-cb (atom #())) + +(defn destroy-recorder [] + (when @recorder-ref + (when (not= (.-state ^js @recorder-ref) DESTROYED) + (.destroy ^js @recorder-ref)) + (reset! recorder-ref nil))) + +(defn destroy-player [] + (when @player-ref + (when (not= (.-state ^js @player-ref) DESTROYED) + (.destroy ^js @player-ref)) + (reset! player-ref nil))) + +(defn reload-recorder [options-ref] + (print "initializing recorder with: " @options-ref) + (when @recorder-ref + (destroy-recorder)) + (reset! recorder-ref + (new ^js Recorder + (:filename @options-ref) + (clj->js @options-ref))) + ;(.prepare ^js @recorder-ref state-cb) ;; if a recorder is prepared, player wont play + (@state-cb) + (.on ^js @recorder-ref "meter" @meter-cb) + (.on ^js @recorder-ref "ended" @state-cb)) + +(defn reload-player [options-ref] + (when @player-ref + (destroy-player)) + (reset! player-ref + (new ^js Player + (:filename @options-ref) + (clj->js {:autoDestroy false}))) + (.prepare ^js @player-ref #(if % + (utils.utils/show-popup (str "prepare " (.-err %)) (.-message %)) + (@state-cb))) + (.on ^js @player-ref "ended" @state-cb)) + +(defn start-recording [] + (when @recorder-ref + (.record ^js @recorder-ref #(if % + (utils.utils/show-popup (.-err %) (.-message %)) + (@state-cb))))) + +(defn start-playing [] + (when @player-ref + (.play ^js @player-ref #(if % + (utils.utils/show-popup (.-err %) (.-message %)) + (@state-cb))))) + +(defn stop-recording [options-ref] + (when @recorder-ref + (.stop ^js @recorder-ref #(if % + (utils.utils/show-popup (.-err %) (.-message %)) + (do + (reload-recorder options-ref) + (reload-player options-ref)))))) + +(defn stop-playing [] + (when @player-ref + (.stop ^js @player-ref #(if % + (utils.utils/show-popup (.-err %) (.-message %)) + (@state-cb))))) + +(defn update-options [new-option options-ref] + (reset! options-ref (merge @options-ref new-option))) + +;; -- UI stuff + +(defn update-info [state-ref info error] + (if info + (let [size (int (.-size info)) + b64s (* size 1.33) + b64kb (quot b64s 1024) + duration (:duration @state-ref) + s (when (and duration (not= duration -1)) + (utils.utils/format-decimals (/ duration 1000) 1)) + ratio (when (and duration (not= duration -1)) + (utils.utils/format-decimals (/ (/ b64s 1024) (/ duration 1000)) 2)) + msg (str s "s --- b64 size: " b64kb "kb --- kb/s: " ratio "kb")] + (reset! state-ref (merge @state-ref {:info msg}))) + (utils.utils/show-popup "fileinfo error" error))) + +;; general state +;; - :recording +;; - :playing +;; - :ready-to-send +;; - :ready-to-record +(defn update-state [state-ref] + (let [player-state (when @player-ref (.-state ^js @player-ref)) + recorder-state (when @recorder-ref (.-state ^js @recorder-ref)) + output-file (or + (when @recorder-ref + (.-fsPath ^js @recorder-ref)) + (:output-file @state-ref)) + general (cond + (= recorder-state RECORDING) :recording + (= player-state PLAYING) :playing + (= player-state PREPARED) :ready-to-send + :else :ready-to-record) + new-state {:general general + :working? (or + (= general :recording) + (= general :playing)) + :output-file output-file + :duration (when (= player-state PREPARED) + (.-duration ^js @player-ref)) + :info (if (= general :recording) + "-recording-" + (:info @state-ref))}] + (when (and output-file (not= general :recording)) + (fs/stat output-file + #(update-info state-ref % nil) + #(update-info state-ref nil %))) + (when (not= @state-ref new-state) + (print "oldstate" @state-ref "newstate" new-state) + (reset! state-ref new-state)))) + +(defn update-meter [meter-data meter-ref] + (reset! meter-ref (str (int (.-value ^js meter-data)) "db"))) + +(def options-btn-cont-style {:height 30 :margin-horizontal 4 :padding-horizontal 12}) +(def options-cont-style {:flex 1 + :flex-direction :row + :align-items :center + :justify-content :center + :margin-top 0}) + +(defview audio-message-view [] + (letsubs [panel-height [:chats/chat-panel-height] + bottom-anim-value (anim/create-value @panel-height) + alpha-value (anim/create-value 0) + state (reagent/atom nil) + meter (reagent/atom "?db") + rec-options (reagent/atom default-rec-options)] + {:component-did-mount (fn [] + (show-panel-anim bottom-anim-value alpha-value) + (reset! state-cb #(update-state state)) + (reset! record-ended-cb #(reload-player rec-options)) + (reset! meter-cb #(update-meter % meter)) + (reload-recorder rec-options) + (add-watch rec-options :watch (fn [] (reload-recorder rec-options)))) + :component-will-unmount (fn [] + (destroy-recorder) + (destroy-player) + (remove-watch rec-options :watch))} + [react/animated-view {:style {:background-color colors/white + :height panel-height + :transform [{:translateY bottom-anim-value}] + :opacity alpha-value}} + [react/view {:style {:flex 1 + :flex-direction :column + :align-items :center + :justify-content :center}} + + ;; options - extension\encoder + [react/view {:style options-cont-style} + + [button/button {:label "mp4" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (string/ends-with? (:filename @rec-options) "mp4")) + :on-press #(update-options {:filename (str base-filename "mp4")} rec-options)}] + [button/button {:label "aac" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (string/ends-with? (:filename @rec-options) "aac")) + :on-press #(update-options {:filename (str base-filename "aac")} rec-options)}] + [button/button {:label "ogg" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (string/ends-with? (:filename @rec-options) "ogg")) + :on-press #(update-options {:filename (str base-filename "ogg")} rec-options)}] + [button/button {:label "webm" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (string/ends-with? (:filename @rec-options) "webm")) + :on-press #(update-options {:filename (str base-filename "webm")} rec-options)}] + [button/button {:label "amr" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (string/ends-with? (:filename @rec-options) "amr")) + :on-press #(update-options {:filename (str base-filename "amr")} rec-options)}]] + + ;; options - samplerate + [react/view {:style options-cont-style} + [button/button {:label "22kHz" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (= (:sampleRate @rec-options) 22050)) + :on-press #(update-options {:sampleRate 22050} rec-options)}] + [button/button {:label "32kHz" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (= (:sampleRate @rec-options) 32000)) + :on-press #(update-options {:sampleRate 32000} rec-options)}] + [button/button {:label "44kHz" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (= (:sampleRate @rec-options) 44100)) + :on-press #(update-options {:sampleRate 44100} rec-options)}]] + + + ;; options - bitrate + + + [react/view {:style options-cont-style} + [button/button {:label "32kbs" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (= (:bitrate @rec-options) 32000)) + :on-press #(update-options {:bitrate 32000} rec-options)}] + [button/button {:label "48kbs" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (= (:bitrate @rec-options) 48000)) + :on-press #(update-options {:bitrate 48000} rec-options)}] + [button/button {:label "64kbs" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (= (:bitrate @rec-options) 64000)) + :on-press #(update-options {:bitrate 64000} rec-options)}] + [button/button {:label "96kbs" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (= (:bitrate @rec-options) 96000)) + :on-press #(update-options {:bitrate 96000} rec-options)}] + [button/button {:label "128kbs" + :container-style options-btn-cont-style + :disabled? (if (:working? @state) + true + (= (:bitrate @rec-options) 128000)) + :on-press #(update-options {:bitrate 128000} rec-options)}]] + + + ;; controls + + + [react/text {:style {:typography :main-medium}} (:info @state)] + [react/view {:style {:flex 1 + :flex-direction :row + :align-items :center + :justify-content :center + :margin-top 20}} + [button/button {:label (if (= (:general @state) :recording) + "stop" + "rec") + :disabled? (= (:general @state) :playing) + :theme :red + :on-press (if (= (:general @state) :recording) + #(stop-recording rec-options) + start-recording)}] + [button/button {:label (if (= (:general @state) :playing) + "stop" + "play") + :disabled? (let [g (:general @state)] + (or + (= g :recording) + (= g :ready-to-record))) + :theme :green + :on-press (if (= (:general @state) :playing) + stop-playing + start-playing)}] + [button/button {:label "send msg" + :disabled? (or + (:working? @state) + (not= (:general @state) :ready-to-send) + (string/blank? (:output-file @state))) + :on-press #(re-frame/dispatch [:chat/send-audio (:output-file @state)])}]] + ;; metering + [react/text {:style {:typography :main-medium :margin-top 20}} @meter]]])) \ No newline at end of file diff --git a/src/status_im/ui/screens/chat/input/input.cljs b/src/status_im/ui/screens/chat/input/input.cljs index 8c8e7ccf065a..fc071954743c 100644 --- a/src/status_im/ui/screens/chat/input/input.cljs +++ b/src/status_im/ui/screens/chat/input/input.cljs @@ -12,6 +12,7 @@ [status-im.ui.components.react :as react] [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.utils.config :as config] + [status-im.ui.screens.chat.audio-message.views :as audio-message] [status-im.ui.screens.chat.image.views :as image] [status-im.ui.screens.chat.stickers.views :as stickers] [status-im.ui.screens.chat.extensions.views :as extensions])) @@ -90,6 +91,8 @@ [send-image-view sending-image]) [react/view {:style style/input-container} [basic-text-input input-text cooldown-enabled?] + (when (and input-text-empty? (not reply-message) (not public?)) + [audio-message/input-button (= :audio-message input-bottom-sheet)]) (when (and input-text-empty? (not reply-message) (not public?)) [image/input-button (= :images input-bottom-sheet)]) (when (and input-text-empty? mainnet? (not reply-message)) diff --git a/src/status_im/ui/screens/chat/message/audio.cljs b/src/status_im/ui/screens/chat/message/audio.cljs new file mode 100644 index 000000000000..e99fa9379406 --- /dev/null +++ b/src/status_im/ui/screens/chat/message/audio.cljs @@ -0,0 +1,82 @@ +(ns status-im.ui.screens.chat.message.audio + (:require-macros [status-im.utils.views :refer [defview letsubs]]) + (:require [reagent.core :as reagent] + [status-im.ui.components.react :as react] + [status-im.ui.components.button :as button] + ["@react-native-community/audio-toolkit" :refer (Player MediaStates)])) + +(defn message-press-handlers [{:keys [content] :as message}] + ;;TBI + ) + +(defonce DESTROYED (.-DESTROYED ^js MediaStates)) +(defonce PLAYING (.-PLAYING ^js MediaStates)) +(defonce PAUSED (.-PAUSED ^js MediaStates)) +(defonce RECORDING (.-RECORDING ^js MediaStates)) +(defonce PREPARED (.-PREPARED ^js MediaStates)) + +(defn update-state [state-ref player-ref error] + (let [player-state (when @player-ref (.-state ^js @player-ref)) + general (cond + (some? error) :error + (= player-state PLAYING) :playing + (= player-state PAUSED) :paused + (= player-state PREPARED) :ready-to-play + :else :preparing) + new-state {:general general + :error-msg error + :duration (when (= player-state PREPARED) + (.-duration ^js @player-ref))}] + (when (not= @state-ref new-state) + (print "oldstate" @state-ref "newstate" new-state) + (reset! state-ref new-state)))) + +(defn destroy-player [player-ref] + (when @player-ref + (when (not= (.-state ^js @player-ref) DESTROYED) + (.destroy ^js @player-ref)) + (reset! player-ref nil))) + +(defn reload-player [player-ref base64-data state-ref] + (when @player-ref + (destroy-player player-ref)) + (reset! player-ref + (new ^js Player + base64-data + (clj->js {:autoDestroy false}))) + (.prepare ^js @player-ref #(if % + (update-state state-ref player-ref (.-message %)) + (update-state state-ref player-ref nil))) + (.on ^js @player-ref "ended" #(update-state state-ref player-ref nil))) + +(defn start-playing [player-ref state-ref] + (when @player-ref + (.play ^js @player-ref #(if % + (update-state state-ref player-ref (.-message %)) + (update-state state-ref player-ref nil))))) + +(defn stop-playing [player-ref state-ref] + (when @player-ref + (.stop ^js @player-ref #(if % + (update-state state-ref player-ref (.-message %)) + (update-state state-ref player-ref nil))))) + +(defview message-content [{:keys [audio]}] + (letsubs [player (reagent/atom nil) + state (reagent/atom nil)] + {:component-did-mount (fn [] + (reload-player player audio state)) + :component-will-unmount (fn [] + (destroy-player player))} + [react/view {:style {:margin-bottom 16}} + [button/button {:label (if (= (:general @state) :playing) + "stop" + "play") + :disabled? (or + (= (:general @state) :preparing) + (= (:general @state) :error)) + :theme :green + :on-press (if (= (:general @state) :playing) + #(stop-playing player state) + #(start-playing player state))}] + [react/text {:style {:typography :main-medium}} (:error-msg @state)]])) diff --git a/src/status_im/ui/screens/chat/message/message.cljs b/src/status_im/ui/screens/chat/message/message.cljs index 129f6acd18bc..1dfe47ec5aed 100644 --- a/src/status_im/ui/screens/chat/message/message.cljs +++ b/src/status_im/ui/screens/chat/message/message.cljs @@ -5,6 +5,7 @@ [status-im.ui.components.colors :as colors] [status-im.ui.components.icons.vector-icons :as vector-icons] [status-im.ui.components.react :as react] + [status-im.ui.screens.chat.message.audio :as message.audio] [status-im.ui.screens.chat.message.command :as message.command] [status-im.ui.screens.chat.photos :as photos] [status-im.ui.screens.chat.sheets :as sheets] @@ -298,6 +299,13 @@ {:content (sheets/sticker-long-press message) :height 64}])})) +(defn message-content-audio + [message] + [react/touchable-highlight (message.audio/message-press-handlers message) + [message-bubble-wrapper message + [message.audio/message-content message] + [message-timestamp message true]]]) + (defn chat-message [{:keys [public? content content-type] :as message}] (if (= content-type constants/content-type-command) [message.command/command-content message-content-wrapper message] @@ -322,4 +330,8 @@ (not public?)) [react/touchable-highlight (image-message-press-handlers message) [message-content-image message]] - [unknown-content-type message])))))]))) + (if (and (= content-type constants/content-type-audio) + ;; Disabling audio for public-chats + (not public?)) + [message-content-audio message] + [unknown-content-type message]))))))]))) diff --git a/src/status_im/ui/screens/chat/views.cljs b/src/status_im/ui/screens/chat/views.cljs index cf01c2abc475..7eee8f0d1b94 100644 --- a/src/status_im/ui/screens/chat/views.cljs +++ b/src/status_im/ui/screens/chat/views.cljs @@ -9,6 +9,7 @@ [status-im.ui.components.react :as react] [status-im.ui.screens.chat.sheets :as sheets] [status-im.ui.screens.chat.input.input :as input] + [status-im.ui.screens.chat.audio-message.views :as audio-message] [status-im.ui.screens.chat.message.message :as message] [status-im.ui.screens.chat.stickers.views :as stickers] [status-im.ui.screens.chat.styles.main :as style] @@ -181,6 +182,8 @@ [extensions/extensions-view] :images [image/image-view] + :audio-message + [audio-message/audio-message-view] [empty-bottom-sheet]))) (defview chat [] diff --git a/src/status_im/utils/fs.cljs b/src/status_im/utils/fs.cljs index ca7a3fdceb31..df2a951452d3 100644 --- a/src/status_im/utils/fs.cljs +++ b/src/status_im/utils/fs.cljs @@ -4,6 +4,11 @@ (defn move-file [src dst] (.moveFile react-native-fs src dst)) +(defn stat [path on-stat on-error] + (-> (.stat react-native-fs path) + (.then on-stat) + (.catch on-error))) + (defn read-file [path encoding on-read on-error] (-> (.readFile react-native-fs path encoding) (.then on-read) diff --git a/status-go-version.json b/status-go-version.json index 996566ac4530..e0c4044d7ed4 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -2,7 +2,7 @@ "_comment": "DO NOT EDIT THIS FILE BY HAND. USE 'scripts/update-status-go.sh ' instead", "owner": "status-im", "repo": "status-go", - "version": "v0.54.1", - "commit-sha1": "20f45a7c1caa25a30853480ac47177b534536f26", - "src-sha256": "1hsjsv00dlbjp4nqnifymldr8v20arzv07l9l27jarq9dk00wbia" + "version": "feature/audio-messages", + "commit-sha1": "f74f8f9d5264848e1a74322c8b86f5cdc8a69af2", + "src-sha256": "0k37ym6xj9xvyibcvyhhd6n9m9h2dcx5a1g12gbb3yf1b142dnbh" }