├── LICENSE.md ├── README.md ├── chat-sample ├── .buckconfig ├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── .vscode │ ├── launch.json │ └── settings.json ├── .watchmanconfig ├── Gemfile ├── Gemfile.lock ├── LICENSE.md ├── README.md ├── __tests__ │ └── App-test.js ├── _bundle │ └── config ├── _ruby-version ├── android │ ├── app │ │ ├── BUCK │ │ ├── build.gradle │ │ ├── build_defs.bzl │ │ ├── debug.keystore │ │ ├── google-services.json │ │ ├── proguard-rules.pro │ │ └── src │ │ │ ├── debug │ │ │ ├── AndroidManifest.xml │ │ │ └── java │ │ │ │ └── com │ │ │ │ └── quickblox │ │ │ │ └── sample │ │ │ │ └── reactnative │ │ │ │ └── chat │ │ │ │ └── ReactNativeFlipper.java │ │ │ └── main │ │ │ ├── AndroidManifest.xml │ │ │ ├── java │ │ │ └── com │ │ │ │ └── quickblox │ │ │ │ └── sample │ │ │ │ └── reactnative │ │ │ │ └── chat │ │ │ │ ├── MainActivity.java │ │ │ │ └── MainApplication.java │ │ │ └── res │ │ │ ├── drawable │ │ │ ├── logo.png │ │ │ ├── rn_edit_text_material.xml │ │ │ └── splash_layout.xml │ │ │ ├── mipmap-hdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_notification.png │ │ │ ├── mipmap-mdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_notification.png │ │ │ ├── mipmap-xhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_notification.png │ │ │ ├── mipmap-xxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_notification.png │ │ │ ├── mipmap-xxxhdpi │ │ │ ├── ic_launcher.png │ │ │ ├── ic_launcher_round.png │ │ │ └── ic_notification.png │ │ │ └── values │ │ │ ├── colors.xml │ │ │ ├── strings.xml │ │ │ └── styles.xml │ ├── build.gradle │ ├── gradle.properties │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── app.json ├── babel.config.js ├── images │ ├── add.png │ ├── add@2x.png │ ├── add@3x.png │ ├── add_user.png │ ├── add_user@2x.png │ ├── add_user@3x.png │ ├── attachment.png │ ├── attachment@2x.png │ ├── attachment@3x.png │ ├── check.png │ ├── check@2x.png │ ├── check@3x.png │ ├── check_double.png │ ├── check_double@2x.png │ ├── check_double@3x.png │ ├── exit.png │ ├── exit@2x.png │ ├── exit@3x.png │ ├── file.png │ ├── file@2x.png │ ├── file@3x.png │ ├── image.png │ ├── image@2x.png │ ├── image@3x.png │ ├── info.png │ ├── info@2x.png │ ├── info@3x.png │ ├── logo.png │ ├── logo@2x.png │ ├── logo@3x.png │ ├── more.png │ ├── more@2x.png │ ├── more@3x.png │ ├── play.png │ ├── play@2x.png │ ├── play@3x.png │ ├── search.png │ ├── search@2x.png │ ├── search@3x.png │ ├── send.png │ ├── send@2x.png │ ├── send@3x.png │ ├── shadow.png │ ├── splash_logo.png │ ├── video.png │ ├── video@2x.png │ └── video@3x.png ├── index.js ├── ios │ ├── .xcode.env │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── 100.png │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 144.png │ │ │ ├── 152.png │ │ │ ├── 167.png │ │ │ ├── 180.png │ │ │ ├── 20.png │ │ │ ├── 29.png │ │ │ ├── 40.png │ │ │ ├── 50.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 72.png │ │ │ ├── 76.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── qb-icon.imageset │ │ │ ├── Contents.json │ │ │ └── qb-icon.png │ ├── LaunchScreen.storyboard │ ├── Podfile │ ├── SampleReactNativeChat.xcodeproj │ │ ├── project.pbxproj │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── SampleReactNativeChat.xcscheme │ ├── SampleReactNativeChat.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── SampleReactNativeChat │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Info.plist │ │ ├── SampleReactNativeChat.entitlements │ │ └── main.m ├── metro.config.js ├── package.json └── src │ ├── App.js │ ├── Navigation.js │ ├── NotificationService.js │ ├── QBConfig.js │ ├── actionCreators │ ├── app.js │ ├── auth.js │ ├── chat.js │ ├── dialogs.js │ ├── file.js │ ├── index.js │ ├── info.js │ ├── messages.js │ ├── netinfo.js │ ├── pushNotifications.js │ └── users.js │ ├── components │ ├── AttachButton │ │ ├── index.android.js │ │ ├── index.ios.js │ │ └── styles.js │ ├── Auth │ │ ├── Login.js │ │ ├── handlers.js │ │ └── styles.js │ ├── ChatConnectionIndicator.js │ ├── Checkbox.js │ ├── Dialogs │ │ ├── AddOccupants.js │ │ ├── Create1.js │ │ ├── Create2.js │ │ ├── Dialog.js │ │ ├── Info.js │ │ ├── List.js │ │ ├── index.js │ │ ├── styles.js │ │ └── useDialogScreenOptions.js │ ├── FormTextInput.js │ ├── HeaderButton.js │ ├── ImageViewer.js │ ├── Info.js │ ├── Messages │ │ ├── DeliveredTo.js │ │ ├── ForwardTo.js │ │ ├── List │ │ │ ├── SectionHeaderRenderer.js │ │ │ ├── index.js │ │ │ └── useMessagesListProps.js │ │ ├── LongPressMenu.js │ │ ├── Message │ │ │ ├── Attachment.js │ │ │ ├── MessageBody.js │ │ │ ├── MessageMeta.js │ │ │ ├── Shadow.js │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── MessageInput.js │ │ ├── MoreMenu.js │ │ ├── ViewedBy.js │ │ ├── index.js │ │ └── styles.js │ ├── RemoteImage.js │ ├── RemoteVideo.js │ ├── SplashScreen.js │ ├── TypingIndicator.js │ ├── UploadIndicator.js │ ├── Users │ │ ├── Filter.js │ │ ├── List.js │ │ ├── User.js │ │ └── styles.js │ └── VideoPlayer.js │ ├── constants │ └── index.js │ ├── hooks │ └── index.js │ ├── images.js │ ├── index.js │ ├── reducers │ ├── app.js │ ├── auth.js │ ├── chat.js │ ├── content.js │ ├── dialogs.js │ ├── index.js │ ├── info.js │ ├── messages.js │ ├── pushNotifications.js │ └── users.js │ ├── sagas │ ├── QBevents.js │ ├── app.js │ ├── auth.js │ ├── chat.js │ ├── dialogs.js │ ├── file.js │ ├── index.js │ ├── info.js │ ├── messages.js │ ├── netinfo.js │ ├── pushNotifications.js │ └── users.js │ ├── selectors │ ├── auth.js │ ├── chat.js │ ├── content.js │ ├── dialogs.js │ ├── index.js │ ├── info.js │ ├── messages.js │ └── users.js │ ├── store │ └── index.js │ ├── theme.js │ └── utils │ └── utils.js └── webrtc-sample ├── .buckconfig ├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── LICENSE.md ├── README.md ├── __tests__ └── App-test.js ├── android ├── app │ ├── BUCK │ ├── build.gradle │ ├── build_defs.bzl │ ├── debug.keystore │ ├── google-services.json │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── quickblox │ │ │ └── sample │ │ │ └── reactnative │ │ │ └── webrtc │ │ │ └── ReactNativeFlipper.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── quickblox │ │ │ └── sample │ │ │ └── reactnative │ │ │ └── webrtc │ │ │ ├── MainActivity.java │ │ │ └── MainApplication.java │ │ └── res │ │ ├── drawable │ │ ├── logo.png │ │ └── splash_layout.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_notification.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_notification.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_notification.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_notification.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ └── ic_notification.png │ │ ├── raw │ │ ├── incallmanager_busytone.mp3 │ │ └── incallmanager_ringback.mp3 │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle ├── app.json ├── babel.config.js ├── images ├── accept.png ├── accept@2x.png ├── accept@3x.png ├── call.png ├── call@2x.png ├── call@3x.png ├── cam-off.png ├── cam-off@2x.png ├── cam-off@3x.png ├── check.png ├── check@2x.png ├── check@3x.png ├── close.png ├── close@2x.png ├── close@3x.png ├── decline.png ├── decline@2x.png ├── decline@3x.png ├── exit.png ├── exit@2x.png ├── exit@3x.png ├── info.png ├── info@2x.png ├── info@3x.png ├── logo.png ├── logo@2x.png ├── logo@3x.png ├── mic.png ├── mic@2x.png ├── mic@3x.png ├── search.png ├── search@2x.png ├── search@3x.png ├── shadow.png ├── speaker.png ├── speaker@2x.png ├── speaker@3x.png ├── splash_logo.png ├── switch-camera.png ├── switch-camera@2x.png ├── switch-camera@3x.png ├── video-accept.png ├── video-accept@2x.png ├── video-accept@3x.png ├── videocall.png ├── videocall@2x.png └── videocall@3x.png ├── index.js ├── ios ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ ├── 100.png │ │ ├── 1024.png │ │ ├── 114.png │ │ ├── 120.png │ │ ├── 144.png │ │ ├── 152.png │ │ ├── 167.png │ │ ├── 180.png │ │ ├── 20.png │ │ ├── 29.png │ │ ├── 40.png │ │ ├── 50.png │ │ ├── 57.png │ │ ├── 58.png │ │ ├── 60.png │ │ ├── 72.png │ │ ├── 76.png │ │ ├── 80.png │ │ ├── 87.png │ │ └── Contents.json │ ├── Contents.json │ └── qb-icon.imageset │ │ ├── Contents.json │ │ └── qb-icon.png ├── Podfile ├── WebRTCSample.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── IDEWorkspaceChecks.plist │ │ │ └── WorkspaceSettings.xcsettings │ └── xcshareddata │ │ └── xcschemes │ │ └── WebRTCSample.xcscheme ├── WebRTCSample.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── WebRTCSample │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── Info.plist │ ├── WebRTCSample.entitlements │ └── main.m ├── incallmanager_busytone.mp3 └── incallmanager_ringback.mp3 ├── metro.config.js ├── package.json └── src ├── App.js ├── Navigation.js ├── NotificationService ├── index.android.js └── index.ios.js ├── PermissionsService └── index.js ├── QBConfig.js ├── actionCreators ├── app.js ├── auth.js ├── chat.js ├── index.js ├── info.js ├── pushNotifications.js ├── subscription.js ├── users.js └── webrtc.js ├── components ├── Auth │ ├── Login.js │ ├── styles.js │ ├── submitHandler.js │ └── validation.js ├── CallScreen │ ├── CallScreen.js │ ├── CallScreenButtons.js │ ├── DialingScreen.js │ ├── OpponentCircle.js │ ├── OpponentsCircles.js │ ├── VideoViews.js │ ├── index.js │ ├── styles.js │ └── useCallScreen.js ├── CallScreenButton.js ├── Checkbox.js ├── FormTextInput.js ├── HeaderButton.js ├── Info.js ├── SplashScreen.js └── Users │ ├── Filter.js │ ├── List.js │ ├── SelectedList │ ├── EmptyComponent.js │ ├── Item.js │ ├── index.js │ └── styles.js │ ├── SelectedUsersAndCallButtons.js │ ├── User.js │ ├── index.js │ ├── styles.js │ └── useUsersScreen.js ├── constants └── index.js ├── hooks └── index.js ├── images.js ├── index.js ├── reducers ├── app.js ├── auth.js ├── chat.js ├── index.js ├── info.js ├── pushNotifications.js ├── subscriptions.js ├── users.js └── webrtc.js ├── sagas ├── CallKeepController.js ├── QBevents.js ├── app.js ├── auth.js ├── chat.js ├── index.js ├── info.js ├── pushNotifications.js ├── users.js └── webrtc.js ├── selectors ├── app.js ├── auth.js ├── chat.js ├── index.js ├── info.js ├── users.js └── webrtc.js ├── store └── index.js └── theme.js /LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, QuickBlox 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This repository contains react-native samples: 2 | 3 | [Chat sample](./chat-sample) 4 | [WebRTC sample](./webrtc-sample) 5 | 6 | See documentation at https://docs.quickblox.com/docs/react-native-quick-start 7 | -------------------------------------------------------------------------------- /chat-sample/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /chat-sample/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | # Windows files 15 | [*.bat] 16 | end_of_line = crlf 17 | -------------------------------------------------------------------------------- /chat-sample/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@react-native-community', 'eslint:recommended'], 3 | parser: '@babel/eslint-parser', 4 | root: true, 5 | rules: {}, 6 | }; 7 | -------------------------------------------------------------------------------- /chat-sample/.gitattributes: -------------------------------------------------------------------------------- 1 | # Windows files should use crlf line endings 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | *.bat text eol=crlf 4 | -------------------------------------------------------------------------------- /chat-sample/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | *~ 4 | .DS_Store 5 | 6 | # Xcode 7 | # 8 | build/ 9 | *.pbxuser 10 | !default.pbxuser 11 | *.mode1v3 12 | !default.mode1v3 13 | *.mode2v3 14 | !default.mode2v3 15 | *.perspectivev3 16 | !default.perspectivev3 17 | xcuserdata 18 | *.xccheckout 19 | *.moved-aside 20 | DerivedData 21 | *.hmap 22 | *.ipa 23 | *.xcuserstate 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | 34 | # node.js 35 | # 36 | node_modules/ 37 | npm-debug.log 38 | yarn-error.log 39 | 40 | # BUCK 41 | buck-out/ 42 | \.buckd/ 43 | *.keystore 44 | !debug.keystore 45 | 46 | # LOCK 47 | package-lock.json 48 | 49 | # fastlane 50 | # 51 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 52 | # screenshots whenever they are needed. 53 | # For more information about the recommended setup visit: 54 | # https://docs.fastlane.tools/best-practices/source-control/ 55 | 56 | */fastlane/report.xml 57 | */fastlane/Preview.html 58 | */fastlane/screenshots 59 | 60 | # Bundle artifact 61 | *.jsbundle 62 | 63 | # CocoaPods 64 | /ios/Pods/ 65 | /ios/Podfile.lock 66 | -------------------------------------------------------------------------------- /chat-sample/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | arrowParens: 'avoid', 7 | }; 8 | -------------------------------------------------------------------------------- /chat-sample/.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "name": "Debug iOS", 9 | "request": "launch", 10 | "type": "reactnative", 11 | "cwd": "${workspaceFolder}", 12 | "platform": "ios" 13 | }, 14 | { 15 | "type": "node", 16 | "request": "launch", 17 | "name": "Launch Program", 18 | "skipFiles": [ 19 | "/**" 20 | ], 21 | "program": "${workspaceFolder}/index.js" 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /chat-sample/.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "java.configuration.updateBuildConfiguration": "interactive" 3 | } -------------------------------------------------------------------------------- /chat-sample/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /chat-sample/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # You may use http://rbenv.org/ or https://rvm.io/ to install and use this version 4 | ruby '2.7.4' 5 | 6 | gem 'cocoapods', '~> 1.11', '>= 1.11.2' 7 | -------------------------------------------------------------------------------- /chat-sample/LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, QuickBlox 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /chat-sample/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /chat-sample/_bundle/config: -------------------------------------------------------------------------------- 1 | BUNDLE_PATH: "vendor/bundle" 2 | BUNDLE_FORCE_RUBY_PLATFORM: 1 3 | -------------------------------------------------------------------------------- /chat-sample/_ruby-version: -------------------------------------------------------------------------------- 1 | 2.7.4 2 | -------------------------------------------------------------------------------- /chat-sample/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.quickblox.sample.reactnative.chat", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.quickblox.sample.reactnative.chat", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /chat-sample/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /chat-sample/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/debug.keystore -------------------------------------------------------------------------------- /chat-sample/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -keep class com.facebook.hermes.unicode.** { *; } 12 | -keep class com.facebook.jni.** { *; } 13 | -------------------------------------------------------------------------------- /chat-sample/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/java/com/quickblox/sample/reactnative/chat/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.quickblox.sample.reactnative.chat; 2 | 3 | import android.os.Bundle; 4 | import com.facebook.react.ReactActivity; 5 | 6 | public class MainActivity extends ReactActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(null); 11 | } 12 | 13 | /** 14 | * Returns the name of the main component registered from JavaScript. 15 | * This is used to schedule rendering of the component. 16 | */ 17 | @Override 18 | protected String getMainComponentName() { 19 | return "SampleReactNativeChat"; 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/drawable/splash_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-hdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-hdpi/ic_notification.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-mdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-mdpi/ic_notification.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xhdpi/ic_notification.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xxhdpi/ic_notification.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_notification.png -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | #FFF 3 | #3978FC 4 | -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Chat 3 | 4 | -------------------------------------------------------------------------------- /chat-sample/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /chat-sample/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | googlePlayServicesVersion = "+" 6 | firebaseMessagingVersion = "21.1.0" 7 | 8 | buildToolsVersion = "33.0.0" 9 | minSdkVersion = 21 10 | compileSdkVersion = 33 11 | targetSdkVersion = 33 12 | ndkVersion = "23.1.7779620" 13 | } 14 | repositories { 15 | google() 16 | mavenCentral() 17 | } 18 | dependencies { 19 | classpath("com.android.tools.build:gradle") 20 | classpath 'com.google.gms:google-services:4.3.3' 21 | classpath("com.facebook.react:react-native-gradle-plugin") 22 | // NOTE: Do not place your application dependencies here; they belong 23 | // in the individual module build.gradle files 24 | } 25 | } -------------------------------------------------------------------------------- /chat-sample/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /chat-sample/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.1-all.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /chat-sample/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'SampleReactNativeChat' 2 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 3 | 4 | include ':react-native-device-info' 5 | project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android') 6 | 7 | include ':app' 8 | includeBuild('../node_modules/@react-native/gradle-plugin') 9 | -------------------------------------------------------------------------------- /chat-sample/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "SampleReactNativeChat", 3 | "displayName": "Quickblox Sample React Native Chat" 4 | } -------------------------------------------------------------------------------- /chat-sample/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /chat-sample/images/add.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/add.png -------------------------------------------------------------------------------- /chat-sample/images/add@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/add@2x.png -------------------------------------------------------------------------------- /chat-sample/images/add@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/add@3x.png -------------------------------------------------------------------------------- /chat-sample/images/add_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/add_user.png -------------------------------------------------------------------------------- /chat-sample/images/add_user@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/add_user@2x.png -------------------------------------------------------------------------------- /chat-sample/images/add_user@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/add_user@3x.png -------------------------------------------------------------------------------- /chat-sample/images/attachment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/attachment.png -------------------------------------------------------------------------------- /chat-sample/images/attachment@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/attachment@2x.png -------------------------------------------------------------------------------- /chat-sample/images/attachment@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/attachment@3x.png -------------------------------------------------------------------------------- /chat-sample/images/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/check.png -------------------------------------------------------------------------------- /chat-sample/images/check@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/check@2x.png -------------------------------------------------------------------------------- /chat-sample/images/check@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/check@3x.png -------------------------------------------------------------------------------- /chat-sample/images/check_double.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/check_double.png -------------------------------------------------------------------------------- /chat-sample/images/check_double@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/check_double@2x.png -------------------------------------------------------------------------------- /chat-sample/images/check_double@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/check_double@3x.png -------------------------------------------------------------------------------- /chat-sample/images/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/exit.png -------------------------------------------------------------------------------- /chat-sample/images/exit@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/exit@2x.png -------------------------------------------------------------------------------- /chat-sample/images/exit@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/exit@3x.png -------------------------------------------------------------------------------- /chat-sample/images/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/file.png -------------------------------------------------------------------------------- /chat-sample/images/file@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/file@2x.png -------------------------------------------------------------------------------- /chat-sample/images/file@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/file@3x.png -------------------------------------------------------------------------------- /chat-sample/images/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/image.png -------------------------------------------------------------------------------- /chat-sample/images/image@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/image@2x.png -------------------------------------------------------------------------------- /chat-sample/images/image@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/image@3x.png -------------------------------------------------------------------------------- /chat-sample/images/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/info.png -------------------------------------------------------------------------------- /chat-sample/images/info@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/info@2x.png -------------------------------------------------------------------------------- /chat-sample/images/info@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/info@3x.png -------------------------------------------------------------------------------- /chat-sample/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/logo.png -------------------------------------------------------------------------------- /chat-sample/images/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/logo@2x.png -------------------------------------------------------------------------------- /chat-sample/images/logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/logo@3x.png -------------------------------------------------------------------------------- /chat-sample/images/more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/more.png -------------------------------------------------------------------------------- /chat-sample/images/more@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/more@2x.png -------------------------------------------------------------------------------- /chat-sample/images/more@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/more@3x.png -------------------------------------------------------------------------------- /chat-sample/images/play.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/play.png -------------------------------------------------------------------------------- /chat-sample/images/play@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/play@2x.png -------------------------------------------------------------------------------- /chat-sample/images/play@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/play@3x.png -------------------------------------------------------------------------------- /chat-sample/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/search.png -------------------------------------------------------------------------------- /chat-sample/images/search@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/search@2x.png -------------------------------------------------------------------------------- /chat-sample/images/search@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/search@3x.png -------------------------------------------------------------------------------- /chat-sample/images/send.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/send.png -------------------------------------------------------------------------------- /chat-sample/images/send@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/send@2x.png -------------------------------------------------------------------------------- /chat-sample/images/send@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/send@3x.png -------------------------------------------------------------------------------- /chat-sample/images/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/shadow.png -------------------------------------------------------------------------------- /chat-sample/images/splash_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/splash_logo.png -------------------------------------------------------------------------------- /chat-sample/images/video.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/video.png -------------------------------------------------------------------------------- /chat-sample/images/video@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/video@2x.png -------------------------------------------------------------------------------- /chat-sample/images/video@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/images/video@3x.png -------------------------------------------------------------------------------- /chat-sample/index.js: -------------------------------------------------------------------------------- 1 | import {AppRegistry} from 'react-native'; 2 | import App from './src'; 3 | import {name as appName} from './app.json'; 4 | 5 | AppRegistry.registerComponent(appName, () => App); 6 | -------------------------------------------------------------------------------- /chat-sample/ios/.xcode.env: -------------------------------------------------------------------------------- 1 | # This `.xcode.env` file is versioned and is used to source the environment 2 | # used when running script phases inside Xcode. 3 | # To customize your local environment, you can create an `.xcode.env.local` 4 | # file that is not versioned. 5 | 6 | # NODE_BINARY variable contains the PATH to the node executable. 7 | # 8 | # Customize the NODE_BINARY variable here. 9 | # For example, to use nvm with brew, add the following line 10 | # . "$(brew --prefix nvm)/nvm.sh" --no-use 11 | export NODE_BINARY=$(command -v node) 12 | -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/qb-icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "qb-icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /chat-sample/ios/Assets.xcassets/qb-icon.imageset/qb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/chat-sample/ios/Assets.xcassets/qb-icon.imageset/qb-icon.png -------------------------------------------------------------------------------- /chat-sample/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, '16.0' 5 | 6 | target 'SampleReactNativeChat' do 7 | config = use_native_modules! 8 | inhibit_all_warnings! 9 | 10 | use_react_native!( 11 | :path => config[:reactNativePath], 12 | # to enable hermes on iOS, change `false` to `true` and then install pods 13 | :hermes_enabled => false 14 | ) 15 | 16 | permissions_path = '../node_modules/react-native-permissions/ios' 17 | 18 | pod 'Permission-Camera', :path => "#{permissions_path}/Camera" 19 | pod 'Permission-PhotoLibrary', :path => "#{permissions_path}/PhotoLibrary" 20 | 21 | # Enables Flipper. 22 | # 23 | # Note that if you have use_frameworks! enabled, Flipper will not work and 24 | # you should disable these next few lines. 25 | use_flipper! 26 | 27 | pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info' 28 | 29 | post_install do |installer| 30 | react_native_post_install(installer) 31 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /chat-sample/ios/SampleReactNativeChat.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /chat-sample/ios/SampleReactNativeChat.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /chat-sample/ios/SampleReactNativeChat/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | 5 | @interface AppDelegate : UIResponder 6 | 7 | @property (nonatomic, strong) UIWindow *window; 8 | 9 | @end 10 | -------------------------------------------------------------------------------- /chat-sample/ios/SampleReactNativeChat/SampleReactNativeChat.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /chat-sample/ios/SampleReactNativeChat/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /chat-sample/metro.config.js: -------------------------------------------------------------------------------- 1 | const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); 2 | 3 | /** 4 | * Metro configuration 5 | * https://facebook.github.io/metro/docs/configuration 6 | * 7 | * @type {import('metro-config').MetroConfig} 8 | */ 9 | 10 | const config = { 11 | resolver: { 12 | sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json'], 13 | }, 14 | transformer: { 15 | getTransformOptions: async () => ({ 16 | transform: { 17 | experimentalImportSupport: false, 18 | inlineRequires: true, 19 | }, 20 | }), 21 | }, 22 | }; 23 | 24 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); 25 | -------------------------------------------------------------------------------- /chat-sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-react-native-chat", 3 | "version": "1.1.1", 4 | "private": true, 5 | "license": "SEE LICENSE IN LICENSE.md", 6 | "scripts": { 7 | "android": "react-native run-android", 8 | "ios": "react-native run-ios", 9 | "lint": "eslint src --ext .js,.jsx", 10 | "lint:fix": "eslint src --ext .js,.jsx --fix", 11 | "start": "react-native start" 12 | }, 13 | "dependencies": { 14 | "@react-native-async-storage/async-storage": "^1.15.9", 15 | "@react-native-community/netinfo": "^9.3.7", 16 | "@react-native-community/push-notification-ios": "^1.11.0", 17 | "@react-native/metro-config": "^0.73.2", 18 | "@react-navigation/elements": "^1.3.21", 19 | "@react-navigation/native": "^6.1.9", 20 | "@react-navigation/stack": "^6.3.20", 21 | "final-form": "^4.20.10", 22 | "quickblox-react-native-sdk": "^0.9.8", 23 | "react": "18.2.0", 24 | "react-final-form": "^6.5.9", 25 | "react-native": "0.72.6", 26 | "react-native-device-info": "^10.11.0", 27 | "react-native-flash-message": "^0.4.2", 28 | "react-native-gesture-handler": "^2.13.4", 29 | "react-native-image-picker": "^7.0.2", 30 | "react-native-permissions": "^3.10.1", 31 | "react-native-push-notification": "^8.1.1", 32 | "react-native-safe-area-context": "^4.7.4", 33 | "react-native-screens": "^3.27.0", 34 | "react-native-svg": "^13.14.0", 35 | "react-native-video": "^5.2.1", 36 | "react-redux": "^8.1.3", 37 | "redux": "^4.2.1", 38 | "redux-logger": "^3.0.6", 39 | "redux-persist": "^6.0.0", 40 | "redux-saga": "^1.2.3", 41 | "reselect": "^4.1.8" 42 | }, 43 | "devDependencies": { 44 | "@babel/core": "^7.23.2", 45 | "@babel/eslint-parser": "^7.22.15", 46 | "@babel/runtime": "^7.12.5", 47 | "@react-native-community/eslint-config": "^2.0.0", 48 | "eslint": "^7.32.0", 49 | "metro-react-native-babel-preset": "^0.66.2" 50 | }, 51 | "jest": { 52 | "preset": "react-native" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /chat-sample/src/App.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {useDispatch, useSelector} from 'react-redux'; 3 | import {StatusBar, StyleSheet} from 'react-native'; 4 | import {SafeAreaProvider} from 'react-native-safe-area-context'; 5 | import FlashMessage from 'react-native-flash-message'; 6 | 7 | import Navigator from './Navigation'; 8 | import ChatConnectionIndicator from './components/ChatConnectionIndicator'; 9 | import { 10 | appStart, 11 | chatConnectAndSubscribe, 12 | createSubscriptions, 13 | } from './actionCreators'; 14 | import {colors} from './theme'; 15 | import config from './QBConfig'; 16 | 17 | const styles = StyleSheet.create({ 18 | navigatorView: { 19 | backgroundColor: colors.primary, 20 | flex: 1, 21 | width: '100%', 22 | }, 23 | }); 24 | 25 | export default function App() { 26 | const dispatch = useDispatch(); 27 | const {appReady, connected, connecting, loggedIn} = useSelector( 28 | ({app, auth, chat}) => ({ 29 | appReady: app.ready, 30 | connected: chat.connected, 31 | connecting: chat.loading, 32 | loggedIn: auth.loggedIn, 33 | }), 34 | ); 35 | 36 | React.useEffect(() => { 37 | dispatch(appStart(config)); 38 | // eslint-disable-next-line react-hooks/exhaustive-deps 39 | }, []); 40 | 41 | React.useEffect(() => { 42 | if (appReady && loggedIn) { 43 | dispatch(chatConnectAndSubscribe()); 44 | dispatch(createSubscriptions()); 45 | } 46 | }, [appReady, dispatch, loggedIn]); 47 | 48 | return ( 49 | 50 | 51 | 52 | {appReady && loggedIn ? ( 53 | 57 | ) : null} 58 | 59 | 60 | ); 61 | } 62 | -------------------------------------------------------------------------------- /chat-sample/src/QBConfig.js: -------------------------------------------------------------------------------- 1 | export default { 2 | accountKey: '', 3 | apiEndpoint: '', 4 | appId: '', 5 | authKey: '', 6 | authSecret: '', 7 | chatEndpoint: '', 8 | }; 9 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/app.js: -------------------------------------------------------------------------------- 1 | import { 2 | INIT_QB_REQUEST_FAIL, 3 | INIT_QB_REQUEST_SUCCESS, 4 | INIT_QB_REQUEST, 5 | } from '../constants'; 6 | 7 | export function appStart(config) { 8 | return {payload: config, type: INIT_QB_REQUEST}; 9 | } 10 | 11 | export function appStartSuccess() { 12 | return {type: INIT_QB_REQUEST_SUCCESS}; 13 | } 14 | 15 | export function appStartFail(error) { 16 | return {error, type: INIT_QB_REQUEST_FAIL}; 17 | } 18 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/auth.js: -------------------------------------------------------------------------------- 1 | import { 2 | AUTH_GET_SESSION_FAIL, 3 | AUTH_GET_SESSION_REQUEST, 4 | AUTH_GET_SESSION_SUCCESS, 5 | AUTH_LOGIN_FAIL, 6 | AUTH_LOGIN_REQUEST, 7 | AUTH_LOGIN_SUCCESS, 8 | AUTH_LOGOUT_FAIL, 9 | AUTH_LOGOUT_REQUEST, 10 | AUTH_LOGOUT_SUCCESS, 11 | } from '../constants'; 12 | 13 | export function sessionGet() { 14 | return {type: AUTH_GET_SESSION_REQUEST}; 15 | } 16 | 17 | export function sessionGetSuccess(session) { 18 | return {payload: session, type: AUTH_GET_SESSION_SUCCESS}; 19 | } 20 | 21 | export function sessionGetFail(error) { 22 | return {error, type: AUTH_GET_SESSION_FAIL}; 23 | } 24 | 25 | export function loginRequest(payload) { 26 | return {payload, type: AUTH_LOGIN_REQUEST}; 27 | } 28 | 29 | export function loginSuccess({session, user}) { 30 | return {payload: {session, user}, type: AUTH_LOGIN_SUCCESS}; 31 | } 32 | 33 | export function loginFail(error) { 34 | return {error, type: AUTH_LOGIN_FAIL}; 35 | } 36 | 37 | export function logoutRequest() { 38 | return {type: AUTH_LOGOUT_REQUEST}; 39 | } 40 | 41 | export function logoutSuccess() { 42 | return {type: AUTH_LOGOUT_SUCCESS}; 43 | } 44 | 45 | export function logoutFail(error) { 46 | return {error, type: AUTH_LOGOUT_FAIL}; 47 | } 48 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/chat.js: -------------------------------------------------------------------------------- 1 | import { 2 | CHAT_CONNECT_AND_SUBSCRIBE, 3 | CHAT_CONNECT_FAIL, 4 | CHAT_CONNECT_REQUEST, 5 | CHAT_CONNECT_SUCCESS, 6 | CHAT_DISCONNECT_FAIL, 7 | CHAT_DISCONNECT_REQUEST, 8 | CHAT_DISCONNECT_SUCCESS, 9 | CHAT_IS_CONNECTED_FAIL, 10 | CHAT_IS_CONNECTED_REQUEST, 11 | CHAT_IS_CONNECTED_SUCCESS, 12 | CHAT_RECONNECT_SUCCESS, 13 | } from '../constants'; 14 | 15 | export function chatIsConnected() { 16 | return {type: CHAT_IS_CONNECTED_REQUEST}; 17 | } 18 | 19 | export function chatIsConnectedSuccess(isConnected) { 20 | return {payload: isConnected, type: CHAT_IS_CONNECTED_SUCCESS}; 21 | } 22 | 23 | export function chatIsConnectedFail(error) { 24 | return {error, type: CHAT_IS_CONNECTED_FAIL}; 25 | } 26 | 27 | export function chatConnectAndSubscribe() { 28 | return {type: CHAT_CONNECT_AND_SUBSCRIBE}; 29 | } 30 | 31 | export function chatConnect({password, userId}) { 32 | return { 33 | payload: {password, userId}, 34 | type: CHAT_CONNECT_REQUEST, 35 | }; 36 | } 37 | 38 | export function chatConnectSuccess() { 39 | return {type: CHAT_CONNECT_SUCCESS}; 40 | } 41 | 42 | export function chatConnectFail(error) { 43 | return {error, type: CHAT_CONNECT_FAIL}; 44 | } 45 | 46 | export function chatDisconnect() { 47 | return {type: CHAT_DISCONNECT_REQUEST}; 48 | } 49 | 50 | export function chatDisconnectSuccess() { 51 | return {type: CHAT_DISCONNECT_SUCCESS}; 52 | } 53 | 54 | export function chatDisconnectFail(error) { 55 | return {error, type: CHAT_DISCONNECT_FAIL}; 56 | } 57 | 58 | export function chatReconnectSuccess() { 59 | return {type: CHAT_RECONNECT_SUCCESS}; 60 | } 61 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/file.js: -------------------------------------------------------------------------------- 1 | import { 2 | FILE_GET_INFO_FAIL, 3 | FILE_GET_INFO_REQUEST, 4 | FILE_GET_INFO_SUCCESS, 5 | FILE_PRIVATE_URL_FAIL, 6 | FILE_PRIVATE_URL_REQUEST, 7 | FILE_PRIVATE_URL_SUCCESS, 8 | FILE_PUBLIC_URL_FAIL, 9 | FILE_PUBLIC_URL_REQUEST, 10 | FILE_PUBLIC_URL_SUCCESS, 11 | FILE_UPLOAD_CANCEL, 12 | FILE_UPLOAD_FAIL, 13 | FILE_UPLOAD_REQUEST, 14 | FILE_UPLOAD_SUCCESS, 15 | } from '../constants'; 16 | 17 | export function fileGetInfo(id) { 18 | return {payload: id, type: FILE_GET_INFO_REQUEST}; 19 | } 20 | 21 | export function fileGetInfoSuccess(info) { 22 | return {payload: info, type: FILE_GET_INFO_SUCCESS}; 23 | } 24 | 25 | export function fileGetInfoFail(error) { 26 | return {error, type: FILE_GET_INFO_FAIL}; 27 | } 28 | 29 | export function fileUpload(payload) { 30 | return {payload, type: FILE_UPLOAD_REQUEST}; 31 | } 32 | 33 | export function fileUploadSucess(file) { 34 | return {payload: file, type: FILE_UPLOAD_SUCCESS}; 35 | } 36 | 37 | export function fileUploadFail(error) { 38 | return {error, type: FILE_UPLOAD_FAIL}; 39 | } 40 | 41 | export function fileUploadCancel() { 42 | return {type: FILE_UPLOAD_CANCEL}; 43 | } 44 | 45 | export function privateUrlGet(uid) { 46 | return {payload: uid, type: FILE_PRIVATE_URL_REQUEST}; 47 | } 48 | 49 | export function privateUrlGetSuccess(uid, url) { 50 | return {payload: {uid, url}, type: FILE_PRIVATE_URL_SUCCESS}; 51 | } 52 | 53 | export function privateUrlGetFail(error) { 54 | return {error, type: FILE_PRIVATE_URL_FAIL}; 55 | } 56 | 57 | export function publicUrlGet(uid) { 58 | return {payload: uid, type: FILE_PUBLIC_URL_REQUEST}; 59 | } 60 | 61 | export function publicUrlGetSuccess(uid, url) { 62 | return {payload: {uid, url}, type: FILE_PUBLIC_URL_SUCCESS}; 63 | } 64 | 65 | export function publicUrlGetFail(error) { 66 | return {error, type: FILE_PUBLIC_URL_FAIL}; 67 | } 68 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/index.js: -------------------------------------------------------------------------------- 1 | export * from './app'; 2 | export * from './auth'; 3 | export * from './chat'; 4 | export * from './dialogs'; 5 | export * from './file'; 6 | export * from './info'; 7 | export * from './messages'; 8 | export * from './netinfo'; 9 | export * from './pushNotifications'; 10 | export * from './users'; 11 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/info.js: -------------------------------------------------------------------------------- 1 | import {GET_INFO_FAIL, GET_INFO_REQUEST, GET_INFO_SUCCESS} from '../constants'; 2 | 3 | export function getInfo() { 4 | return {type: GET_INFO_REQUEST}; 5 | } 6 | 7 | export function getInfoSuccess(info) { 8 | return {payload: info, type: GET_INFO_SUCCESS}; 9 | } 10 | 11 | export function getInfoFail(error) { 12 | return {error, type: GET_INFO_FAIL}; 13 | } 14 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/netinfo.js: -------------------------------------------------------------------------------- 1 | import {NETWORK_STATE_CHANGED} from '../constants'; 2 | 3 | export function networkStateChanged(online) { 4 | return {payload: online, type: NETWORK_STATE_CHANGED}; 5 | } 6 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/pushNotifications.js: -------------------------------------------------------------------------------- 1 | import { 2 | CREATE_PUSH_SUBSCRIPTIONS, 3 | DEVICE_UDID_REMOVE, 4 | DEVICE_UDID_SET, 5 | PUSH_TOKEN_REMOVE, 6 | PUSH_TOKEN_SET, 7 | REMOVE_PUSH_SUBSCRIPTIONS, 8 | } from '../constants'; 9 | 10 | export function saveUdid(udid) { 11 | return {payload: udid, type: DEVICE_UDID_SET}; 12 | } 13 | 14 | export function removeUdid() { 15 | return {type: DEVICE_UDID_REMOVE}; 16 | } 17 | 18 | export function saveToken(token) { 19 | return {payload: token, type: PUSH_TOKEN_SET}; 20 | } 21 | 22 | export function removeToken() { 23 | return {type: PUSH_TOKEN_REMOVE}; 24 | } 25 | 26 | export function createSubscriptions() { 27 | return {type: CREATE_PUSH_SUBSCRIPTIONS}; 28 | } 29 | 30 | export function removePushSubscriptions(params) { 31 | return {payload: params, type: REMOVE_PUSH_SUBSCRIPTIONS}; 32 | } 33 | -------------------------------------------------------------------------------- /chat-sample/src/actionCreators/users.js: -------------------------------------------------------------------------------- 1 | import { 2 | USERS_BULK_SELECT, 3 | USERS_CREATE_FAIL, 4 | USERS_CREATE_REQUEST, 5 | USERS_CREATE_SUCCESS, 6 | USERS_GET_FAIL, 7 | USERS_GET_REQUEST, 8 | USERS_GET_SUCCESS, 9 | USERS_SELECT, 10 | USERS_SET_FILTER, 11 | USERS_SET_PAGE, 12 | USERS_UPDATE_FAIL, 13 | USERS_UPDATE_REQUEST, 14 | USERS_UPDATE_SUCCESS, 15 | } from '../constants'; 16 | 17 | export function usersCreate(data) { 18 | return {payload: data, type: USERS_CREATE_REQUEST}; 19 | } 20 | 21 | export function usersCreateSuccess(user) { 22 | return {payload: user, type: USERS_CREATE_SUCCESS}; 23 | } 24 | 25 | export function usersCreateFail(error) { 26 | return {error, type: USERS_CREATE_FAIL}; 27 | } 28 | 29 | export function usersGet(payload) { 30 | return {payload, type: USERS_GET_REQUEST}; 31 | } 32 | 33 | export function usersGetSuccess(data) { 34 | return {payload: data, type: USERS_GET_SUCCESS}; 35 | } 36 | 37 | export function usersGetFail(error) { 38 | return {error, type: USERS_GET_FAIL}; 39 | } 40 | 41 | export function usersUpdate(profile) { 42 | return {payload: profile, type: USERS_UPDATE_REQUEST}; 43 | } 44 | 45 | export function usersUpdateSuccess(user) { 46 | return {payload: user, type: USERS_UPDATE_SUCCESS}; 47 | } 48 | 49 | export function usersUpdateFail(error) { 50 | return {error, type: USERS_UPDATE_FAIL}; 51 | } 52 | 53 | export function usersSelect(userId) { 54 | return {payload: userId, type: USERS_SELECT}; 55 | } 56 | 57 | export function usersBulkSelect(userIds) { 58 | return {payload: userIds, type: USERS_BULK_SELECT}; 59 | } 60 | 61 | export function usersSetFilter(filter) { 62 | return {payload: filter, type: USERS_SET_FILTER}; 63 | } 64 | 65 | export function usersSetPage(page) { 66 | return {payload: page, type: USERS_SET_PAGE}; 67 | } 68 | -------------------------------------------------------------------------------- /chat-sample/src/components/AttachButton/styles.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | import {colors} from '../../theme'; 3 | 4 | export default StyleSheet.create({ 5 | attachButton: { 6 | tintColor: colors.primary, 7 | alignItems: 'center', 8 | justifyContent: 'center', 9 | padding: 6, 10 | }, 11 | attachButtonImage: { 12 | tintColor: colors.primary, 13 | height: 30, 14 | resizeMode: 'contain', 15 | width: 30, 16 | }, 17 | }); 18 | -------------------------------------------------------------------------------- /chat-sample/src/components/Auth/styles.js: -------------------------------------------------------------------------------- 1 | import {Platform, StyleSheet} from 'react-native'; 2 | 3 | import {colors} from '../../theme'; 4 | 5 | export default StyleSheet.create({ 6 | headerLeft: { 7 | flex: 1, 8 | width: 56, 9 | }, 10 | headerText: { 11 | color: colors.label, 12 | fontSize: 17, 13 | paddingVertical: 25, 14 | textAlign: 'center', 15 | }, 16 | headerTitle: { 17 | color: colors.white, 18 | fontSize: Platform.OS === 'ios' ? 17 : 20, 19 | fontWeight: 'bold', 20 | textAlign: 'center', 21 | width: '100%', 22 | }, 23 | headerView: { 24 | width: '50%', 25 | }, 26 | scrollView: { 27 | flex: 1, 28 | width: '100%', 29 | }, 30 | scrollViewContainer: { 31 | alignItems: 'center', 32 | }, 33 | submitBtn: { 34 | alignItems: 'center', 35 | backgroundColor: colors.primary, 36 | borderRadius: 4, 37 | justifyContent: 'center', 38 | paddingVertical: 12, 39 | shadowColor: colors.primary, 40 | shadowOffset: {height: 4, width: 0}, 41 | shadowOpacity: 1, 42 | shadowRadius: 4, 43 | width: '100%', 44 | }, 45 | submitBtnDisabled: { 46 | backgroundColor: colors.primaryDisabled, 47 | shadowOpacity: 0, 48 | }, 49 | submitBtnDisabledShadow: { 50 | opacity: 0, 51 | }, 52 | submitBtnShadow: { 53 | height: '190%', 54 | left: '-14%', 55 | position: 'absolute', 56 | resizeMode: 'stretch', 57 | top: '-20%', 58 | width: '120%', 59 | zIndex: -1, 60 | }, 61 | submitBtnText: { 62 | color: colors.white, 63 | fontSize: 17, 64 | fontWeight: '600', 65 | lineHeight: 20, 66 | }, 67 | submitError: { 68 | alignSelf: 'center', 69 | color: colors.error, 70 | }, 71 | submitView: { 72 | alignItems: 'center', 73 | justifyContent: 'center', 74 | marginBottom: 30, 75 | marginTop: 35, 76 | width: '60%', 77 | }, 78 | topView: { 79 | backgroundColor: colors.lightGray, 80 | flex: 1, 81 | width: '100%', 82 | }, 83 | }); 84 | -------------------------------------------------------------------------------- /chat-sample/src/components/Checkbox.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Image, StyleSheet, View} from 'react-native'; 3 | 4 | import {CHECKMARK} from '../images'; 5 | import {colors} from '../theme'; 6 | 7 | const styles = StyleSheet.create({ 8 | checkMark: { 9 | height: 14, 10 | resizeMode: 'center', 11 | tintColor: colors.white, 12 | width: 12, 13 | }, 14 | checkbox: { 15 | borderColor: colors.gray, 16 | borderRadius: 4, 17 | borderWidth: 1, 18 | height: 20, 19 | width: 20, 20 | }, 21 | checkboxChecked: { 22 | alignItems: 'center', 23 | backgroundColor: colors.primary, 24 | borderRadius: 4, 25 | height: 20, 26 | justifyContent: 'center', 27 | width: 20, 28 | }, 29 | }); 30 | 31 | export default React.memo(({checked = false}) => ( 32 | 33 | {checked ? : null} 34 | 35 | )); 36 | -------------------------------------------------------------------------------- /chat-sample/src/components/Dialogs/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {SafeAreaView} from 'react-native-safe-area-context'; 3 | 4 | import DialogsList from './List'; 5 | import useDialogScreenOptions from './useDialogScreenOptions'; 6 | import {styles} from '../../theme'; 7 | 8 | function DialogsScreen(props) { 9 | const {navigation} = props; 10 | const [deleteMode, setDeleteMode] = React.useState(false); 11 | 12 | const turnDeleteModeOn = () => { 13 | if (deleteMode) { 14 | return; 15 | } 16 | setDeleteMode(true); 17 | }; 18 | 19 | const turnDeleteModeOff = () => { 20 | if (!deleteMode) { 21 | return; 22 | } 23 | setDeleteMode(false); 24 | }; 25 | 26 | const navigationOptions = useDialogScreenOptions( 27 | deleteMode, 28 | turnDeleteModeOff, 29 | ); 30 | 31 | React.useLayoutEffect(() => { 32 | if (navigation && navigationOptions) { 33 | navigation.setOptions(navigationOptions); 34 | } 35 | }, [navigation, navigationOptions]); 36 | 37 | const goToDialog = dialog => 38 | navigation.navigate('Messages', {dialogId: dialog.id}); 39 | 40 | return ( 41 | 42 | 47 | 48 | ); 49 | } 50 | 51 | export default React.memo(DialogsScreen); 52 | -------------------------------------------------------------------------------- /chat-sample/src/components/FormTextInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | LayoutAnimation, 4 | Platform, 5 | StyleSheet, 6 | Text, 7 | TextInput, 8 | UIManager, 9 | } from 'react-native'; 10 | 11 | import {colors} from '../theme'; 12 | 13 | const styles = StyleSheet.create({ 14 | hint: { 15 | color: colors.primaryDisabled, 16 | fontSize: 13, 17 | lineHeight: 15, 18 | paddingVertical: 10, 19 | textAlign: 'center', 20 | }, 21 | }); 22 | 23 | if ( 24 | Platform.OS === 'android' && 25 | UIManager.setLayoutAnimationEnabledExperimental 26 | ) { 27 | UIManager.setLayoutAnimationEnabledExperimental(true); 28 | } 29 | 30 | export default function FormTextInput(props) { 31 | const {activeStyle, input, meta, style, ...rest} = props; 32 | const {inputRef, ...inputProps} = rest; 33 | 34 | React.useEffect(() => { 35 | LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); 36 | }, [meta]); 37 | 38 | return ( 39 | 40 | 49 | {(meta.touched || meta.active) && meta.error ? ( 50 | {meta.error} 51 | ) : null} 52 | 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /chat-sample/src/components/HeaderButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Image, Pressable, StyleSheet} from 'react-native'; 3 | 4 | import {colors} from '../theme'; 5 | 6 | const styles = StyleSheet.create({ 7 | button: { 8 | alignItems: 'center', 9 | backgroundColor: colors.transparent, 10 | height: '100%', 11 | justifyContent: 'center', 12 | paddingHorizontal: 10, 13 | }, 14 | image: { 15 | height: 28, 16 | width: 28, 17 | }, 18 | }); 19 | 20 | export default ({onPress, imageSource}) => ( 21 | 22 | 23 | 24 | ); 25 | -------------------------------------------------------------------------------- /chat-sample/src/components/ImageViewer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | Image, 4 | SafeAreaView, 5 | StatusBar, 6 | StyleSheet, 7 | Text, 8 | View, 9 | } from 'react-native'; 10 | import {HeaderBackButton} from '@react-navigation/elements'; 11 | import {useSafeAreaInsets} from 'react-native-safe-area-context'; 12 | 13 | import {colors} from '../theme'; 14 | 15 | const styles = StyleSheet.create({ 16 | absoluteFill: StyleSheet.absoluteFill, 17 | backButtonView: { 18 | alignItems: 'center', 19 | height: 45, 20 | justifyContent: 'center', 21 | left: 10, 22 | position: 'absolute', 23 | width: 45, 24 | zIndex: 1, 25 | }, 26 | image: { 27 | height: '100%', 28 | width: '100%', 29 | }, 30 | safeArea: { 31 | backgroundColor: colors.black, 32 | flex: 1, 33 | width: '100%', 34 | }, 35 | }); 36 | 37 | export default function ImageViewer({navigation, route}) { 38 | const [error, setError] = React.useState(''); 39 | const insets = useSafeAreaInsets(); 40 | 41 | const onLoadFail = e => { 42 | setError(e.nativeEvent.error); 43 | }; 44 | 45 | return ( 46 | 47 | 63 | ); 64 | } 65 | -------------------------------------------------------------------------------- /chat-sample/src/components/Messages/List/SectionHeaderRenderer.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Text, View} from 'react-native'; 3 | 4 | import styles from '../styles'; 5 | 6 | /** 7 | * @param {Date} date 8 | * @returns {string} 9 | */ 10 | const getDateString = date => { 11 | const now = new Date(); 12 | if (date.getFullYear() === now.getFullYear()) { 13 | if (date.getMonth() === now.getMonth()) { 14 | if (date.getDate() === now.getDate()) { 15 | return 'Today'; 16 | } 17 | if (date.getDate() === now.getDate() - 1) { 18 | return 'Yesterday'; 19 | } 20 | } 21 | return date 22 | .toDateString() 23 | .replace(/(^\w+\s)|(\s\d+$)/g, '') 24 | .split(' ') 25 | .reverse() 26 | .join(' ') 27 | .replace(/^0/, ''); 28 | } else { 29 | const [month, day, year] = date 30 | .toDateString() 31 | .replace(/(^\w+\s)/, '') 32 | .split(' '); 33 | return [day, month, year].join(' '); 34 | } 35 | }; 36 | 37 | export default function SectionHeaderRenderer(props) { 38 | const {section} = props; 39 | return ( 40 | 41 | 42 | 43 | {getDateString(section.title)} 44 | 45 | 46 | 47 | ); 48 | } 49 | -------------------------------------------------------------------------------- /chat-sample/src/components/Messages/Message/Attachment.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Image, Pressable, Linking} from 'react-native'; 3 | 4 | import RemoteImage from '../../RemoteImage'; 5 | import RemoteVideo from '../../RemoteVideo'; 6 | import {FILE} from '../../../images'; 7 | import styles from './styles'; 8 | 9 | function Attachment({attachmentType, attachmentUrl, onLongPress}) { 10 | const downloadAttachment = React.useCallback(() => { 11 | if (attachmentUrl) { 12 | Linking.openURL(attachmentUrl.url); 13 | } 14 | }, [attachmentUrl]); 15 | 16 | if (attachmentType === 'image') { 17 | return ( 18 | 25 | ); 26 | } else if (attachmentType === 'video') { 27 | return ( 28 | 35 | ); 36 | } else if (attachmentType === 'file') { 37 | return ( 38 | 39 | 40 | 41 | ); 42 | } 43 | } 44 | 45 | export default React.memo(Attachment); 46 | -------------------------------------------------------------------------------- /chat-sample/src/components/Messages/Message/Shadow.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Image, Platform} from 'react-native'; 3 | 4 | import {SHADOW} from '../../../images'; 5 | import styles from './styles'; 6 | 7 | export default Platform.select({ 8 | android: () => ( 9 | 10 | ), 11 | ios: () => null, 12 | }); 13 | -------------------------------------------------------------------------------- /chat-sample/src/components/SplashScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | ActivityIndicator, 4 | Image, 5 | SafeAreaView, 6 | StyleSheet, 7 | Text, 8 | View, 9 | } from 'react-native'; 10 | 11 | import {SPLASH_LOGO} from '../images'; 12 | import {colors} from '../theme'; 13 | 14 | const styles = StyleSheet.create({ 15 | centerView: { 16 | ...StyleSheet.absoluteFillObject, 17 | alignItems: 'center', 18 | justifyContent: 'center', 19 | }, 20 | image: { 21 | height: 100, 22 | width: 100, 23 | }, 24 | message: { 25 | color: colors.white, 26 | textAlign: 'center', 27 | }, 28 | safeArea: { 29 | alignItems: 'center', 30 | backgroundColor: colors.primary, 31 | flex: 1, 32 | justifyContent: 'flex-end', 33 | paddingBottom: 15, 34 | width: '100%', 35 | }, 36 | text: { 37 | color: colors.white, 38 | fontSize: 18, 39 | marginTop: 50, 40 | }, 41 | }); 42 | 43 | export default ({message}) => ( 44 | 45 | 46 | 47 | 48 | 49 | {message ? {message} : null} 50 | 55 | React Native Chat Sample 56 | 57 | 58 | ); 59 | -------------------------------------------------------------------------------- /chat-sample/src/components/UploadIndicator.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {View} from 'react-native'; 3 | import {Svg, Circle, Text} from 'react-native-svg'; 4 | 5 | import {colors} from '../theme'; 6 | 7 | export default props => { 8 | const { 9 | borderWidth = 2, 10 | color = colors.primary, 11 | percent, 12 | radius = 15, 13 | showText = false, 14 | style = {}, 15 | textColor = colors.white, 16 | } = props; 17 | const c = 2 * Math.PI * (radius - borderWidth); 18 | const percentage = percent < 0 ? 0 : percent > 100 ? 100 : percent; 19 | const dashOffset = ((100 - percentage) / 100) * c; 20 | return ( 21 | 22 | 23 | 31 | 42 | {showText ? ( 43 | 49 | {percentage}% 50 | 51 | ) : null} 52 | 53 | 54 | ); 55 | }; 56 | -------------------------------------------------------------------------------- /chat-sample/src/components/Users/User.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Pressable, Text, View} from 'react-native'; 3 | 4 | import Checkbox from '../Checkbox'; 5 | import {colors} from '../../theme'; 6 | import styles from './styles'; 7 | import {generateColor} from '../../utils/utils'; 8 | 9 | function User(props) { 10 | const {isSelected, onSelect, selectable = false, user} = props; 11 | 12 | const onUserSelect = () => onSelect && onSelect(user); 13 | 14 | const username = user ? user.fullName || user.login || user.email : ''; 15 | const btnStyle = isSelected 16 | ? [styles.userBtn, styles.userBtnSelected] 17 | : styles.userBtn; 18 | 19 | let circleBackground = colors.primaryDisabled; 20 | if (user && user.color) { 21 | circleBackground = user.color; 22 | } else if (user && user.id) { 23 | circleBackground = generateColor(user.id.toString()); 24 | } 25 | 26 | const circleText = username 27 | .split(' ') 28 | .filter((str, i) => (i < 2 ? str : undefined)) 29 | .reduce((res, val) => res + val.trim().charAt(0).toUpperCase(), ''); 30 | return ( 31 | 36 | 37 | 38 | {circleText} 39 | 40 | 41 | 42 | {username} 43 | 44 | {selectable ? : null} 45 | 46 | ); 47 | } 48 | 49 | export default React.memo(User); 50 | -------------------------------------------------------------------------------- /chat-sample/src/hooks/index.js: -------------------------------------------------------------------------------- 1 | import {useEffect, useMemo, useState} from 'react'; 2 | import {bindActionCreators} from 'redux'; 3 | import {useDispatch} from 'react-redux'; 4 | 5 | export function useActions(actions, deps) { 6 | const dispatch = useDispatch(); 7 | return useMemo( 8 | () => { 9 | if (Array.isArray(actions)) { 10 | return actions.map(a => bindActionCreators(a, dispatch)); 11 | } 12 | return bindActionCreators(actions, dispatch); 13 | }, 14 | // eslint-disable-next-line react-hooks/exhaustive-deps 15 | deps ? [dispatch, ...deps] : [dispatch], 16 | ); 17 | } 18 | 19 | export function useDebounce(value, delay) { 20 | const [debouncedValue, setDebouncedValue] = useState(value); 21 | 22 | useEffect(() => { 23 | const handler = setTimeout(() => { 24 | setDebouncedValue(value); 25 | }, delay); 26 | return () => clearTimeout(handler); 27 | }, [delay, value]); 28 | 29 | return debouncedValue; 30 | } 31 | -------------------------------------------------------------------------------- /chat-sample/src/images.js: -------------------------------------------------------------------------------- 1 | export const ADD = require('sample-react-native-chat/images/add.png'); 2 | export const ADD_USER = require('sample-react-native-chat/images/add_user.png'); 3 | export const ATTACHMENT = require('sample-react-native-chat/images/attachment.png'); 4 | export const CHECKMARK = require('sample-react-native-chat/images/check.png'); 5 | export const CHECKMARK_DOUBLE = require('sample-react-native-chat/images/check_double.png'); 6 | export const EXIT = require('sample-react-native-chat/images/exit.png'); 7 | export const FILE = require('sample-react-native-chat/images/file.png'); 8 | export const IMAGE = require('sample-react-native-chat/images/image.png'); 9 | export const INFO = require('sample-react-native-chat/images/info.png'); 10 | export const LOGO = require('sample-react-native-chat/images/logo.png'); 11 | export const MORE = require('sample-react-native-chat/images/more.png'); 12 | export const PLAY = require('sample-react-native-chat/images/play.png'); 13 | export const SEARCH = require('sample-react-native-chat/images/search.png'); 14 | export const SEND = require('sample-react-native-chat/images/send.png'); 15 | export const SHADOW = require('sample-react-native-chat/images/shadow.png'); 16 | export const SPLASH_LOGO = require('sample-react-native-chat/images/splash_logo.png'); 17 | export const VIDEO = require('sample-react-native-chat/images/video.png'); 18 | 19 | export default { 20 | ADD, 21 | ADD_USER, 22 | ATTACHMENT, 23 | CHECKMARK, 24 | CHECKMARK_DOUBLE, 25 | EXIT, 26 | FILE, 27 | IMAGE, 28 | INFO, 29 | LOGO, 30 | MORE, 31 | PLAY, 32 | SEARCH, 33 | SEND, 34 | SHADOW, 35 | SPLASH_LOGO, 36 | VIDEO, 37 | }; 38 | -------------------------------------------------------------------------------- /chat-sample/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Provider} from 'react-redux'; 3 | import {PersistGate} from 'redux-persist/integration/react'; 4 | import {enableScreens} from 'react-native-screens'; 5 | import {GestureHandlerRootView} from 'react-native-gesture-handler'; 6 | 7 | import App from './App'; 8 | import SplashScreen from './components/SplashScreen'; 9 | import {setupPushNotifications} from './NotificationService'; 10 | import configureStore from './store'; 11 | import rootSaga from './sagas'; 12 | 13 | const {runSaga, store, persistor} = configureStore(); 14 | runSaga(rootSaga); 15 | enableScreens(false); 16 | setupPushNotifications(); 17 | 18 | export default function Root() { 19 | return ( 20 | 21 | 22 | } persistor={persistor}> 23 | 24 | 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /chat-sample/src/reducers/app.js: -------------------------------------------------------------------------------- 1 | import { 2 | INIT_QB_REQUEST_FAIL, 3 | INIT_QB_REQUEST_SUCCESS, 4 | NETWORK_STATE_CHANGED, 5 | } from '../constants'; 6 | 7 | const initialState = { 8 | connected: false, 9 | ready: undefined, 10 | }; 11 | 12 | export default (state = initialState, action) => { 13 | switch (action.type) { 14 | case INIT_QB_REQUEST_SUCCESS: { 15 | return {...state, ready: true}; 16 | } 17 | case INIT_QB_REQUEST_FAIL: { 18 | return {...state, ready: false}; 19 | } 20 | case NETWORK_STATE_CHANGED: 21 | return {...state, connected: action.payload}; 22 | default: 23 | return state; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /chat-sample/src/reducers/auth.js: -------------------------------------------------------------------------------- 1 | import { 2 | AUTH_LOGIN_FAIL, 3 | AUTH_LOGIN_REQUEST, 4 | AUTH_LOGIN_SUCCESS, 5 | AUTH_LOGOUT_FAIL, 6 | AUTH_LOGOUT_REQUEST, 7 | AUTH_LOGOUT_SUCCESS, 8 | AUTH_SET_LOGIN, 9 | AUTH_SET_PASSWORD, 10 | USERS_UPDATE_REQUEST, 11 | USERS_UPDATE_FAIL, 12 | USERS_UPDATE_SUCCESS, 13 | } from '../constants'; 14 | 15 | const initialState = { 16 | error: undefined, 17 | loading: false, 18 | loggedIn: false, 19 | login: '', 20 | password: '', 21 | session: undefined, 22 | user: undefined, 23 | }; 24 | 25 | export default (state = initialState, action) => { 26 | switch (action.type) { 27 | case AUTH_SET_LOGIN: 28 | return {...state, login: action.payload}; 29 | case AUTH_SET_PASSWORD: 30 | return {...state, password: action.payload}; 31 | case AUTH_LOGIN_REQUEST: 32 | case AUTH_LOGOUT_REQUEST: 33 | case USERS_UPDATE_REQUEST: 34 | return {...state, error: undefined, loading: true}; 35 | case AUTH_LOGIN_SUCCESS: 36 | return { 37 | ...state, 38 | loading: false, 39 | loggedIn: true, 40 | login: initialState.login, 41 | password: initialState.password, 42 | session: action.payload.session, 43 | user: action.payload.user, 44 | }; 45 | case USERS_UPDATE_SUCCESS: 46 | return { 47 | ...state, 48 | loading: false, 49 | user: {...state.user, ...action.payload}, 50 | }; 51 | case AUTH_LOGIN_FAIL: 52 | case USERS_UPDATE_FAIL: 53 | return {...state, error: action.error, loading: false}; 54 | case AUTH_LOGOUT_FAIL: 55 | case AUTH_LOGOUT_SUCCESS: 56 | return initialState; 57 | default: 58 | return state; 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /chat-sample/src/reducers/chat.js: -------------------------------------------------------------------------------- 1 | import QB from 'quickblox-react-native-sdk'; 2 | 3 | import { 4 | AUTH_LOGOUT_SUCCESS, 5 | CHAT_CONNECT_FAIL, 6 | CHAT_CONNECT_REQUEST, 7 | CHAT_CONNECT_SUCCESS, 8 | CHAT_DISCONNECT_FAIL, 9 | CHAT_DISCONNECT_REQUEST, 10 | CHAT_DISCONNECT_SUCCESS, 11 | CHAT_IS_CONNECTED_SUCCESS, 12 | CHAT_RECONNECT_SUCCESS, 13 | } from '../constants'; 14 | 15 | const initialState = { 16 | connected: false, 17 | error: undefined, 18 | loading: false, 19 | }; 20 | 21 | export default (state = initialState, action) => { 22 | switch (action.type) { 23 | case CHAT_IS_CONNECTED_SUCCESS: 24 | return {...state, connected: action.payload, loading: false}; 25 | case CHAT_CONNECT_REQUEST: 26 | case CHAT_DISCONNECT_REQUEST: 27 | return {...state, error: undefined, loading: true}; 28 | case CHAT_CONNECT_SUCCESS: 29 | case QB.chat.EVENT_TYPE.CONNECTED: 30 | case CHAT_RECONNECT_SUCCESS: 31 | return {...state, connected: true, loading: false}; 32 | case CHAT_CONNECT_FAIL: 33 | case CHAT_DISCONNECT_FAIL: 34 | return {...state, error: action.error, loading: false}; 35 | case CHAT_DISCONNECT_SUCCESS: 36 | case QB.chat.EVENT_TYPE.CONNECTION_CLOSED: 37 | case QB.chat.EVENT_TYPE.RECONNECTION_FAILED: 38 | case AUTH_LOGOUT_SUCCESS: 39 | return initialState; 40 | default: 41 | return state; 42 | } 43 | }; 44 | -------------------------------------------------------------------------------- /chat-sample/src/reducers/content.js: -------------------------------------------------------------------------------- 1 | import QB from 'quickblox-react-native-sdk'; 2 | import { 3 | AUTH_LOGOUT_SUCCESS, 4 | FILE_PRIVATE_URL_SUCCESS, 5 | FILE_PUBLIC_URL_SUCCESS, 6 | FILE_UPLOAD_CANCEL, 7 | FILE_UPLOAD_FAIL, 8 | FILE_UPLOAD_REQUEST, 9 | FILE_UPLOAD_SUCCESS, 10 | } from '../constants'; 11 | 12 | const initialState = { 13 | uploadProgress: 0, 14 | uploading: false, 15 | }; 16 | 17 | export default (state = initialState, action) => { 18 | switch (action.type) { 19 | case FILE_PRIVATE_URL_SUCCESS: 20 | case FILE_PUBLIC_URL_SUCCESS: 21 | return { 22 | ...state, 23 | [action.payload.uid]: { 24 | obtained: Date.now(), 25 | url: action.payload.url, 26 | }, 27 | }; 28 | case FILE_UPLOAD_REQUEST: 29 | return {...state, uploading: true}; 30 | case FILE_UPLOAD_CANCEL: 31 | case FILE_UPLOAD_FAIL: 32 | case FILE_UPLOAD_SUCCESS: 33 | return {...state, ...initialState}; 34 | case QB.content.EVENT_TYPE.FILE_UPLOAD_PROGRESS: 35 | return {...state, uploadProgress: action.payload.progress}; 36 | case AUTH_LOGOUT_SUCCESS: 37 | return initialState; 38 | default: 39 | return state; 40 | } 41 | }; 42 | -------------------------------------------------------------------------------- /chat-sample/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import {combineReducers} from 'redux'; 2 | 3 | import app from './app'; 4 | import auth from './auth'; 5 | import chat from './chat'; 6 | import content from './content'; 7 | import dialogs from './dialogs'; 8 | import info from './info'; 9 | import messages from './messages'; 10 | import pushNotifications from './pushNotifications'; 11 | import users from './users'; 12 | 13 | export default combineReducers({ 14 | app, 15 | auth, 16 | chat, 17 | content, 18 | dialogs, 19 | info, 20 | messages, 21 | pushNotifications, 22 | users, 23 | }); 24 | -------------------------------------------------------------------------------- /chat-sample/src/reducers/info.js: -------------------------------------------------------------------------------- 1 | import {GET_INFO_FAIL, GET_INFO_REQUEST, GET_INFO_SUCCESS} from '../constants'; 2 | 3 | const initialState = { 4 | accountKey: '', 5 | apiEndpoint: '', 6 | appId: '', 7 | authKey: '', 8 | authSecret: '', 9 | chatEndpoint: '', 10 | error: '', 11 | loading: false, 12 | sdkVersion: '', 13 | }; 14 | 15 | export default (state = initialState, action) => { 16 | switch (action.type) { 17 | case GET_INFO_REQUEST: 18 | return {...state, error: '', loading: true}; 19 | case GET_INFO_SUCCESS: 20 | return {...state, ...action.payload, loading: false}; 21 | case GET_INFO_FAIL: 22 | return {...state, error: action.error, loading: false}; 23 | default: 24 | return state; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /chat-sample/src/reducers/pushNotifications.js: -------------------------------------------------------------------------------- 1 | import { 2 | DEVICE_UDID_SET, 3 | DEVICE_UDID_REMOVE, 4 | PUSH_TOKEN_SET, 5 | PUSH_TOKEN_REMOVE, 6 | } from '../constants'; 7 | 8 | const initialState = { 9 | token: undefined, 10 | udid: undefined, 11 | }; 12 | 13 | export default (state = initialState, action) => { 14 | switch (action.type) { 15 | case DEVICE_UDID_SET: 16 | return {...state, udid: action.payload}; 17 | case PUSH_TOKEN_SET: 18 | return {...state, token: action.payload}; 19 | case DEVICE_UDID_REMOVE: 20 | return {...state, udid: initialState.udid}; 21 | case PUSH_TOKEN_REMOVE: 22 | return {...state, token: initialState.token}; 23 | default: 24 | return state; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /chat-sample/src/sagas/auth.js: -------------------------------------------------------------------------------- 1 | import {call, put, takeLatest} from 'redux-saga/effects'; 2 | import QB from 'quickblox-react-native-sdk'; 3 | 4 | import { 5 | loginFail, 6 | loginSuccess, 7 | logoutFail, 8 | logoutSuccess, 9 | sessionGetFail, 10 | sessionGetSuccess, 11 | } from '../actionCreators'; 12 | import { 13 | AUTH_LOGIN_REQUEST, 14 | AUTH_LOGOUT_REQUEST, 15 | AUTH_GET_SESSION_REQUEST, 16 | } from '../constants'; 17 | import {showError} from '../NotificationService'; 18 | 19 | export function* loginSaga(action = {}) { 20 | const {login, password = 'quickblox', resolve, reject} = action.payload; 21 | try { 22 | const {session, user} = yield call(QB.auth.login, {login, password}); 23 | const result = loginSuccess({session, user: {...user, password}}); 24 | yield put(result); 25 | if (resolve) { 26 | resolve(result); 27 | } 28 | } catch (e) { 29 | const result = loginFail(e.message); 30 | yield put(result); 31 | if (reject) { 32 | reject(result); 33 | } 34 | } 35 | } 36 | 37 | export function* logout() { 38 | try { 39 | yield call(QB.auth.logout); 40 | yield put(logoutSuccess()); 41 | } catch (e) { 42 | yield put(logoutFail(e.message)); 43 | showError(e.message); 44 | } 45 | } 46 | 47 | export function* getSession() { 48 | try { 49 | const session = yield call(QB.auth.getSession); 50 | yield put(sessionGetSuccess(session)); 51 | return session; 52 | } catch (e) { 53 | yield put(sessionGetFail(e.message)); 54 | } 55 | } 56 | 57 | export default [ 58 | takeLatest(AUTH_LOGIN_REQUEST, loginSaga), 59 | takeLatest(AUTH_LOGOUT_REQUEST, logout), 60 | takeLatest(AUTH_GET_SESSION_REQUEST, getSession), 61 | ]; 62 | -------------------------------------------------------------------------------- /chat-sample/src/sagas/chat.js: -------------------------------------------------------------------------------- 1 | import { 2 | call, 3 | put, 4 | race, 5 | take, 6 | takeLatest, 7 | takeLeading, 8 | } from 'redux-saga/effects'; 9 | import QB from 'quickblox-react-native-sdk'; 10 | 11 | import { 12 | chatConnectFail, 13 | chatConnectSuccess, 14 | chatDisconnectFail, 15 | chatDisconnectSuccess, 16 | chatIsConnectedFail, 17 | chatIsConnectedSuccess, 18 | } from '../actionCreators'; 19 | import {showError} from '../NotificationService'; 20 | import { 21 | AUTH_LOGOUT_REQUEST, 22 | CHAT_CONNECT_AND_SUBSCRIBE, 23 | CHAT_CONNECT_REQUEST, 24 | CHAT_DISCONNECT_REQUEST, 25 | CHAT_IS_CONNECTED_REQUEST, 26 | } from '../constants'; 27 | 28 | export function* isChatConnected() { 29 | try { 30 | const isConnected = yield call(QB.chat.isConnected); 31 | yield put(chatIsConnectedSuccess(isConnected)); 32 | return isConnected; 33 | } catch (e) { 34 | yield put(chatIsConnectedFail(e.message)); 35 | } 36 | } 37 | 38 | export function* chatConnect(action = {}) { 39 | const {userId, password} = action.payload; 40 | try { 41 | yield call(QB.chat.connect, {password, userId}); 42 | yield put(chatConnectSuccess()); 43 | } catch (e) { 44 | showError('Failed to connect to chat', e.message); 45 | yield put(chatConnectFail(e.message)); 46 | } 47 | } 48 | 49 | export function* chatDisconnect() { 50 | try { 51 | const {connect} = yield race({ 52 | connect: take(CHAT_CONNECT_AND_SUBSCRIBE), 53 | disconnect: call(QB.chat.disconnect), 54 | }); 55 | if (!connect) { 56 | yield put(chatDisconnectSuccess()); 57 | } 58 | } catch (e) { 59 | showError('Failed to disconnect from chat', e.message); 60 | yield put(chatDisconnectFail(e.message)); 61 | } 62 | } 63 | 64 | export default [ 65 | takeLatest(CHAT_IS_CONNECTED_REQUEST, isChatConnected), 66 | takeLeading(CHAT_CONNECT_REQUEST, chatConnect), 67 | takeLatest([AUTH_LOGOUT_REQUEST, CHAT_DISCONNECT_REQUEST], chatDisconnect), 68 | ]; 69 | -------------------------------------------------------------------------------- /chat-sample/src/sagas/index.js: -------------------------------------------------------------------------------- 1 | import {all} from 'redux-saga/effects'; 2 | 3 | import appSagas from './app'; 4 | import authSagas from './auth'; 5 | import chatSagas from './chat'; 6 | import dialogsSagas from './dialogs'; 7 | import fileSagas from './file'; 8 | import infoSagas from './info'; 9 | import messagesSagas from './messages'; 10 | import netInfoSagas from './netinfo'; 11 | import pushNotificationsSagas from './pushNotifications'; 12 | import usersSagas from './users'; 13 | import QBeventsSagas from './QBevents'; 14 | 15 | export default function* rootSaga() { 16 | yield all([ 17 | ...appSagas, 18 | ...authSagas, 19 | ...chatSagas, 20 | ...dialogsSagas, 21 | ...fileSagas, 22 | ...infoSagas, 23 | ...messagesSagas, 24 | ...netInfoSagas, 25 | ...pushNotificationsSagas, 26 | ...usersSagas, 27 | ...QBeventsSagas, 28 | ]); 29 | } 30 | -------------------------------------------------------------------------------- /chat-sample/src/sagas/info.js: -------------------------------------------------------------------------------- 1 | import {call, put, takeLatest} from 'redux-saga/effects'; 2 | import QB from 'quickblox-react-native-sdk'; 3 | 4 | import {getInfoFail, getInfoSuccess} from '../actionCreators'; 5 | import {GET_INFO_REQUEST} from '../constants'; 6 | 7 | export function* getSdkInfo() { 8 | try { 9 | const settings = yield call(QB.settings.get); 10 | yield put(getInfoSuccess(settings)); 11 | } catch (e) { 12 | yield put(getInfoFail(e.message)); 13 | } 14 | } 15 | 16 | export default [takeLatest(GET_INFO_REQUEST, getSdkInfo)]; 17 | -------------------------------------------------------------------------------- /chat-sample/src/sagas/netinfo.js: -------------------------------------------------------------------------------- 1 | import {eventChannel} from 'redux-saga'; 2 | import {call, put, select, spawn, take} from 'redux-saga/effects'; 3 | import NetInfo from '@react-native-community/netinfo'; 4 | 5 | import {chatConnectAndSubscribe, networkStateChanged} from '../actionCreators'; 6 | 7 | function createNetInfoChannel() { 8 | return eventChannel(NetInfo.addEventListener); 9 | } 10 | 11 | export function* startNetInfoListener() { 12 | try { 13 | const netInfoChannel = yield call(createNetInfoChannel); 14 | while (true) { 15 | const state = yield take(netInfoChannel); 16 | yield put(networkStateChanged(state.isConnected)); 17 | const isConnected = yield select(({app}) => app.connected); 18 | if (state.isConnected && state.isConnected !== isConnected) { 19 | yield put(chatConnectAndSubscribe()); 20 | } 21 | } 22 | } catch (e) { 23 | yield put({error: e.message, type: 'ERROR'}); 24 | } 25 | } 26 | 27 | export default [spawn(startNetInfoListener)]; 28 | -------------------------------------------------------------------------------- /chat-sample/src/selectors/auth.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const authSelector = state => state.auth; 4 | 5 | export const authUserSelector = createSelector(authSelector, auth => auth.user); 6 | 7 | export const authLoadingSelector = createSelector( 8 | authSelector, 9 | auth => auth.loading, 10 | ); 11 | -------------------------------------------------------------------------------- /chat-sample/src/selectors/chat.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const chatSelector = state => state.chat; 4 | 5 | export const chatConnectedSelector = createSelector( 6 | chatSelector, 7 | chat => chat.connected, 8 | ); 9 | 10 | export const chatErrorSelector = createSelector( 11 | chatSelector, 12 | chat => chat.error, 13 | ); 14 | 15 | export const chatLoadingSelector = createSelector( 16 | chatSelector, 17 | chat => chat.loading, 18 | ); 19 | -------------------------------------------------------------------------------- /chat-sample/src/selectors/content.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const contentSelector = state => state.content; 4 | 5 | export const contentUploadProgressSelector = createSelector( 6 | contentSelector, 7 | state => state.uploadProgress, 8 | ); 9 | 10 | export const contentIsUploadingSelector = createSelector( 11 | contentSelector, 12 | state => state.uploading, 13 | ); 14 | 15 | export const contentFileUrlForMessageOwnPropsSelector = createSelector( 16 | contentSelector, 17 | (_, props) => 18 | props.message && Array.isArray(props.message.attachments) 19 | ? props.message.attachments[0] 20 | : undefined, 21 | (state, attachment) => (attachment ? state[attachment.id] : undefined), 22 | ); 23 | -------------------------------------------------------------------------------- /chat-sample/src/selectors/dialogs.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const dialogsSelector = state => state.dialogs; 4 | 5 | export const dialogsItemsSelector = createSelector( 6 | dialogsSelector, 7 | dialogs => dialogs.dialogs, 8 | ); 9 | 10 | export const dialogsLimitSelector = createSelector( 11 | dialogsSelector, 12 | dialogs => dialogs.limit, 13 | ); 14 | 15 | export const dialogsLoadingSelector = createSelector( 16 | dialogsSelector, 17 | dialogs => dialogs.loading, 18 | ); 19 | 20 | export const dialogsSelectedSelector = createSelector( 21 | dialogsSelector, 22 | dialogs => dialogs.selected, 23 | ); 24 | 25 | export const dialogsSkipSelector = createSelector( 26 | dialogsSelector, 27 | dialogs => dialogs.skip, 28 | ); 29 | 30 | export const dialogsTotalSelector = createSelector( 31 | dialogsSelector, 32 | dialogs => dialogs.total, 33 | ); 34 | 35 | export const dialogsTypingSelector = createSelector( 36 | dialogsSelector, 37 | dialogs => dialogs.dialogTyping, 38 | ); 39 | 40 | export const dialogByIdRouteParamSelector = createSelector( 41 | dialogsItemsSelector, 42 | (_, props) => 43 | props.route && props.route.params ? props.route.params.dialogId : undefined, 44 | (dialogs, dialogId) => 45 | dialogId ? dialogs.find(dialog => dialog.id === dialogId) : undefined, 46 | ); 47 | 48 | export const dialogByIdOwnPropsSelector = createSelector( 49 | dialogsItemsSelector, 50 | (_, props) => (props ? props.dialogId : undefined), 51 | (dialogs, dialogId) => 52 | dialogId ? dialogs.find(dialog => dialog.id === dialogId) : undefined, 53 | ); 54 | 55 | export const dialogFromItemOwnPropSelector = createSelector( 56 | dialogsItemsSelector, 57 | (_, props) => (props.item ? props.item.dialogId : undefined), 58 | (dialogs, dialogId) => 59 | dialogId ? dialogs.find(({id}) => id === dialogId) : undefined, 60 | ); 61 | -------------------------------------------------------------------------------- /chat-sample/src/selectors/index.js: -------------------------------------------------------------------------------- 1 | export * from './auth'; 2 | export * from './chat'; 3 | export * from './content'; 4 | export * from './dialogs'; 5 | export * from './info'; 6 | export * from './messages'; 7 | export * from './users'; 8 | -------------------------------------------------------------------------------- /chat-sample/src/selectors/info.js: -------------------------------------------------------------------------------- 1 | export const infoSelector = state => state.info; 2 | -------------------------------------------------------------------------------- /chat-sample/src/selectors/messages.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const messagesSelector = state => state.messages; 4 | 5 | const messagesItemsSelectors = createSelector( 6 | messagesSelector, 7 | state => state.messages, 8 | ); 9 | 10 | export const messagesLoadingSelector = createSelector( 11 | messagesSelector, 12 | state => state.loading, 13 | ); 14 | 15 | export const messagesSendingSelector = createSelector( 16 | messagesSelector, 17 | state => state.sending, 18 | ); 19 | 20 | export const messagesByIdSelector = createSelector( 21 | messagesItemsSelectors, 22 | messages => messages.byId, 23 | ); 24 | 25 | export const messagesItemsByDialogIdSelector = createSelector( 26 | messagesItemsSelectors, 27 | (_, props) => props.dialogId, 28 | (messages, dialogId) => 29 | messages.byDialogId[dialogId] 30 | ? Object.values(messages.byDialogId[dialogId]).filter( 31 | v => typeof v === 'object', 32 | ) 33 | : [], 34 | ); 35 | 36 | export const messagesHasMoreByDialogIdSelector = createSelector( 37 | messagesItemsSelectors, 38 | (_, props) => props.dialogId, 39 | (messages, dialogId) => 40 | messages.byDialogId[dialogId] 41 | ? messages.byDialogId[dialogId].hasMore 42 | : false, 43 | ); 44 | 45 | export const messageByIdRouteParamSelector = createSelector( 46 | messagesByIdSelector, 47 | (_, props) => 48 | props.route && props.route.params && props.route.params.messageId 49 | ? props.route.params.messageId 50 | : undefined, 51 | (byId, messageId) => byId[messageId], 52 | ); 53 | -------------------------------------------------------------------------------- /chat-sample/src/selectors/users.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const usersSelector = state => state.users; 4 | 5 | export const usersItemsSelector = createSelector( 6 | usersSelector, 7 | users => users.users, 8 | ); 9 | 10 | export const usersFilterSelector = createSelector( 11 | usersSelector, 12 | users => users.filter, 13 | ); 14 | 15 | export const usersLoadingSelector = createSelector( 16 | usersSelector, 17 | users => users.loading, 18 | ); 19 | 20 | export const usersSelectedSelector = createSelector( 21 | usersSelector, 22 | users => users.selected, 23 | ); 24 | 25 | export const usersPageSelector = createSelector( 26 | usersSelector, 27 | users => users.page, 28 | ); 29 | 30 | export const usersPerPageSelector = createSelector( 31 | usersSelector, 32 | users => users.perPage, 33 | ); 34 | 35 | export const usersTotalSelector = createSelector( 36 | usersSelector, 37 | users => users.total, 38 | ); 39 | -------------------------------------------------------------------------------- /chat-sample/src/store/index.js: -------------------------------------------------------------------------------- 1 | import {applyMiddleware, compose, createStore} from 'redux'; 2 | import {persistStore, persistReducer} from 'redux-persist'; 3 | import storage from '@react-native-async-storage/async-storage'; 4 | import createSagaMiddleware from 'redux-saga'; 5 | import {createLogger} from 'redux-logger'; 6 | 7 | import rootReducer from '../reducers'; 8 | import * as actionCreators from '../actionCreators'; 9 | 10 | const sagaMiddleware = createSagaMiddleware(); 11 | const middlewares = [sagaMiddleware]; 12 | if (__DEV__) { 13 | const stateTransformer = state => state; 14 | // uncomment to return only part of the store 15 | /* const stateTransformer = state => ({ 16 | app: state.app, 17 | auth: state.auth, 18 | chat: state.chat, 19 | device: state.device, 20 | }); */ 21 | middlewares.push(createLogger({stateTransformer})); 22 | } 23 | 24 | const persistConfig = { 25 | key: 'root', 26 | storage, 27 | whitelist: ['auth', 'device'], 28 | }; 29 | 30 | const persistedReducer = persistReducer(persistConfig, rootReducer); 31 | let store; 32 | 33 | export default function configureStore(preloadedState) { 34 | const composeEnhancers = 35 | typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ 36 | ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({actionCreators}) 37 | : compose; 38 | 39 | const enhancer = composeEnhancers(applyMiddleware(...middlewares)); 40 | 41 | store = createStore(persistedReducer, preloadedState, enhancer); 42 | const persistor = persistStore(store); 43 | return { 44 | persistor, 45 | runSaga: sagaMiddleware.run, 46 | store, 47 | }; 48 | } 49 | 50 | export {store}; 51 | -------------------------------------------------------------------------------- /chat-sample/src/utils/utils.js: -------------------------------------------------------------------------------- 1 | export const generateColor = str => { 2 | const color = str => { 3 | let hash = 0; 4 | for (var i = 0; i < str.length; i++) { 5 | hash = str.charCodeAt(i) + ((hash << 5) - hash); 6 | } 7 | return hash; 8 | }; 9 | return `hsl(${color(str) % 360}, 100%, 50%)`; 10 | }; 11 | 12 | export const differenceBetweenSets = (setA, setB) => { 13 | return new Set([...setA].filter(element => !setB.has(element))); 14 | }; 15 | -------------------------------------------------------------------------------- /webrtc-sample/.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /webrtc-sample/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | 14 | # Windows files 15 | [*.bat] 16 | end_of_line = crlf 17 | -------------------------------------------------------------------------------- /webrtc-sample/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@react-native-community', 'eslint:recommended'], 3 | root: true, 4 | }; 5 | -------------------------------------------------------------------------------- /webrtc-sample/.gitattributes: -------------------------------------------------------------------------------- 1 | # Windows files should use crlf line endings 2 | # https://help.github.com/articles/dealing-with-line-endings/ 3 | *.bat text eol=crlf 4 | -------------------------------------------------------------------------------- /webrtc-sample/.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | *~ 4 | .DS_Store 5 | 6 | # Xcode 7 | # 8 | build/ 9 | *.pbxuser 10 | !default.pbxuser 11 | *.mode1v3 12 | !default.mode1v3 13 | *.mode2v3 14 | !default.mode2v3 15 | *.perspectivev3 16 | !default.perspectivev3 17 | xcuserdata 18 | *.xccheckout 19 | *.moved-aside 20 | DerivedData 21 | *.hmap 22 | *.ipa 23 | *.xcuserstate 24 | 25 | # Android/IntelliJ 26 | # 27 | build/ 28 | .idea 29 | .gradle 30 | local.properties 31 | *.iml 32 | *.hprof 33 | 34 | # node.js 35 | # 36 | node_modules/ 37 | npm-debug.log 38 | yarn-error.log 39 | 40 | # BUCK 41 | buck-out/ 42 | \.buckd/ 43 | *.keystore 44 | !debug.keystore 45 | 46 | # LOCK 47 | package-lock.json 48 | 49 | # fastlane 50 | # 51 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 52 | # screenshots whenever they are needed. 53 | # For more information about the recommended setup visit: 54 | # https://docs.fastlane.tools/best-practices/source-control/ 55 | 56 | */fastlane/report.xml 57 | */fastlane/Preview.html 58 | */fastlane/screenshots 59 | 60 | # Bundle artifact 61 | *.jsbundle 62 | 63 | # CocoaPods 64 | /ios/Pods/ 65 | /ios/Podfile.lock 66 | -------------------------------------------------------------------------------- /webrtc-sample/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | arrowParens: 'avoid', 7 | }; 8 | -------------------------------------------------------------------------------- /webrtc-sample/.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /webrtc-sample/LICENSE.md: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2019, QuickBlox 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /webrtc-sample/__tests__/App-test.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | 5 | import 'react-native'; 6 | import React from 'react'; 7 | import App from '../App'; 8 | 9 | // Note: test renderer must be required after react-native. 10 | import renderer from 'react-test-renderer'; 11 | 12 | it('renders correctly', () => { 13 | renderer.create(); 14 | }); 15 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/BUCK: -------------------------------------------------------------------------------- 1 | # To learn about Buck see [Docs](https://buckbuild.com/). 2 | # To run your application with Buck: 3 | # - install Buck 4 | # - `npm start` - to start the packager 5 | # - `cd android` 6 | # - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"` 7 | # - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck 8 | # - `buck install -r android/app` - compile, install and run application 9 | # 10 | 11 | load(":build_defs.bzl", "create_aar_targets", "create_jar_targets") 12 | 13 | lib_deps = [] 14 | 15 | create_aar_targets(glob(["libs/*.aar"])) 16 | 17 | create_jar_targets(glob(["libs/*.jar"])) 18 | 19 | android_library( 20 | name = "all-libs", 21 | exported_deps = lib_deps, 22 | ) 23 | 24 | android_library( 25 | name = "app-code", 26 | srcs = glob([ 27 | "src/main/java/**/*.java", 28 | ]), 29 | deps = [ 30 | ":all-libs", 31 | ":build_config", 32 | ":res", 33 | ], 34 | ) 35 | 36 | android_build_config( 37 | name = "build_config", 38 | package = "com.quickblox.sample.reactnative.webrtc", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.quickblox.sample.reactnative.webrtc", 44 | res = "src/main/res", 45 | ) 46 | 47 | android_binary( 48 | name = "app", 49 | keystore = "//android/keystores:debug", 50 | manifest = "src/main/AndroidManifest.xml", 51 | package_type = "debug", 52 | deps = [ 53 | ":app-code", 54 | ], 55 | ) 56 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/build_defs.bzl: -------------------------------------------------------------------------------- 1 | """Helper definitions to glob .aar and .jar targets""" 2 | 3 | def create_aar_targets(aarfiles): 4 | for aarfile in aarfiles: 5 | name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")] 6 | lib_deps.append(":" + name) 7 | android_prebuilt_aar( 8 | name = name, 9 | aar = aarfile, 10 | ) 11 | 12 | def create_jar_targets(jarfiles): 13 | for jarfile in jarfiles: 14 | name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")] 15 | lib_deps.append(":" + name) 16 | prebuilt_jar( 17 | name = name, 18 | binary_jar = jarfile, 19 | ) 20 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/debug.keystore -------------------------------------------------------------------------------- /webrtc-sample/android/app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /usr/local/Cellar/android-sdk/24.3.3/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | -keep class com.facebook.hermes.unicode.** { *; } 12 | -keep class com.facebook.jni.** { *; } 13 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/java/com/quickblox/sample/reactnative/webrtc/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.quickblox.sample.reactnative.webrtc; 2 | 3 | import com.facebook.react.ReactActivity; 4 | import com.facebook.react.ReactActivityDelegate; 5 | import com.facebook.react.ReactRootView; 6 | import android.os.Bundle; 7 | import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; 8 | 9 | public class MainActivity extends ReactActivity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(null); 14 | } 15 | 16 | /** 17 | * Returns the name of the main component registered from JavaScript. 18 | * This is used to schedule rendering of the component. 19 | */ 20 | @Override 21 | protected String getMainComponentName() { 22 | return "WebRTCSample"; 23 | } 24 | 25 | @Override 26 | protected ReactActivityDelegate createReactActivityDelegate() { 27 | return new ReactActivityDelegate(this, getMainComponentName()) { 28 | @Override 29 | protected ReactRootView createRootView() { 30 | return new RNGestureHandlerEnabledRootView(MainActivity.this); 31 | } 32 | }; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/drawable/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/drawable/logo.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/drawable/splash_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-hdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-hdpi/ic_notification.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-mdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-mdpi/ic_notification.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xhdpi/ic_notification.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xxhdpi/ic_notification.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/mipmap-xxxhdpi/ic_notification.png -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/raw/incallmanager_busytone.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/raw/incallmanager_busytone.mp3 -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/raw/incallmanager_ringback.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/app/src/main/res/raw/incallmanager_ringback.mp3 -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | #FFF 3 | #0165FF 4 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | WebRTC sample 3 | 4 | -------------------------------------------------------------------------------- /webrtc-sample/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /webrtc-sample/android/build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | ext { 5 | googlePlayServicesVersion = "+" 6 | firebaseMessagingVersion = "21.1.0" 7 | 8 | buildToolsVersion = "32.0.0" 9 | minSdkVersion = 21 10 | compileSdkVersion = 32 11 | targetSdkVersion = 32 12 | ndkVersion = "21.4.7075529" 13 | } 14 | repositories { 15 | google() 16 | mavenCentral() 17 | } 18 | dependencies { 19 | classpath("com.android.tools.build:gradle:4.2.2") 20 | classpath("com.facebook.react:react-native-gradle-plugin") 21 | classpath 'com.google.gms:google-services:4.3.14' 22 | // NOTE: Do not place your application dependencies here; they belong 23 | // in the individual module build.gradle files 24 | } 25 | } 26 | 27 | allprojects { 28 | repositories { 29 | mavenLocal() 30 | maven { 31 | // Android JSC is installed from npm 32 | url("$rootDir/../node_modules/jsc-android/dist") 33 | } 34 | mavenCentral { 35 | // We don't want to fetch react-native from Maven Central as there are 36 | // older versions over there. 37 | content { 38 | excludeGroup "com.facebook.react" 39 | } 40 | } 41 | google() 42 | maven { url 'https://www.jitpack.io' } 43 | jcenter() { 44 | content { 45 | includeModule("com.yqritc", "android-scalablevideoview") 46 | } 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /webrtc-sample/android/gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | org.gradle.jvmargs=-XX:+IgnoreUnrecognizedVMOptions -Xmx4096m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true 19 | 20 | android.useAndroidX=true 21 | android.enableJetifier=true 22 | 23 | # Version of flipper SDK to use with React Native 24 | FLIPPER_VERSION=0.99.0 25 | 26 | hermesEnabled=false 27 | -------------------------------------------------------------------------------- /webrtc-sample/android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /webrtc-sample/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /webrtc-sample/android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'WebRTCSample' 2 | 3 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 4 | 5 | include ':app' 6 | 7 | includeBuild('../node_modules/@react-native/gradle-plugin') 8 | 9 | if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") { 10 | include(":ReactAndroid") 11 | project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid') 12 | } 13 | -------------------------------------------------------------------------------- /webrtc-sample/app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "WebRTCSample", 3 | "displayName": "Quickblox WebRTC Sample" 4 | } -------------------------------------------------------------------------------- /webrtc-sample/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | }; 4 | -------------------------------------------------------------------------------- /webrtc-sample/images/accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/accept.png -------------------------------------------------------------------------------- /webrtc-sample/images/accept@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/accept@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/accept@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/accept@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/call.png -------------------------------------------------------------------------------- /webrtc-sample/images/call@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/call@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/call@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/call@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/cam-off.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/cam-off.png -------------------------------------------------------------------------------- /webrtc-sample/images/cam-off@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/cam-off@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/cam-off@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/cam-off@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/check.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/check.png -------------------------------------------------------------------------------- /webrtc-sample/images/check@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/check@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/check@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/check@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/close.png -------------------------------------------------------------------------------- /webrtc-sample/images/close@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/close@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/close@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/close@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/decline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/decline.png -------------------------------------------------------------------------------- /webrtc-sample/images/decline@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/decline@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/decline@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/decline@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/exit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/exit.png -------------------------------------------------------------------------------- /webrtc-sample/images/exit@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/exit@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/exit@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/exit@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/info.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/info.png -------------------------------------------------------------------------------- /webrtc-sample/images/info@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/info@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/info@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/info@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/logo.png -------------------------------------------------------------------------------- /webrtc-sample/images/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/logo@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/logo@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/mic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/mic.png -------------------------------------------------------------------------------- /webrtc-sample/images/mic@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/mic@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/mic@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/mic@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/search.png -------------------------------------------------------------------------------- /webrtc-sample/images/search@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/search@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/search@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/search@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/shadow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/shadow.png -------------------------------------------------------------------------------- /webrtc-sample/images/speaker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/speaker.png -------------------------------------------------------------------------------- /webrtc-sample/images/speaker@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/speaker@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/speaker@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/speaker@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/splash_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/splash_logo.png -------------------------------------------------------------------------------- /webrtc-sample/images/switch-camera.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/switch-camera.png -------------------------------------------------------------------------------- /webrtc-sample/images/switch-camera@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/switch-camera@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/switch-camera@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/switch-camera@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/video-accept.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/video-accept.png -------------------------------------------------------------------------------- /webrtc-sample/images/video-accept@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/video-accept@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/video-accept@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/video-accept@3x.png -------------------------------------------------------------------------------- /webrtc-sample/images/videocall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/videocall.png -------------------------------------------------------------------------------- /webrtc-sample/images/videocall@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/videocall@2x.png -------------------------------------------------------------------------------- /webrtc-sample/images/videocall@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/images/videocall@3x.png -------------------------------------------------------------------------------- /webrtc-sample/index.js: -------------------------------------------------------------------------------- 1 | import { AppRegistry } from 'react-native'; 2 | import App from './src'; 3 | import { name as appName } from './app.json'; 4 | 5 | AppRegistry.registerComponent(appName, () => App); 6 | -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/100.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/144.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/152.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/152.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/167.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/20.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/50.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/72.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/76.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/qb-icon.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "qb-icon.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /webrtc-sample/ios/Assets.xcassets/qb-icon.imageset/qb-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/Assets.xcassets/qb-icon.imageset/qb-icon.png -------------------------------------------------------------------------------- /webrtc-sample/ios/Podfile: -------------------------------------------------------------------------------- 1 | require_relative '../node_modules/react-native/scripts/react_native_pods' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | platform :ios, '14.0' 5 | 6 | target 'WebRTCSample' do 7 | config = use_native_modules! 8 | inhibit_all_warnings! 9 | 10 | use_react_native!( 11 | :path => config[:reactNativePath], 12 | # to enable hermes on iOS, change `false` to `true` and then install pods 13 | :hermes_enabled => false 14 | ) 15 | 16 | permissions_path = '../node_modules/react-native-permissions/ios' 17 | 18 | pod 'Permission-Camera', :path => "#{permissions_path}/Camera" 19 | pod 'Permission-Notifications', :path => "#{permissions_path}/Notifications" 20 | pod 'Permission-Microphone', :path => "#{permissions_path}/Microphone" 21 | 22 | # Enables Flipper. 23 | # 24 | # Note that if you have use_frameworks! enabled, Flipper will not work and 25 | # you should disable these next few lines. 26 | use_flipper!() 27 | post_install do |installer| 28 | react_native_post_install(installer) 29 | __apply_Xcode_12_5_M1_post_install_workaround(installer) 30 | end 31 | 32 | end 33 | -------------------------------------------------------------------------------- /webrtc-sample/ios/WebRTCSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /webrtc-sample/ios/WebRTCSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /webrtc-sample/ios/WebRTCSample.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /webrtc-sample/ios/WebRTCSample.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /webrtc-sample/ios/WebRTCSample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /webrtc-sample/ios/WebRTCSample/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /webrtc-sample/ios/WebRTCSample/WebRTCSample.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | 8 | 9 | -------------------------------------------------------------------------------- /webrtc-sample/ios/WebRTCSample/main.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | #import "AppDelegate.h" 4 | 5 | int main(int argc, char * argv[]) { 6 | @autoreleasepool { 7 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /webrtc-sample/ios/incallmanager_busytone.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/incallmanager_busytone.mp3 -------------------------------------------------------------------------------- /webrtc-sample/ios/incallmanager_ringback.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/QuickBlox/quickblox-react-native-samples/4eb1bbea967d4199784692d3517a6f4bb43670d3/webrtc-sample/ios/incallmanager_ringback.mp3 -------------------------------------------------------------------------------- /webrtc-sample/metro.config.js: -------------------------------------------------------------------------------- 1 | const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config'); 2 | 3 | /** 4 | * Metro configuration 5 | * https://facebook.github.io/metro/docs/configuration 6 | * 7 | * @type {import('metro-config').MetroConfig} 8 | */ 9 | 10 | const config = { 11 | resolver: { 12 | sourceExts: ['js', 'jsx', 'ts', 'tsx', 'json'], 13 | }, 14 | transformer: { 15 | getTransformOptions: async () => ({ 16 | transform: { 17 | experimentalImportSupport: false, 18 | inlineRequires: true, 19 | }, 20 | }), 21 | }, 22 | }; 23 | 24 | module.exports = mergeConfig(getDefaultConfig(__dirname), config); -------------------------------------------------------------------------------- /webrtc-sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sample-react-native-webrtc", 3 | "version": "1.1.1", 4 | "private": true, 5 | "license": "SEE LICENSE IN LICENSE.md", 6 | "scripts": { 7 | "android": "react-native run-android", 8 | "ios": "react-native run-ios", 9 | "lint": "eslint src --ext .js", 10 | "lint:fix": "eslint src --ext .js,.jsx --fix", 11 | "start": "react-native start" 12 | }, 13 | "dependencies": { 14 | "@react-native-async-storage/async-storage": "^1.13.3", 15 | "@react-native-community/cli-platform-android": "^12.3.5", 16 | "@react-native-community/masked-view": "^0.1.10", 17 | "@react-native-community/netinfo": "^6.0.0", 18 | "@react-native/metro-config": "^0.73.2", 19 | "@react-navigation/native": "^6.0.2", 20 | "@react-navigation/native-stack": "^6.1.0", 21 | "@react-navigation/stack": "^6.0.7", 22 | "final-form": "^4.20.0", 23 | "quickblox-react-native-sdk": "^0.9.8", 24 | "react": "18.2.0", 25 | "react-final-form": "^6.5.9", 26 | "react-native": "0.72.6", 27 | "react-native-callkeep": "^4.0.1", 28 | "react-native-flash-message": "^0.1.15", 29 | "react-native-gesture-handler": "^2.13.4", 30 | "react-native-incall-manager": "^3.3.0", 31 | "react-native-permissions": "^3.3.1", 32 | "react-native-push-notification": "^8.1.1", 33 | "react-native-reanimated": "^3.6.0", 34 | "react-native-safe-area-context": "^3.1.7", 35 | "react-native-screens": "^3.6.0", 36 | "react-native-voip-push-notification": "^3.1.0", 37 | "react-redux": "^7.2.0", 38 | "redux": "^4.0.5", 39 | "redux-logger": "^3.0.6", 40 | "redux-persist": "^6.0.0", 41 | "redux-saga": "^1.1.3", 42 | "reselect": "^4.1.5", 43 | "hermes-engine": "^0.11.0" 44 | }, 45 | "devDependencies": { 46 | "@babel/core": "^7.12.9", 47 | "@babel/runtime": "^7.12.5", 48 | "@react-native-community/eslint-config": "^2.0.0", 49 | "eslint": "^7.32.0", 50 | "metro-react-native-babel-preset": "^0.66.2" 51 | }, 52 | "jest": { 53 | "preset": "react-native" 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /webrtc-sample/src/Navigation.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {NavigationContainer} from '@react-navigation/native'; 3 | import {createNativeStackNavigator} from '@react-navigation/native-stack'; 4 | 5 | import Login from './components/Auth/Login'; 6 | import Users from './components/Users'; 7 | import CallScreen from './components/CallScreen'; 8 | import Info from './components/Info'; 9 | import SplashScreen from './components/SplashScreen'; 10 | import {navigationHeader} from './theme'; 11 | 12 | const INIT_FAILED_MSG = 13 | 'SDK initialization failed.\nCheck if your config is valid.'; 14 | 15 | const Stack = createNativeStackNavigator(); 16 | 17 | const AuthScreens = () => ( 18 | <> 19 | 20 | 21 | 22 | ); 23 | 24 | const LoggedInScreens = (call) => call ? ( 25 | 30 | ) : ( 31 | <> 32 | 33 | 34 | 35 | ); 36 | 37 | export default props => ( 38 | props.appReady ? ( 39 | 40 | 41 | {props.loggedIn ? LoggedInScreens(props.call) : AuthScreens()} 42 | 43 | 44 | ) : ( 45 | 48 | ) 49 | ); 50 | -------------------------------------------------------------------------------- /webrtc-sample/src/PermissionsService/index.js: -------------------------------------------------------------------------------- 1 | import {Platform} from 'react-native'; 2 | import { 3 | checkMultiple, 4 | PERMISSIONS, 5 | requestMultiple, 6 | RESULTS, 7 | } from 'react-native-permissions'; 8 | import InCallManager from 'react-native-incall-manager'; 9 | 10 | const REQUIRED_PERMISSIONS = 11 | Platform.OS === 'ios' 12 | ? [PERMISSIONS.IOS.CAMERA, PERMISSIONS.IOS.MICROPHONE] 13 | : [ 14 | PERMISSIONS.ANDROID.CAMERA, 15 | PERMISSIONS.ANDROID.RECORD_AUDIO, 16 | PERMISSIONS.ANDROID.BLUETOOTH_CONNECT, 17 | ]; 18 | 19 | function isPermissionsGranted(statuses) { 20 | return REQUIRED_PERMISSIONS.every( 21 | permission => 22 | statuses[permission] === RESULTS.UNAVAILABLE || 23 | statuses[permission] === RESULTS.GRANTED, 24 | ); 25 | } 26 | 27 | export function checkAndRequestPermissions() { 28 | return checkMultiple(REQUIRED_PERMISSIONS).then(statuses => { 29 | if (isPermissionsGranted(statuses)) { 30 | return true; 31 | } else { 32 | const askPermissions = REQUIRED_PERMISSIONS.filter( 33 | permission => statuses[permission] === RESULTS.DENIED, 34 | ); 35 | if (askPermissions.length) { 36 | requestMultiple(REQUIRED_PERMISSIONS).then(results => { 37 | // activate InCallManager audio permissions, fix bug for ios when ringback sound not playing in first launch 38 | InCallManager.checkRecordPermission(); 39 | if (isPermissionsGranted(results)) { 40 | return true; 41 | } else { 42 | return checkAndRequestPermissions(); 43 | } 44 | }); 45 | } else { 46 | return true; 47 | } 48 | } 49 | }); 50 | } 51 | -------------------------------------------------------------------------------- /webrtc-sample/src/QBConfig.js: -------------------------------------------------------------------------------- 1 | export default { 2 | accountKey: '', 3 | apiEndpoint: '', 4 | appId: '', 5 | authKey: '', 6 | authSecret: '', 7 | chatEndpoint: '', 8 | }; 9 | -------------------------------------------------------------------------------- /webrtc-sample/src/actionCreators/app.js: -------------------------------------------------------------------------------- 1 | import { 2 | CONNECTION_CHANGED, 3 | INIT_QB_REQUEST_FAIL, 4 | INIT_QB_REQUEST_SUCCESS, 5 | INIT_QB_REQUEST, 6 | } from '../constants'; 7 | 8 | export function appStart(payload) { 9 | return {type: INIT_QB_REQUEST, payload}; 10 | } 11 | 12 | export function appStartSuccess() { 13 | return {type: INIT_QB_REQUEST_SUCCESS}; 14 | } 15 | 16 | export function appStartFail(error) { 17 | return {type: INIT_QB_REQUEST_FAIL, error}; 18 | } 19 | 20 | export function connectionStateChanged(isConnected) { 21 | return {type: CONNECTION_CHANGED, payload: isConnected}; 22 | } 23 | -------------------------------------------------------------------------------- /webrtc-sample/src/actionCreators/auth.js: -------------------------------------------------------------------------------- 1 | import { 2 | AUTH_GET_SESSION_FAIL, 3 | AUTH_GET_SESSION_REQUEST, 4 | AUTH_GET_SESSION_SUCCESS, 5 | AUTH_LOGIN_FAIL, 6 | AUTH_LOGIN_REQUEST, 7 | AUTH_LOGIN_SUCCESS, 8 | AUTH_LOGOUT_FAIL, 9 | AUTH_LOGOUT_REQUEST, 10 | AUTH_LOGOUT_SUCCESS, 11 | } from '../constants'; 12 | 13 | export function sessionGet() { 14 | return {type: AUTH_GET_SESSION_REQUEST}; 15 | } 16 | 17 | export function sessionGetSuccess(session) { 18 | return {type: AUTH_GET_SESSION_SUCCESS, payload: session}; 19 | } 20 | 21 | export function sessionGetFail(error) { 22 | return {type: AUTH_GET_SESSION_FAIL, error}; 23 | } 24 | 25 | export function loginRequest(payload) { 26 | return {type: AUTH_LOGIN_REQUEST, payload}; 27 | } 28 | 29 | export function loginSuccess(payload) { 30 | return {type: AUTH_LOGIN_SUCCESS, payload}; 31 | } 32 | 33 | export function loginFail(error) { 34 | return {type: AUTH_LOGIN_FAIL, error}; 35 | } 36 | 37 | export function logoutRequest() { 38 | return {type: AUTH_LOGOUT_REQUEST}; 39 | } 40 | 41 | export function logoutSuccess() { 42 | return {type: AUTH_LOGOUT_SUCCESS}; 43 | } 44 | 45 | export function logoutFail(error) { 46 | return {type: AUTH_LOGOUT_FAIL, error}; 47 | } 48 | -------------------------------------------------------------------------------- /webrtc-sample/src/actionCreators/chat.js: -------------------------------------------------------------------------------- 1 | import { 2 | CHAT_CONNECT_AND_SUBSCRIBE, 3 | CHAT_CONNECT_FAIL, 4 | CHAT_CONNECT_REQUEST, 5 | CHAT_CONNECT_SUCCESS, 6 | CHAT_DISCONNECT_FAIL, 7 | CHAT_DISCONNECT_REQUEST, 8 | CHAT_DISCONNECT_SUCCESS, 9 | CHAT_IS_CONNECTED_FAIL, 10 | CHAT_IS_CONNECTED_REQUEST, 11 | CHAT_IS_CONNECTED_SUCCESS, 12 | } from '../constants'; 13 | 14 | export function chatIsConnected() { 15 | return {type: CHAT_IS_CONNECTED_REQUEST}; 16 | } 17 | 18 | export function chatIsConnectedSuccess(isConnected) { 19 | return {type: CHAT_IS_CONNECTED_SUCCESS, payload: isConnected}; 20 | } 21 | 22 | export function chatIsConnectedFail(error) { 23 | return {type: CHAT_IS_CONNECTED_FAIL, error}; 24 | } 25 | 26 | export function chatConnectAndSubscribe() { 27 | return {type: CHAT_CONNECT_AND_SUBSCRIBE}; 28 | } 29 | 30 | export function chatConnect({userId, password}) { 31 | return { 32 | type: CHAT_CONNECT_REQUEST, 33 | payload: {userId, password}, 34 | }; 35 | } 36 | 37 | export function chatConnectSuccess() { 38 | return {type: CHAT_CONNECT_SUCCESS}; 39 | } 40 | 41 | export function chatConnectFail(error) { 42 | return {type: CHAT_CONNECT_FAIL, error}; 43 | } 44 | 45 | export function chatDisconnect() { 46 | return {type: CHAT_DISCONNECT_REQUEST}; 47 | } 48 | 49 | export function chatDisconnectSuccess() { 50 | return {type: CHAT_DISCONNECT_SUCCESS}; 51 | } 52 | 53 | export function chatDisconnectFail(error) { 54 | return {type: CHAT_DISCONNECT_FAIL, error}; 55 | } 56 | -------------------------------------------------------------------------------- /webrtc-sample/src/actionCreators/index.js: -------------------------------------------------------------------------------- 1 | export * from './app'; 2 | export * from './auth'; 3 | export * from './chat'; 4 | export * from './info'; 5 | export * from './pushNotifications'; 6 | export * from './subscription'; 7 | export * from './users'; 8 | export * from './webrtc'; 9 | -------------------------------------------------------------------------------- /webrtc-sample/src/actionCreators/info.js: -------------------------------------------------------------------------------- 1 | import {GET_INFO_FAIL, GET_INFO_REQUEST, GET_INFO_SUCCESS} from '../constants'; 2 | 3 | export function getInfo() { 4 | return {type: GET_INFO_REQUEST}; 5 | } 6 | 7 | export function getInfoSuccess(info) { 8 | return {type: GET_INFO_SUCCESS, payload: info}; 9 | } 10 | 11 | export function getInfoFail(error) { 12 | return {type: GET_INFO_FAIL, error}; 13 | } 14 | -------------------------------------------------------------------------------- /webrtc-sample/src/actionCreators/pushNotifications.js: -------------------------------------------------------------------------------- 1 | import { 2 | DEVICE_UDID_REMOVE, 3 | DEVICE_UDID_SET, 4 | PUSH_NOTIFICATION_CREATE_FAIL, 5 | PUSH_NOTIFICATION_CREATE_SUCCESS, 6 | PUSH_TOKEN_REMOVE, 7 | PUSH_TOKEN_SET, 8 | } from '../constants'; 9 | 10 | export function saveUdid(udid) { 11 | return {payload: udid, type: DEVICE_UDID_SET}; 12 | } 13 | 14 | export function removeUdid() { 15 | return {type: DEVICE_UDID_REMOVE}; 16 | } 17 | 18 | export function saveToken(token) { 19 | return {payload: token, type: PUSH_TOKEN_SET}; 20 | } 21 | 22 | export function removeToken() { 23 | return {type: PUSH_TOKEN_REMOVE}; 24 | } 25 | 26 | export function pushNotificationCreateSuccess(payload) { 27 | return {type: PUSH_NOTIFICATION_CREATE_SUCCESS, payload}; 28 | } 29 | 30 | export function pushNotificationCreateFail(error) { 31 | return {type: PUSH_NOTIFICATION_CREATE_FAIL, error}; 32 | } 33 | -------------------------------------------------------------------------------- /webrtc-sample/src/actionCreators/subscription.js: -------------------------------------------------------------------------------- 1 | import { 2 | PUSH_SUBSCRIPTION_CREATE_FAIL, 3 | PUSH_SUBSCRIPTION_CREATE_REQUEST, 4 | PUSH_SUBSCRIPTION_CREATE_SUCCESS, 5 | PUSH_SUBSCRIPTION_DELETE_FAIL, 6 | PUSH_SUBSCRIPTION_DELETE_REQUEST, 7 | PUSH_SUBSCRIPTION_DELETE_SUCCESS, 8 | } from '../constants'; 9 | 10 | export function createPushSubscription(channel) { 11 | return { 12 | type: PUSH_SUBSCRIPTION_CREATE_REQUEST, 13 | payload: {channel}, 14 | }; 15 | } 16 | 17 | export function createPushSubscriptionSuccess(payload) { 18 | return {type: PUSH_SUBSCRIPTION_CREATE_SUCCESS, payload}; 19 | } 20 | 21 | export function createPushSubscriptionFailure(error) { 22 | return {type: PUSH_SUBSCRIPTION_CREATE_FAIL, error}; 23 | } 24 | 25 | export function deletePushSubscription({resolve, reject}) { 26 | return { 27 | type: PUSH_SUBSCRIPTION_DELETE_REQUEST, 28 | payload: {resolve, reject}, 29 | }; 30 | } 31 | 32 | export function deletePushSubscriptionSuccess() { 33 | return {type: PUSH_SUBSCRIPTION_DELETE_SUCCESS}; 34 | } 35 | 36 | export function deletePushSubscriptionFailure(error) { 37 | return {type: PUSH_SUBSCRIPTION_DELETE_FAIL, error}; 38 | } 39 | -------------------------------------------------------------------------------- /webrtc-sample/src/actionCreators/users.js: -------------------------------------------------------------------------------- 1 | import { 2 | USERS_BULK_SELECT, 3 | USERS_CREATE_FAIL, 4 | USERS_CREATE_REQUEST, 5 | USERS_CREATE_SUCCESS, 6 | USERS_GET_FAIL, 7 | USERS_GET_REQUEST, 8 | USERS_GET_SUCCESS, 9 | USERS_SELECT, 10 | USERS_SET_FILTER, 11 | USERS_SET_PAGE, 12 | USERS_UPDATE_FAIL, 13 | USERS_UPDATE_REQUEST, 14 | USERS_UPDATE_SUCCESS, 15 | } from '../constants'; 16 | 17 | export function usersCreate(data) { 18 | return {type: USERS_CREATE_REQUEST, payload: data}; 19 | } 20 | 21 | export function usersCreateSuccess(user) { 22 | return {type: USERS_CREATE_SUCCESS, payload: user}; 23 | } 24 | 25 | export function usersCreateFail(error) { 26 | return {type: USERS_CREATE_FAIL, error}; 27 | } 28 | 29 | export function usersGet(payload) { 30 | return {type: USERS_GET_REQUEST, payload}; 31 | } 32 | 33 | export function usersGetSuccess(data) { 34 | return {type: USERS_GET_SUCCESS, payload: data}; 35 | } 36 | 37 | export function usersGetFail(error) { 38 | return {type: USERS_GET_FAIL, error}; 39 | } 40 | 41 | export function usersUpdate(profile) { 42 | return {type: USERS_UPDATE_REQUEST, payload: profile}; 43 | } 44 | 45 | export function usersUpdateSuccess(user) { 46 | return {type: USERS_UPDATE_SUCCESS, payload: user}; 47 | } 48 | 49 | export function usersUpdateFail(error) { 50 | return {type: USERS_UPDATE_FAIL, error}; 51 | } 52 | 53 | export function usersSelect(payload) { 54 | return {type: USERS_SELECT, payload}; 55 | } 56 | 57 | export function usersBulkSelect(userIds) { 58 | return {type: USERS_BULK_SELECT, payload: userIds}; 59 | } 60 | 61 | export function usersSetFilter(filter) { 62 | return {type: USERS_SET_FILTER, payload: filter}; 63 | } 64 | 65 | export function usersSetPage(page) { 66 | return {type: USERS_SET_PAGE, payload: page}; 67 | } 68 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Auth/submitHandler.js: -------------------------------------------------------------------------------- 1 | import {loginRequest, usersCreate, usersUpdate} from '../../actionCreators'; 2 | import {showError} from '../../NotificationService'; 3 | import {useActions} from '../../hooks'; 4 | 5 | const actions = { 6 | createUser: usersCreate, 7 | signIn: loginRequest, 8 | updateUser: usersUpdate, 9 | }; 10 | 11 | export function useSubmitHandler() { 12 | const {createUser, signIn, updateUser} = useActions(actions); 13 | 14 | const createUserAndSubmit = ({login, username}) => { 15 | createUser({ 16 | fullName: username, 17 | login, 18 | password: 'quickblox', 19 | resolve: () => submit({login, username}), 20 | reject: (userCreateFailureAction => { 21 | const {error: createUserError} = userCreateFailureAction; 22 | if (createUserError) { 23 | showError('Failed to create user account', createUserError); 24 | } 25 | }), 26 | }); 27 | } 28 | 29 | const checkIfUsernameMatch = (username, user) => { 30 | const updateFullNameIfNotMatch = 31 | user.fullName !== username 32 | ? new Promise((resolve, reject) => 33 | updateUser({ 34 | fullName: username, 35 | login: user.login, 36 | resolve, 37 | reject, 38 | }), 39 | ) 40 | : Promise.resolve(); 41 | updateFullNameIfNotMatch 42 | .catch(action => { 43 | if (action && action.error) { 44 | showError('Failed to update user', action.error); 45 | } 46 | }); 47 | }; 48 | 49 | const submit = ({login, username}) => { 50 | signIn({ 51 | login, 52 | resolve: (action) => checkIfUsernameMatch(username, action.payload.user), 53 | reject: ({error}) => { 54 | if (error.toLowerCase().indexOf('unauthorized') > -1) { 55 | createUserAndSubmit({login, username}); 56 | } else { 57 | showError('Failed to sign in', error); 58 | } 59 | }, 60 | }); 61 | }; 62 | 63 | return submit; 64 | } 65 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Auth/validation.js: -------------------------------------------------------------------------------- 1 | // w3c email regex https://html.spec.whatwg.org/multipage/input.html#e-mail-state-(type=email) 2 | const emailRegex = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/; 3 | const LOGIN_HINT = 4 | 'Use your email or alphanumeric characters in a range from 3 to 50. First character must be a letter.'; 5 | const USERNAME_HINT = 6 | 'Use alphanumeric characters and spaces in a range from 3 to 20. Cannot contain more than one space in a row.'; 7 | 8 | export const validate = values => { 9 | const errors = []; 10 | if (values.login) { 11 | if (values.login.indexOf('@') > -1) { 12 | if (!emailRegex.test(values.login)) { 13 | errors.login = LOGIN_HINT; 14 | } 15 | } else { 16 | if (!/^[a-zA-Z][\w\-.]{1,48}\w$/.test(values.login)) { 17 | errors.login = LOGIN_HINT; 18 | } 19 | } 20 | } else { 21 | errors.login = LOGIN_HINT; 22 | } 23 | if (values.username) { 24 | if (!/^(?=.{3,20}$)(?!.*([\s])\1{2})[\w\s]+$/.test(values.username)) { 25 | errors.username = USERNAME_HINT; 26 | } 27 | } else { 28 | errors.username = USERNAME_HINT; 29 | } 30 | return errors; 31 | }; 32 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/CallScreen/CallScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {View} from 'react-native'; 3 | 4 | import VideoViews from './VideoViews'; 5 | import CallScreenButtons from './CallScreenButtons'; 6 | import styles from './styles'; 7 | 8 | export default function CallScreen(props) { 9 | const { 10 | currentUser, 11 | displayingUser, 12 | isLoudspeaker, 13 | muteAudio, 14 | muteVideo, 15 | onCallEndPress, 16 | onSwitchAudioOutputPress, 17 | onSwitchCameraPress, 18 | onToggleAudioPress, 19 | onToggleVideoPress, 20 | peers, 21 | session, 22 | users, 23 | } = props; 24 | return ( 25 | 26 | 34 | 45 | 46 | ); 47 | } 48 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/CallScreen/OpponentCircle.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Text, View} from 'react-native'; 3 | import QB from 'quickblox-react-native-sdk'; 4 | 5 | import {colors} from '../../theme'; 6 | import styles from './styles'; 7 | 8 | const PeerStateText = { 9 | [QB.webrtc.RTC_PEER_CONNECTION_STATE.NEW]: 'Calling...', 10 | [QB.webrtc.RTC_PEER_CONNECTION_STATE.CONNECTED]: 'Connected', 11 | [QB.webrtc.RTC_PEER_CONNECTION_STATE.DISCONNECTED]: 'Disconnected', 12 | [QB.webrtc.RTC_PEER_CONNECTION_STATE.FAILED]: 'Failed to connect', 13 | [QB.webrtc.RTC_PEER_CONNECTION_STATE.CLOSED]: 'Connection closed', 14 | }; 15 | 16 | export default function OpponentCircle(props) { 17 | const {peers, style, user} = props; 18 | const username = user ? user.fullName || user.login || user.email : ''; 19 | const backgroundColor = 20 | user && user.color ? user.color : colors.primaryDisabled; 21 | const peerState = user ? peers[user.id] || 0 : 0; 22 | return ( 23 | 24 | 25 | {username.charAt(0)} 26 | 27 | {username} 28 | {PeerStateText[peerState]} 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/CallScreen/OpponentsCircles.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {View} from 'react-native'; 3 | 4 | import OpponentCircle from './OpponentCircle'; 5 | import styles from './styles'; 6 | 7 | export default function OpponentsCircles(props) { 8 | const {currentUser, peers, session, users} = props; 9 | const userIds = session.opponentsIds 10 | .concat(session.initiatorId) 11 | .filter(userId => userId !== currentUser.id); 12 | return ( 13 | 14 | {userIds.map(userId => ( 15 | user.id === userId)} 18 | peers={peers} 19 | /> 20 | ))} 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/CallScreenButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Image, Pressable, StyleSheet, Text, View} from 'react-native'; 3 | 4 | import {colors} from '../theme'; 5 | 6 | const styles = StyleSheet.create({ 7 | button: { 8 | alignItems: 'center', 9 | backgroundColor: colors.greyedBlue, 10 | borderRadius: 28, 11 | height: 56, 12 | justifyContent: 'center', 13 | width: 56, 14 | }, 15 | image: { 16 | height: 30, 17 | resizeMode: 'contain', 18 | width: 32, 19 | }, 20 | text: { 21 | color: colors.white, 22 | fontSize: 10, 23 | lineHeight: 12, 24 | marginTop: 6, 25 | }, 26 | view: { 27 | alignItems: 'center', 28 | justifyContent: 'center', 29 | }, 30 | }); 31 | 32 | export default props => { 33 | const {buttonStyle, image, imageStyle, onPress, text, textStyle} = props; 34 | const buttonStyles = buttonStyle 35 | ? [styles.button, buttonStyle] 36 | : styles.button; 37 | const imageStyles = imageStyle ? [styles.image, imageStyle] : styles.image; 38 | const textStyles = textStyle ? [styles.text, textStyle] : styles.text; 39 | return ( 40 | 41 | 42 | 43 | 44 | {text} 45 | 46 | ); 47 | }; 48 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Checkbox.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Image, StyleSheet, View} from 'react-native'; 3 | 4 | import {CHECKMARK} from '../images'; 5 | import {colors} from '../theme'; 6 | 7 | const styles = StyleSheet.create({ 8 | checkbox: { 9 | borderColor: colors.gray, 10 | borderRadius: 4, 11 | borderWidth: 1, 12 | height: 20, 13 | width: 20, 14 | }, 15 | checkboxChecked: { 16 | alignItems: 'center', 17 | backgroundColor: colors.primary, 18 | borderRadius: 4, 19 | height: 20, 20 | justifyContent: 'center', 21 | width: 20, 22 | }, 23 | checkMark: { 24 | height: 12, 25 | resizeMode: 'contain', 26 | tintColor: colors.white, 27 | width: 12, 28 | }, 29 | }); 30 | 31 | export default ({checked = false}) => ( 32 | 33 | {checked ? : null} 34 | 35 | ); 36 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/FormTextInput.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | LayoutAnimation, 4 | Platform, 5 | StyleSheet, 6 | Text, 7 | TextInput, 8 | UIManager, 9 | } from 'react-native'; 10 | 11 | import {colors} from '../theme'; 12 | 13 | const styles = StyleSheet.create({ 14 | hint: { 15 | color: colors.primaryDisabled, 16 | fontSize: 13, 17 | lineHeight: 15, 18 | paddingVertical: 10, 19 | textAlign: 'center', 20 | }, 21 | }); 22 | 23 | if ( 24 | Platform.OS === 'android' && 25 | UIManager.setLayoutAnimationEnabledExperimental 26 | ) { 27 | UIManager.setLayoutAnimationEnabledExperimental(true); 28 | } 29 | 30 | export default function FormTextInput(props) { 31 | const {activeStyle, input, meta, style, ...rest} = props; 32 | const {inputRef, ...inputProps} = rest; 33 | 34 | React.useEffect(() => { 35 | LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut); 36 | }, [meta]); 37 | 38 | return ( 39 | 40 | 49 | {(meta.touched || meta.active) && meta.error ? ( 50 | {meta.error} 51 | ) : null} 52 | 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/HeaderButton.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Image, Pressable, StyleSheet} from 'react-native'; 3 | 4 | import {colors} from '../theme'; 5 | 6 | const styles = StyleSheet.create({ 7 | button: { 8 | alignItems: 'center', 9 | backgroundColor: colors.primary, 10 | height: '100%', 11 | justifyContent: 'center', 12 | paddingHorizontal: 10, 13 | }, 14 | image: { 15 | height: 28, 16 | width: 28, 17 | }, 18 | }); 19 | 20 | export default ({onPress, imageSource}) => ( 21 | 22 | 23 | 24 | ); 25 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/SplashScreen.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { 3 | ActivityIndicator, 4 | Image, 5 | SafeAreaView, 6 | StyleSheet, 7 | Text, 8 | View, 9 | } from 'react-native'; 10 | 11 | import {SPLASH_LOGO} from '../images'; 12 | import {colors} from '../theme'; 13 | 14 | const styles = StyleSheet.create({ 15 | centerView: { 16 | ...StyleSheet.absoluteFillObject, 17 | alignItems: 'center', 18 | justifyContent: 'center', 19 | }, 20 | image: { 21 | height: 100, 22 | width: 100, 23 | }, 24 | message: { 25 | color: colors.white, 26 | textAlign: 'center', 27 | }, 28 | safeArea: { 29 | alignItems: 'center', 30 | backgroundColor: colors.primary, 31 | flex: 1, 32 | justifyContent: 'flex-end', 33 | paddingBottom: 15, 34 | width: '100%', 35 | }, 36 | text: { 37 | color: colors.white, 38 | fontSize: 18, 39 | marginTop: 50, 40 | }, 41 | }); 42 | 43 | export default ({message}) => ( 44 | 45 | 46 | 47 | 48 | 49 | {message ? {message} : null} 50 | 55 | React Native WebRTC Sample 56 | 57 | 58 | ); 59 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Users/SelectedList/EmptyComponent.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Text} from 'react-native'; 3 | 4 | import styles from './styles'; 5 | 6 | export default () => ( 7 | You can select maximum 3 users 8 | ); 9 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Users/SelectedList/Item.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {useDispatch} from 'react-redux'; 3 | import {Image, Text, TouchableOpacity, View} from 'react-native'; 4 | 5 | import {CLOSE} from '../../../images'; 6 | import {usersSelect} from '../../../actionCreators'; 7 | 8 | import styles from './styles'; 9 | 10 | export default ({item}) => { 11 | const dispatch = useDispatch(); 12 | const pressHandler = () => dispatch(usersSelect(item)); 13 | return ( 14 | 15 | 16 | {item.name} 17 | 18 | 19 | 20 | 21 | 22 | ); 23 | }; 24 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Users/SelectedList/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {ScrollView} from 'react-native'; 3 | 4 | import Item from './Item'; 5 | import EmptyComponent from './EmptyComponent'; 6 | import styles from './styles'; 7 | 8 | export default ({users = []}) => ( 9 | 10 | {users.length ? ( 11 | users.map(user => ) 12 | ) : ( 13 | 14 | )} 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Users/SelectedList/styles.js: -------------------------------------------------------------------------------- 1 | import {StyleSheet} from 'react-native'; 2 | 3 | import {colors} from '../../../theme'; 4 | 5 | export default StyleSheet.create({ 6 | emptyListText: { 7 | color: colors.mutedText, 8 | fontSize: 15, 9 | lineHeight: 50, 10 | }, 11 | itemRemoveButton: { 12 | alignItems: 'center', 13 | justifyContent: 'center', 14 | padding: 7, 15 | }, 16 | itemRemoveIcon: { 17 | height: 10, 18 | resizeMode: 'contain', 19 | width: 10, 20 | }, 21 | itemText: { 22 | color: colors.mutedText, 23 | fontSize: 15, 24 | lineHeight: 18, 25 | }, 26 | itemView: { 27 | alignItems: 'center', 28 | borderColor: colors.gray, 29 | borderRadius: 4, 30 | borderWidth: 1, 31 | flexDirection: 'row', 32 | justifyContent: 'center', 33 | margin: 4, 34 | paddingLeft: 8, 35 | }, 36 | scrollViewContent: { 37 | alignItems: 'flex-start', 38 | flexDirection: 'row', 39 | flexWrap: 'wrap', 40 | justifyContent: 'flex-start', 41 | paddingVertical: 5, 42 | width: '100%', 43 | }, 44 | }); 45 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Users/User.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Pressable, Text, View} from 'react-native'; 3 | 4 | import Checkbox from '../Checkbox'; 5 | import styles from './styles'; 6 | import {colors} from '../../theme'; 7 | 8 | function User(props) { 9 | const {isSelected, onSelect, selectable = false, user} = props; 10 | 11 | const onUserSelect = () => onSelect && onSelect(user); 12 | 13 | const username = user ? user.fullName || user.login || user.email : ''; 14 | const btnStyle = isSelected 15 | ? [styles.userButton, styles.userButtonSelected] 16 | : styles.userButton; 17 | const circleBackground = user ? user.color : colors.primaryDisabled; 18 | const circleText = username.trim().charAt(0).toUpperCase(); 19 | return ( 20 | 25 | 27 | 28 | {circleText} 29 | 30 | 31 | 32 | {username} 33 | 34 | {selectable ? : null} 35 | 36 | ); 37 | } 38 | 39 | export default React.memo(User); 40 | -------------------------------------------------------------------------------- /webrtc-sample/src/components/Users/useUsersScreen.js: -------------------------------------------------------------------------------- 1 | import {useSelector} from 'react-redux'; 2 | import {createStructuredSelector} from 'reselect'; 3 | 4 | import { 5 | deletePushSubscription, 6 | logoutRequest, 7 | } from '../../actionCreators'; 8 | import { 9 | authLoadingSelector, 10 | authUserSelector, 11 | } from '../../selectors'; 12 | import {useActions} from '../../hooks'; 13 | 14 | const selector = createStructuredSelector({ 15 | loading: authLoadingSelector, 16 | user: authUserSelector, 17 | }); 18 | 19 | const actions = { 20 | deleteSubscription: deletePushSubscription, 21 | logout: logoutRequest, 22 | }; 23 | 24 | export function useUsersScreen() { 25 | const {loading, user} = useSelector(selector); 26 | const {deleteSubscription, logout} = useActions(actions); 27 | 28 | const logoutPressHandler = () => { 29 | deleteSubscription({ 30 | resolve: () => logout(), 31 | reject: () => logout(), 32 | }); 33 | } 34 | 35 | return {loading, logoutPressHandler, user}; 36 | } 37 | -------------------------------------------------------------------------------- /webrtc-sample/src/hooks/index.js: -------------------------------------------------------------------------------- 1 | import {useEffect, useMemo, useRef, useState} from 'react'; 2 | import {bindActionCreators} from 'redux'; 3 | import {useDispatch} from 'react-redux'; 4 | 5 | export function useActions(actions, deps) { 6 | const dispatch = useDispatch(); 7 | return useMemo( 8 | () => { 9 | if (Array.isArray(actions)) { 10 | return actions.map(a => bindActionCreators(a, dispatch)); 11 | } 12 | return bindActionCreators(actions, dispatch); 13 | }, 14 | // eslint-disable-next-line react-hooks/exhaustive-deps 15 | deps ? [dispatch, ...deps] : [dispatch], 16 | ); 17 | } 18 | 19 | export function useDebounce(value, delay) { 20 | const [debouncedValue, setDebouncedValue] = useState(value); 21 | 22 | useEffect(() => { 23 | const handler = setTimeout(() => { 24 | setDebouncedValue(value); 25 | }, delay); 26 | return () => clearTimeout(handler); 27 | }, [delay, value]); 28 | 29 | return debouncedValue; 30 | } 31 | 32 | export function usePrevious(value) { 33 | const ref = useRef(); 34 | useEffect(() => { 35 | ref.current = value; 36 | }); 37 | return ref.current; 38 | } 39 | -------------------------------------------------------------------------------- /webrtc-sample/src/images.js: -------------------------------------------------------------------------------- 1 | export const CALL_ACCEPT = require('sample-react-native-webrtc/images/accept.png'); 2 | export const CALL_END = require('sample-react-native-webrtc/images/decline.png'); 3 | export const CALL = require('sample-react-native-webrtc/images/call.png'); 4 | export const CAM_OFF = require('sample-react-native-webrtc/images/cam-off.png'); 5 | export const CHECKMARK = require('sample-react-native-webrtc/images/check.png'); 6 | export const CLOSE = require('sample-react-native-webrtc/images/close.png'); 7 | export const EXIT = require('sample-react-native-webrtc/images/exit.png'); 8 | export const INFO = require('sample-react-native-webrtc/images/info.png'); 9 | export const LOGO = require('sample-react-native-webrtc/images/logo.png'); 10 | export const MIC_OFF = require('sample-react-native-webrtc/images/mic.png'); 11 | export const SEARCH = require('sample-react-native-webrtc/images/search.png'); 12 | export const SHADOW = require('sample-react-native-webrtc/images/shadow.png'); 13 | export const SPEAKER = require('sample-react-native-webrtc/images/speaker.png'); 14 | export const SPLASH_LOGO = require('sample-react-native-webrtc/images/splash_logo.png'); 15 | export const SWITCH_CAMERA = require('sample-react-native-webrtc/images/switch-camera.png'); 16 | export const VIDEO_ACCEPT = require('sample-react-native-webrtc/images/video-accept.png'); 17 | export const VIDEO_CALL = require('sample-react-native-webrtc/images/videocall.png'); 18 | 19 | export default { 20 | CALL_ACCEPT, 21 | CALL_END, 22 | CALL, 23 | CAM_OFF, 24 | CHECKMARK, 25 | CLOSE, 26 | EXIT, 27 | INFO, 28 | LOGO, 29 | MIC_OFF, 30 | SEARCH, 31 | SHADOW, 32 | SPEAKER, 33 | SPLASH_LOGO, 34 | SWITCH_CAMERA, 35 | VIDEO_ACCEPT, 36 | VIDEO_CALL, 37 | }; 38 | -------------------------------------------------------------------------------- /webrtc-sample/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {Provider} from 'react-redux'; 3 | import {PersistGate} from 'redux-persist/integration/react'; 4 | 5 | import App from './App'; 6 | import SplashScreen from './components/SplashScreen'; 7 | import configureStore from './store'; 8 | import rootSaga from './sagas'; 9 | import {setupPushNotifications} from './NotificationService'; 10 | import {GestureHandlerRootView} from 'react-native-gesture-handler'; 11 | 12 | setupPushNotifications(); 13 | 14 | // eslint-disable-next-line no-undef 15 | globalThis.ANSWER_TIME_INTERVAL = 30; 16 | 17 | const {runSaga, store, persistor} = configureStore(); 18 | runSaga(rootSaga); 19 | 20 | export default () => ( 21 | 22 | 23 | } persistor={persistor}> 24 | 25 | 26 | 27 | 28 | ); 29 | -------------------------------------------------------------------------------- /webrtc-sample/src/reducers/app.js: -------------------------------------------------------------------------------- 1 | import { 2 | CONNECTION_CHANGED, 3 | INIT_QB_REQUEST_FAIL, 4 | INIT_QB_REQUEST_SUCCESS, 5 | } from '../constants'; 6 | 7 | const initialState = { 8 | ready: undefined, 9 | connected: false, 10 | }; 11 | 12 | export default (state = initialState, action) => { 13 | switch (action.type) { 14 | case INIT_QB_REQUEST_SUCCESS: { 15 | return {...state, ready: true}; 16 | } 17 | case INIT_QB_REQUEST_FAIL: { 18 | return {...state, ready: false}; 19 | } 20 | case CONNECTION_CHANGED: 21 | return {...state, connected: action.payload}; 22 | default: 23 | return state; 24 | } 25 | }; 26 | -------------------------------------------------------------------------------- /webrtc-sample/src/reducers/auth.js: -------------------------------------------------------------------------------- 1 | import { 2 | AUTH_LOGIN_FAIL, 3 | AUTH_LOGIN_REQUEST, 4 | AUTH_LOGIN_SUCCESS, 5 | AUTH_LOGOUT_FAIL, 6 | AUTH_LOGOUT_REQUEST, 7 | AUTH_LOGOUT_SUCCESS, 8 | AUTH_SET_LOGIN, 9 | AUTH_SET_PASSWORD, 10 | USERS_UPDATE_REQUEST, 11 | USERS_UPDATE_FAIL, 12 | USERS_UPDATE_SUCCESS, 13 | } from '../constants'; 14 | 15 | const initialState = { 16 | error: undefined, 17 | loading: false, 18 | loggedIn: false, 19 | login: '', 20 | password: '', 21 | session: undefined, 22 | user: undefined, 23 | }; 24 | 25 | export default (state = initialState, action) => { 26 | switch (action.type) { 27 | case AUTH_SET_LOGIN: 28 | return {...state, login: action.payload}; 29 | case AUTH_SET_PASSWORD: 30 | return {...state, password: action.payload}; 31 | case AUTH_LOGIN_REQUEST: 32 | case AUTH_LOGOUT_REQUEST: 33 | case USERS_UPDATE_REQUEST: 34 | return {...state, loading: true, error: undefined}; 35 | case AUTH_LOGIN_SUCCESS: 36 | return { 37 | ...state, 38 | loading: false, 39 | loggedIn: true, 40 | login: initialState.login, 41 | password: initialState.password, 42 | session: action.payload.session, 43 | user: action.payload.user, 44 | }; 45 | case USERS_UPDATE_SUCCESS: 46 | return { 47 | ...state, 48 | loading: false, 49 | user: {...state.user, ...action.payload}, 50 | }; 51 | case AUTH_LOGIN_FAIL: 52 | case AUTH_LOGOUT_FAIL: 53 | case USERS_UPDATE_FAIL: 54 | return {...state, loading: false, error: action.error}; 55 | case AUTH_LOGOUT_SUCCESS: 56 | return initialState; 57 | default: 58 | return state; 59 | } 60 | }; 61 | -------------------------------------------------------------------------------- /webrtc-sample/src/reducers/chat.js: -------------------------------------------------------------------------------- 1 | import QB from 'quickblox-react-native-sdk'; 2 | import { 3 | AUTH_LOGOUT_SUCCESS, 4 | CHAT_CONNECT_FAIL, 5 | CHAT_CONNECT_REQUEST, 6 | CHAT_CONNECT_SUCCESS, 7 | CHAT_DISCONNECT_FAIL, 8 | CHAT_DISCONNECT_REQUEST, 9 | CHAT_DISCONNECT_SUCCESS, 10 | CHAT_IS_CONNECTED_SUCCESS, 11 | } from '../constants'; 12 | 13 | const initialState = { 14 | connected: false, 15 | error: undefined, 16 | loading: false, 17 | }; 18 | 19 | export default (state = initialState, action) => { 20 | switch (action.type) { 21 | case CHAT_IS_CONNECTED_SUCCESS: 22 | return {...state, connected: action.payload}; 23 | case CHAT_CONNECT_REQUEST: 24 | case CHAT_DISCONNECT_REQUEST: 25 | return {...state, loading: true, error: undefined}; 26 | case CHAT_CONNECT_SUCCESS: 27 | case QB.chat.EVENT_TYPE.CONNECTED: 28 | case QB.chat.EVENT_TYPE.RECONNECTION_SUCCESSFUL: 29 | return {...state, connected: true, loading: false}; 30 | case CHAT_CONNECT_FAIL: 31 | case CHAT_DISCONNECT_FAIL: 32 | return {...state, loading: false, error: action.error}; 33 | case CHAT_DISCONNECT_SUCCESS: 34 | case AUTH_LOGOUT_SUCCESS: 35 | case QB.chat.EVENT_TYPE.CONNECTION_CLOSED: 36 | case QB.chat.EVENT_TYPE.CONNECTION_CLOSED_ON_ERROR: 37 | case QB.chat.EVENT_TYPE.RECONNECTION_FAILED: 38 | return initialState; 39 | default: 40 | return state; 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /webrtc-sample/src/reducers/index.js: -------------------------------------------------------------------------------- 1 | import {combineReducers} from 'redux'; 2 | 3 | import app from './app'; 4 | import auth from './auth'; 5 | import chat from './chat'; 6 | import info from './info'; 7 | import pushNotifications from './pushNotifications'; 8 | import subscriptions from './subscriptions'; 9 | import users from './users'; 10 | import webrtc from './webrtc'; 11 | 12 | export default combineReducers({ 13 | app, 14 | auth, 15 | chat, 16 | info, 17 | pushNotifications, 18 | subscriptions, 19 | users, 20 | webrtc, 21 | }); 22 | -------------------------------------------------------------------------------- /webrtc-sample/src/reducers/info.js: -------------------------------------------------------------------------------- 1 | import {GET_INFO_FAIL, GET_INFO_REQUEST, GET_INFO_SUCCESS} from '../constants'; 2 | 3 | const initialState = { 4 | accountKey: '', 5 | apiEndpoint: '', 6 | appId: '', 7 | authKey: '', 8 | authSecret: '', 9 | chatEndpoint: '', 10 | error: '', 11 | loading: false, 12 | sdkVersion: '', 13 | }; 14 | 15 | export default (state = initialState, action) => { 16 | switch (action.type) { 17 | case GET_INFO_REQUEST: 18 | return {...state, error: '', loading: true}; 19 | case GET_INFO_SUCCESS: 20 | return {...state, ...action.payload, loading: false}; 21 | case GET_INFO_FAIL: 22 | return {...state, error: action.error, loading: false}; 23 | default: 24 | return state; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /webrtc-sample/src/reducers/pushNotifications.js: -------------------------------------------------------------------------------- 1 | import { 2 | DEVICE_UDID_SET, 3 | DEVICE_UDID_REMOVE, 4 | PUSH_TOKEN_SET, 5 | PUSH_TOKEN_REMOVE, 6 | } from '../constants'; 7 | 8 | const initialState = { 9 | token: undefined, 10 | udid: undefined, 11 | }; 12 | 13 | export default (state = initialState, action) => { 14 | switch (action.type) { 15 | case DEVICE_UDID_SET: 16 | return {...state, udid: action.payload}; 17 | case PUSH_TOKEN_SET: 18 | return {...state, token: action.payload}; 19 | case DEVICE_UDID_REMOVE: 20 | return {...state, udid: initialState.udid}; 21 | case PUSH_TOKEN_REMOVE: 22 | return {...state, token: initialState.token}; 23 | default: 24 | return state; 25 | } 26 | }; 27 | -------------------------------------------------------------------------------- /webrtc-sample/src/reducers/subscriptions.js: -------------------------------------------------------------------------------- 1 | import { 2 | PUSH_SUBSCRIPTION_CREATE_SUCCESS, 3 | PUSH_SUBSCRIPTION_DELETE_SUCCESS, 4 | } from '../constants'; 5 | 6 | export default (state = [], action) => { 7 | switch (action.type) { 8 | case PUSH_SUBSCRIPTION_CREATE_SUCCESS: 9 | return action.payload; 10 | case PUSH_SUBSCRIPTION_DELETE_SUCCESS: 11 | return []; 12 | default: 13 | return state; 14 | } 15 | }; 16 | -------------------------------------------------------------------------------- /webrtc-sample/src/sagas/auth.js: -------------------------------------------------------------------------------- 1 | import {call, put, takeLatest} from 'redux-saga/effects'; 2 | import QB from 'quickblox-react-native-sdk'; 3 | 4 | import { 5 | loginFail, 6 | loginSuccess, 7 | logoutFail, 8 | logoutSuccess, 9 | sessionGetFail, 10 | sessionGetSuccess, 11 | } from '../actionCreators'; 12 | import { 13 | AUTH_LOGIN_REQUEST, 14 | AUTH_LOGOUT_REQUEST, 15 | AUTH_GET_SESSION_REQUEST, 16 | } from '../constants'; 17 | import {showError} from '../NotificationService'; 18 | 19 | export function* login(action = {}) { 20 | const {login, password = 'quickblox', resolve, reject} = action.payload; 21 | try { 22 | const {session, user} = yield call(QB.auth.login, {login, password}); 23 | const result = loginSuccess({session, user: {...user, password}}); 24 | yield put(result); 25 | if (resolve) { 26 | resolve(result); 27 | } 28 | } catch (e) { 29 | const result = loginFail(e.message); 30 | yield put(result); 31 | if (reject) { 32 | reject(result); 33 | } 34 | } 35 | } 36 | 37 | export function* logout() { 38 | try { 39 | yield call(QB.auth.logout); 40 | yield put(logoutSuccess()); 41 | } catch (e) { 42 | if (e.message.toLowerCase().includes('base forbidden')) { 43 | yield put(logoutSuccess()); 44 | } else { 45 | yield put(logoutFail(e.message)); 46 | showError(e.message); 47 | } 48 | } 49 | } 50 | 51 | export function* getSession() { 52 | try { 53 | const session = yield call(QB.auth.getSession); 54 | yield put(sessionGetSuccess(session)); 55 | } catch (e) { 56 | yield put(sessionGetFail(e.message)); 57 | } 58 | } 59 | 60 | export default [ 61 | takeLatest(AUTH_LOGIN_REQUEST, login), 62 | takeLatest(AUTH_LOGOUT_REQUEST, logout), 63 | takeLatest(AUTH_GET_SESSION_REQUEST, getSession), 64 | ]; 65 | -------------------------------------------------------------------------------- /webrtc-sample/src/sagas/chat.js: -------------------------------------------------------------------------------- 1 | import {call, put, takeEvery} from 'redux-saga/effects'; 2 | import QB from 'quickblox-react-native-sdk'; 3 | 4 | import { 5 | chatConnectFail, 6 | chatConnectSuccess, 7 | chatDisconnectFail, 8 | chatDisconnectSuccess, 9 | chatIsConnectedFail, 10 | chatIsConnectedSuccess, 11 | } from '../actionCreators'; 12 | import { 13 | AUTH_LOGOUT_REQUEST, 14 | CHAT_CONNECT_REQUEST, 15 | CHAT_DISCONNECT_REQUEST, 16 | CHAT_IS_CONNECTED_REQUEST, 17 | } from '../constants'; 18 | import {showError} from '../NotificationService'; 19 | 20 | export function* isChatConnected() { 21 | try { 22 | const isConnected = yield call(QB.chat.isConnected); 23 | yield put(chatIsConnectedSuccess(isConnected)); 24 | return isConnected; 25 | } catch (e) { 26 | yield put(chatIsConnectedFail(e.message)); 27 | } 28 | } 29 | 30 | export function* chatConnect(action = {}) { 31 | const {userId, password} = action.payload; 32 | try { 33 | yield call(QB.chat.connect, {userId, password}); 34 | yield put(chatConnectSuccess()); 35 | } catch (e) { 36 | showError('Failed to connect to chat', e.message); 37 | yield put(chatConnectFail(e.message)); 38 | } 39 | } 40 | 41 | export function* chatDisconnect() { 42 | try { 43 | yield call(QB.chat.disconnect); 44 | yield put(chatDisconnectSuccess()); 45 | } catch (e) { 46 | showError('Failed to disconnect from chat', e.message); 47 | yield put(chatDisconnectFail(e.message)); 48 | } 49 | } 50 | 51 | export default [ 52 | takeEvery(CHAT_IS_CONNECTED_REQUEST, isChatConnected), 53 | takeEvery(CHAT_CONNECT_REQUEST, chatConnect), 54 | takeEvery([AUTH_LOGOUT_REQUEST, CHAT_DISCONNECT_REQUEST], chatDisconnect), 55 | ]; 56 | -------------------------------------------------------------------------------- /webrtc-sample/src/sagas/index.js: -------------------------------------------------------------------------------- 1 | import {all} from 'redux-saga/effects'; 2 | 3 | import appSagas from './app'; 4 | import authSagas from './auth'; 5 | import CallKeepController from './CallKeepController'; 6 | import chatSagas from './chat'; 7 | import infoSagas from './info'; 8 | import pushNotificationsSagas from './pushNotifications'; 9 | import usersSagas from './users'; 10 | import webRTCSagas from './webrtc'; 11 | import QBeventsSagas from './QBevents'; 12 | 13 | export default function* rootSaga() { 14 | yield all([ 15 | ...appSagas, 16 | ...authSagas, 17 | ...CallKeepController, 18 | ...chatSagas, 19 | ...infoSagas, 20 | ...pushNotificationsSagas, 21 | ...usersSagas, 22 | ...webRTCSagas, 23 | ...QBeventsSagas, 24 | ]); 25 | } 26 | -------------------------------------------------------------------------------- /webrtc-sample/src/sagas/info.js: -------------------------------------------------------------------------------- 1 | import {call, put, takeLatest} from 'redux-saga/effects'; 2 | import QB from 'quickblox-react-native-sdk'; 3 | 4 | import {getInfoFail, getInfoSuccess} from '../actionCreators'; 5 | import {GET_INFO_REQUEST} from '../constants'; 6 | 7 | export function* getSdkInfo() { 8 | try { 9 | const settings = yield call(QB.settings.get); 10 | yield put(getInfoSuccess(settings)); 11 | } catch (e) { 12 | yield put(getInfoFail(e.message)); 13 | } 14 | } 15 | 16 | export default [takeLatest(GET_INFO_REQUEST, getSdkInfo)]; 17 | -------------------------------------------------------------------------------- /webrtc-sample/src/selectors/app.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const appSelector = state => state.app; 4 | 5 | export const appReadySelector = createSelector(appSelector, app => app.ready); 6 | 7 | export const appConnectedSelector = createSelector( 8 | appSelector, 9 | app => app.connected, 10 | ); 11 | -------------------------------------------------------------------------------- /webrtc-sample/src/selectors/auth.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const authSelector = state => state.auth; 4 | 5 | export const authUserSelector = createSelector(authSelector, auth => auth.user); 6 | 7 | export const authLoadingSelector = createSelector( 8 | authSelector, 9 | auth => auth.loading, 10 | ); 11 | 12 | export const authLoggedInSelector = createSelector( 13 | authSelector, 14 | auth => auth.loggedIn, 15 | ); 16 | -------------------------------------------------------------------------------- /webrtc-sample/src/selectors/chat.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const chatSelector = state => state.chat; 4 | 5 | export const chatConnectedSelector = createSelector( 6 | chatSelector, 7 | chat => chat.connected, 8 | ); 9 | 10 | export const chatErrorSelector = createSelector( 11 | chatSelector, 12 | chat => chat.error, 13 | ); 14 | 15 | export const chatLoadingSelector = createSelector( 16 | chatSelector, 17 | chat => chat.loading, 18 | ); 19 | -------------------------------------------------------------------------------- /webrtc-sample/src/selectors/index.js: -------------------------------------------------------------------------------- 1 | export * from './app'; 2 | export * from './auth'; 3 | export * from './chat'; 4 | export * from './info'; 5 | export * from './users'; 6 | export * from './webrtc'; 7 | -------------------------------------------------------------------------------- /webrtc-sample/src/selectors/info.js: -------------------------------------------------------------------------------- 1 | export const infoSelector = state => state.info; 2 | -------------------------------------------------------------------------------- /webrtc-sample/src/selectors/users.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | import {authUserSelector} from './auth'; 4 | 5 | const usersSelector = state => state.users; 6 | 7 | export const usersItemsSelector = createSelector( 8 | usersSelector, 9 | authUserSelector, 10 | ({users}, currentUser) => users.filter(user => user.id !== currentUser.id), 11 | ); 12 | 13 | export const usersFilterSelector = createSelector( 14 | usersSelector, 15 | users => users.filter, 16 | ); 17 | 18 | export const usersLoadingSelector = createSelector( 19 | usersSelector, 20 | users => users.loading, 21 | ); 22 | 23 | export const usersSelectedSelector = createSelector( 24 | usersSelector, 25 | users => users.selected, 26 | ); 27 | 28 | export const usersPageSelector = createSelector( 29 | usersSelector, 30 | users => users.page, 31 | ); 32 | 33 | export const usersPerPageSelector = createSelector( 34 | usersSelector, 35 | users => users.perPage, 36 | ); 37 | 38 | export const usersTotalSelector = createSelector( 39 | usersSelector, 40 | users => users.total, 41 | ); 42 | 43 | export const usersItemsExludingIdsSelector = createSelector( 44 | usersItemsSelector, 45 | (_, props) => props.exclude, 46 | (users, excludeIds) => 47 | excludeIds && Array.isArray(excludeIds) && excludeIds.length 48 | ? users.filter(user => !excludeIds.includes(user.id)) 49 | : users, 50 | ); 51 | -------------------------------------------------------------------------------- /webrtc-sample/src/selectors/webrtc.js: -------------------------------------------------------------------------------- 1 | import {createSelector} from 'reselect'; 2 | 3 | const webrtcSelector = state => state.webrtc; 4 | 5 | export const webrtcDisplayingUserSelector = createSelector( 6 | webrtcSelector, 7 | state => state.displayingUser 8 | ); 9 | 10 | export const webrtcLoadingSelector = createSelector( 11 | webrtcSelector, 12 | state => state.loading, 13 | ); 14 | 15 | export const webrtcOnCallSelector = createSelector( 16 | webrtcSelector, 17 | state => state.onCall, 18 | ); 19 | 20 | export const webrtcSessionSelector = createSelector( 21 | webrtcSelector, 22 | state => state.session, 23 | ); 24 | 25 | export const webrtcPeersSelector = createSelector( 26 | webrtcSelector, 27 | state => state.peers, 28 | ); 29 | -------------------------------------------------------------------------------- /webrtc-sample/src/store/index.js: -------------------------------------------------------------------------------- 1 | import {applyMiddleware, compose, createStore} from 'redux'; 2 | import {persistStore, persistReducer} from 'redux-persist'; 3 | import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2'; 4 | import storage from '@react-native-async-storage/async-storage'; 5 | import createSagaMiddleware from 'redux-saga'; 6 | import {createLogger} from 'redux-logger'; 7 | 8 | import rootReducer from '../reducers'; 9 | import * as actionCreators from '../actionCreators'; 10 | 11 | const sagaMiddleware = createSagaMiddleware(); 12 | const middlewares = [sagaMiddleware]; 13 | if (__DEV__) { 14 | const stateTransformer = state => state; 15 | middlewares.push(createLogger({stateTransformer})); 16 | } 17 | 18 | const persistConfig = { 19 | key: 'root', 20 | storage, 21 | stateReconciler: autoMergeLevel2, 22 | whitelist: ['auth', 'device', 'pushNotifications'], 23 | }; 24 | 25 | const persistedReducer = persistReducer(persistConfig, rootReducer); 26 | let store; 27 | 28 | export default function configureStore(preloadedState) { 29 | const composeEnhancers = 30 | typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ 31 | ? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({actionCreators}) 32 | : compose; 33 | 34 | const enhancer = composeEnhancers(applyMiddleware(...middlewares)); 35 | 36 | store = createStore(persistedReducer, preloadedState, enhancer); 37 | const persistor = persistStore(store); 38 | return { 39 | persistor, 40 | runSaga: sagaMiddleware.run, 41 | store, 42 | }; 43 | } 44 | 45 | export {store}; 46 | -------------------------------------------------------------------------------- /webrtc-sample/src/theme.js: -------------------------------------------------------------------------------- 1 | export const colors = { 2 | black: '#000000', 3 | darkBackground: '#323232', 4 | error: '#ff0000', 5 | gray: '#6c7a92', 6 | greyedBlue: '#d9e3f7', 7 | inputShadow: '#d8e5ff', 8 | label: '#333333', 9 | lightGray: '#eeeeee', 10 | lightGreen: '#00cc4c', 11 | mutedText: '#72819a', 12 | primary: '#3978fc', 13 | primaryDisabled: '#99a9c6', 14 | redBackground: '#ef3248', 15 | transparent: 'transparent', 16 | white: '#ffffff', 17 | whiteBackground: '#f4f6f9', 18 | }; 19 | 20 | export const navigationHeader = { 21 | animation: 'fade', 22 | headerBackTitleVisible: false, 23 | headerStyle: { 24 | backgroundColor: colors.primary, 25 | elevation: 6, 26 | shadowColor: colors.primary, 27 | shadowOffset: {height: 4, width: 0}, 28 | shadowOpacity: 0.4, 29 | shadowRadius: 4, 30 | }, 31 | headerTintColor: colors.white, 32 | headerTitleAlign: 'center', 33 | headerTitleStyle: {fontWeight: 'bold'}, 34 | }; 35 | 36 | export default { 37 | colors, 38 | navigationHeader, 39 | }; 40 | --------------------------------------------------------------------------------