├── .buckconfig ├── .eslintrc.js ├── .flowconfig ├── .gitattributes ├── .github ├── logo.svg ├── screens.gif └── screens │ ├── 1.png │ ├── 2.png │ ├── 3.png │ ├── 4.png │ ├── 5.png │ ├── 6.png │ ├── 7.png │ ├── 8.png │ └── 9.png ├── .gitignore ├── .prettierrc.js ├── .watchmanconfig ├── App.js ├── Layout └── DevQuiz.xd ├── README.md ├── __tests__ └── App-test.js ├── android ├── app │ ├── BUCK │ ├── build.gradle │ ├── build_defs.bzl │ ├── debug.keystore │ ├── proguard-rules.pro │ └── src │ │ ├── debug │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── devquiz │ │ │ └── ReactNativeFlipper.java │ │ └── main │ │ ├── AndroidManifest.xml │ │ ├── assets │ │ └── fonts │ │ │ ├── Ubuntu-Bold.ttf │ │ │ ├── Ubuntu-Medium.ttf │ │ │ └── Ubuntu-Regular.ttf │ │ ├── java │ │ └── com │ │ │ └── devquiz │ │ │ ├── MainActivity.java │ │ │ └── MainApplication.java │ │ └── res │ │ ├── drawable-hdpi │ │ ├── ic_stat_onesignal_default.png │ │ └── logo.png │ │ ├── drawable-mdpi │ │ ├── ic_stat_onesignal_default.png │ │ └── logo.png │ │ ├── drawable-xhdpi │ │ ├── ic_stat_onesignal_default.png │ │ └── logo.png │ │ ├── drawable-xxhdpi │ │ ├── ic_stat_onesignal_default.png │ │ └── logo.png │ │ ├── drawable-xxxhdpi │ │ ├── ic_stat_onesignal_default.png │ │ └── logo.png │ │ ├── layout │ │ └── launch_screen.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── raw │ │ ├── WhatsAppClone 2020-05-05 06-57-30 │ │ │ ├── DistributionSummary.plist │ │ │ ├── ExportOptions.plist │ │ │ └── Packaging.log │ │ ├── click.mp3 │ │ ├── countdown.mp3 │ │ ├── error.mp3 │ │ ├── lobby.mp3 │ │ ├── looser.mp3 │ │ ├── new_user.mp3 │ │ ├── success.wav │ │ └── winner.mp3 │ │ └── values │ │ ├── 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 ├── index.js ├── ios ├── DevQuiz-tvOS │ └── Info.plist ├── DevQuiz-tvOSTests │ └── Info.plist ├── DevQuiz.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ └── xcshareddata │ │ └── xcschemes │ │ ├── DevQuiz-tvOS.xcscheme │ │ └── DevQuiz.xcscheme ├── DevQuiz.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── DevQuiz │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ │ └── LaunchScreen.xib │ ├── DevQuiz.entitlements │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── 1024.png │ │ │ ├── 114.png │ │ │ ├── 120.png │ │ │ ├── 180.png │ │ │ ├── 29.png │ │ │ ├── 40.png │ │ │ ├── 57.png │ │ │ ├── 58.png │ │ │ ├── 60.png │ │ │ ├── 80.png │ │ │ ├── 87.png │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── Image.imageset │ │ │ ├── Contents.json │ │ │ ├── logo.png │ │ │ ├── logo@2x.png │ │ │ └── logo@3x.png │ ├── Info.plist │ └── main.m ├── DevQuizTests │ ├── DevQuizTests.m │ └── Info.plist ├── Podfile ├── Podfile.lock └── fonts │ ├── Ubuntu-Bold.ttf │ ├── Ubuntu-Medium.ttf │ └── Ubuntu-Regular.ttf ├── jsconfig.json ├── metro.config.js ├── package.json ├── src ├── Assets │ ├── Animations │ │ ├── countdown.json │ │ ├── countdown2.json │ │ ├── swords.json │ │ └── timer.json │ ├── Images │ │ ├── logo.png │ │ ├── logo@2x.png │ │ ├── logo@3x.png │ │ ├── loose_icon.png │ │ ├── loose_icon@2x.png │ │ ├── loose_icon@3x.png │ │ ├── repo_icon.png │ │ ├── repo_icon@2x.png │ │ ├── repo_icon@3x.png │ │ ├── smart_key.png │ │ ├── smart_key@2x.png │ │ ├── smart_key@3x.png │ │ ├── sword.png │ │ ├── win_icon.png │ │ ├── win_icon@2x.png │ │ └── win_icon@3x.png │ └── fonts │ │ ├── Ubuntu-Bold.ttf │ │ ├── Ubuntu-Medium.ttf │ │ └── Ubuntu-Regular.ttf ├── Components │ ├── Animations │ │ ├── fade.js │ │ └── index.js │ ├── CustomButton │ │ ├── index.js │ │ └── styles.js │ ├── GameTopInfo │ │ ├── Countdown │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── ScoreProfile │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── index.js │ │ └── styles.js │ ├── Header │ │ ├── index.js │ │ └── styles.js │ ├── IconContainer │ │ ├── index.js │ │ └── styles.js │ ├── InputText │ │ ├── index.js │ │ └── styles.js │ ├── Layout │ │ ├── containers.js │ │ └── index.js │ ├── Loading │ │ ├── index.js │ │ └── styles.js │ ├── ProfileDisplay │ │ ├── index.js │ │ └── styles.js │ ├── ProfileHomeDisplay │ │ ├── index.js │ │ └── styles.js │ ├── Quiz │ │ ├── AwnserButton │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── Awnsers │ │ │ ├── index.js │ │ │ └── styles.js │ │ ├── index.js │ │ └── styles.js │ ├── RoundCounter │ │ ├── index.js │ │ └── styles.js │ └── UserList │ │ ├── UserListItem.js │ │ ├── index.js │ │ └── styles.js ├── Contexts │ ├── AppContext.js │ ├── AuthContext.js │ └── GameContext.js ├── Navigation │ └── index.js ├── Screens │ ├── Game │ │ └── index.js │ ├── Home copy │ │ ├── index.js │ │ └── styles.js │ ├── Home │ │ ├── index.js │ │ └── styles.js │ ├── JoinRoom │ │ ├── index.js │ │ └── styles.js │ ├── Main │ │ ├── index.js │ │ └── styles.js │ ├── Profile │ │ ├── index.js │ │ └── styles.js │ ├── Result │ │ ├── index.js │ │ └── styles.js │ └── WaitingRoom │ │ ├── index.js │ │ └── styles.js ├── Service │ ├── AuthApi.js │ ├── MatchApi.js │ ├── SocketIOClient.js │ ├── githubApi.js │ ├── index.js │ └── pushService.js ├── Storage │ ├── AppStorage.js │ └── UserStorage.js ├── Utils │ ├── AudioPlayer.js │ └── styles │ │ └── index.js └── config.js └── yarn.lock /.buckconfig: -------------------------------------------------------------------------------- 1 | 2 | [android] 3 | target = Google Inc.:Google APIs:23 4 | 5 | [maven_repositories] 6 | central = https://repo1.maven.org/maven2 7 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | extends: '@react-native-community', 4 | plugins: ['import', 'eslint-plugin-import-helpers'], 5 | rules: { 6 | 'import-helpers/order-imports': [ 7 | 'warn', 8 | { 9 | newlinesBetween: 'always', 10 | groups: ['module', '/^~//', ['parent', 'sibling', 'index']], 11 | alphabetize: {order: 'asc', ignoreCase: true}, 12 | }, 13 | ], 14 | }, 15 | settings: { 16 | 'import/resolver': { 17 | node: { 18 | paths: ['src'], 19 | }, 20 | 'babel-module': {}, 21 | }, 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | ; We fork some components by platform 3 | .*/*[.]android.js 4 | 5 | ; Ignore "BUCK" generated dirs 6 | /\.buckd/ 7 | 8 | ; Ignore polyfills 9 | node_modules/react-native/Libraries/polyfills/.* 10 | 11 | ; These should not be required directly 12 | ; require from fbjs/lib instead: require('fbjs/lib/warning') 13 | node_modules/warning/.* 14 | 15 | ; Flow doesn't support platforms 16 | .*/Libraries/Utilities/LoadingView.js 17 | 18 | [untyped] 19 | .*/node_modules/@react-native-community/cli/.*/.* 20 | 21 | [include] 22 | 23 | [libs] 24 | node_modules/react-native/interface.js 25 | node_modules/react-native/flow/ 26 | 27 | [options] 28 | emoji=true 29 | 30 | esproposal.optional_chaining=enable 31 | esproposal.nullish_coalescing=enable 32 | 33 | module.file_ext=.js 34 | module.file_ext=.json 35 | module.file_ext=.ios.js 36 | 37 | munge_underscores=true 38 | 39 | module.name_mapper='^react-native/\(.*\)$' -> '/node_modules/react-native/\1' 40 | module.name_mapper='^@?[./a-zA-Z0-9$_-]+\.\(bmp\|gif\|jpg\|jpeg\|png\|psd\|svg\|webp\|m4v\|mov\|mp4\|mpeg\|mpg\|webm\|aac\|aiff\|caf\|m4a\|mp3\|wav\|html\|pdf\)$' -> '/node_modules/react-native/Libraries/Image/RelativeImageStub' 41 | 42 | suppress_type=$FlowIssue 43 | suppress_type=$FlowFixMe 44 | suppress_type=$FlowFixMeProps 45 | suppress_type=$FlowFixMeState 46 | 47 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) 48 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ 49 | suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError 50 | 51 | [lints] 52 | sketchy-null-number=warn 53 | sketchy-null-mixed=warn 54 | sketchy-number=warn 55 | untyped-type-import=warn 56 | nonstrict-import=warn 57 | deprecated-type=warn 58 | unsafe-getters-setters=warn 59 | inexact-spread=warn 60 | unnecessary-invariant=warn 61 | signature-verification-failure=warn 62 | deprecated-utility=error 63 | 64 | [strict] 65 | deprecated-type 66 | nonstrict-import 67 | sketchy-null 68 | unclear-type 69 | unsafe-getters-setters 70 | untyped-import 71 | untyped-type-import 72 | 73 | [version] 74 | ^0.113.0 75 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.pbxproj -text 2 | -------------------------------------------------------------------------------- /.github/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /.github/screens.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens.gif -------------------------------------------------------------------------------- /.github/screens/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/1.png -------------------------------------------------------------------------------- /.github/screens/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/2.png -------------------------------------------------------------------------------- /.github/screens/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/3.png -------------------------------------------------------------------------------- /.github/screens/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/4.png -------------------------------------------------------------------------------- /.github/screens/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/5.png -------------------------------------------------------------------------------- /.github/screens/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/6.png -------------------------------------------------------------------------------- /.github/screens/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/7.png -------------------------------------------------------------------------------- /.github/screens/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/8.png -------------------------------------------------------------------------------- /.github/screens/9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/.github/screens/9.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OSX 2 | # 3 | .DS_Store 4 | 5 | # Xcode 6 | # 7 | build/ 8 | *.pbxuser 9 | !default.pbxuser 10 | *.mode1v3 11 | !default.mode1v3 12 | *.mode2v3 13 | !default.mode2v3 14 | *.perspectivev3 15 | !default.perspectivev3 16 | xcuserdata 17 | *.xccheckout 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | *.xcuserstate 23 | 24 | # Android/IntelliJ 25 | # 26 | build/ 27 | .idea 28 | .gradle 29 | local.properties 30 | *.iml 31 | 32 | # node.js 33 | # 34 | node_modules/ 35 | npm-debug.log 36 | yarn-error.log 37 | 38 | # BUCK 39 | buck-out/ 40 | \.buckd/ 41 | *.keystore 42 | !debug.keystore 43 | 44 | # fastlane 45 | # 46 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 47 | # screenshots whenever they are needed. 48 | # For more information about the recommended setup visit: 49 | # https://docs.fastlane.tools/best-practices/source-control/ 50 | 51 | */fastlane/report.xml 52 | */fastlane/Preview.html 53 | */fastlane/screenshots 54 | 55 | # Bundle artifact 56 | *.jsbundle 57 | 58 | # CocoaPods 59 | /ios/Pods/ 60 | .env 61 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | bracketSpacing: false, 3 | jsxBracketSameLine: true, 4 | singleQuote: true, 5 | trailingComma: 'all', 6 | }; 7 | -------------------------------------------------------------------------------- /.watchmanconfig: -------------------------------------------------------------------------------- 1 | {} -------------------------------------------------------------------------------- /App.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect} from 'react'; 2 | 3 | import Navigation from './src/Navigation'; 4 | import styles from './src/Utils/styles'; 5 | import {StatusBar} from 'react-native'; 6 | import AppContext from '~/Contexts/AppContext'; 7 | import OneSignalConfig from './src/Service/pushService'; 8 | 9 | export default function app() { 10 | return ( 11 | 12 | 16 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /Layout/DevQuiz.xd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/Layout/DevQuiz.xd -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | DevQuiz 3 |

4 | 5 |

6 | A simple real time quiz game 7 |

8 |

9 | GitHub language count 10 | 11 | Repository size 12 | 13 | 14 | GitHub last commit 15 | 16 | 17 | 18 | Repository issues 19 | 20 | 21 |

22 | 23 |
24 | 25 |

26 | Screens 27 | 28 |

29 | 30 | ## Technologies 31 | 32 | This project was built using: 33 | 34 | - [React Native](https://facebook.github.io/react-native/) 35 | - [SocketIO](https://socket.io/) 36 | - [Lottie](https://airbnb.design/lottie/) 37 | - [One Signal](https://onesignal.com/) 38 | - [React Native Vector Icons](https://github.com/oblador/react-native-vector-icons) 39 | - [Styled Components](https://styled-components.com/) 40 | - [React Navigation](https://reactnavigation.org/) 41 | - and more... 42 | 43 |
44 | 45 | ## Project 46 | 47 | DevQuiz is a question and answer game for developers, where only using the Github user you can enter and invite your friends to play and have fun. 48 | 49 |
50 | 51 | ## How to make it work 52 | 53 | To make this project alive, you will need to run the [Backend](https://github.com/DreamteamApps/devquiz-backend-nodejs) project (NodeJS + AdonisJS) and to manage the questions and game configurations, you will need to run the [Admin Dashboard](https://github.com/DreamteamApps/devquiz-admin-react): 54 | 55 | - [Backend](https://github.com/DreamteamApps/devquiz-backend-nodejs) 56 | - [Admin](https://github.com/DreamteamApps/devquiz-admin-react) 57 | 58 |
59 | 60 | ## Install 61 | 62 | ### `yarn install` 63 | 64 | or 65 | 66 | ### `npm install` 67 | 68 | You need to change the SERVER_API url to your server in the configuration file. 69 | 70 |
71 | 72 | ## Running 73 | 74 | Then run the project to Android or IOS 75 | 76 | ### `yarn ios` 77 | 78 | ### `yarn android` 79 | 80 |
81 | 82 | ## Contributors 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |

Erick Alves

Linkedin

Ricardo Vaz

Linkedin

Daniel Porto

Linkedin
92 | -------------------------------------------------------------------------------- /__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 | -------------------------------------------------------------------------------- /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.devquiz", 39 | ) 40 | 41 | android_resource( 42 | name = "res", 43 | package = "com.devquiz", 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 | -------------------------------------------------------------------------------- /android/app/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | maven { url 'https://plugins.gradle.org/m2/' } // Gradle Plugin Portal 4 | } 5 | dependencies { 6 | classpath 'gradle.plugin.com.onesignal:onesignal-gradle-plugin:[0.12.1, 0.99.99]' 7 | } 8 | } 9 | 10 | apply plugin: 'com.onesignal.androidsdk.onesignal-gradle-plugin' 11 | 12 | apply plugin: "com.android.application" 13 | apply from: "../../node_modules/react-native-vector-icons/fonts.gradle" 14 | import com.android.build.OutputFile 15 | 16 | /** 17 | * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets 18 | * and bundleReleaseJsAndAssets). 19 | * These basically call `react-native bundle` with the correct arguments during the Android build 20 | * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the 21 | * bundle directly from the development server. Below you can see all the possible configurations 22 | * and their defaults. If you decide to add a configuration block, make sure to add it before the 23 | * `apply from: "../../node_modules/react-native/react.gradle"` line. 24 | * 25 | * project.ext.react = [ 26 | * // the name of the generated asset file containing your JS bundle 27 | * bundleAssetName: "index.android.bundle", 28 | * 29 | * // the entry file for bundle generation. If none specified and 30 | * // "index.android.js" exists, it will be used. Otherwise "index.js" is 31 | * // default. Can be overridden with ENTRY_FILE environment variable. 32 | * entryFile: "index.android.js", 33 | * 34 | * // https://facebook.github.io/react-native/docs/performance#enable-the-ram-format 35 | * bundleCommand: "ram-bundle", 36 | * 37 | * // whether to bundle JS and assets in debug mode 38 | * bundleInDebug: false, 39 | * 40 | * // whether to bundle JS and assets in release mode 41 | * bundleInRelease: true, 42 | * 43 | * // whether to bundle JS and assets in another build variant (if configured). 44 | * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants 45 | * // The configuration property can be in the following formats 46 | * // 'bundleIn${productFlavor}${buildType}' 47 | * // 'bundleIn${buildType}' 48 | * // bundleInFreeDebug: true, 49 | * // bundleInPaidRelease: true, 50 | * // bundleInBeta: true, 51 | * 52 | * // whether to disable dev mode in custom build variants (by default only disabled in release) 53 | * // for example: to disable dev mode in the staging build type (if configured) 54 | * devDisabledInStaging: true, 55 | * // The configuration property can be in the following formats 56 | * // 'devDisabledIn${productFlavor}${buildType}' 57 | * // 'devDisabledIn${buildType}' 58 | * 59 | * // the root of your project, i.e. where "package.json" lives 60 | * root: "../../", 61 | * 62 | * // where to put the JS bundle asset in debug mode 63 | * jsBundleDirDebug: "$buildDir/intermediates/assets/debug", 64 | * 65 | * // where to put the JS bundle asset in release mode 66 | * jsBundleDirRelease: "$buildDir/intermediates/assets/release", 67 | * 68 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 69 | * // require('./image.png')), in debug mode 70 | * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug", 71 | * 72 | * // where to put drawable resources / React Native assets, e.g. the ones you use via 73 | * // require('./image.png')), in release mode 74 | * resourcesDirRelease: "$buildDir/intermediates/res/merged/release", 75 | * 76 | * // by default the gradle tasks are skipped if none of the JS files or assets change; this means 77 | * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to 78 | * // date; if you have any other folders that you want to ignore for performance reasons (gradle 79 | * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/ 80 | * // for example, you might want to remove it from here. 81 | * inputExcludes: ["android/**", "ios/**"], 82 | * 83 | * // override which node gets called and with what additional arguments 84 | * nodeExecutableAndArgs: ["node"], 85 | * 86 | * // supply additional arguments to the packager 87 | * extraPackagerArgs: [] 88 | * ] 89 | */ 90 | 91 | project.ext.react = [ 92 | enableHermes: false, // clean and rebuild if changing 93 | ] 94 | 95 | apply from: "../../node_modules/react-native/react.gradle" 96 | 97 | /** 98 | * Set this to true to create two separate APKs instead of one: 99 | * - An APK that only works on ARM devices 100 | * - An APK that only works on x86 devices 101 | * The advantage is the size of the APK is reduced by about 4MB. 102 | * Upload all the APKs to the Play Store and people will download 103 | * the correct one based on the CPU architecture of their device. 104 | */ 105 | def enableSeparateBuildPerCPUArchitecture = false 106 | 107 | /** 108 | * Run Proguard to shrink the Java bytecode in release builds. 109 | */ 110 | def enableProguardInReleaseBuilds = false 111 | 112 | /** 113 | * The preferred build flavor of JavaScriptCore. 114 | * 115 | * For example, to use the international variant, you can use: 116 | * `def jscFlavor = 'org.webkit:android-jsc-intl:+'` 117 | * 118 | * The international variant includes ICU i18n library and necessary data 119 | * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that 120 | * give correct results when using with locales other than en-US. Note that 121 | * this variant is about 6MiB larger per architecture than default. 122 | */ 123 | def jscFlavor = 'org.webkit:android-jsc:+' 124 | 125 | /** 126 | * Whether to enable the Hermes VM. 127 | * 128 | * This should be set on project.ext.react and mirrored here. If it is not set 129 | * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode 130 | * and the benefits of using Hermes will therefore be sharply reduced. 131 | */ 132 | def enableHermes = project.ext.react.get("enableHermes", false); 133 | 134 | android { 135 | compileSdkVersion rootProject.ext.compileSdkVersion 136 | 137 | compileOptions { 138 | sourceCompatibility JavaVersion.VERSION_1_8 139 | targetCompatibility JavaVersion.VERSION_1_8 140 | } 141 | 142 | defaultConfig { 143 | applicationId "com.devquiz" 144 | minSdkVersion rootProject.ext.minSdkVersion 145 | targetSdkVersion rootProject.ext.targetSdkVersion 146 | versionCode 1 147 | versionName "1.0" 148 | multiDexEnabled true 149 | } 150 | splits { 151 | abi { 152 | reset() 153 | enable enableSeparateBuildPerCPUArchitecture 154 | universalApk false // If true, also generate a universal APK 155 | include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" 156 | } 157 | } 158 | signingConfigs { 159 | debug { 160 | storeFile file('debug.keystore') 161 | storePassword 'android' 162 | keyAlias 'androiddebugkey' 163 | keyPassword 'android' 164 | } 165 | } 166 | buildTypes { 167 | debug { 168 | signingConfig signingConfigs.debug 169 | } 170 | release { 171 | // Caution! In production, you need to generate your own keystore file. 172 | // see https://facebook.github.io/react-native/docs/signed-apk-android. 173 | signingConfig signingConfigs.debug 174 | minifyEnabled enableProguardInReleaseBuilds 175 | proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" 176 | } 177 | } 178 | 179 | packagingOptions { 180 | pickFirst "lib/armeabi-v7a/libc++_shared.so" 181 | pickFirst "lib/arm64-v8a/libc++_shared.so" 182 | pickFirst "lib/x86/libc++_shared.so" 183 | pickFirst "lib/x86_64/libc++_shared.so" 184 | } 185 | 186 | // applicationVariants are e.g. debug, release 187 | applicationVariants.all { variant -> 188 | variant.outputs.each { output -> 189 | // For each separate APK per architecture, set a unique version code as described here: 190 | // https://developer.android.com/studio/build/configure-apk-splits.html 191 | def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] 192 | def abi = output.getFilter(OutputFile.ABI) 193 | if (abi != null) { // null for the universal-debug, universal-release variants 194 | output.versionCodeOverride = 195 | versionCodes.get(abi) * 1048576 + defaultConfig.versionCode 196 | } 197 | 198 | } 199 | } 200 | } 201 | 202 | dependencies { 203 | implementation fileTree(dir: "libs", include: ["*.jar"]) 204 | //noinspection GradleDynamicVersion 205 | implementation "com.facebook.react:react-native:+" // From node_modules 206 | implementation 'com.android.support:multidex:1.0.3' 207 | 208 | 209 | implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" 210 | 211 | debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { 212 | exclude group:'com.facebook.fbjni' 213 | } 214 | 215 | debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { 216 | exclude group:'com.facebook.flipper' 217 | } 218 | 219 | debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { 220 | exclude group:'com.facebook.flipper' 221 | } 222 | 223 | if (enableHermes) { 224 | def hermesPath = "../../node_modules/hermes-engine/android/"; 225 | debugImplementation files(hermesPath + "hermes-debug.aar") 226 | releaseImplementation files(hermesPath + "hermes-release.aar") 227 | } else { 228 | implementation jscFlavor 229 | } 230 | } 231 | 232 | // Run this once to be able to run the application with BUCK 233 | // puts all compile dependencies into folder libs for BUCK to use 234 | task copyDownloadableDepsToLibs(type: Copy) { 235 | from configurations.compile 236 | into 'libs' 237 | } 238 | 239 | apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) 240 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/app/debug.keystore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/debug.keystore -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /android/app/src/debug/java/com/devquiz/ReactNativeFlipper.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) Facebook, Inc. and its affiliates. 3 | * 4 | *

This source code is licensed under the MIT license found in the LICENSE file in the root 5 | * directory of this source tree. 6 | */ 7 | package com.devquiz; 8 | 9 | import android.content.Context; 10 | import com.facebook.flipper.android.AndroidFlipperClient; 11 | import com.facebook.flipper.android.utils.FlipperUtils; 12 | import com.facebook.flipper.core.FlipperClient; 13 | import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; 14 | import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; 15 | import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; 16 | import com.facebook.flipper.plugins.inspector.DescriptorMapping; 17 | import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; 18 | import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; 19 | import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; 20 | import com.facebook.flipper.plugins.react.ReactFlipperPlugin; 21 | import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; 22 | import com.facebook.react.ReactInstanceManager; 23 | import com.facebook.react.bridge.ReactContext; 24 | import com.facebook.react.modules.network.NetworkingModule; 25 | import okhttp3.OkHttpClient; 26 | 27 | public class ReactNativeFlipper { 28 | public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { 29 | if (FlipperUtils.shouldEnableFlipper(context)) { 30 | final FlipperClient client = AndroidFlipperClient.getInstance(context); 31 | 32 | client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); 33 | client.addPlugin(new ReactFlipperPlugin()); 34 | client.addPlugin(new DatabasesFlipperPlugin(context)); 35 | client.addPlugin(new SharedPreferencesFlipperPlugin(context)); 36 | client.addPlugin(CrashReporterPlugin.getInstance()); 37 | 38 | NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); 39 | NetworkingModule.setCustomClientBuilder( 40 | new NetworkingModule.CustomClientBuilder() { 41 | @Override 42 | public void apply(OkHttpClient.Builder builder) { 43 | builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); 44 | } 45 | }); 46 | client.addPlugin(networkFlipperPlugin); 47 | client.start(); 48 | 49 | // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized 50 | // Hence we run if after all native modules have been initialized 51 | ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); 52 | if (reactContext == null) { 53 | reactInstanceManager.addReactInstanceEventListener( 54 | new ReactInstanceManager.ReactInstanceEventListener() { 55 | @Override 56 | public void onReactContextInitialized(ReactContext reactContext) { 57 | reactInstanceManager.removeReactInstanceEventListener(this); 58 | reactContext.runOnNativeModulesQueueThread( 59 | new Runnable() { 60 | @Override 61 | public void run() { 62 | client.addPlugin(new FrescoFlipperPlugin()); 63 | } 64 | }); 65 | } 66 | }); 67 | } else { 68 | client.addPlugin(new FrescoFlipperPlugin()); 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | 13 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Ubuntu-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/assets/fonts/Ubuntu-Bold.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Ubuntu-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/assets/fonts/Ubuntu-Medium.ttf -------------------------------------------------------------------------------- /android/app/src/main/assets/fonts/Ubuntu-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/assets/fonts/Ubuntu-Regular.ttf -------------------------------------------------------------------------------- /android/app/src/main/java/com/devquiz/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.devquiz; 2 | import android.os.Bundle; 3 | import com.facebook.react.ReactActivity; 4 | import org.devio.rn.splashscreen.SplashScreen; 5 | public class MainActivity extends ReactActivity { 6 | 7 | @Override 8 | protected void onCreate(Bundle savedInstanceState) { 9 | SplashScreen.show(this); // here 10 | super.onCreate(savedInstanceState); 11 | } 12 | /** 13 | * Returns the name of the main component registered from JavaScript. This is used to schedule 14 | * rendering of the component. 15 | */ 16 | @Override 17 | protected String getMainComponentName() { 18 | 19 | return "DevQuiz"; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /android/app/src/main/java/com/devquiz/MainApplication.java: -------------------------------------------------------------------------------- 1 | package com.devquiz; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import com.facebook.react.PackageList; 6 | import com.facebook.react.ReactApplication; 7 | import org.devio.rn.splashscreen.SplashScreenReactPackage; 8 | import com.geektime.rnonesignalandroid.ReactNativeOneSignalPackage; 9 | import com.facebook.react.ReactInstanceManager; 10 | import com.facebook.react.ReactNativeHost; 11 | import com.facebook.react.ReactPackage; 12 | import com.facebook.soloader.SoLoader; 13 | import java.lang.reflect.InvocationTargetException; 14 | import java.util.List; 15 | 16 | public class MainApplication extends Application implements ReactApplication { 17 | 18 | private final ReactNativeHost mReactNativeHost = 19 | new ReactNativeHost(this) { 20 | @Override 21 | public boolean getUseDeveloperSupport() { 22 | return BuildConfig.DEBUG; 23 | } 24 | 25 | @Override 26 | protected List getPackages() { 27 | @SuppressWarnings("UnnecessaryLocalVariable") 28 | List packages = new PackageList(this).getPackages(); 29 | // Packages that cannot be autolinked yet can be added manually here, for example: 30 | // packages.add(new MyReactNativePackage()); 31 | return packages; 32 | } 33 | 34 | @Override 35 | protected String getJSMainModuleName() { 36 | return "index"; 37 | } 38 | }; 39 | 40 | @Override 41 | public ReactNativeHost getReactNativeHost() { 42 | return mReactNativeHost; 43 | } 44 | 45 | @Override 46 | public void onCreate() { 47 | super.onCreate(); 48 | SoLoader.init(this, /* native exopackage */ false); 49 | initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 50 | } 51 | 52 | /** 53 | * Loads Flipper in React Native templates. Call this in the onCreate method with something like 54 | * initializeFlipper(this, getReactNativeHost().getReactInstanceManager()); 55 | * 56 | * @param context 57 | * @param reactInstanceManager 58 | */ 59 | private static void initializeFlipper( 60 | Context context, ReactInstanceManager reactInstanceManager) { 61 | if (BuildConfig.DEBUG) { 62 | try { 63 | /* 64 | We use reflection here to pick up the class that initializes Flipper, 65 | since Flipper library is not available in release mode 66 | */ 67 | Class aClass = Class.forName("com.devquiz.ReactNativeFlipper"); 68 | aClass 69 | .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) 70 | .invoke(null, context, reactInstanceManager); 71 | } catch (ClassNotFoundException e) { 72 | e.printStackTrace(); 73 | } catch (NoSuchMethodException e) { 74 | e.printStackTrace(); 75 | } catch (IllegalAccessException e) { 76 | e.printStackTrace(); 77 | } catch (InvocationTargetException e) { 78 | e.printStackTrace(); 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/ic_stat_onesignal_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-hdpi/ic_stat_onesignal_default.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-hdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-hdpi/logo.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/ic_stat_onesignal_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-mdpi/ic_stat_onesignal_default.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-mdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-mdpi/logo.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/ic_stat_onesignal_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-xhdpi/ic_stat_onesignal_default.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-xhdpi/logo.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/ic_stat_onesignal_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-xxhdpi/ic_stat_onesignal_default.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-xxhdpi/logo.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/ic_stat_onesignal_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-xxxhdpi/ic_stat_onesignal_default.png -------------------------------------------------------------------------------- /android/app/src/main/res/drawable-xxxhdpi/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/drawable-xxxhdpi/logo.png -------------------------------------------------------------------------------- /android/app/src/main/res/layout/launch_screen.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 14 | -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /android/app/src/main/res/raw/WhatsAppClone 2020-05-05 06-57-30/DistributionSummary.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WhatsAppClone.ipa 6 | 7 | 8 | architectures 9 | 10 | armv7 11 | arm64 12 | 13 | bitcode 14 | 15 | certificate 16 | 17 | SHA1 18 | AA26B8CA895BDEA3841EF9B425528FD928C2059D 19 | dateExpires 20 | 02/05/21 21 | type 22 | Apple Distribution 23 | 24 | entitlements 25 | 26 | application-identifier 27 | 85E8WAS7T4.br.com.dreamteamapp.simplechat 28 | beta-reports-active 29 | 30 | com.apple.developer.team-identifier 31 | 85E8WAS7T4 32 | get-task-allow 33 | 34 | keychain-access-groups 35 | 36 | 85E8WAS7T4.br.com.dreamteamapp.simplechat 37 | 38 | 39 | name 40 | SimpleChat.app 41 | profile 42 | 43 | UUID 44 | 06221364-4f24-48dc-a850-555b9cd52858 45 | name 46 | iOS Team Store Provisioning Profile: * 47 | 48 | symbols 49 | 50 | team 51 | 52 | id 53 | 85E8WAS7T4 54 | name 55 | LITHIC SOLUCOES DE INTERNET LTDA ME 56 | 57 | 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /android/app/src/main/res/raw/WhatsAppClone 2020-05-05 06-57-30/ExportOptions.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | destination 6 | upload 7 | method 8 | app-store 9 | signingStyle 10 | automatic 11 | stripSwiftSymbols 12 | 13 | teamID 14 | 85E8WAS7T4 15 | uploadBitcode 16 | 17 | uploadSymbols 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /android/app/src/main/res/raw/click.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/raw/click.mp3 -------------------------------------------------------------------------------- /android/app/src/main/res/raw/countdown.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/raw/countdown.mp3 -------------------------------------------------------------------------------- /android/app/src/main/res/raw/error.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/raw/error.mp3 -------------------------------------------------------------------------------- /android/app/src/main/res/raw/lobby.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/raw/lobby.mp3 -------------------------------------------------------------------------------- /android/app/src/main/res/raw/looser.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/raw/looser.mp3 -------------------------------------------------------------------------------- /android/app/src/main/res/raw/new_user.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/raw/new_user.mp3 -------------------------------------------------------------------------------- /android/app/src/main/res/raw/success.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/raw/success.wav -------------------------------------------------------------------------------- /android/app/src/main/res/raw/winner.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/app/src/main/res/raw/winner.mp3 -------------------------------------------------------------------------------- /android/app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | DevQuiz 3 | 4 | -------------------------------------------------------------------------------- /android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /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 | buildToolsVersion = "28.0.3" 6 | minSdkVersion = 16 7 | compileSdkVersion = 28 8 | targetSdkVersion = 28 9 | } 10 | repositories { 11 | google() 12 | jcenter() 13 | } 14 | dependencies { 15 | classpath("com.android.tools.build:gradle:3.5.2") 16 | 17 | // NOTE: Do not place your application dependencies here; they belong 18 | // in the individual module build.gradle files 19 | } 20 | } 21 | 22 | allprojects { 23 | repositories { 24 | mavenLocal() 25 | maven { 26 | // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm 27 | url("$rootDir/../node_modules/react-native/android") 28 | } 29 | maven { 30 | // Android JSC is installed from npm 31 | url("$rootDir/../node_modules/jsc-android/dist") 32 | } 33 | 34 | google() 35 | jcenter() 36 | maven { url 'https://www.jitpack.io' } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /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=-Xmx2048m -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 | # AndroidX package structure to make it clearer which packages are bundled with the 21 | # Android operating system, and which are packaged with your app's APK 22 | # https://developer.android.com/topic/libraries/support-library/androidx-rn 23 | android.useAndroidX=true 24 | # Automatically convert third-party libraries to use AndroidX 25 | android.enableJetifier=true 26 | 27 | # Version of flipper SDK to use with React Native 28 | FLIPPER_VERSION=0.33.1 29 | -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/android/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /android/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | # 4 | # Copyright 2015 the original author or authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | ## 21 | ## Gradle start up script for UN*X 22 | ## 23 | ############################################################################## 24 | 25 | # Attempt to set APP_HOME 26 | # Resolve links: $0 may be a link 27 | PRG="$0" 28 | # Need this for relative symlinks. 29 | while [ -h "$PRG" ] ; do 30 | ls=`ls -ld "$PRG"` 31 | link=`expr "$ls" : '.*-> \(.*\)$'` 32 | if expr "$link" : '/.*' > /dev/null; then 33 | PRG="$link" 34 | else 35 | PRG=`dirname "$PRG"`"/$link" 36 | fi 37 | done 38 | SAVED="`pwd`" 39 | cd "`dirname \"$PRG\"`/" >/dev/null 40 | APP_HOME="`pwd -P`" 41 | cd "$SAVED" >/dev/null 42 | 43 | APP_NAME="Gradle" 44 | APP_BASE_NAME=`basename "$0"` 45 | 46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 48 | 49 | # Use the maximum available, or set MAX_FD != -1 to use that value. 50 | MAX_FD="maximum" 51 | 52 | warn () { 53 | echo "$*" 54 | } 55 | 56 | die () { 57 | echo 58 | echo "$*" 59 | echo 60 | exit 1 61 | } 62 | 63 | # OS specific support (must be 'true' or 'false'). 64 | cygwin=false 65 | msys=false 66 | darwin=false 67 | nonstop=false 68 | case "`uname`" in 69 | CYGWIN* ) 70 | cygwin=true 71 | ;; 72 | Darwin* ) 73 | darwin=true 74 | ;; 75 | MINGW* ) 76 | msys=true 77 | ;; 78 | NONSTOP* ) 79 | nonstop=true 80 | ;; 81 | esac 82 | 83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 84 | 85 | # Determine the Java command to use to start the JVM. 86 | if [ -n "$JAVA_HOME" ] ; then 87 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 88 | # IBM's JDK on AIX uses strange locations for the executables 89 | JAVACMD="$JAVA_HOME/jre/sh/java" 90 | else 91 | JAVACMD="$JAVA_HOME/bin/java" 92 | fi 93 | if [ ! -x "$JAVACMD" ] ; then 94 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 95 | 96 | Please set the JAVA_HOME variable in your environment to match the 97 | location of your Java installation." 98 | fi 99 | else 100 | JAVACMD="java" 101 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 102 | 103 | Please set the JAVA_HOME variable in your environment to match the 104 | location of your Java installation." 105 | fi 106 | 107 | # Increase the maximum file descriptors if we can. 108 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 109 | MAX_FD_LIMIT=`ulimit -H -n` 110 | if [ $? -eq 0 ] ; then 111 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 112 | MAX_FD="$MAX_FD_LIMIT" 113 | fi 114 | ulimit -n $MAX_FD 115 | if [ $? -ne 0 ] ; then 116 | warn "Could not set maximum file descriptor limit: $MAX_FD" 117 | fi 118 | else 119 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 120 | fi 121 | fi 122 | 123 | # For Darwin, add options to specify how the application appears in the dock 124 | if $darwin; then 125 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 126 | fi 127 | 128 | # For Cygwin or MSYS, switch paths to Windows format before running java 129 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then 130 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 131 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 132 | JAVACMD=`cygpath --unix "$JAVACMD"` 133 | 134 | # We build the pattern for arguments to be converted via cygpath 135 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 136 | SEP="" 137 | for dir in $ROOTDIRSRAW ; do 138 | ROOTDIRS="$ROOTDIRS$SEP$dir" 139 | SEP="|" 140 | done 141 | OURCYGPATTERN="(^($ROOTDIRS))" 142 | # Add a user-defined pattern to the cygpath arguments 143 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 144 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 145 | fi 146 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 147 | i=0 148 | for arg in "$@" ; do 149 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 150 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 151 | 152 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 153 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 154 | else 155 | eval `echo args$i`="\"$arg\"" 156 | fi 157 | i=$((i+1)) 158 | done 159 | case $i in 160 | (0) set -- ;; 161 | (1) set -- "$args0" ;; 162 | (2) set -- "$args0" "$args1" ;; 163 | (3) set -- "$args0" "$args1" "$args2" ;; 164 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 165 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 166 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 167 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 168 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 169 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 170 | esac 171 | fi 172 | 173 | # Escape application args 174 | save () { 175 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 176 | echo " " 177 | } 178 | APP_ARGS=$(save "$@") 179 | 180 | # Collect all arguments for the java command, following the shell quoting and substitution rules 181 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 182 | 183 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 184 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 185 | cd "$(dirname "$0")" 186 | fi 187 | 188 | exec "$JAVACMD" "$@" 189 | -------------------------------------------------------------------------------- /android/gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 33 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 34 | 35 | @rem Find java.exe 36 | if defined JAVA_HOME goto findJavaFromJavaHome 37 | 38 | set JAVA_EXE=java.exe 39 | %JAVA_EXE% -version >NUL 2>&1 40 | if "%ERRORLEVEL%" == "0" goto init 41 | 42 | echo. 43 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 44 | echo. 45 | echo Please set the JAVA_HOME variable in your environment to match the 46 | echo location of your Java installation. 47 | 48 | goto fail 49 | 50 | :findJavaFromJavaHome 51 | set JAVA_HOME=%JAVA_HOME:"=% 52 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 53 | 54 | if exist "%JAVA_EXE%" goto init 55 | 56 | echo. 57 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 58 | echo. 59 | echo Please set the JAVA_HOME variable in your environment to match the 60 | echo location of your Java installation. 61 | 62 | goto fail 63 | 64 | :init 65 | @rem Get command-line arguments, handling Windows variants 66 | 67 | if not "%OS%" == "Windows_NT" goto win9xME_args 68 | 69 | :win9xME_args 70 | @rem Slurp the command line arguments. 71 | set CMD_LINE_ARGS= 72 | set _SKIP=2 73 | 74 | :win9xME_args_slurp 75 | if "x%~1" == "x" goto execute 76 | 77 | set CMD_LINE_ARGS=%* 78 | 79 | :execute 80 | @rem Setup the command line 81 | 82 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 83 | 84 | @rem Execute Gradle 85 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 86 | 87 | :end 88 | @rem End local scope for the variables with windows NT shell 89 | if "%ERRORLEVEL%"=="0" goto mainEnd 90 | 91 | :fail 92 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 93 | rem the _cmd.exe /c_ return code! 94 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 95 | exit /b 1 96 | 97 | :mainEnd 98 | if "%OS%"=="Windows_NT" endlocal 99 | 100 | :omega 101 | -------------------------------------------------------------------------------- /android/settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'DevQuiz' 2 | include ':react-native-splash-screen' 3 | project(':react-native-splash-screen').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-splash-screen/android') 4 | include ':react-native-onesignal' 5 | project(':react-native-onesignal').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-onesignal/android') 6 | apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) 7 | include ':app' 8 | -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DevQuiz", 3 | "displayName": "DevQuiz" 4 | } -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['module:metro-react-native-babel-preset'], 3 | plugins: [ 4 | [ 5 | 'babel-plugin-root-import', 6 | { 7 | rootPathSuffix: './src/', 8 | rootPathPrefix: '~/', 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @format 3 | */ 4 | require('react-native').unstable_enableLogBox(); 5 | import 'react-native-gesture-handler'; 6 | import {AppRegistry} from 'react-native'; 7 | import App from './App'; 8 | import {name as appName} from './app.json'; 9 | 10 | AppRegistry.registerComponent(appName, () => App); 11 | -------------------------------------------------------------------------------- /ios/DevQuiz-tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSExceptionDomains 28 | 29 | localhost 30 | 31 | NSExceptionAllowsInsecureHTTPLoads 32 | 33 | 34 | 35 | 36 | NSLocationWhenInUseUsageDescription 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UISupportedInterfaceOrientations 45 | 46 | UIInterfaceOrientationPortrait 47 | UIInterfaceOrientationLandscapeLeft 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UIViewControllerBasedStatusBarAppearance 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /ios/DevQuiz-tvOSTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | org.reactjs.native.example.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ios/DevQuiz.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios/DevQuiz.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/DevQuiz.xcodeproj/xcshareddata/xcschemes/DevQuiz-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /ios/DevQuiz.xcodeproj/xcshareddata/xcschemes/DevQuiz.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 53 | 55 | 61 | 62 | 63 | 64 | 70 | 72 | 78 | 79 | 80 | 81 | 83 | 84 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /ios/DevQuiz.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /ios/DevQuiz.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios/DevQuiz/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | @interface AppDelegate : UIResponder 5 | 6 | @property (nonatomic, strong) UIWindow *window; 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /ios/DevQuiz/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | #import 4 | #import 5 | #import 6 | #import 7 | #import "RNSplashScreen.h" // here 8 | 9 | #if DEBUG 10 | #import 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | 17 | 18 | static void InitializeFlipper(UIApplication *application) { 19 | FlipperClient *client = [FlipperClient sharedClient]; 20 | SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults]; 21 | [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]]; 22 | [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; 23 | [client addPlugin:[FlipperKitReactPlugin new]]; 24 | [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; 25 | [client start]; 26 | } 27 | #endif 28 | 29 | @implementation AppDelegate 30 | 31 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 32 | { 33 | #if DEBUG 34 | InitializeFlipper(application); 35 | #endif 36 | 37 | 38 | RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions]; 39 | RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge 40 | moduleName:@"DevQuiz" 41 | initialProperties:nil]; 42 | 43 | rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1]; 44 | 45 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 46 | UIViewController *rootViewController = [UIViewController new]; 47 | rootViewController.view = rootView; 48 | self.window.rootViewController = rootViewController; 49 | [self.window makeKeyAndVisible]; 50 | [RNSplashScreen show]; 51 | return YES; 52 | } 53 | 54 | - (NSURL *)sourceURLForBridge:(RCTBridge *)bridge 55 | { 56 | #if DEBUG 57 | return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil]; 58 | #else 59 | return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; 60 | #endif 61 | } 62 | 63 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 64 | sourceApplication:(NSString *)sourceApplication annotation:(id)annotation 65 | { 66 | return [RCTLinkingManager application:application openURL:url 67 | sourceApplication:sourceApplication annotation:annotation]; 68 | } 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /ios/DevQuiz/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /ios/DevQuiz/DevQuiz.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | aps-environment 6 | development 7 | com.apple.developer.associated-domains 8 | 9 | devquiz.app 10 | applinks:devquiz.app 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/1024.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/114.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/114.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/120.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/180.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/180.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/29.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/40.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/57.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/58.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/58.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/60.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/80.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/87.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/AppIcon.appiconset/87.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | {"images":[{"size":"60x60","expected-size":"180","filename":"180.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"40x40","expected-size":"80","filename":"80.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"40x40","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"60x60","expected-size":"120","filename":"120.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"57x57","expected-size":"57","filename":"57.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"58","filename":"58.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"29x29","expected-size":"29","filename":"29.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"1x"},{"size":"29x29","expected-size":"87","filename":"87.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"57x57","expected-size":"114","filename":"114.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"40","filename":"40.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"2x"},{"size":"20x20","expected-size":"60","filename":"60.png","folder":"Assets.xcassets/AppIcon.appiconset/","idiom":"iphone","scale":"3x"},{"size":"1024x1024","filename":"1024.png","expected-size":"1024","idiom":"ios-marketing","folder":"Assets.xcassets/AppIcon.appiconset/","scale":"1x"}]} -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "logo.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "filename" : "logo@2x.png", 10 | "idiom" : "universal", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "filename" : "logo@3x.png", 15 | "idiom" : "universal", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "author" : "xcode", 21 | "version" : 1 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/Image.imageset/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/Image.imageset/logo.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/Image.imageset/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/Image.imageset/logo@2x.png -------------------------------------------------------------------------------- /ios/DevQuiz/Images.xcassets/Image.imageset/logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/DevQuiz/Images.xcassets/Image.imageset/logo@3x.png -------------------------------------------------------------------------------- /ios/DevQuiz/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | DevQuiz 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleURLTypes 24 | 25 | 26 | CFBundleTypeRole 27 | Editor 28 | CFBundleURLName 29 | devquiz 30 | CFBundleURLSchemes 31 | 32 | devquiz.app 33 | 34 | 35 | 36 | CFBundleTypeRole 37 | Editor 38 | CFBundleURLName 39 | devquiz 40 | CFBundleURLSchemes 41 | 42 | devquiz 43 | 44 | 45 | 46 | CFBundleTypeRole 47 | Editor 48 | CFBundleURLName 49 | http 50 | CFBundleURLSchemes 51 | 52 | devquiz.app 53 | 54 | 55 | 56 | CFBundleVersion 57 | $(CURRENT_PROJECT_VERSION) 58 | ITSAppUsesNonExemptEncryption 59 | 60 | LSApplicationCategoryType 61 | 62 | LSRequiresIPhoneOS 63 | 64 | NSAppTransportSecurity 65 | 66 | NSAllowsArbitraryLoads 67 | 68 | NSExceptionDomains 69 | 70 | localhost 71 | 72 | NSExceptionAllowsInsecureHTTPLoads 73 | 74 | 75 | 76 | 77 | NSLocationWhenInUseUsageDescription 78 | 79 | UIAppFonts 80 | 81 | Ubuntu-Bold.ttf 82 | Ubuntu-Medium.ttf 83 | Ubuntu-Regular.ttf 84 | AntDesign.ttf 85 | Entypo.ttf 86 | EvilIcons.ttf 87 | Feather.ttf 88 | FontAwesome.ttf 89 | FontAwesome5_Brands.ttf 90 | FontAwesome5_Regular.ttf 91 | FontAwesome5_Solid.ttf 92 | Fontisto.ttf 93 | Foundation.ttf 94 | Ionicons.ttf 95 | MaterialCommunityIcons.ttf 96 | MaterialIcons.ttf 97 | Octicons.ttf 98 | SimpleLineIcons.ttf 99 | Zocial.ttf 100 | 101 | UIBackgroundModes 102 | 103 | remote-notification 104 | 105 | UILaunchStoryboardName 106 | LaunchScreen 107 | UIRequiredDeviceCapabilities 108 | 109 | armv7 110 | 111 | UISupportedInterfaceOrientations 112 | 113 | UIInterfaceOrientationPortrait 114 | 115 | UIViewControllerBasedStatusBarAppearance 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /ios/DevQuiz/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 | -------------------------------------------------------------------------------- /ios/DevQuizTests/DevQuizTests.m: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | 4 | #import 5 | #import 6 | 7 | #define TIMEOUT_SECONDS 600 8 | #define TEXT_TO_LOOK_FOR @"Welcome to React" 9 | 10 | @interface DevQuizTests : XCTestCase 11 | 12 | @end 13 | 14 | @implementation DevQuizTests 15 | 16 | - (BOOL)findSubviewInView:(UIView *)view matching:(BOOL(^)(UIView *view))test 17 | { 18 | if (test(view)) { 19 | return YES; 20 | } 21 | for (UIView *subview in [view subviews]) { 22 | if ([self findSubviewInView:subview matching:test]) { 23 | return YES; 24 | } 25 | } 26 | return NO; 27 | } 28 | 29 | - (void)testRendersWelcomeScreen 30 | { 31 | UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController]; 32 | NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS]; 33 | BOOL foundElement = NO; 34 | 35 | __block NSString *redboxError = nil; 36 | #ifdef DEBUG 37 | RCTSetLogFunction(^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) { 38 | if (level >= RCTLogLevelError) { 39 | redboxError = message; 40 | } 41 | }); 42 | #endif 43 | 44 | while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) { 45 | [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 46 | [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]]; 47 | 48 | foundElement = [self findSubviewInView:vc.view matching:^BOOL(UIView *view) { 49 | if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) { 50 | return YES; 51 | } 52 | return NO; 53 | }]; 54 | } 55 | 56 | #ifdef DEBUG 57 | RCTSetLogFunction(RCTDefaultLogFunction); 58 | #endif 59 | 60 | XCTAssertNil(redboxError, @"RedBox error: %@", redboxError); 61 | XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS); 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /ios/DevQuizTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /ios/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '9.0' 2 | require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' 3 | 4 | def add_flipper_pods!(versions = {}) 5 | versions['Flipper'] ||= '~> 0.33.1' 6 | versions['DoubleConversion'] ||= '1.1.7' 7 | versions['Flipper-Folly'] ||= '~> 2.1' 8 | versions['Flipper-Glog'] ||= '0.3.6' 9 | versions['Flipper-PeerTalk'] ||= '~> 0.0.4' 10 | versions['Flipper-RSocket'] ||= '~> 1.0' 11 | 12 | pod 'FlipperKit', versions['Flipper'], :configuration => 'Debug' 13 | pod 'FlipperKit/FlipperKitLayoutPlugin', versions['Flipper'], :configuration => 'Debug' 14 | pod 'FlipperKit/SKIOSNetworkPlugin', versions['Flipper'], :configuration => 'Debug' 15 | pod 'FlipperKit/FlipperKitUserDefaultsPlugin', versions['Flipper'], :configuration => 'Debug' 16 | pod 'FlipperKit/FlipperKitReactPlugin', versions['Flipper'], :configuration => 'Debug' 17 | 18 | # List all transitive dependencies for FlipperKit pods 19 | # to avoid them being linked in Release builds 20 | pod 'Flipper', versions['Flipper'], :configuration => 'Debug' 21 | pod 'Flipper-DoubleConversion', versions['DoubleConversion'], :configuration => 'Debug' 22 | pod 'Flipper-Folly', versions['Flipper-Folly'], :configuration => 'Debug' 23 | pod 'Flipper-Glog', versions['Flipper-Glog'], :configuration => 'Debug' 24 | pod 'Flipper-PeerTalk', versions['Flipper-PeerTalk'], :configuration => 'Debug' 25 | pod 'Flipper-RSocket', versions['Flipper-RSocket'], :configuration => 'Debug' 26 | pod 'FlipperKit/Core', versions['Flipper'], :configuration => 'Debug' 27 | pod 'FlipperKit/CppBridge', versions['Flipper'], :configuration => 'Debug' 28 | pod 'FlipperKit/FBCxxFollyDynamicConvert', versions['Flipper'], :configuration => 'Debug' 29 | pod 'FlipperKit/FBDefines', versions['Flipper'], :configuration => 'Debug' 30 | pod 'FlipperKit/FKPortForwarding', versions['Flipper'], :configuration => 'Debug' 31 | pod 'FlipperKit/FlipperKitHighlightOverlay', versions['Flipper'], :configuration => 'Debug' 32 | pod 'FlipperKit/FlipperKitLayoutTextSearchable', versions['Flipper'], :configuration => 'Debug' 33 | pod 'FlipperKit/FlipperKitNetworkPlugin', versions['Flipper'], :configuration => 'Debug' 34 | end 35 | 36 | # Post Install processing for Flipper 37 | def flipper_post_install(installer) 38 | installer.pods_project.targets.each do |target| 39 | if target.name == 'YogaKit' 40 | target.build_configurations.each do |config| 41 | config.build_settings['SWIFT_VERSION'] = '4.1' 42 | end 43 | end 44 | end 45 | end 46 | 47 | target 'DevQuiz' do 48 | # Pods for DevQuiz 49 | pod 'FBLazyVector', :path => "../node_modules/react-native/Libraries/FBLazyVector" 50 | pod 'FBReactNativeSpec', :path => "../node_modules/react-native/Libraries/FBReactNativeSpec" 51 | pod 'RCTRequired', :path => "../node_modules/react-native/Libraries/RCTRequired" 52 | pod 'RCTTypeSafety', :path => "../node_modules/react-native/Libraries/TypeSafety" 53 | pod 'React', :path => '../node_modules/react-native/' 54 | pod 'React-Core', :path => '../node_modules/react-native/' 55 | pod 'React-CoreModules', :path => '../node_modules/react-native/React/CoreModules' 56 | pod 'React-Core/DevSupport', :path => '../node_modules/react-native/' 57 | pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' 58 | pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' 59 | pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' 60 | pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' 61 | pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' 62 | pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' 63 | pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' 64 | pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' 65 | pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' 66 | pod 'React-Core/RCTWebSocket', :path => '../node_modules/react-native/' 67 | 68 | pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' 69 | pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' 70 | pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' 71 | pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' 72 | pod 'ReactCommon/callinvoker', :path => "../node_modules/react-native/ReactCommon" 73 | pod 'ReactCommon/turbomodule/core', :path => "../node_modules/react-native/ReactCommon" 74 | pod 'Yoga', :path => '../node_modules/react-native/ReactCommon/yoga', :modular_headers => true 75 | 76 | pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' 77 | pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' 78 | pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' 79 | 80 | pod 'react-native-onesignal', :path => '../node_modules/react-native-onesignal' 81 | 82 | pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen' 83 | 84 | target 'DevQuizTests' do 85 | inherit! :complete 86 | # Pods for testing 87 | end 88 | 89 | use_native_modules! 90 | 91 | # Enables Flipper. 92 | # 93 | # Note that if you have use_frameworks! enabled, Flipper will not work and 94 | # you should disable these next few lines. 95 | add_flipper_pods! 96 | post_install do |installer| 97 | flipper_post_install(installer) 98 | end 99 | end 100 | 101 | target 'DevQuiz-tvOS' do 102 | # Pods for DevQuiz-tvOS 103 | 104 | target 'DevQuiz-tvOSTests' do 105 | inherit! :search_paths 106 | # Pods for testing 107 | end 108 | end 109 | -------------------------------------------------------------------------------- /ios/fonts/Ubuntu-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/fonts/Ubuntu-Bold.ttf -------------------------------------------------------------------------------- /ios/fonts/Ubuntu-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/fonts/Ubuntu-Medium.ttf -------------------------------------------------------------------------------- /ios/fonts/Ubuntu-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/ios/fonts/Ubuntu-Regular.ttf -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES6", 4 | "module": "commonjs", 5 | "allowSyntheticDefaultImports": true, 6 | "baseUrl": "./src", 7 | "paths": { 8 | "~/*": ["./*"] 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /metro.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Metro configuration for React Native 3 | * https://github.com/facebook/react-native 4 | * 5 | * @format 6 | */ 7 | 8 | module.exports = { 9 | transformer: { 10 | getTransformOptions: async () => ({ 11 | transform: { 12 | experimentalImportSupport: false, 13 | inlineRequires: false, 14 | }, 15 | }), 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "DevQuiz", 3 | "version": "0.0.1", 4 | "private": true, 5 | "scripts": { 6 | "android": "react-native run-android", 7 | "ios": "react-native run-ios", 8 | "start": "react-native start", 9 | "test": "jest", 10 | "lint": "eslint .", 11 | "release": "cd android/ && ./gradlew assembleRelease", 12 | "androidinstall": "cd android/app/build/outputs/apk/release && adb install app-release.apk", 13 | "iosrelease": "react-native run-ios --configuration Release" 14 | }, 15 | "rnpm": { 16 | "assets": [ 17 | "./src/Assets/fonts/" 18 | ] 19 | }, 20 | "dependencies": { 21 | "@react-native-community/async-storage": "^1.9.0", 22 | "@react-native-community/hooks": "^2.5.1", 23 | "@react-native-community/masked-view": "^0.1.10", 24 | "@react-navigation/native": "^5.1.6", 25 | "@react-navigation/stack": "^5.2.13", 26 | "axios": "^0.19.2", 27 | "lottie-react-native": "^3.3.2", 28 | "react": "16.11.0", 29 | "react-native": "0.62.2", 30 | "react-native-confirmation-code-field": "^6.0.0", 31 | "react-native-gesture-handler": "^1.6.1", 32 | "react-native-keyboard-aware-scroll-view": "^0.9.1", 33 | "react-native-onesignal": "^3.7.3", 34 | "react-native-reanimated": "^1.8.0", 35 | "react-native-safe-area-context": "^0.7.3", 36 | "react-native-safe-area-view": "^1.1.0", 37 | "react-native-screens": "^2.5.0", 38 | "react-native-share": "^3.3.0", 39 | "react-native-snackbar": "^2.2.0", 40 | "react-native-sound": "^0.11.0", 41 | "react-native-splash-screen": "^3.2.0", 42 | "react-native-vector-icons": "^6.6.0", 43 | "socket.io-client": "^2.3.0", 44 | "styled-components": "^5.1.0" 45 | }, 46 | "devDependencies": { 47 | "@babel/core": "^7.9.0", 48 | "@babel/runtime": "^7.9.2", 49 | "@react-native-community/eslint-config": "^1.1.0", 50 | "babel-jest": "^25.4.0", 51 | "babel-plugin-module-alias": "^1.6.0", 52 | "babel-plugin-root-import": "^6.5.0", 53 | "eslint": "^6.8.0", 54 | "eslint-plugin-import-helpers": "^1.0.2", 55 | "jest": "^25.4.0", 56 | "metro-react-native-babel-preset": "^0.59.0", 57 | "react-test-renderer": "16.11.0", 58 | "rn-async-storage-flipper": "^0.0.6" 59 | }, 60 | "jest": { 61 | "preset": "react-native" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/Assets/Animations/countdown.json: -------------------------------------------------------------------------------- 1 | {"v":"5.6.5","fr":30,"ip":0,"op":118,"w":300,"h":300,"nm":"Composição 1","ddd":0,"assets":[],"fonts":{"list":[{"fName":"SegoeUIEmoji","fFamily":"Segoe UI Emoji","fStyle":"Regular","ascent":74.0234375}]},"layers":[{"ddd":0,"ind":1,"ty":5,"nm":"GO","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":87,"s":[0]},{"t":90,"s":[100]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[29,206,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[168.183,161.193,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":101,"f":"SegoeUIEmoji","t":"GO","j":0,"tr":0,"lh":121.2,"ls":0,"fc":[0.443,0.349,0.757]},"t":0}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":5,"nm":"3","sr":1,"ks":{"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":29,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":32,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":60,"s":[0]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":62,"s":[100]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":89,"s":[7]},{"t":90,"s":[0]}],"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[110.458,200.99,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[90.48,90.48,100],"ix":6}},"ao":0,"t":{"d":{"k":[{"s":{"s":160,"f":"SegoeUIEmoji","t":"3","j":0,"tr":0,"lh":192,"ls":0,"fc":[0.443,0.349,0.757]},"t":0},{"s":{"s":160,"f":"SegoeUIEmoji","t":"2","j":0,"tr":0,"lh":192,"ls":0,"fc":[0.443,0.349,0.757]},"t":30},{"s":{"s":160,"f":"SegoeUIEmoji","t":"1","j":0,"tr":0,"lh":192,"ls":0,"fc":[0.443,0.349,0.757]},"t":60},{"s":{"s":160,"f":"SegoeUIEmoji","t":"1","j":0,"tr":0,"lh":192,"ls":0,"fc":[0.443,0.349,0.757]},"t":87}]},"p":{},"m":{"g":1,"a":{"a":0,"k":[0,0],"ix":2}},"a":[]},"ip":0,"op":900,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"Camada de forma 1","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150,150,0],"ix":2},"a":{"a":0,"k":[0,0,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[276,276],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Caminho da elipse 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[1,1,1,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Traçado 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[1,1,1,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Preenchimento 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[1,-2],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transformar"}],"nm":"Elipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":900,"st":0,"bm":0}],"markers":[],"chars":[{"ch":"3","size":160,"style":"Regular","w":53.91,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-6.641,0],[-4.509,3.857],[0,6.283],[2.979,3.044],[5.045,0.488],[0,0],[0,9.212],[3.532,3.125],[5.891,0],[4.492,-2.669],[0,0],[-4.916,0],[0,-7.942],[11.555,0],[0,0],[0,0],[0,0],[0,-9.147],[2.913,-2.441],[4.883,0],[4.785,3.777],[0,0]],"o":[[7.389,0],[4.508,-3.857],[0,-4.557],[-2.979,-3.043],[0,0],[9.375,-2.637],[0,-4.883],[-3.532,-3.125],[-6.12,0],[0,0],[4.362,-3.352],[8.821,0],[0,8.594],[0,0],[0,0],[0,0],[12.988,0],[0,4.134],[-2.914,2.441],[-6.023,0],[0,0],[3.938,2.507]],"v":[[22.266,1.172],[40.112,-4.614],[46.875,-19.824],[42.407,-31.226],[30.371,-36.523],[30.371,-36.719],[44.434,-54.492],[39.136,-66.504],[25,-71.191],[9.082,-67.188],[9.082,-59.375],[22.998,-64.404],[36.23,-52.49],[18.896,-39.6],[13.379,-39.6],[13.379,-32.813],[19.189,-32.813],[38.672,-19.092],[34.302,-9.229],[22.607,-5.566],[6.396,-11.23],[6.396,-2.588]],"c":true},"ix":2},"nm":"3","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"3","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Segoe UI Emoji"},{"ch":"2","size":160,"style":"Regular","w":53.91,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0.439,-1.709],[1.041,-1.66],[1.709,-1.66],[2.539,-1.823],[2.425,-2.051],[1.497,-2.051],[0.651,-2.278],[0,-2.995],[0,0],[0,0],[0,0],[0,0],[-0.505,1.449],[-1.254,1.449],[-2.132,1.66],[-3.288,2.344],[-1.953,1.823],[-1.286,1.986],[-0.635,2.246],[0,2.767],[1.025,2.344],[1.79,1.595],[2.441,0.83],[2.864,0],[2.783,-1.155],[2.246,-2.18],[0,0],[-1.318,1.042],[-1.416,0.749],[-1.498,0.423],[-1.563,0],[-1.563,-0.52],[-1.156,-1.057],[-0.668,-1.595],[0,-2.148]],"o":[[-0.439,1.709],[-1.042,1.66],[-1.709,1.66],[-3.516,2.572],[-2.425,2.051],[-1.498,2.051],[-0.652,2.279],[0,0],[0,0],[0,0],[0,0],[0,-1.888],[0.504,-1.448],[1.253,-1.448],[2.132,-1.66],[2.637,-1.888],[1.953,-1.823],[1.286,-1.985],[0.635,-2.246],[0,-3.027],[-1.025,-2.344],[-1.791,-1.595],[-2.441,-0.83],[-4.004,0],[-2.783,1.156],[0,0],[1.139,-1.27],[1.318,-1.041],[1.416,-0.748],[1.497,-0.423],[1.823,0],[1.563,0.521],[1.155,1.058],[0.667,1.595],[0,1.921]],"v":[[37.036,-46.216],[34.814,-41.162],[30.688,-36.182],[24.316,-30.957],[15.405,-24.023],[9.521,-17.871],[6.299,-11.377],[5.322,-3.467],[5.322,0],[48.535,0],[48.535,-7.178],[13.672,-7.178],[14.429,-12.183],[17.065,-16.528],[22.144,-21.191],[30.273,-27.197],[37.158,-32.764],[42.017,-38.477],[44.897,-44.824],[45.85,-52.344],[44.312,-60.4],[40.088,-66.309],[33.74,-69.946],[25.781,-71.191],[15.601,-69.458],[8.057,-64.453],[8.057,-55.859],[11.743,-59.326],[15.845,-62.012],[20.215,-63.77],[24.805,-64.404],[29.883,-63.623],[33.96,-61.255],[36.694,-57.275],[37.695,-51.66]],"c":true},"ix":2},"nm":"2","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"2","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Segoe UI Emoji"},{"ch":"1","size":160,"style":"Regular","w":53.91,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[1.692,-1.123],[1.904,-1.025],[1.969,-0.83],[1.758,-0.488],[0,0],[-1.644,0.684],[-1.482,0.781],[-1.189,0.798],[-0.619,0.619],[0,0],[0,0]],"o":[[0,0],[-1.237,1.074],[-1.693,1.123],[-1.904,1.025],[-1.97,0.83],[0,0],[1.563,-0.391],[1.643,-0.684],[1.481,-0.781],[1.188,-0.797],[0,0],[0,0],[0,0]],"v":[[35.352,-71.582],[32.324,-71.582],[27.93,-68.286],[22.534,-65.063],[16.724,-62.28],[11.133,-60.303],[11.133,-52.197],[15.942,-53.809],[20.63,-56.006],[24.634,-58.374],[27.344,-60.498],[27.344,0],[35.352,0]],"c":true},"ix":2},"nm":"1","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Segoe UI Emoji"},{"ch":"G","size":101,"style":"Regular","w":68.6,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[5.469,0],[4.655,5.062],[0,8.855],[-5.013,5.404],[-7.845,0],[-5.664,-3.58],[0,0],[7.617,0],[6.852,-6.95],[0,-10.84],[-6.169,-6.445],[-9.994,0],[-7.031,3.972]],"o":[[0,0],[0,0],[0,0],[0,0],[-4.004,2.181],[-7.976,0],[-4.655,-5.061],[0,-8.594],[5.013,-5.403],[7.747,0],[0,0],[-5.176,-2.473],[-10.515,0],[-6.853,6.95],[0,10.612],[6.168,6.445],[8.594,0],[0,0]],"v":[[61.523,-36.523],[37.988,-36.523],[37.988,-29.102],[53.32,-29.102],[53.32,-9.473],[39.111,-6.201],[20.166,-13.794],[13.184,-34.668],[20.703,-55.664],[39.99,-63.77],[60.107,-58.398],[60.107,-67.48],[40.918,-71.191],[14.868,-60.767],[4.59,-34.082],[13.843,-8.496],[38.086,1.172],[61.523,-4.785]],"c":true},"ix":2},"nm":"G","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"G","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Segoe UI Emoji"},{"ch":"O","size":101,"style":"Regular","w":75.39,"data":{"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-6.055,6.641],[0,11.426],[5.908,6.511],[9.668,0],[6.087,-6.705],[0,-11.263],[-5.974,-6.543],[-9.929,0]],"o":[[6.055,-6.641],[0,-10.514],[-5.908,-6.51],[-10.482,0],[-6.087,6.706],[0,10.482],[5.973,6.543],[10.156,0]],"v":[[61.719,-8.789],[70.801,-35.889],[61.938,-61.426],[38.574,-71.191],[13.721,-61.133],[4.59,-34.18],[13.55,-8.643],[37.402,1.172]],"c":true},"ix":2},"nm":"O","mn":"ADBE Vector Shape - Group","hd":false},{"ind":1,"ty":"sh","ix":2,"ks":{"a":0,"k":{"i":[[-4.297,-5.045],[0,-9.245],[4.427,-5.013],[7.682,0],[4.475,5.257],[0,8.627],[-4.59,5.306],[-7.357,0]],"o":[[4.297,5.046],[0,9.017],[-4.427,5.013],[-7.195,0],[-4.476,-5.257],[0,-8.626],[4.59,-5.305],[7.552,0]],"v":[[55.762,-56.201],[62.207,-34.766],[55.566,-13.721],[37.402,-6.201],[19.897,-14.087],[13.184,-34.912],[20.068,-55.811],[37.988,-63.77]],"c":true},"ix":2},"nm":"O","mn":"ADBE Vector Shape - Group","hd":false}],"nm":"O","np":5,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}]},"fFamily":"Segoe UI Emoji"}]} -------------------------------------------------------------------------------- /src/Assets/Images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/logo.png -------------------------------------------------------------------------------- /src/Assets/Images/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/logo@2x.png -------------------------------------------------------------------------------- /src/Assets/Images/logo@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/logo@3x.png -------------------------------------------------------------------------------- /src/Assets/Images/loose_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/loose_icon.png -------------------------------------------------------------------------------- /src/Assets/Images/loose_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/loose_icon@2x.png -------------------------------------------------------------------------------- /src/Assets/Images/loose_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/loose_icon@3x.png -------------------------------------------------------------------------------- /src/Assets/Images/repo_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/repo_icon.png -------------------------------------------------------------------------------- /src/Assets/Images/repo_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/repo_icon@2x.png -------------------------------------------------------------------------------- /src/Assets/Images/repo_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/repo_icon@3x.png -------------------------------------------------------------------------------- /src/Assets/Images/smart_key.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/smart_key.png -------------------------------------------------------------------------------- /src/Assets/Images/smart_key@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/smart_key@2x.png -------------------------------------------------------------------------------- /src/Assets/Images/smart_key@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/smart_key@3x.png -------------------------------------------------------------------------------- /src/Assets/Images/sword.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/sword.png -------------------------------------------------------------------------------- /src/Assets/Images/win_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/win_icon.png -------------------------------------------------------------------------------- /src/Assets/Images/win_icon@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/win_icon@2x.png -------------------------------------------------------------------------------- /src/Assets/Images/win_icon@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/Images/win_icon@3x.png -------------------------------------------------------------------------------- /src/Assets/fonts/Ubuntu-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/fonts/Ubuntu-Bold.ttf -------------------------------------------------------------------------------- /src/Assets/fonts/Ubuntu-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/fonts/Ubuntu-Medium.ttf -------------------------------------------------------------------------------- /src/Assets/fonts/Ubuntu-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DreamteamApps/devquiz-react-native/5b92f9c500278ae84975360bb41e22fbfa2ee1cf/src/Assets/fonts/Ubuntu-Regular.ttf -------------------------------------------------------------------------------- /src/Components/Animations/fade.js: -------------------------------------------------------------------------------- 1 | import React, {forwardRef, useRef, useImperativeHandle} from 'react'; 2 | import {Animated} from 'react-native'; 3 | 4 | const Fade = forwardRef((props, ref) => { 5 | const fadeAnim = useRef(new Animated.Value(props?.start ?? 0)).current; 6 | 7 | useImperativeHandle(ref, (onAnimationDone) => ({ 8 | start(onAnimationDone) { 9 | Animated.timing(fadeAnim, { 10 | toValue: props?.end ?? 1, 11 | duration: props?.duration ?? 2000, 12 | delay: props?.delay || 0, 13 | useNativeDriver: true, 14 | }).start(() => onAnimationDone && onAnimationDone()); 15 | }, 16 | reverse(onAnimationDone) { 17 | Animated.timing(fadeAnim, { 18 | toValue: props?.start ?? 0, 19 | duration: props?.duration ?? 2000, 20 | delay: props?.delay || 0, 21 | useNativeDriver: true, 22 | }).start(() => onAnimationDone && onAnimationDone()); 23 | }, 24 | cycle(onAnimationDone) { 25 | this.start(() => 26 | this.reverse(() => onAnimationDone && onAnimationDone()), 27 | ); 28 | }, 29 | })); 30 | 31 | return ( 32 | 40 | {props.children} 41 | 42 | ); 43 | }); 44 | 45 | export default Fade; 46 | -------------------------------------------------------------------------------- /src/Components/Animations/index.js: -------------------------------------------------------------------------------- 1 | import Fade from './fade'; 2 | 3 | export {Fade}; 4 | -------------------------------------------------------------------------------- /src/Components/CustomButton/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {TouchableOpacity} from 'react-native'; 3 | 4 | import {Container, Text} from './styles'; 5 | 6 | export default function CustomButton({ 7 | children, 8 | onPress, 9 | onLongPress, 10 | containerStyle, 11 | disabled, 12 | }) { 13 | return ( 14 | 15 | 19 | {children} 20 | 21 | 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/Components/CustomButton/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | background: ${(props) => props.theme.colors.btnBg}; 6 | width: 100%; 7 | padding: ${hpx(15)}; 8 | border-radius: ${hpx(10)}; 9 | opacity: ${(props) => (props.disabled ? '0.5' : '1')}; 10 | margin-bottom: ${hpx(20)}; 11 | `; 12 | export const Text = styled.Text` 13 | text-align: center; 14 | width: 100%; 15 | font-size: ${(props) => props.theme.fonts.medium}; 16 | color: ${(props) => props.theme.colors.secondary}; 17 | font-family: 'Ubuntu-Bold'; 18 | `; 19 | -------------------------------------------------------------------------------- /src/Components/GameTopInfo/Countdown/index.js: -------------------------------------------------------------------------------- 1 | import React, {memo} from 'react'; 2 | 3 | import {Container, Text} from './styles'; 4 | import {useGame} from '~/Contexts/GameContext'; 5 | 6 | function Countdown() { 7 | const {roundTime} = useGame(); 8 | 9 | return ( 10 | 11 | {roundTime} 12 | 13 | ); 14 | } 15 | export default memo(Countdown); 16 | -------------------------------------------------------------------------------- /src/Components/GameTopInfo/Countdown/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | background: ${(props) => props.theme.colors.secondary}; 6 | border-radius: ${hpx(30)}; 7 | width: ${hpx(60)}; 8 | height: ${hpx(60)}; 9 | align-items: center; 10 | justify-content: center; 11 | border: 3px #a790f4; 12 | `; 13 | 14 | export const Text = styled.Text` 15 | color: ${(props) => props.theme.colors.primary}; 16 | font-size: ${(props) => props.theme.fonts.xlarge}; 17 | `; 18 | -------------------------------------------------------------------------------- /src/Components/GameTopInfo/ScoreProfile/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {Container, Avatar, ProfileInfo, Name, Score} from './styles'; 4 | 5 | export default function ScoreProfile({data, alternative}) { 6 | return ( 7 | 8 | {data?.avatar && } 9 | 10 | {data?.name} 11 | {data?.score || 0} 12 | 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/Components/GameTopInfo/ScoreProfile/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | flex-direction: ${(props) => (props.alternative ? 'row-reverse' : 'row')}; 6 | padding: ${hpx(25)}; 7 | align-items: center; 8 | `; 9 | 10 | export const Avatar = styled.Image` 11 | width: ${hpx(50)}; 12 | height: ${hpx(50)}; 13 | border-radius: ${hpx(25)}; 14 | border-width: 2px; 15 | border-color: #fff; 16 | `; 17 | export const ProfileInfo = styled.View` 18 | margin-left: ${wpx(10)}; 19 | margin-right: ${(props) => (props.alternative ? '10px' : '0')}; 20 | `; 21 | export const Name = styled.Text.attrs((props) => ({ 22 | ellipsizeMode: 'tail', 23 | numberOfLines: 1, 24 | }))` 25 | color: #fff; 26 | font-size: ${(props) => props.theme.fonts.xxsmall}; 27 | width: 90px; 28 | text-align: ${(props) => (props.alternative ? 'right' : 'left')}; 29 | `; 30 | 31 | export const Score = styled.Text` 32 | color: #fff; 33 | font-size: ${(props) => props.theme.fonts.xxsmall}; 34 | text-align: ${(props) => (props.alternative ? 'right' : 'left')}; 35 | `; 36 | -------------------------------------------------------------------------------- /src/Components/GameTopInfo/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect, useRef} from 'react'; 2 | 3 | import {Container, ContainerScore} from './styles'; 4 | import ScoreProfile from './ScoreProfile'; 5 | import Countdown from './Countdown'; 6 | import {useGame} from '~/Contexts/GameContext'; 7 | 8 | export default function GameTopInfo() { 9 | const {players} = useGame(); 10 | 11 | return ( 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | ); 20 | } 21 | -------------------------------------------------------------------------------- /src/Components/GameTopInfo/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | justify-content: center; 6 | align-items: center; 7 | width: 100%; 8 | margin-top: ${hpx(5)}; 9 | `; 10 | 11 | export const ContainerScore = styled.View` 12 | justify-content: space-between; 13 | flex-direction: row; 14 | width: 100%; 15 | `; 16 | -------------------------------------------------------------------------------- /src/Components/Header/index.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect} from 'react'; 2 | import {TouchableOpacity} from 'react-native'; 3 | import IconIonicons from 'react-native-vector-icons/Ionicons'; 4 | import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityIcons'; 5 | import {useTheme} from 'styled-components'; 6 | 7 | import {Container, ButtonArea} from './styles'; 8 | import {useNavigation} from '@react-navigation/native'; 9 | import {useApp} from '~/Contexts/AppContext'; 10 | 11 | import AudioPlayer from '~/Utils/AudioPlayer'; 12 | 13 | export default function Header({exitRoom, back, music}) { 14 | const navigation = useNavigation(); 15 | const theme = useTheme(); 16 | const {musicStatus, changeMusicStatus} = useApp(); 17 | 18 | useEffect(() => { 19 | if (musicStatus) { 20 | AudioPlayer.resume(); 21 | } else { 22 | AudioPlayer.mute(); 23 | } 24 | }, [musicStatus]); 25 | 26 | const handleBack = () => { 27 | exitRoom && exitRoom(); 28 | navigation.goBack(); 29 | }; 30 | 31 | return ( 32 | 33 | {back && ( 34 | handleBack()}> 35 | 36 | 41 | 42 | 43 | )} 44 | {music && ( 45 | changeMusicStatus((musicStatus) => !musicStatus)}> 47 | 48 | 53 | 54 | 55 | )} 56 | 57 | ); 58 | } 59 | -------------------------------------------------------------------------------- /src/Components/Header/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | flex-direction: row; 6 | justify-content: space-between; 7 | padding: ${hpx(10)}; 8 | width: 100%; 9 | `; 10 | export const ButtonArea = styled.View` 11 | padding: ${hpx(10)}; 12 | justify-content: flex-end; 13 | align-items: flex-end; 14 | `; 15 | -------------------------------------------------------------------------------- /src/Components/IconContainer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {Container, Avatar, Title} from './styles'; 4 | 5 | export default function IconContainer({icon, title, children}) { 6 | return ( 7 | 8 | {icon && } 9 | {title} 10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /src/Components/IconContainer/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | padding: ${hpx(25)}; 6 | background: ${(props) => props.theme.colors.secondary}; 7 | align-items: center; 8 | margin-top: ${hpx(110)}; 9 | border-radius: ${hpx(20)}; 10 | width: 80%; 11 | `; 12 | 13 | export const Avatar = styled.Image` 14 | width: ${wpx(100)}; 15 | height: ${hpx(120)}; 16 | border-radius: ${hpx(20)}; 17 | margin-top: ${hpx(-110)}; 18 | margin-bottom: ${hpx(10)}; 19 | resize-mode: contain; 20 | `; 21 | export const Title = styled.Text` 22 | font-size: ${(props) => props.theme.fonts.large}; 23 | font-family: ${(props) => props.theme.fontName.bold}; 24 | color: ${(props) => props.theme.colors.primary}; 25 | margin-bottom: ${hpx(5)}; 26 | text-align: ${(props) => (props.alternative ? 'right' : 'left')}; 27 | `; 28 | -------------------------------------------------------------------------------- /src/Components/InputText/index.js: -------------------------------------------------------------------------------- 1 | import React, {forwardRef} from 'react'; 2 | 3 | import {Input} from './styles'; 4 | 5 | const InputText = forwardRef((props, ref) => { 6 | return ; 7 | }); 8 | export default InputText; 9 | -------------------------------------------------------------------------------- /src/Components/InputText/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Input = styled.TextInput.attrs((props) => ({ 5 | placeholderTextColor: '#999', 6 | }))` 7 | background: ${(props) => props.theme.colors.secondary}; 8 | color: ${(props) => props.theme.colors.primary}; 9 | border-radius: 10px; 10 | margin-vertical: ${wpx(20)}; 11 | font-size: ${(props) => props.theme.fonts.medium}; 12 | padding: ${hpx(10)}; 13 | width: 100%; 14 | text-align: center; 15 | `; 16 | -------------------------------------------------------------------------------- /src/Components/Layout/containers.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | import SafeAreaView from 'react-native-safe-area-view'; 4 | export const PageContainer = styled(SafeAreaView)` 5 | background: ${(props) => props.theme.colors.primary}; 6 | flex: 1; 7 | align-items: ${(props) => props.alignItems ?? 'center'}; 8 | justify-content: ${(props) => props.justifyContent ?? 'center'}; 9 | `; 10 | -------------------------------------------------------------------------------- /src/Components/Layout/index.js: -------------------------------------------------------------------------------- 1 | import * as Containers from './containers'; 2 | export const {PageContainer} = Containers; 3 | -------------------------------------------------------------------------------- /src/Components/Loading/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {View, ActivityIndicator} from 'react-native'; 3 | 4 | import {Container} from './styles'; 5 | 6 | export default function Loading() { 7 | return ( 8 | 9 | 10 | 11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/Components/Loading/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | align-items: center; 6 | justify-content: center; 7 | top: 0; 8 | left: 0; 9 | width: 100%; 10 | height: 100%; 11 | background: rgba(0, 0, 0, 0.5); 12 | 13 | position: absolute; 14 | z-index: 10; 15 | `; 16 | -------------------------------------------------------------------------------- /src/Components/ProfileDisplay/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; 3 | 4 | import { 5 | Container, 6 | Avatar, 7 | ProfileInfo, 8 | Name, 9 | Username, 10 | ReposContainer, 11 | Repos, 12 | } from './styles'; 13 | import {useAuth} from '~/Contexts/AuthContext'; 14 | 15 | export default function ProfileDisplay({data, alternative}) { 16 | const {user} = useAuth(); 17 | 18 | const {name, login, avatar, repos} = data || user; 19 | 20 | return ( 21 | 22 | {avatar && } 23 | 24 | {name} 25 | @{login} 26 | 27 | 28 | {repos} 29 | 30 | 31 | 32 | ); 33 | } 34 | -------------------------------------------------------------------------------- /src/Components/ProfileDisplay/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | flex-direction: ${(props) => (props.alternative ? 'row-reverse' : 'row')}; 6 | padding: 25px; 7 | `; 8 | 9 | export const Avatar = styled.Image` 10 | width: ${hpx(100)}; 11 | height: ${hpx(100)}; 12 | border-radius: ${hpx(50)}; 13 | border-width: 2px; 14 | border-color: #fff; 15 | `; 16 | export const ProfileInfo = styled.View` 17 | margin-left: ${wpx(10)}; 18 | margin-right: ${(props) => (props.alternative ? '10px' : '0')}; 19 | `; 20 | export const Name = styled.Text` 21 | color: #fff; 22 | font-size: ${(props) => props.theme.fonts.large}; 23 | text-align: ${(props) => (props.alternative ? 'right' : 'left')}; 24 | font-family: ${(props) => props.theme.fontName.bold}; 25 | `; 26 | export const Username = styled.Text` 27 | color: #fff; 28 | font-size: ${(props) => props.theme.fonts.medium}; 29 | margin-bottom: ${hpx(10)}; 30 | text-align: ${(props) => (props.alternative ? 'right' : 'left')}; 31 | font-family: ${(props) => props.theme.fontName.medium}; 32 | `; 33 | export const ReposContainer = styled.View` 34 | flex-direction: ${(props) => (props.alternative ? 'row-reverse' : 'row')}; 35 | `; 36 | export const RepoIcon = styled.View` 37 | width: ${wpx(20)}; 38 | height: ${hpx(20)}; 39 | `; 40 | export const Repos = styled.Text` 41 | color: #fff; 42 | font-size: ${(props) => props.theme.fonts.medium}; 43 | font-family: ${(props) => props.theme.fontName.medium}; 44 | `; 45 | -------------------------------------------------------------------------------- /src/Components/ProfileHomeDisplay/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Icon from 'react-native-vector-icons/MaterialCommunityIcons'; 3 | 4 | import { 5 | Container, 6 | Avatar, 7 | ProfileInfo, 8 | Name, 9 | Username, 10 | ReposContainer, 11 | Repos, 12 | RepoIcon, 13 | ScoreContainer, 14 | ScoreTitle, 15 | ScoreWinValue, 16 | ScoreLooseValue, 17 | WinsLoosesContainer, 18 | } from './styles'; 19 | import {useAuth} from '~/Contexts/AuthContext'; 20 | 21 | export default function ProfileHomeDisplay({data, alternative}) { 22 | const {user} = useAuth(); 23 | 24 | const {name, login, avatar, repos, wins, losses} = data || user; 25 | 26 | return ( 27 | 28 | {avatar && } 29 | 30 | {name} 31 | @{login} 32 | 33 | 34 | {/* */} 35 | {repos} 36 | 37 | 38 | 39 | 40 | Wins 41 | {wins || 0} 42 | 43 | 44 | Losses 45 | {losses || 0} 46 | 47 | 48 | 49 | 50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /src/Components/ProfileHomeDisplay/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | padding: ${wpx(15)}; 6 | background: ${(props) => props.theme.colors.secondary}; 7 | align-items: center; 8 | margin-top: ${hpx(50)}; 9 | border-radius: ${wpx(20)}; 10 | width: 80%; 11 | height: ${hpx(200)}; 12 | `; 13 | 14 | export const Avatar = styled.Image` 15 | width: ${hpx(100)}; 16 | height: ${hpx(120)}; 17 | border-radius: 20px; 18 | margin-top: -${hpx(110)}; 19 | margin-bottom: ${hpx(10)}; 20 | `; 21 | export const ProfileInfo = styled.View` 22 | margin-left: ${wpx(10)}; 23 | margin-right: ${(props) => (props.alternative ? '10px' : '0')}; 24 | align-items: center; 25 | `; 26 | export const Name = styled.Text` 27 | color: #fff; 28 | font-size: ${(props) => props.theme.fonts.large}; 29 | font-family: ${(props) => props.theme.fontName.bold}; 30 | color: ${(props) => props.theme.colors.primary}; 31 | margin-bottom: ${hpx(5)}; 32 | text-align: ${(props) => (props.alternative ? 'right' : 'left')}; 33 | `; 34 | export const Username = styled.Text` 35 | color: #fff; 36 | font-size: ${(props) => props.theme.fonts.medium}; 37 | margin-bottom: ${hpx(10)}; 38 | color: ${(props) => props.theme.colors.gray}; 39 | font-family: ${(props) => props.theme.fontName.medium}; 40 | `; 41 | export const ReposContainer = styled.View` 42 | flex-direction: ${(props) => (props.alternative ? 'row-reverse' : 'row')}; 43 | color: ${(props) => props.theme.colors.gray}; 44 | justify-content: center; 45 | align-items: center; 46 | `; 47 | export const RepoIcon = styled.Image` 48 | width: ${hpx(17)}; 49 | height: ${hpx(17)}; 50 | resize-mode: contain; 51 | `; 52 | 53 | export const Repos = styled.Text` 54 | color: #fff; 55 | font-size: ${(props) => props.theme.fonts.medium}; 56 | color: ${(props) => props.theme.colors.gray}; 57 | font-family: ${(props) => props.theme.fontName.regular}; 58 | `; 59 | 60 | export const ScoreContainer = styled.View` 61 | flex-direction: row; 62 | width: 100%; 63 | align-items: center; 64 | align-content: space-around; 65 | margin-top: ${hpx(10)}; 66 | `; 67 | export const WinsLoosesContainer = styled.View` 68 | align-items: center; 69 | margin-horizontal: 10px; 70 | `; 71 | export const ScoreTitle = styled.Text` 72 | font-size: ${(props) => props.theme.fonts.small}; 73 | color: ${(props) => props.theme.colors.gray}; 74 | font-family: ${(props) => props.theme.fontName.regular}; 75 | `; 76 | export const ScoreLooseValue = styled.Text` 77 | font-size: ${(props) => props.theme.fonts.large}; 78 | color: ${(props) => props.theme.colors.red}; 79 | font-family: ${(props) => props.theme.fontName.bold}; 80 | `; 81 | export const ScoreWinValue = styled.Text` 82 | font-size: ${(props) => props.theme.fonts.large}; 83 | color: ${(props) => props.theme.colors.green}; 84 | font-family: ${(props) => props.theme.fontName.bold}; 85 | `; 86 | -------------------------------------------------------------------------------- /src/Components/Quiz/AwnserButton/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {ButtonContainer, AwnserText, AvatarLeft, AvatarRight} from './styles'; 3 | import {useGame} from '~/Contexts/GameContext'; 4 | 5 | export default function AwnserButton({ 6 | onSelect, 7 | correct, 8 | playerSelected, 9 | opponentSelected, 10 | showCorrectAnswer, 11 | index, 12 | disabled, 13 | small, 14 | children, 15 | }) { 16 | const { 17 | players: {player, opponent}, 18 | } = useGame(); 19 | 20 | return ( 21 | 28 | 36 | {children} 37 | 38 | {playerSelected && ( 39 | 40 | )} 41 | {opponentSelected && ( 42 | 43 | )} 44 | 45 | ); 46 | } 47 | -------------------------------------------------------------------------------- /src/Components/Quiz/AwnserButton/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const ButtonContainer = styled.TouchableOpacity` 5 | flex-grow: 1; 6 | flex-shrink: 2; 7 | flex-basis: ${(props) => (props.small ? '40%' : '100%')}; 8 | justify-content: center; 9 | align-items: center; 10 | height: ${hpx(66)}; 11 | margin: ${hpx(10)}; 12 | border-radius: ${hpx(10)}; 13 | background-color: ${(props) => 14 | props.showCorrectAnwser && props.correct 15 | ? props.theme.colors.green 16 | : props.showCorrectAnwser && !props.correct && props.selected 17 | ? props.theme.colors.red 18 | : props.theme.colors.secondary}; 19 | `; 20 | 21 | export const AwnserText = styled.Text` 22 | opacity: ${(props) => (props.opacity ? 0.5 : 1)}; 23 | color: ${(props) => 24 | props.showCorrectAnwser && (props.correct || props.selected) 25 | ? props.theme.colors.secondary 26 | : props.theme.colors.btnText}; 27 | text-align: center; 28 | font-size: ${(props) => props.theme.fonts.xxlarge}; 29 | padding: ${hpx(10)}; 30 | `; 31 | 32 | export const AvatarLeft = styled.Image` 33 | position: absolute; 34 | left: ${wpx(-18)}; 35 | width: ${hpx(36)}; 36 | height: ${hpx(36)}; 37 | border-radius: ${hpx(25)}; 38 | border-width: 2px; 39 | border-color: #fff; 40 | `; 41 | 42 | export const AvatarRight = styled.Image` 43 | position: absolute; 44 | right: ${wpx(-18)}; 45 | width: ${hpx(36)}; 46 | height: ${hpx(36)}; 47 | border-radius: ${hpx(25)}; 48 | border-width: 2px; 49 | border-color: #fff; 50 | `; 51 | -------------------------------------------------------------------------------- /src/Components/Quiz/Awnsers/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useCallback, useEffect, useRef} from 'react'; 2 | import {Container, AwnserContainer} from './styles'; 3 | import AwnserButton from '../AwnserButton'; 4 | import {useGame} from '~/Contexts/GameContext'; 5 | import {useAuth} from '~/Contexts/AuthContext'; 6 | 7 | export default function Awnser() { 8 | const { 9 | quiz, 10 | setQuiz, 11 | emit, 12 | game: {matchId}, 13 | roundTime, 14 | } = useGame(); 15 | const {user} = useAuth(); 16 | const fadeRef = useRef(null); 17 | 18 | const [disableAllButtons, setDisableAllButtons] = useState(false); 19 | 20 | useEffect(() => { 21 | fadeRef.current.start(); 22 | }, []); 23 | 24 | const selectAwnser = useCallback( 25 | (id) => { 26 | setDisableAllButtons(true); 27 | let newAnswers = quiz.answers; 28 | console.log('resp', id, quiz.answers, newAnswers[id - 1]); 29 | newAnswers[id - 1].playerSelected = true; 30 | setQuiz({ 31 | ...quiz, 32 | disableAllButtons: true, 33 | answers: newAnswers, 34 | }); 35 | emit('answer-question', { 36 | userId: user.id, 37 | matchId: matchId, 38 | questionId: quiz.questionId, 39 | answer: id, 40 | time: roundTime, 41 | }); 42 | }, 43 | [setQuiz, quiz.answers, roundTime], 44 | ); 45 | 46 | return ( 47 | 48 | 53 | {quiz.answers.map((i) => ( 54 | selectAwnser(i.id)} 57 | showCorrectAnswer={quiz.showCorrectAnswer} 58 | key={i.id} 59 | correct={i.correct} 60 | playerSelected={i.playerSelected} 61 | opponentSelected={i.opponentSelected} 62 | small={!!quiz.questionImage}> 63 | {i.text} 64 | 65 | ))} 66 | 67 | 68 | ); 69 | } 70 | -------------------------------------------------------------------------------- /src/Components/Quiz/Awnsers/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | import {Fade} from '~/Components/Animations'; 4 | 5 | export const Container = styled(Fade).attrs({ 6 | flex: 1, 7 | justifyContent: 'flex-end', 8 | })` 9 | justify-content: flex-end; 10 | padding: ${hpx(10)}; 11 | height: 100%; 12 | width: 100%; 13 | `; 14 | 15 | export const AwnserContainer = styled.View` 16 | flex-direction: row; 17 | flex-wrap: wrap; 18 | height: ${(props) => 19 | props.small ? props.theme.hpx(200) : props.theme.hpx(340)}; 20 | margin-bottom: ${hpx(10)}; 21 | `; 22 | -------------------------------------------------------------------------------- /src/Components/Quiz/index.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useRef} from 'react'; 2 | import {useGame} from '~/Contexts/GameContext'; 3 | import {Container, QuestionContainer, Question, Image} from './styles'; 4 | import Awnsers from './Awnsers'; 5 | import {Fade} from '../Animations'; 6 | 7 | export default function Quiz() { 8 | const {quiz, setQuiz, hubConnect} = useGame(); 9 | const fadeRef = useRef(null); 10 | 11 | useEffect(() => { 12 | fadeRef.current.start(); 13 | }, [fadeRef.current]); 14 | 15 | return ( 16 | 17 | 18 | 19 | 23 | {quiz.question} 24 | 25 | 26 | {!!quiz?.questionImage && } 27 | 28 | 29 | 30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /src/Components/Quiz/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | flex: 1; 6 | align-items: center; 7 | justify-content: flex-start; 8 | width: 100%; 9 | `; 10 | 11 | export const QuestionContainer = styled.View` 12 | align-items: center; 13 | justify-content: center; 14 | height: ${(props) => 15 | props.small ? props.theme.hpx(150) : props.theme.hpx(250)}; 16 | `; 17 | 18 | export const Question = styled.Text` 19 | color: ${(props) => props.theme.colors.secondary}; 20 | text-align: center; 21 | font-size: ${(props) => props.theme.fonts.xxlarge}; 22 | padding: ${hpx(10)} ${wpx(20)}; 23 | `; 24 | 25 | export const Image = styled.Image` 26 | min-height: ${hpx(220)}; 27 | min-width: 90%; 28 | resize-mode: contain; 29 | `; 30 | -------------------------------------------------------------------------------- /src/Components/RoundCounter/index.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, useRef} from 'react'; 2 | import {Fade} from '../Animations'; 3 | import {RoundConteiner, RoundTitle} from './styles'; 4 | 5 | export default function RoundCounter({actualRound, totalRound, hideScreen}) { 6 | const fadeRef = useRef(null); 7 | 8 | useEffect(() => { 9 | fadeRef.current.cycle(hideScreen); 10 | }, [fadeRef.current]); 11 | 12 | return ( 13 | 14 | 15 | Round {actualRound} 16 | 17 | {actualRound} of {totalRound} 18 | 19 | 20 | 21 | ); 22 | } 23 | -------------------------------------------------------------------------------- /src/Components/RoundCounter/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | import {Animated} from 'react-native'; 4 | 5 | export const RoundConteiner = styled.View` 6 | flex: 1; 7 | align-items: center; 8 | justify-content: center; 9 | `; 10 | 11 | export const RoundTitle = styled.Text` 12 | color: #fff; 13 | font-size: ${(props) => 14 | props.small ? props.theme.fonts.large : props.theme.fonts.xxlarge}; 15 | margin-bottom: ${hpx(20)}; 16 | font-family: ${(props) => props.theme.fontName.bold}; 17 | `; 18 | -------------------------------------------------------------------------------- /src/Components/UserList/UserListItem.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import {ContainerUserList, Image, Name} from './styles'; 4 | import {TouchableOpacity} from 'react-native'; 5 | import {useNavigation} from '@react-navigation/native'; 6 | 7 | export default function UserListItem({data, onPress}) { 8 | const navigation = useNavigation(); 9 | const {id, login, avatar} = data; 10 | 11 | return ( 12 | navigation.navigate('Profile', {data})}> 13 | 14 | 15 | @{login} 16 | 17 | 18 | ); 19 | } 20 | -------------------------------------------------------------------------------- /src/Components/UserList/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react'; 2 | 3 | import {Container, Title, LoadingContainer} from './styles'; 4 | import {FlatList, ActivityIndicator} from 'react-native'; 5 | import UserListItem from './UserListItem'; 6 | 7 | export default function UserList({data, title, onPress}) { 8 | console.log('dataUsers', data); 9 | return ( 10 | 11 | {title} 12 | {data ? ( 13 | item.id.toString()} 17 | showsHorizontalScrollIndicator={false} 18 | renderItem={({item}) => } 19 | /> 20 | ) : ( 21 | 22 | 23 | 24 | )} 25 | 26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/Components/UserList/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Container = styled.View` 5 | align-items: flex-start; 6 | width: 100%; 7 | background: rgba(255, 255, 255, 0.3); 8 | padding-vertical: ${hpx(10)}; 9 | margin-top: ${hpx(20)}; 10 | height: ${hpx(140)}; 11 | `; 12 | 13 | export const ContainerUserList = styled.View` 14 | align-items: center; 15 | margin-right: ${wpx(5)}; 16 | `; 17 | export const Image = styled.Image` 18 | height: ${hpx(60)}; 19 | width: ${hpx(60)}; 20 | border-radius: ${hpx(30)}; 21 | `; 22 | export const Name = styled.Text.attrs((props) => ({ 23 | ellipsizeMode: 'tail', 24 | numberOfLines: 1, 25 | }))` 26 | width: ${wpx(90)}; 27 | color: ${(props) => props.theme.colors.secondary}; 28 | text-align: center; 29 | font-size: ${(props) => props.theme.fonts.small}; 30 | margin-top: ${hpx(5)}; 31 | `; 32 | 33 | export const Title = styled.Text` 34 | color: ${(props) => props.theme.colors.secondary}; 35 | text-align: center; 36 | font-size: ${(props) => props.theme.fonts.small}; 37 | padding-horizontal: ${wpx(20)}; 38 | font-weight: bold; 39 | margin-bottom: ${hpx(10)}; 40 | `; 41 | export const LoadingContainer = styled.View` 42 | align-items: center; 43 | justify-content: center; 44 | width: 100%; 45 | flex: 1; 46 | `; 47 | -------------------------------------------------------------------------------- /src/Contexts/AppContext.js: -------------------------------------------------------------------------------- 1 | import React, {createContext, useContext, useState, useEffect} from 'react'; 2 | import styles from '~/Utils/styles'; 3 | import {ThemeProvider} from 'styled-components'; 4 | import GameProvider from './GameContext'; 5 | import AuthProvider from './AuthContext'; 6 | import {SafeAreaProvider} from 'react-native-safe-area-context'; 7 | import Loading from '~/Components/Loading'; 8 | import {getMusicEnabled, setMusicEnabled} from '~/Storage/AppStorage'; 9 | 10 | export const AppContext = createContext(); 11 | 12 | export default function AppProvider({children}) { 13 | const [musicStatus, setMusicStatus] = useState(true); 14 | const [loading, setLoading] = useState(false); 15 | 16 | useEffect(() => { 17 | checkMusicEnabled(); 18 | }, []); 19 | 20 | const checkMusicEnabled = async () => { 21 | const music = await getMusicEnabled(); 22 | setMusicStatus(music); 23 | }; 24 | 25 | const changeMusicStatus = async () => { 26 | const newStatus = !musicStatus; 27 | await setMusicEnabled(newStatus); 28 | setMusicStatus(newStatus); 29 | }; 30 | 31 | return ( 32 | 34 | 35 | 36 | 37 | {loading && } 38 | {children} 39 | 40 | 41 | 42 | 43 | ); 44 | } 45 | 46 | export function useApp() { 47 | const context = useContext(AppContext); 48 | return context; 49 | } 50 | -------------------------------------------------------------------------------- /src/Contexts/AuthContext.js: -------------------------------------------------------------------------------- 1 | import React, {createContext, useState, useContext, useEffect} from 'react'; 2 | import {saveUser, getUser} from '~/Storage/UserStorage'; 3 | export const AuthContext = createContext(); 4 | 5 | const AuthProvider = ({children}) => { 6 | const [user, setUser] = useState({}); 7 | 8 | useEffect(() => { 9 | getLocalUserData(); 10 | }, []); 11 | 12 | const getLocalUserData = async () => { 13 | const user = await getUser(); 14 | 15 | if (user?.login) { 16 | setUser(user); 17 | } 18 | }; 19 | 20 | return ( 21 | 22 | {children} 23 | 24 | ); 25 | }; 26 | export default AuthProvider; 27 | 28 | export function useAuth() { 29 | const context = useContext(AuthContext); 30 | return context; 31 | } 32 | -------------------------------------------------------------------------------- /src/Contexts/GameContext.js: -------------------------------------------------------------------------------- 1 | import React, {createContext, useState, useContext, useEffect} from 'react'; 2 | import {connect, hubEmit} from '~/Service/SocketIOClient'; 3 | 4 | export const GameContext = createContext(); 5 | const GameProvider = ({children}) => { 6 | const [hubConnect, setHubConnect] = useState(); 7 | const [showQuestionScreen, setShowQuestionScreen] = useState(false); 8 | const [showRoundScreen, setShowRoundScreen] = useState(true); 9 | const [players, setPlayers] = useState({ 10 | player: { 11 | name: 'Ricardo Vaz Correia Dutra', 12 | score: 10, 13 | avatar: 14 | 'https://img.quizur.com/f/img5dcff6e29551f7.10735221.png?lastEdited=1573910302', 15 | }, 16 | opponent: { 17 | name: 'Daniel Porto Carvalho', 18 | score: 30, 19 | avatar: 20 | 'https://img.quizur.com/f/img5dcff6e29551f7.10735221.png?lastEdited=1573910302', 21 | }, 22 | }); 23 | const [roundTime, setRoundTime] = useState(''); 24 | const [result, setResult] = useState({ 25 | opponent: {id: 8, losses: 7, score: 0, ties: 0, wins: 5}, 26 | owner: {id: 1, losses: 21, score: 0, ties: 8, wins: 33}, 27 | }); 28 | 29 | const isPlayer = (ownerId) => { 30 | return players.player.id === ownerId; 31 | }; 32 | 33 | const [quiz, setQuiz] = useState({ 34 | answers: [], 35 | showCorrectAnwser: false, 36 | questionImage: null, 37 | disableAllButtons: false, 38 | }); 39 | 40 | const [game, setGame] = useState({ 41 | currentRound: 1, 42 | totalRound: 5, 43 | showRoundScreen: false, 44 | matchId: 10, 45 | roomCode: '', 46 | }); 47 | 48 | const emit = (path, body) => { 49 | hubEmit(hubConnect, path, body); 50 | }; 51 | useEffect(() => { 52 | async function connectHub() { 53 | let hubConnect = await connect(); 54 | console.log('conectar no socket'); 55 | setHubConnect(hubConnect); 56 | } 57 | connectHub(); 58 | }, []); 59 | 60 | useEffect(() => { 61 | console.log('GameUpdated', game); 62 | }, [game]); 63 | 64 | useEffect(() => { 65 | console.log('Initializing GameContext', game); 66 | }, []); 67 | return ( 68 | 89 | {children} 90 | 91 | ); 92 | }; 93 | export default GameProvider; 94 | export function useGame() { 95 | const context = useContext(GameContext); 96 | return context; 97 | } 98 | -------------------------------------------------------------------------------- /src/Navigation/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {createStackNavigator} from '@react-navigation/stack'; 3 | import {NavigationContainer} from '@react-navigation/native'; 4 | 5 | import Main from '../Screens/Main'; 6 | import Home from '../Screens/Home'; 7 | import WaitingRoom from '../Screens/WaitingRoom'; 8 | import JoinRoom from '../Screens/JoinRoom'; 9 | import Game from '../Screens/Game'; 10 | import Result from '../Screens/Result'; 11 | import Profile from '~/Screens/Profile'; 12 | 13 | const Stack = createStackNavigator(); 14 | 15 | export default function Navigation() { 16 | return ( 17 | 18 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | ); 32 | } 33 | -------------------------------------------------------------------------------- /src/Screens/Game/index.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect, memo, useCallback} from 'react'; 2 | import {PageContainer} from '~/Components/Layout'; 3 | import RoundCounter from '~/Components/RoundCounter'; 4 | import Question from '~/Components/Quiz'; 5 | import GameTopInfo from '../../Components/GameTopInfo'; 6 | import {useGame} from '~/Contexts/GameContext'; 7 | import AudioPlayer, { AUDIOS } from '~/Utils/AudioPlayer'; 8 | 9 | function Game({navigation}) { 10 | const { 11 | game, 12 | quiz, 13 | setQuiz, 14 | setGame, 15 | hubConnect, 16 | isPlayer, 17 | players, 18 | setPlayers, 19 | setRoundTime, 20 | showQuestionScreen, 21 | setShowQuestionScreen, 22 | } = useGame(); 23 | 24 | const onQuestionRecived = useCallback((data) => { 25 | setQuiz({ 26 | ...quiz, 27 | answers: [ 28 | {text: data.answer1, id: 1}, 29 | {text: data.answer2, id: 2}, 30 | {text: data.answer3, id: 3}, 31 | {text: data.answer4, id: 4}, 32 | ], 33 | disableAllButtons: false, 34 | showCorrectAnswer: false, 35 | questionImage: data.image, 36 | question: data.title, 37 | questionId: data.id, 38 | }); 39 | }, []); 40 | 41 | //TESTAR 42 | const onRoundEnd = useCallback( 43 | (data) => { 44 | AudioPlayer.stop('countdown'); 45 | console.log('onRoundEnd'); 46 | let newAnwsers = quiz.answers; 47 | let newPlayers = players; 48 | const isOwner = isPlayer(data?.owner?.id); 49 | const myData = isOwner ? data.owner : data.opponent; 50 | const myOpponentData = !isOwner ? data.owner : data.opponent; 51 | newPlayers.player.score = myData.score; 52 | newPlayers.opponent.score = myOpponentData.score; 53 | 54 | newAnwsers[data.correctAnswer - 1].correct = true; 55 | 56 | if (myOpponentData.answer > 0) { 57 | newAnwsers[myOpponentData.answer - 1].opponentSelected = true; 58 | } 59 | if (myData.answer == data.correctAnswer) { 60 | AudioPlayer.play(AUDIOS.SUCCESS, 'ui'); 61 | } else { 62 | AudioPlayer.play(AUDIOS.ERROR, 'ui'); 63 | } 64 | 65 | setPlayers(newPlayers); 66 | 67 | setQuiz({ 68 | ...quiz, 69 | answers: newAnwsers, 70 | showCorrectAnswer: true, 71 | disableAllButtons: true, 72 | }); 73 | }, 74 | [quiz, quiz.answers, players], 75 | ); 76 | 77 | const onMatchEndRecived = useCallback((data) => { 78 | console.log('onMatchEnd'); 79 | let winned = false; 80 | let tied = !data?.opponent?.winned && !data?.owner?.winned; 81 | if (isPlayer(data?.owner?.id)) { 82 | winned = data?.owner?.winned; 83 | } else if (isPlayer(data?.opponent?.id)) { 84 | winned = data?.opponent?.winned; 85 | } 86 | setShowQuestionScreen(false); 87 | 88 | navigation.replace('Result', {didWin: winned, didTie: tied}); 89 | }, []); 90 | 91 | useEffect(() => { 92 | console.log('assign match-start-question'); 93 | hubConnect.on('match-start-question', onQuestionRecived); 94 | hubConnect.on('match-round-end', onRoundEnd); 95 | hubConnect.on('match-countdown', ({seconds}) => { 96 | console.log('Going to update CountDown', seconds); 97 | setRoundTime(seconds); 98 | }); 99 | hubConnect.on('match-start-round', ({currentRound, totalRound}) => { 100 | console.log('match-start-round'); 101 | setGame({ 102 | ...game, 103 | showRoundScreen: true, 104 | currentRound: currentRound, 105 | totalRound: totalRound, 106 | }); 107 | setShowQuestionScreen(false); 108 | //navigation.navigate('Game'); 109 | }); 110 | 111 | hubConnect.on('match-start-question', () => { 112 | console.log('match-start-question'); 113 | setRoundTime(''); 114 | setShowQuestionScreen(true); 115 | AudioPlayer.play(AUDIOS.COUNTDOWN, 'countdown'); 116 | setGame({ 117 | ...game, 118 | showRoundScreen: false, 119 | }); 120 | }); 121 | 122 | hubConnect.on('match-end', onMatchEndRecived); 123 | 124 | return () => { 125 | console.log('unassign match-start-question'); 126 | hubConnect.off('match-start-question', onQuestionRecived); 127 | hubConnect.off('match-round-end', onRoundEnd); 128 | hubConnect.off('match-countdown'); 129 | hubConnect.off('match-start-question'); 130 | hubConnect.off('match-start-round'); 131 | hubConnect.off('match-end', onMatchEndRecived); 132 | }; 133 | }, [onQuestionRecived, onRoundEnd]); 134 | 135 | return ( 136 | 137 | {game.showRoundScreen && ( 138 | 142 | )} 143 | 144 | {showQuestionScreen && ( 145 | <> 146 | 147 | 148 | 149 | )} 150 | 151 | ); 152 | } 153 | 154 | export default memo(Game); 155 | -------------------------------------------------------------------------------- /src/Screens/Home copy/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | import {Platform} from 'react-native'; 3 | 4 | import {Container, ButtonsContainer} from './styles'; 5 | import {PageContainer} from './node_modules/~/Components/Layout'; 6 | import Header from './node_modules/~/Components/Header'; 7 | import ProfileHomeDisplay from './node_modules/~/Components/ProfileHomeDisplay'; 8 | import CustomButton from './node_modules/~/Components/CustomButton'; 9 | import {createRoom} from './node_modules/~/Service/MatchApi'; 10 | import {getRecentlyUsers} from './node_modules/~/Service/AuthApi'; 11 | import {useAuth} from './node_modules/~/Contexts/AuthContext'; 12 | import {useGame} from './node_modules/~/Contexts/GameContext'; 13 | import {useApp} from './node_modules/~/Contexts/AppContext'; 14 | import UserList from './node_modules/~/Components/UserList'; 15 | 16 | export default function Home({navigation}) { 17 | const [recentlyUsers, setRecentlyUsers] = useState([]); 18 | const {user} = useAuth(); 19 | const {game, setGame, hubConnect, emit} = useGame(); 20 | const {setLoading} = useApp(); 21 | 22 | useEffect(() => { 23 | getRecentlyUsersData(); 24 | hubConnect.on('recent-played', onRecentPlayed); 25 | emit('client-connect'); 26 | 27 | return () => { 28 | hubConnect.off('recent-played', onRecentPlayed); 29 | }; 30 | }, []); 31 | 32 | const getRecentlyUsersData = async () => { 33 | const userList = await getRecentlyUsers(); 34 | setRecentlyUsers(filterMyselfFromRecentUsers(userList.data)); 35 | }; 36 | const onRecentPlayed = (data) => { 37 | console.log(`onRecentPlayed ${Platform.OS}`, data); 38 | setRecentlyUsers(filterMyselfFromRecentUsers(data)); 39 | }; 40 | const filterMyselfFromRecentUsers = (data) => { 41 | return data.filter((item) => item.id != user.id); 42 | }; 43 | const handleCreateRoom = async (opponentId = '') => { 44 | setLoading(true); 45 | try { 46 | const dataReturn = await createRoom(user.id, opponentId); 47 | const {matchId, matchCode} = dataReturn.data; 48 | setGame({...game, matchId: matchId, roomCode: matchCode}); 49 | navigation.navigate('WaitingRoom'); 50 | } catch (error) { 51 | console.log(error); 52 | Snackbar.show({ 53 | text: 'Server error, try again later.', 54 | duration: Snackbar.LENGTH_SHORT, 55 | }); 56 | } 57 | 58 | setLoading(false); 59 | }; 60 | return ( 61 | 62 |

63 | 64 | 69 | 70 | handleCreateRoom()}> 71 | Create Room 72 | 73 | navigation.navigate('JoinRoom')}> 74 | Join Room 75 | 76 | 77 | 78 | ); 79 | } 80 | -------------------------------------------------------------------------------- /src/Screens/Home copy/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from './node_modules/~/Utils/styles'; 3 | 4 | export const ButtonsContainer = styled.View` 5 | position: absolute; 6 | bottom: ${hpx(20)}; 7 | width: 100%; 8 | padding-horizontal: ${hpx(20)}; 9 | `; 10 | -------------------------------------------------------------------------------- /src/Screens/Home/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | import {Platform} from 'react-native'; 3 | 4 | import {Container, ButtonsContainer} from './styles'; 5 | import {PageContainer} from '~/Components/Layout'; 6 | import Header from '~/Components/Header'; 7 | import ProfileHomeDisplay from '~/Components/ProfileHomeDisplay'; 8 | import CustomButton from '~/Components/CustomButton'; 9 | import {createRoom} from '~/Service/MatchApi'; 10 | import {getRecentlyUsers} from '~/Service/AuthApi'; 11 | import {useAuth} from '~/Contexts/AuthContext'; 12 | import {useGame} from '~/Contexts/GameContext'; 13 | import {useApp} from '~/Contexts/AppContext'; 14 | import UserList from '~/Components/UserList'; 15 | 16 | export default function Home({navigation}) { 17 | const [recentlyUsers, setRecentlyUsers] = useState([]); 18 | const {user} = useAuth(); 19 | const {game, setGame, hubConnect, emit} = useGame(); 20 | const {setLoading} = useApp(); 21 | 22 | useEffect(() => { 23 | getRecentlyUsersData(); 24 | hubConnect.on('recent-played', onRecentPlayed); 25 | emit('client-connect'); 26 | 27 | return () => { 28 | hubConnect.off('recent-played', onRecentPlayed); 29 | }; 30 | }, []); 31 | 32 | const getRecentlyUsersData = async () => { 33 | const userList = await getRecentlyUsers(); 34 | setRecentlyUsers(filterMyselfFromRecentUsers(userList.data)); 35 | }; 36 | const onRecentPlayed = (data) => { 37 | console.log(`onRecentPlayed ${Platform.OS}`, data); 38 | setRecentlyUsers(filterMyselfFromRecentUsers(data)); 39 | }; 40 | const filterMyselfFromRecentUsers = (data) => { 41 | return data.filter((item) => item.id != user.id); 42 | }; 43 | 44 | const handleCreateRoom = async () => { 45 | setLoading(true); 46 | try { 47 | const dataReturn = await createRoom(user.id); 48 | const {matchId, matchCode} = dataReturn.data; 49 | setGame({...game, matchId: matchId, roomCode: matchCode}); 50 | navigation.navigate('WaitingRoom'); 51 | } catch (error) { 52 | console.log(error); 53 | Snackbar.show({ 54 | text: 'Server error, try again later.', 55 | duration: Snackbar.LENGTH_SHORT, 56 | }); 57 | } 58 | 59 | setLoading(false); 60 | }; 61 | return ( 62 | 63 |
64 | 65 | 66 | 67 | handleCreateRoom()}> 68 | Create Room 69 | 70 | navigation.navigate('JoinRoom')}> 71 | Join Room 72 | 73 | 74 | 75 | ); 76 | } 77 | -------------------------------------------------------------------------------- /src/Screens/Home/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const ButtonsContainer = styled.View` 5 | position: absolute; 6 | bottom: ${hpx(20)}; 7 | width: 100%; 8 | padding-horizontal: ${hpx(20)}; 9 | `; 10 | -------------------------------------------------------------------------------- /src/Screens/JoinRoom/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect, useRef} from 'react'; 2 | import {Keyboard} from 'react-native'; 3 | import { 4 | Container, 5 | Title, 6 | ButtonsContainer, 7 | ContentContainer, 8 | Image, 9 | Digit, 10 | } from './styles'; 11 | import {PageContainer} from '../../Components/Layout'; 12 | 13 | import CustomButton from '../../Components/CustomButton'; 14 | import Snackbar from 'react-native-snackbar'; 15 | import Header from '../../Components/Header'; 16 | import {useGame} from '~/Contexts/GameContext'; 17 | import {useAuth} from '~/Contexts/AuthContext'; 18 | import {joinMatch} from '~/Service/MatchApi'; 19 | import {useApp} from '~/Contexts/AppContext'; 20 | import { 21 | CodeField, 22 | Cursor, 23 | useClearByFocusCell, 24 | } from 'react-native-confirmation-code-field'; 25 | 26 | export default function JoinRoom({navigation, route}) { 27 | const [roomCode, setRoomCode] = useState(''); 28 | const {params} = route; 29 | const [value, setValue] = useState(''); 30 | const [props, getCellOnLayoutHandler] = useClearByFocusCell({ 31 | value, 32 | setValue, 33 | }); 34 | const CodeInputRef = useRef(); 35 | const {user} = useAuth(); 36 | const {game, setGame} = useGame(); 37 | const {setLoading} = useApp(); 38 | 39 | useEffect(() => { 40 | if (roomCode.length == 6 && !params?.roomCode) { 41 | getRoom(roomCode); 42 | } 43 | }, [roomCode]); 44 | 45 | useEffect(() => { 46 | CodeInputRef.current.focus(); 47 | }, []); 48 | 49 | useEffect(() => { 50 | if (params?.roomCode) { 51 | console.log(user); 52 | setRoomCode(params.roomCode); 53 | getRoom(params.roomCode); 54 | } 55 | }, [params]); 56 | 57 | const getRoom = async (roomCode) => { 58 | if (roomCode) { 59 | Keyboard.dismiss(); 60 | setLoading(true); 61 | try { 62 | const dataReturn = await joinMatch(user.id, roomCode); 63 | const {matchId} = dataReturn.data; 64 | setGame({...game, matchId: matchId}); 65 | setTimeout(() => { 66 | navigation.replace('WaitingRoom'); 67 | }, 100); 68 | } catch (error) { 69 | Snackbar.show({ 70 | text: error.response.data.message, 71 | duration: Snackbar.LENGTH_SHORT, 72 | }); 73 | } 74 | setLoading(false); 75 | } else { 76 | Snackbar.show({ 77 | text: 'Type the Room Code', 78 | duration: Snackbar.LENGTH_SHORT, 79 | }); 80 | } 81 | }; 82 | 83 | return ( 84 | 85 |
86 | 87 | 88 | Room Code 89 | setRoomCode(text)} 94 | value={roomCode} 95 | renderCell={({index, symbol, isFocused}) => ( 96 | 97 | {symbol || (isFocused ? : null)} 98 | 99 | )}> 100 | 101 | 102 | getRoom(roomCode)}>Enter 103 | 104 | 105 | ); 106 | } 107 | -------------------------------------------------------------------------------- /src/Screens/JoinRoom/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Title = styled.Text` 5 | color: ${(props) => props.theme.colors.secondary}; 6 | font-size: ${(props) => props.theme.fonts.xlarge}; 7 | margin-bottom: ${hpx(20)}; 8 | text-align: center; 9 | font-family: ${(props) => props.theme.fontName.medium}; 10 | `; 11 | 12 | export const ContentContainer = styled.View` 13 | align-items: center; 14 | margin-bottom: ${hpx(40)}; 15 | `; 16 | export const Image = styled.Image` 17 | margin-bottom: ${hpx(20)}; 18 | `; 19 | 20 | export const ButtonsContainer = styled.View` 21 | bottom: ${hpx(20)}; 22 | width: 100%; 23 | padding-horizontal: ${wpx(20)}; 24 | `; 25 | 26 | export const Digit = styled.Text` 27 | width: ${hpx(50)}; 28 | height: ${hpx(50)}; 29 | line-height: ${hpx(50)}; 30 | font-size: ${(props) => props.theme.fonts.xlarge}; 31 | margin-right: ${wpx(10)}; 32 | color: ${(props) => props.theme.colors.secondary}; 33 | background: #a790f4; 34 | text-align: center; 35 | font-family: ${(props) => props.theme.fontName.medium}; 36 | `; 37 | -------------------------------------------------------------------------------- /src/Screens/Main/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect, useRef} from 'react'; 2 | import {Title, ButtonsContainer, Logo, UserContainer} from './styles'; 3 | 4 | import {getData} from '~/Service/AuthApi'; 5 | import InputText from '~/Components/InputText'; 6 | import CustomButton from '~/Components/CustomButton'; 7 | import SplashScreen from 'react-native-splash-screen'; 8 | 9 | import { 10 | saveUser, 11 | getUser, 12 | savePushToken, 13 | getPushToken, 14 | } from '~/Storage/UserStorage'; 15 | import {PageContainer} from '~/Components/Layout'; 16 | import Snackbar from 'react-native-snackbar'; 17 | import {useLinking} from '@react-navigation/native'; 18 | import {useAuth} from '~/Contexts/AuthContext'; 19 | import {useApp} from '~/Contexts/AppContext'; 20 | import {useKeyboard} from '@react-native-community/hooks'; 21 | import OneSignalConfig from '~/Service/pushService'; 22 | import {KeyboardAwareScrollView} from 'react-native-keyboard-aware-scroll-view'; 23 | 24 | export default function Main({navigation}) { 25 | const keyboard = useKeyboard(); 26 | const [username, setUsername] = useState(''); 27 | const ref = React.useRef(); 28 | const {setUser} = useAuth(); 29 | const {setLoading} = useApp(); 30 | const [autoFocusLogin, setAutoFocusLogin] = useState(false); 31 | const {getInitialState} = useLinking(ref, { 32 | prefixes: [ 33 | 'http://devquiz.app/invite', 34 | 'devquiz://invite', 35 | 'https://devquiz.app/invite', 36 | ], 37 | }); 38 | const loginRef = useRef(); 39 | 40 | const getLocalUserData = async () => { 41 | const user = await getUser(); 42 | 43 | if (user?.login) { 44 | const roomCode = await getDeepLink(); 45 | if (roomCode) { 46 | navigation.navigate('Home'); 47 | navigation.navigate('JoinRoom', {roomCode: roomCode}); 48 | setLoading(false); 49 | } else { 50 | getUserData(user.login); 51 | } 52 | } else { 53 | loginRef.current.focus(); 54 | setLoading(false); 55 | } 56 | }; 57 | useEffect(() => { 58 | SplashScreen.hide(); 59 | //check if we have this Local User 60 | setLoading(true); 61 | getLocalUserData(); 62 | }, []); 63 | 64 | const getDeepLink = async () => { 65 | const deepLink = await getInitialState(); 66 | let roomCode = deepLink?.routes[0]?.name; 67 | return roomCode; 68 | }; 69 | const getUserData = async (username) => { 70 | setLoading(true); 71 | if (username) { 72 | try { 73 | let pushToken = await getPushToken(); 74 | const dataReturn = await getData(username, pushToken); 75 | await saveUser(dataReturn.data); 76 | setUser(dataReturn.data); 77 | navigation.navigate('Home'); 78 | } catch (error) { 79 | console.log(error); 80 | Snackbar.show({ 81 | text: error.response.data.message, 82 | duration: Snackbar.LENGTH_SHORT, 83 | }); 84 | } 85 | } else { 86 | Snackbar.show({ 87 | text: 'Type your github username', 88 | duration: Snackbar.LENGTH_SHORT, 89 | }); 90 | } 91 | setLoading(false); 92 | }; 93 | 94 | return ( 95 | 96 | 97 | 108 | 109 | 113 | Type your Github 114 | 115 | setUsername(text)} 118 | onSubmitEditing={() => getUserData(username)} 119 | autoCapitalize={'none'} 120 | ref={loginRef} 121 | style={{width: '90%'}} 122 | /> 123 | 124 | 125 | getUserData(username)}> 126 | Enter 127 | 128 | 129 | 130 | 131 | ); 132 | } 133 | -------------------------------------------------------------------------------- /src/Screens/Main/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Title = styled.Text` 5 | color: ${(props) => props.theme.colors.secondary}; 6 | font-size: ${(props) => props.theme.fonts.large}; 7 | font-family: 'Ubuntu-Regular'; 8 | `; 9 | 10 | export const ButtonsContainer = styled.View` 11 | position: absolute; 12 | bottom: ${hpx(20)}; 13 | width: 100%; 14 | padding: ${hpx(20)}; 15 | `; 16 | export const Logo = styled.Image` 17 | width: 100%; 18 | height: ${hpx(80)}; 19 | resize-mode: contain; 20 | margin-bottom: ${hpx(40)}; 21 | display: ${(props) => (props.hide ? 'none' : 'flex')}; 22 | `; 23 | 24 | export const UserContainer = styled.View` 25 | flex: 1; 26 | width: 100%; 27 | justify-content: center; 28 | align-items: center; 29 | `; 30 | -------------------------------------------------------------------------------- /src/Screens/Profile/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | import {Platform} from 'react-native'; 3 | 4 | import {Container, ButtonsContainer} from './styles'; 5 | import {PageContainer} from '~/Components/Layout'; 6 | import Header from '~/Components/Header'; 7 | import ProfileHomeDisplay from '~/Components/ProfileHomeDisplay'; 8 | import CustomButton from '~/Components/CustomButton'; 9 | import {createRoom} from '~/Service/MatchApi'; 10 | import {getRecentlyUsers} from '~/Service/AuthApi'; 11 | import {useAuth} from '~/Contexts/AuthContext'; 12 | import {useGame} from '~/Contexts/GameContext'; 13 | import {useApp} from '~/Contexts/AppContext'; 14 | 15 | export default function Profile({navigation, route}) { 16 | const {user} = useAuth(); 17 | const {game, setGame, hubConnect, emit} = useGame(); 18 | const { 19 | params: {data}, 20 | } = route; 21 | const {setLoading} = useApp(); 22 | 23 | useEffect(() => {}, []); 24 | 25 | const handleCreateRoom = async (opponentId = '') => { 26 | setLoading(true); 27 | try { 28 | const dataReturn = await createRoom(user.id, opponentId); 29 | const {matchId, matchCode} = dataReturn.data; 30 | setGame({...game, matchId: matchId, roomCode: matchCode}); 31 | navigation.navigate('WaitingRoom'); 32 | } catch (error) { 33 | console.log(error); 34 | Snackbar.show({ 35 | text: 'Server error, try again later.', 36 | duration: Snackbar.LENGTH_SHORT, 37 | }); 38 | } 39 | 40 | setLoading(false); 41 | }; 42 | return ( 43 | 44 |
45 | 46 | 47 | 48 | handleCreateRoom(data.id)}> 49 | Challenge {data.name} 50 | 51 | 52 | 53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /src/Screens/Profile/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const ButtonsContainer = styled.View` 5 | position: absolute; 6 | bottom: ${hpx(20)}; 7 | width: 100%; 8 | padding-horizontal: ${hpx(20)}; 9 | `; 10 | -------------------------------------------------------------------------------- /src/Screens/Result/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | import {SafeAreaView, Text, StyleSheet} from 'react-native'; 3 | import { 4 | Container, 5 | PlayerAvatar, 6 | ButtonsContainer, 7 | PlayerName, 8 | ScoreContainer, 9 | ScoreWinValue, 10 | ScoreLooseValue, 11 | WinsLoosesContainer, 12 | } from './styles'; 13 | import {PageContainer} from '../../Components/Layout'; 14 | 15 | import CustomButton from '../../Components/CustomButton'; 16 | import {useGame} from '~/Contexts/GameContext'; 17 | import {useAuth} from '~/Contexts/AuthContext'; 18 | import {useApp} from '~/Contexts/AppContext'; 19 | import IconContainer from '~/Components/IconContainer'; 20 | import winIcon from '~/Assets/Images/win_icon.png'; 21 | import looseIcon from '~/Assets/Images/loose_icon.png'; 22 | import AudioPlayer, { AUDIOS } from '~/Utils/AudioPlayer'; 23 | 24 | export default function Result({navigation, route}) { 25 | const [title, setTitle] = useState(''); 26 | const [btnPlayAgainText, setbtnPlayAgainText] = useState('Play again'); 27 | const [btnPlayDisabled, setBtnPlayDisabled] = useState(false); 28 | const [seconds, setSeconds] = useState(10); 29 | const [icon, setIcon] = useState(winIcon); 30 | const {user, setUser} = useAuth(); 31 | const {didWin, didTie} = route.params; 32 | const { 33 | hubConnect, 34 | game, 35 | setGame, 36 | emit, 37 | players: {player, opponent}, 38 | } = useGame(); 39 | 40 | useEffect(() => { 41 | console.log(route.params); 42 | if (didWin) { 43 | setTitle('You win!'); 44 | setIcon(winIcon); 45 | AudioPlayer.play(AUDIOS.WINNER, 'ui'); 46 | } else if (didTie) { 47 | setTitle('Draw!'); 48 | setIcon(winIcon); 49 | AudioPlayer.play(AUDIOS.WINNER, 'ui'); 50 | } else { 51 | setTitle('You loose :('); 52 | setIcon(looseIcon); 53 | AudioPlayer.play(AUDIOS.LOOSER, 'ui'); 54 | } 55 | }, []); 56 | 57 | const handlePlayAgain = () => { 58 | emit('answer-play-again', { 59 | userId: player.id, 60 | matchId: game.matchId, 61 | }); 62 | setBtnPlayDisabled(true); 63 | }; 64 | useEffect(() => { 65 | hubConnect.on('play-again-countdown', onPlayAgainCountdownReceived); 66 | hubConnect.on('play-again', onPlayAgainReceived); 67 | 68 | return () => { 69 | console.log('unassign play-again-countdown'); 70 | hubConnect.off('play-again-countdown', onPlayAgainCountdownReceived); 71 | hubConnect.off('play-again', onPlayAgainReceived); 72 | }; 73 | }, [onPlayAgainCountdownReceived]); 74 | 75 | const onPlayAgainCountdownReceived = ({seconds}) => { 76 | setSeconds(seconds); 77 | setbtnPlayAgainText(`Play again (${seconds})`); 78 | if (seconds == 0) { 79 | setBtnPlayDisabled(true); 80 | setbtnPlayAgainText(`Play again`); 81 | } 82 | }; 83 | 84 | const onPlayAgainReceived = ({userId, matchId, matchCode}) => { 85 | console.log('onPlayAgainReceived'); 86 | if (userId == user.id) { 87 | setGame({...game, matchId: matchId, roomCode: matchCode, player: {}}); 88 | navigation.replace('WaitingRoom', {restart: true}); 89 | } 90 | }; 91 | return ( 92 | 93 | 94 | 95 | 96 | 97 | {player?.name} 98 | {didWin ? ( 99 | {player?.score} 100 | ) : ( 101 | {player?.score} 102 | )} 103 | 104 | 105 | 106 | {opponent?.name} 107 | {didWin ? ( 108 | {opponent?.score} 109 | ) : ( 110 | {opponent?.score} 111 | )} 112 | 113 | 114 | 115 | 116 | 117 | handlePlayAgain()} 119 | disabled={btnPlayDisabled}> 120 | {btnPlayAgainText} 121 | 122 | navigation.replace('Home')}> 123 | Give up 124 | 125 | 126 | 127 | ); 128 | } 129 | -------------------------------------------------------------------------------- /src/Screens/Result/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const Title = styled.Text` 5 | color: ${(props) => props.theme.colors.primary}; 6 | font-size: ${(props) => props.theme.fonts.xlarge}; 7 | margin: ${hpx(20)}; 8 | text-align: center; 9 | `; 10 | 11 | export const ContentContainer = styled.View` 12 | border-radius: ${hpx(10)}; 13 | align-self: center; 14 | `; 15 | 16 | export const ButtonsContainer = styled.View` 17 | bottom: ${hpx(20)}; 18 | width: 100%; 19 | padding-horizontal: ${hpx(20)}; 20 | `; 21 | 22 | export const ScoreContainer = styled.View` 23 | flex-direction: row; 24 | width: 100%; 25 | align-items: center; 26 | align-content: center; 27 | justify-content: space-around; 28 | margin-top: ${hpx(20)}; 29 | `; 30 | export const WinsLoosesContainer = styled.View` 31 | align-items: center; 32 | margin-horizontal: ${wpx(10)}; 33 | `; 34 | export const PlayerAvatar = styled.Image` 35 | width: ${hpx(100)}; 36 | height: ${hpx(100)}; 37 | border-radius: ${hpx(50)}; 38 | `; 39 | export const PlayerName = styled.Text.attrs((props) => ({ 40 | ellipsizeMode: 'tail', 41 | numberOfLines: 1, 42 | }))` 43 | width: ${wpx(120)}; 44 | text-align: center; 45 | font-size: ${(props) => props.theme.fonts.small}; 46 | color: ${(props) => props.theme.colors.gray}; 47 | font-family: ${(props) => props.theme.fontName.regular}; 48 | margin-vertical: ${hpx(10)}; 49 | `; 50 | export const ScoreLooseValue = styled.Text` 51 | font-size: ${(props) => props.theme.fonts.large}; 52 | color: ${(props) => props.theme.colors.red}; 53 | font-family: ${(props) => props.theme.fontName.bold}; 54 | `; 55 | export const ScoreWinValue = styled.Text` 56 | font-size: ${(props) => props.theme.fonts.large}; 57 | color: ${(props) => props.theme.colors.green}; 58 | font-family: ${(props) => props.theme.fontName.bold}; 59 | `; 60 | -------------------------------------------------------------------------------- /src/Screens/WaitingRoom/index.js: -------------------------------------------------------------------------------- 1 | import React, {useState, useEffect} from 'react'; 2 | import {Platform, BackHandler, AppState} from 'react-native'; 3 | import { 4 | VSContainer, 5 | VSLine, 6 | VSImageContainer, 7 | OpponentContainer, 8 | GameContainer, 9 | ShareContainer, 10 | CodeExplainText, 11 | Code, 12 | ButtonsContainer, 13 | CheckOpponent, 14 | CheckFirstPlayer, 15 | } from './styles'; 16 | import {PageContainer} from '../../Components/Layout'; 17 | import Snackbar from 'react-native-snackbar'; 18 | 19 | import Header from '../../Components/Header'; 20 | import ProfileDisplay from '../../Components/ProfileDisplay'; 21 | import CustomButton from '../../Components/CustomButton'; 22 | import LottieView from 'lottie-react-native'; 23 | import IconIonicons from 'react-native-vector-icons/Ionicons'; 24 | import {useAuth} from '~/Contexts/AuthContext'; 25 | import timer from '~/Assets/Animations/timer.json'; 26 | import swords from '~/Assets/Animations/swords.json'; 27 | import countdown from '~/Assets/Animations/countdown.json'; 28 | import {useGame} from '~/Contexts/GameContext'; 29 | import Share from 'react-native-share'; 30 | import AudioPlayer, {AUDIOS} from '~/Utils/AudioPlayer'; 31 | import {useTheme} from 'styled-components'; 32 | 33 | export default function WaitingRoom({navigation, route}) { 34 | const [opponent, setOpponent] = useState(); 35 | const [ready, setReady] = useState(false); 36 | const [startMatch, setStartMatch] = useState(false); 37 | const [opponentReady, setOpponentReady] = useState(false); 38 | const theme = useTheme(); 39 | 40 | const {user} = useAuth(); 41 | const { 42 | hubConnect, 43 | game, 44 | setGame, 45 | emit, 46 | players, 47 | setPlayers, 48 | setRoundTime, 49 | } = useGame(); 50 | const backButtonHandler = () => { 51 | emit('leave-match'); 52 | }; 53 | 54 | const onPlayerJoined = (data) => { 55 | console.log(`player-joined ${Platform.OS}`); 56 | 57 | if (user.id == data.opponent?.id) { 58 | setOpponent(data.owner); 59 | setPlayers({...players, player: data.opponent, opponent: data.owner}); 60 | AudioPlayer.play(AUDIOS.NEWUSER, 'ui'); 61 | } else { 62 | if (data.opponent) { 63 | setOpponent(data.opponent); 64 | AudioPlayer.play(AUDIOS.NEWUSER, 'ui'); 65 | } 66 | 67 | setPlayers({...players, player: data.owner, opponent: data.opponent}); 68 | } 69 | }; 70 | useEffect(() => { 71 | AppState.addEventListener('change', handleChangeAppState); 72 | 73 | AudioPlayer.play(AUDIOS.LOBBY); 74 | 75 | if (game.matchId) { 76 | console.log('joinmatch', { 77 | userId: user.id, 78 | matchId: game.matchId, 79 | }); 80 | emit('join-match', { 81 | userId: user.id, 82 | matchId: game.matchId, 83 | }); 84 | } 85 | 86 | hubConnect.on('player-joined', onPlayerJoined); 87 | 88 | hubConnect.on('player-ready', (data) => { 89 | console.log('player-ready'); 90 | if (data.userId != user.id) { 91 | setOpponentReady(true); 92 | AudioPlayer.play(AUDIOS.READY, 'ui'); 93 | } else { 94 | setReady(true); 95 | AudioPlayer.play(AUDIOS.READY, 'ui'); 96 | } 97 | }); 98 | 99 | hubConnect.on('match-start', (data) => { 100 | console.log('match-start'); 101 | setStartMatch(true); 102 | // setTimeout(() => { 103 | // }, 5000); 104 | }); 105 | 106 | hubConnect.on('player-leaved', ({isMatchOwner, userId}) => { 107 | console.log('player-leaved', isMatchOwner, userId); 108 | if (user.id != userId) { 109 | if (isMatchOwner) { 110 | navigation.goBack(); 111 | backButtonHandler(); 112 | } else { 113 | setOpponent(null); 114 | setOpponentReady(false); 115 | } 116 | 117 | Snackbar.show({ 118 | text: 'Your opponent leave the match', 119 | duration: Snackbar.LENGTH_SHORT, 120 | }); 121 | } 122 | }); 123 | 124 | hubConnect.on('match-start-round', ({currentRound, totalRound}) => { 125 | console.log('match-start-round'); 126 | setGame({ 127 | ...game, 128 | showRoundScreen: true, 129 | currentRound: currentRound, 130 | totalRound: totalRound, 131 | }); 132 | 133 | navigation.replace('Game'); 134 | }); 135 | 136 | // hubConnect.on('match-round-end', (data) => { 137 | // console.log('match-round-end'); 138 | // }); 139 | BackHandler.addEventListener('hardwareBackPress', backButtonHandler); 140 | return () => { 141 | AudioPlayer.stop(); 142 | BackHandler.removeEventListener('hardwareBackPress', backButtonHandler); 143 | hubConnect.off('player-leaved'); 144 | hubConnect.off('match-start-round'); 145 | hubConnect.off('match-start'); 146 | hubConnect.off('player-ready'); 147 | hubConnect.off('player-joined', onPlayerJoined); 148 | AppState.removeEventListener('change', handleChangeAppState); 149 | }; 150 | }, []); 151 | const changeMyStatus = () => { 152 | emit('set-ready', { 153 | userId: user.id, 154 | matchId: game.matchId, 155 | }); 156 | }; 157 | const handleChangeAppState = (newState) => { 158 | if (newState === 'active') { 159 | AudioPlayer.play(AUDIOS.LOBBY); 160 | } else { 161 | AudioPlayer.stop(); 162 | } 163 | }; 164 | const handleFriendInvite = () => { 165 | const shareOptions = { 166 | title: 'DevQuiz', 167 | message: `I challenged you on DevQuiz! You can use this Room Code ${game.roomCode} or just click on the link below to enter.`, 168 | url: `https://devquiz.app/invite/${game.roomCode}`, 169 | }; 170 | Share.open(shareOptions).catch((error) => { 171 | console.log('Failed to share:', error); 172 | }); 173 | }; 174 | 175 | return ( 176 | 177 |
emit('leave-match')} music /> 178 | 179 | 180 | 181 | 182 | 183 | 184 | {!opponent && ( 185 | 194 | )} 195 | {opponent && startMatch && ( 196 | 205 | )} 206 | 207 | {opponent && !startMatch && ( 208 | 209 | )} 210 | 211 | 212 | {opponent && ( 213 | <> 214 | 215 | 220 | 221 | 222 | 227 | 228 | 229 | )} 230 | 231 | 232 | {opponent ? ( 233 | <> 234 | 235 | 236 | 237 | 238 | changeMyStatus()} 241 | disabled={!!ready}> 242 | Ready 243 | 244 | 245 | 246 | ) : ( 247 | <> 248 | 249 | {game.roomCode} 250 | 251 | Share this code with your friend 252 | 253 | Waiting for an opponent... 254 | 255 | 256 | handleFriendInvite()} 259 | onLongPress={() => setOpponent(game.opponent)}> 260 | Invite a friend 261 | 262 | 263 | 264 | )} 265 | 266 | 267 | ); 268 | } 269 | -------------------------------------------------------------------------------- /src/Screens/WaitingRoom/styles.js: -------------------------------------------------------------------------------- 1 | import styled from 'styled-components/native'; 2 | import {hpx, wpx} from '~/Utils/styles'; 3 | 4 | export const GameContainer = styled.View` 5 | width: 100%; 6 | align-items: center; 7 | justify-content: space-between; 8 | flex: 1; 9 | `; 10 | 11 | export const VSContainer = styled.View` 12 | width: 100%; 13 | align-items: center; 14 | justify-content: center; 15 | flex-direction: row; 16 | `; 17 | 18 | export const VSImageContainer = styled.View` 19 | background: #fff; 20 | width: ${hpx(100)}; 21 | height: ${hpx(100)}; 22 | border-radius: ${hpx(50)}; 23 | 24 | align-items: center; 25 | justify-content: center; 26 | elevation: 5; 27 | `; 28 | 29 | export const VSImage = styled.Image``; 30 | 31 | export const VSLine = styled.View` 32 | background: #fff; 33 | width: 100%; 34 | height: ${hpx(5)}; 35 | position: relative; 36 | flex: 1; 37 | `; 38 | 39 | export const OpponentContainer = styled.View` 40 | width: 100%; 41 | align-items: center; 42 | justify-content: center; 43 | flex-direction: row; 44 | margin-bottom: ${hpx(50)}; 45 | `; 46 | 47 | export const ShareContainer = styled.View` 48 | align-items: center; 49 | justify-content: center; 50 | `; 51 | export const Code = styled.Text` 52 | color: ${(props) => props.theme.colors.secondary}; 53 | font-size: ${(props) => props.theme.fonts.xxlarge}; 54 | margin-bottom: ${hpx(20)}; 55 | font-family: ${(props) => props.theme.fontName.bold}; 56 | `; 57 | export const CodeExplainText = styled.Text` 58 | color: ${(props) => props.theme.colors.secondary}; 59 | font-size: ${(props) => props.theme.fonts.medium}; 60 | font-family: ${(props) => props.theme.fontName.regular}; 61 | `; 62 | 63 | export const ButtonsContainer = styled.View` 64 | width: 80%; 65 | `; 66 | 67 | export const CheckFirstPlayer = styled.View` 68 | position: absolute; 69 | bottom: ${hpx(10)}; 70 | right: ${wpx(10)}; 71 | opacity: ${(props) => (props.enabled ? '1' : '0.5')}; 72 | `; 73 | 74 | export const CheckOpponent = styled.View` 75 | position: absolute; 76 | bottom: ${wpx(-65)}; 77 | right: ${wpx(10)}; 78 | opacity: ${(props) => (props.enabled ? '1' : '0.5')}; 79 | `; 80 | -------------------------------------------------------------------------------- /src/Service/AuthApi.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import {SERVER_URL} from '~/config'; 3 | 4 | export function getData(username, playerId = '') { 5 | return axios.post(`${SERVER_URL}user/create`, { 6 | githubuser: username, 7 | pushToken: playerId, 8 | }); 9 | } 10 | export function getRecentlyUsers() { 11 | return axios.get(`${SERVER_URL}user/recent/`); 12 | } 13 | -------------------------------------------------------------------------------- /src/Service/MatchApi.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import {SERVER_URL} from '~/config'; 3 | 4 | export function createRoom(userId, opponentId = '') { 5 | return axios.post(`${SERVER_URL}match/create/`, { 6 | opponentId: opponentId, 7 | userId: userId, 8 | }); 9 | } 10 | export function joinMatch(userId, roomCode) { 11 | return axios.post(`${SERVER_URL}match/join/`, { 12 | matchCode: roomCode, 13 | userId: userId, 14 | }); 15 | } 16 | -------------------------------------------------------------------------------- /src/Service/SocketIOClient.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import {View} from 'react-native'; 3 | import io from 'socket.io-client'; 4 | import {SERVER_URL} from '~/config'; 5 | 6 | export const connect = () => { 7 | try { 8 | const con = io.connect(SERVER_URL, {forceNode: true}); 9 | return con; 10 | } catch (error) { 11 | console.log('SOCKETCON', error); 12 | } 13 | }; 14 | 15 | export const hubEmit = (con, path, body) => { 16 | try { 17 | con.emit(path, body); 18 | } catch (error) { 19 | console.log('socketError', error); 20 | } 21 | }; 22 | // io.on('connect', function () { 23 | // console.log('connect'); 24 | 25 | // io.emit('join-match', { 26 | // match_id: matchId, 27 | // user_id: userId, 28 | // }); 29 | // }); 30 | -------------------------------------------------------------------------------- /src/Service/githubApi.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | const githubRestUrl = 'https://api.github.com/users/'; 3 | 4 | export function getData(username) { 5 | return axios.get(`${githubRestUrl}${username}`); 6 | } 7 | -------------------------------------------------------------------------------- /src/Service/index.js: -------------------------------------------------------------------------------- 1 | const url = 'http://meuguiaapi-dev.us-east-2.elasticbeanstalk.com/api/'; 2 | export const app = { 3 | id: 7, 4 | }; 5 | 6 | export const api = { 7 | categories: `${url}categories/`, 8 | stores: `${url}Stores/app/${app.id}/`, 9 | postStore: `${url}Stores`, 10 | neighborhoods: `${url}neighborhoods/app/${app.id}/`, 11 | }; 12 | 13 | export default api; 14 | -------------------------------------------------------------------------------- /src/Service/pushService.js: -------------------------------------------------------------------------------- 1 | import React, {useEffect} from 'react'; 2 | import OneSignal from 'react-native-onesignal'; 3 | import {savePushToken} from '~/Storage/UserStorage'; 4 | import {useNavigation} from '@react-navigation/native'; 5 | import {ONESIGNAL_APP_KEY} from '~/config'; 6 | 7 | export default function OneSignalConfig() { 8 | const navigation = useNavigation(); 9 | 10 | useEffect(() => { 11 | startOnesignal(); 12 | }, []); 13 | 14 | const startOnesignal = () => { 15 | OneSignal.init(ONESIGNAL_APP_KEY, { 16 | kOSSettingsKeyInAppLaunchURL: false, 17 | kOSSettingsKeyInFocusDisplayOption: 2, 18 | }); 19 | 20 | OneSignal.inFocusDisplaying(2); 21 | OneSignal.addEventListener('opened', onPushOpened); 22 | OneSignal.addEventListener('ids', (device) => { 23 | if (device && device.userId) { 24 | savePushToken(device.userId); 25 | } 26 | }); 27 | }; 28 | 29 | const onPushOpened = ({notification}) => { 30 | console.log('matchCode', notification.payload?.additionalData?.matchCode); 31 | let roomCode = notification?.payload?.additionalData?.matchCode; 32 | roomCode && navigation.navigate('JoinRoom', {roomCode: roomCode}); 33 | }; 34 | 35 | return <>; 36 | } 37 | -------------------------------------------------------------------------------- /src/Storage/AppStorage.js: -------------------------------------------------------------------------------- 1 | import AsyncStorage from '@react-native-community/async-storage'; 2 | 3 | export const setMusicEnabled = async (status) => { 4 | try { 5 | await AsyncStorage.setItem('musicEnabled', JSON.stringify(status)); 6 | } catch (e) { 7 | // saving error 8 | } 9 | }; 10 | export const getMusicEnabled = async () => { 11 | try { 12 | const value = await AsyncStorage.getItem('musicEnabled'); 13 | if (value !== null) { 14 | return JSON.parse(value); 15 | } else { 16 | return true; 17 | } 18 | } catch (e) { 19 | // error reading value 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/Storage/UserStorage.js: -------------------------------------------------------------------------------- 1 | import AsyncStorage from '@react-native-community/async-storage'; 2 | 3 | export const saveUser = async (user) => { 4 | try { 5 | await AsyncStorage.setItem('user', JSON.stringify(user)); 6 | } catch (e) { 7 | // saving error 8 | } 9 | }; 10 | 11 | export const getUser = async () => { 12 | try { 13 | const value = await AsyncStorage.getItem('user'); 14 | if (value !== null) { 15 | return JSON.parse(value); 16 | } 17 | } catch (e) { 18 | // error reading value 19 | } 20 | }; 21 | 22 | export const savePushToken = async (pushToken) => { 23 | try { 24 | await AsyncStorage.setItem('pushToken', pushToken); 25 | } catch (e) { 26 | // saving error 27 | } 28 | }; 29 | export const getPushToken = async () => { 30 | try { 31 | const value = await AsyncStorage.getItem('pushToken'); 32 | if (value !== null) { 33 | return value; 34 | } 35 | } catch (e) { 36 | // error reading value 37 | } 38 | }; 39 | -------------------------------------------------------------------------------- /src/Utils/AudioPlayer.js: -------------------------------------------------------------------------------- 1 | import Sound from 'react-native-sound'; 2 | import {getMusicEnabled} from '~/Storage/AppStorage'; 3 | 4 | export const AUDIOS = { 5 | LOBBY: 'lobby.mp3', 6 | READY: 'click.mp3', 7 | NEWUSER: 'new_user.mp3', 8 | COUNTDOWN: 'countdown.mp3', 9 | WINNER: 'winner.mp3', 10 | LOOSER: 'looser.mp3', 11 | ERROR: 'error.mp3', 12 | SUCCESS: 'success.wav', 13 | }; 14 | 15 | const AudioPlayer = () => { 16 | Sound.setCategory('Playback'); 17 | 18 | let playerBG; 19 | let playerUI; 20 | 21 | const play = async (audioFile, track = 'background') => { 22 | let isMusicEnabled = await getMusicEnabled(); 23 | if (!isMusicEnabled) return; 24 | 25 | console.log('audioLog', audioFile); 26 | 27 | if (track == `background`) { 28 | playerBG = new Sound(audioFile, Sound.MAIN_BUNDLE, (error) => { 29 | if (error) return; 30 | 31 | playerBG.setNumberOfLoops(-1); 32 | playerBG.setVolume(0.5); 33 | playerBG.play(); 34 | }); 35 | } else { 36 | playerUI = new Sound(audioFile, Sound.MAIN_BUNDLE, (error) => { 37 | if (error) return; 38 | 39 | playerUI.setVolume(0.5); 40 | playerUI.play(() => { 41 | playerUI.release(); 42 | }); 43 | }); 44 | } 45 | }; 46 | 47 | const stop = async (track = 'background') => { 48 | let isMusicEnabled = await getMusicEnabled(); 49 | if (!isMusicEnabled) return; 50 | 51 | const player = track == 'background' ? playerBG : playerUI; 52 | player.stop(); 53 | player.release(); 54 | }; 55 | 56 | const mute = async () => { 57 | if (playerBG) { 58 | playerBG.pause(); 59 | } 60 | } 61 | 62 | const resume = () => { 63 | if(playerBG) { 64 | playerBG.play(); 65 | } 66 | } 67 | 68 | return { 69 | play, 70 | stop, 71 | mute, 72 | resume 73 | }; 74 | }; 75 | 76 | export default AudioPlayer(); 77 | -------------------------------------------------------------------------------- /src/Utils/styles/index.js: -------------------------------------------------------------------------------- 1 | import {Dimensions} from 'react-native'; 2 | 3 | const sizeMultiplier = { 4 | height: Dimensions.get('window').height / 812, 5 | width: Dimensions.get('window').width / 375, 6 | }; 7 | 8 | export const hpx = (value) => { 9 | return value * sizeMultiplier.height + 'px'; 10 | }; 11 | export const wpx = (value) => { 12 | return value * sizeMultiplier.width + 'px'; 13 | }; 14 | 15 | const colors = { 16 | primary: '#7159C1', 17 | secondary: '#fff', 18 | btnText: '#4B4B4B', 19 | btnBg: '#514089', 20 | backgroundGray: '#e3dddd', 21 | green: '#85C159', 22 | red: '#EB6464', 23 | gray: '#585858', 24 | themeType: 'light-content', 25 | }; 26 | const fonts = { 27 | xxsmall: hpx(12), 28 | xsmall: hpx(14), 29 | small: hpx(16), 30 | medium: hpx(18), 31 | large: hpx(28), 32 | xlarge: hpx(34), 33 | xxlarge: hpx(50), 34 | }; 35 | const fontName = { 36 | regular: 'Ubuntu-Regular', 37 | medium: 'Ubuntu-Medium', 38 | bold: 'Ubuntu-Bold', 39 | }; 40 | let fontsInt = {}; 41 | Object.keys(fonts).forEach( 42 | (key) => (fontsInt[key] = parseInt(fonts[key].replace('px', ''))), 43 | ); 44 | 45 | const style = { 46 | colors, 47 | fonts, 48 | fontsInt, 49 | fontName, 50 | hpx, 51 | wpx, 52 | }; 53 | 54 | export default style; 55 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | export const SERVER_URL = 'https://devquiz-backend.herokuapp.com/'; 2 | export const ONESIGNAL_APP_KEY = '96aa2b3c-b7a4-411c-a10a-0b14fe2c6d0a'; 3 | --------------------------------------------------------------------------------