├── .env.example
├── .eslintrc.js
├── .github
└── workflows
│ ├── production.yml
│ └── staging.yml
├── .gitignore
├── .husky
└── commit-msg
├── App.js
├── CHANGELOG.md
├── LICENSE
├── README.md
├── __mocks__
└── axios.js
├── __tests__
├── app.js
└── smoke.spec.ts
├── app.config.js
├── app
├── features
│ └── messages
│ │ ├── MessagesComponent.tsx
│ │ ├── __tests__
│ │ └── MessagesSagas.ts
│ │ ├── messagesHelpers.ts
│ │ ├── messagesSagas.ts
│ │ └── messagesSlice.ts
├── screens
│ ├── ErrorScreen
│ │ ├── ErrorBoundary.tsx
│ │ └── ErrorDetails.tsx
│ └── Main.tsx
├── services
│ └── api.ts
├── store
│ ├── index.ts
│ └── rootSaga.ts
└── utils
│ └── newId.ts
├── assets
├── adaptive-icon.png
├── context.ts
├── favicon.png
├── icon.png
└── splash.png
├── babel.config.js
├── commitlint.config.js
├── package-lock.json
├── package.json
├── release.config.js
└── tsconfig.json
/.env.example:
--------------------------------------------------------------------------------
1 | HUGGINGFACE_KEY="xxxx"
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ["universe/native", "universe/shared/typescript-analysis"],
3 |
4 | overrides: [
5 | {
6 | files: ["*.ts", "*.tsx", "*.d.ts"],
7 |
8 | parserOptions: {
9 | project: "./tsconfig.json",
10 | },
11 | },
12 | ],
13 |
14 | env: {
15 | node: true,
16 | },
17 | };
18 |
--------------------------------------------------------------------------------
/.github/workflows/production.yml:
--------------------------------------------------------------------------------
1 | name: Production Test, Lint, and Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: 🏗 Setup repo
13 | uses: actions/checkout@v3
14 | with:
15 | fetch-depth: "0"
16 |
17 | - name: 🏗 Setup Node
18 | uses: actions/setup-node@v3
19 | with:
20 | node-version: 16
21 | cache: 'npm'
22 |
23 | - name: Install dependencies
24 | run: npm ci
25 |
26 | - name: Install semantic-release extra plugins
27 | run: npm install --save-dev @semantic-release/changelog @semantic-release/git
28 |
29 | - name: Format and Lint
30 | run: |
31 | npm run format
32 | npm run lint
33 |
34 | - name: Test with Jest
35 | run: npm run test
36 |
37 | - name: Bump Version and Release on Github
38 | env:
39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40 | run: npx semantic-release
41 |
--------------------------------------------------------------------------------
/.github/workflows/staging.yml:
--------------------------------------------------------------------------------
1 | name: Staging Test, Lint, and Release
2 |
3 | on:
4 | push:
5 | branches:
6 | - staging
7 |
8 | jobs:
9 | build:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: 🏗 Setup repo
13 | uses: actions/checkout@v3
14 | with:
15 | fetch-depth: "0"
16 |
17 | - name: 🏗 Setup Node
18 | uses: actions/setup-node@v3
19 | with:
20 | node-version: 16
21 | cache: 'npm'
22 |
23 | - name: Install dependencies
24 | run: npm ci
25 |
26 | - name: Install semantic-release extra plugins
27 | run: npm install --save-dev @semantic-release/changelog @semantic-release/git
28 |
29 | - name: Format and Lint
30 | run: |
31 | npm run format
32 | npm run lint
33 |
34 | - name: Test with Jest
35 | run: npm run test
36 |
37 | - name: Bump Version and Release on Github
38 | env:
39 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40 | run: npx semantic-release
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | .expo/
3 | dist/
4 | npm-debug.*
5 | *.jks
6 | *.p8
7 | *.p12
8 | *.key
9 | *.mobileprovision
10 | *.orig.*
11 | web-build/
12 |
13 | # macOS
14 | .DS_Store
15 |
16 | .env
--------------------------------------------------------------------------------
/.husky/commit-msg:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 | . "$(dirname -- "$0")/_/husky.sh"
3 |
4 | npx --no-install commitlint --edit "$1"
5 |
--------------------------------------------------------------------------------
/App.js:
--------------------------------------------------------------------------------
1 | import { Provider } from "react-redux";
2 |
3 | import { ErrorBoundary } from "./app/screens/ErrorScreen/ErrorBoundary";
4 | import Main from "./app/screens/Main";
5 | import { store } from "./app/store";
6 |
7 | export default function App() {
8 | return (
9 |
10 |
11 |
12 |
13 |
14 | );
15 | }
16 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # [1.5.0](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.4.0...v1.5.0) (2022-12-04)
2 |
3 |
4 | ### Bug Fixes
5 |
6 | * remove no-irregular-whitespace ([a37d059](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/a37d059cd8cf1ef7aeef833f19a7a633cd349e96))
7 |
8 |
9 | ### Features
10 |
11 | * change context to Nintendo history ([c91f1b3](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/c91f1b34fa3ced7dc5984aea8bb46f8a25192f2d))
12 | * change context to Nintendo history ([415f63f](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/415f63f363bcf80ab446a13dcc02b0962e4c7f7c))
13 |
14 | # [1.5.0-staging.1](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.4.0...v1.5.0-staging.1) (2022-12-04)
15 |
16 |
17 | ### Bug Fixes
18 |
19 | * remove no-irregular-whitespace ([a37d059](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/a37d059cd8cf1ef7aeef833f19a7a633cd349e96))
20 |
21 |
22 | ### Features
23 |
24 | * change context to Nintendo history ([c91f1b3](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/c91f1b34fa3ced7dc5984aea8bb46f8a25192f2d))
25 | * change context to Nintendo history ([415f63f](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/415f63f363bcf80ab446a13dcc02b0962e4c7f7c))
26 |
27 | # [1.4.0](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.3.0...v1.4.0) (2022-12-03)
28 |
29 |
30 | ### Bug Fixes
31 |
32 | * add try catch to API call in saga ([71f6a92](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/71f6a92de3898314e1283a2edd92354b09aeb003))
33 | * only cancel API when MessagesComponent unmounts ([5b5b2ef](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/5b5b2ef5561c3d397a2c629d133fd87312784a83))
34 |
35 |
36 | ### Features
37 |
38 | * add axios validateStatus < 500 ([366d879](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/366d87916a255a9614cc8e78839b3038acf15b0a))
39 | * add react error boundary ([dee627e](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/dee627ed8b63f3d2c626605ca2143805371627d0))
40 | * add validateStatus for status code < 500 ([ce4a6ae](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/ce4a6ae3ce3c3e0202c2688069c29eb2aa3cbc96))
41 | * cancel API requests when components unmount ([6b99ac2](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/6b99ac27c0a3f7815a45c0f36bd75f2f5f487b47))
42 |
43 | # [1.3.0-staging.4](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.3.0-staging.3...v1.3.0-staging.4) (2022-12-03)
44 |
45 |
46 | ### Bug Fixes
47 |
48 | * add try catch to API call in saga ([71f6a92](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/71f6a92de3898314e1283a2edd92354b09aeb003))
49 |
50 | # [1.3.0-staging.3](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.3.0-staging.2...v1.3.0-staging.3) (2022-12-03)
51 |
52 |
53 | ### Features
54 |
55 | * add axios validateStatus < 500 ([366d879](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/366d87916a255a9614cc8e78839b3038acf15b0a))
56 | * add react error boundary ([dee627e](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/dee627ed8b63f3d2c626605ca2143805371627d0))
57 |
58 | # [1.3.0-staging.2](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.3.0-staging.1...v1.3.0-staging.2) (2022-12-03)
59 |
60 |
61 | ### Bug Fixes
62 |
63 | * only cancel API when MessagesComponent unmounts ([5b5b2ef](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/5b5b2ef5561c3d397a2c629d133fd87312784a83))
64 |
65 |
66 | ### Features
67 |
68 | * add validateStatus for status code < 500 ([ce4a6ae](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/ce4a6ae3ce3c3e0202c2688069c29eb2aa3cbc96))
69 | * cancel API requests when components unmount ([6b99ac2](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/6b99ac27c0a3f7815a45c0f36bd75f2f5f487b47))
70 |
71 | # [1.3.0](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.2.0...v1.3.0) (2022-12-01)
72 |
73 |
74 | ### Features
75 |
76 | * add textInputStyle props to Gifted Chat for background color ([1e72ee9](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/1e72ee94eee513bc9be6e21ef9aa016e8e6713c6))
77 |
78 | # [1.3.0-staging.1](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.2.0...v1.3.0-staging.1) (2022-12-01)
79 |
80 |
81 | ### Features
82 |
83 | * add textInputStyle props to Gifted Chat for background color ([1e72ee9](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/1e72ee94eee513bc9be6e21ef9aa016e8e6713c6))
84 |
85 | # [1.2.0](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.1.0...v1.2.0) (2022-11-24)
86 |
87 |
88 | ### Features
89 |
90 | * add isTyping to chat ([21cecfe](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/21cecfe8f2529b84e80c4c86ec277bbe79cfaa56))
91 |
92 | # [1.2.0-staging.1](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.1.0...v1.2.0-staging.1) (2022-11-24)
93 |
94 |
95 | ### Features
96 |
97 | * add isTyping to chat ([21cecfe](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/21cecfe8f2529b84e80c4c86ec277bbe79cfaa56))
98 |
99 | # [1.1.0](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.0.0...v1.1.0) (2022-11-24)
100 |
101 |
102 | ### Features
103 |
104 | * add axios-retry ([b9a6b1e](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/b9a6b1ee8d8723ed9b9cadd4d2b0cbe37c4a1e7f))
105 | * add axios-retry ([b6b6418](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/b6b641830dab877e503e7ae80b0bb63822c292bb))
106 |
107 | # [1.1.0-staging.1](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.0.0...v1.1.0-staging.1) (2022-11-24)
108 |
109 |
110 | ### Features
111 |
112 | * add axios-retry ([b9a6b1e](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/b9a6b1ee8d8723ed9b9cadd4d2b0cbe37c4a1e7f))
113 | * add axios-retry ([b6b6418](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/b6b641830dab877e503e7ae80b0bb63822c292bb))
114 |
115 | # [1.0.0-staging.3](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.0.0-staging.2...v1.0.0-staging.3) (2022-11-24)
116 |
117 |
118 | ### Features
119 |
120 | * add axios-retry ([b6b6418](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/b6b641830dab877e503e7ae80b0bb63822c292bb))
121 |
122 | # 1.0.0 (2022-11-24)
123 |
124 |
125 | ### Bug Fixes
126 |
127 | * add error types ([b42cee5](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/b42cee51c9ef1b790912acd775d0cbb4af8a6841))
128 | * add replyMessages type IMessage ([a2092a6](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/a2092a60b924810a36e6da49490d57128dc8526f))
129 | * add useCallback to onSend ([ed21cf9](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/ed21cf9ce4b2a6b225d9b890069bdb49d04023f7))
130 | * delete files in wrong directory ([2ece434](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/2ece434ff3ff81d9bf79177f7388f533b96f6bd6))
131 | * remove console.log ([133f91c](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/133f91c656864fc277f6b306306df10971e170b0))
132 | * remove unused import ([a964dd4](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/a964dd4b034b7fee9447c4936ab05f96759db146))
133 |
134 |
135 | ### Features
136 |
137 | * add avatar png ([4554907](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/4554907316de50f560ff67e113de1399b09966a0))
138 | * add avatar png ([5abba79](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/5abba79ad4f122222e50cd836e022f5e1cfe4b17))
139 | * add error handling to API ([d69ee0f](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/d69ee0fe51cf57669ad69cf58cc9e12fdb733df9))
140 | * add Gifted Chat and Redux Saga ([823f886](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/823f8860278b01e7d0ea24e2ea563126323f80a5))
141 | * add Gifted Chat and Redux Saga ([fd106e8](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/fd106e82f334b9bdfa9350ddbcb53f300c79787c))
142 | * add huggingface API ([a71d3cd](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/a71d3cd1a47e7457eabaa3b748256e3e11b3b9e2))
143 | * add placeholder text ([c814a9e](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/c814a9e7361ac66519dcd0ec46a4359dffc6846c))
144 | * add SafeAreaView ([ccd18c2](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/ccd18c2aa30c3dfebdfe7c4566cdf5eb684918ac))
145 | * use gravatar for avatars ([92cd512](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/92cd5127be0ed481e7ef4eb01fc2316c3b38e2d0))
146 |
147 | # [1.0.0-staging.2](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/compare/v1.0.0-staging.1...v1.0.0-staging.2) (2022-11-24)
148 |
149 |
150 | ### Bug Fixes
151 |
152 | * delete files in wrong directory ([2ece434](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/2ece434ff3ff81d9bf79177f7388f533b96f6bd6))
153 |
154 | # 1.0.0-staging.1 (2022-11-24)
155 |
156 |
157 | ### Bug Fixes
158 |
159 | * add error types ([b42cee5](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/b42cee51c9ef1b790912acd775d0cbb4af8a6841))
160 | * add replyMessages type IMessage ([a2092a6](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/a2092a60b924810a36e6da49490d57128dc8526f))
161 | * add useCallback to onSend ([ed21cf9](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/ed21cf9ce4b2a6b225d9b890069bdb49d04023f7))
162 | * remove console.log ([133f91c](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/133f91c656864fc277f6b306306df10971e170b0))
163 | * remove unused import ([a964dd4](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/a964dd4b034b7fee9447c4936ab05f96759db146))
164 |
165 |
166 | ### Features
167 |
168 | * add avatar png ([4554907](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/4554907316de50f560ff67e113de1399b09966a0))
169 | * add avatar png ([5abba79](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/5abba79ad4f122222e50cd836e022f5e1cfe4b17))
170 | * add error handling to API ([d69ee0f](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/d69ee0fe51cf57669ad69cf58cc9e12fdb733df9))
171 | * add Gifted Chat and Redux Saga ([823f886](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/823f8860278b01e7d0ea24e2ea563126323f80a5))
172 | * add Gifted Chat and Redux Saga ([fd106e8](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/fd106e82f334b9bdfa9350ddbcb53f300c79787c))
173 | * add huggingface API ([a71d3cd](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/a71d3cd1a47e7457eabaa3b748256e3e11b3b9e2))
174 | * add placeholder text ([c814a9e](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/c814a9e7361ac66519dcd0ec46a4359dffc6846c))
175 | * add SafeAreaView ([ccd18c2](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/ccd18c2aa30c3dfebdfe7c4566cdf5eb684918ac))
176 | * use gravatar for avatars ([92cd512](https://github.com/kurtvandusen/React-Native-Easy-Chatbot/commit/92cd5127be0ed481e7ef4eb01fc2316c3b38e2d0))
177 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Kurt VanDusen
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React-Native-Easy-Chatbot
2 |
3 | A chatbot demo app using Huggingface inference API, React Native, Expo, and Redux Sagas. Build for Android, iOS, and Web.
4 |
5 | 
6 | 
7 | 
8 | [](https://expo.dev/client)
9 |
10 | Based on:
11 |
12 | - Expo SDK `46` React Native for Android, iOS, Web and Expo Go
13 | - [Huggingface Question Answering API](https://huggingface.co/deepset/tinyroberta-squad2) open source machine learning model
14 | - [Redux-Saga](https://redux-saga.js.org/) Async middleware for Redux
15 | - [Ignite from Infinite Red](https://github.com/infinitered/ignite) React Native Boilerplate
16 |
17 | ## Features
18 |
19 | - The API is called using Redux-Saga for clear, testable async logic
20 | - Axios with Axios-Retry for data fetching
21 | - API error handling
22 | - React Error Boundary
23 | - ESLint and Prettier to standarize formating
24 | - Husky for conventional commits
25 | - Jest for unit testing
26 | - Semantic Release to bump versions and automatically generate [CHANGELOG.md](./CHANGELOG.md)
27 | - Github Actions for CI/CD
28 | - [Gifted Chat](https://github.com/FaridSafi/react-native-gifted-chat) for Material Design and accesability
29 | - Reusable chat component
30 |
31 | ## Installation
32 |
33 | ```sh
34 | git clone https://github.com/kurtvandusen/React-Native-Easy-Chatbot
35 | cd React-Native-Easy-Chatbot
36 | npm i
37 | ```
38 |
39 | ## Optional - Create .env
40 |
41 | In the root directory, create a new file named .env and copy and paste the contents from .env.example. Then replace the example value with your own Huggingface API key.
42 |
43 | [Create a huggingface.co account to get your free API key](https://huggingface.co/)
44 |
45 | ## Optional - Customize Constants in app.config.js
46 |
47 | In the root directory, locate the app.config.js file. Edit the ` extra: {}` section to customize the values the will be used by Expo-Constants for
48 | - huggingfaceKey
49 | - baseURL
50 | - messagesPlaceholder
51 | - messagesErrorMessage
52 |
53 | ## Optional - Change baseURL to use a different Question Answering NLP model
54 |
55 | [Explore more Question Answering NLP models on huggingface](https://huggingface.co/models?pipeline_tag=question-answering&sort=downloads&search=question+answering)
56 |
57 | Simply change your baseURL to use a different model.
58 |
59 | ## Optional - Change Question Answering Context
60 |
61 | Update [context.ts](./assets/context.ts) with the text string of your choice. The chatbot will draw all answers from this text only. The current example context file contains text about the history of Nintendo Co, Ltd. drawn from [Wikipedia](https://en.wikipedia.org/wiki/Nintendo)
62 |
63 | ## Unit Testing Sagas
64 |
65 | [Here is an example of testing the saga async logic using Jest](./app/features/messages/__tests__/MessagesSagas.ts)
--------------------------------------------------------------------------------
/__mocks__/axios.js:
--------------------------------------------------------------------------------
1 | import mockAxios from 'jest-mock-axios';
2 | export default mockAxios;
--------------------------------------------------------------------------------
/__tests__/app.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import renderer from 'react-test-renderer';
3 |
4 | import App from '../App';
5 |
6 | describe('', () => {
7 | it('has 1 child', () => {
8 | const tree = renderer.create().toJSON();
9 | expect(tree.children.length).toBe(1);
10 | });
11 | });
--------------------------------------------------------------------------------
/__tests__/smoke.spec.ts:
--------------------------------------------------------------------------------
1 | describe('truth', () => {
2 | it('is true', () => {
3 | expect(true).toEqual(true);
4 | });
5 | });
--------------------------------------------------------------------------------
/app.config.js:
--------------------------------------------------------------------------------
1 | import "dotenv/config";
2 | import * as pkg from "./package.json";
3 |
4 | export default {
5 | expo: {
6 | name: "Easy-Chatbot",
7 | slug: "Easy-Chatbot",
8 | version: pkg.version,
9 | orientation: "portrait",
10 | icon: "./assets/icon.png",
11 | userInterfaceStyle: "light",
12 | splash: {
13 | image: "./assets/splash.png",
14 | resizeMode: "contain",
15 | backgroundColor: "#ffffff",
16 | },
17 | updates: {
18 | fallbackToCacheTimeout: 0,
19 | },
20 | assetBundlePatterns: ["**/*"],
21 | ios: {
22 | supportsTablet: true,
23 | },
24 | android: {
25 | adaptiveIcon: {
26 | foregroundImage: "./assets/adaptive-icon.png",
27 | backgroundColor: "#FFFFFF",
28 | },
29 | },
30 | web: {
31 | favicon: "./assets/favicon.png",
32 | },
33 | extra: {
34 | huggingfaceKey:
35 | process.env.HUGGINGFACE_KEY ?? "getYourFreeKeyForUnlimitedCalls",
36 | baseURL:
37 | "https://api-inference.huggingface.co/models/deepset/tinyroberta-squad2",
38 | messagesPlaceholder: "Ask about Nintendo history...",
39 | messagesErrorMessage: "Sorry, there was an error. "
40 | },
41 | },
42 | };
43 |
--------------------------------------------------------------------------------
/app/features/messages/MessagesComponent.tsx:
--------------------------------------------------------------------------------
1 | import Constants from "expo-constants";
2 | import React, { useCallback, useEffect } from "react";
3 | import { StyleProp, TextStyle } from "react-native";
4 | import { GiftedChat } from "react-native-gifted-chat";
5 | import { useSelector, useDispatch } from "react-redux";
6 |
7 | import { controller } from "../../services/api";
8 | import { RootState } from "../../store";
9 | import { sendMessage, defaultUser } from "./messagesSlice";
10 |
11 | export interface MessagesComponentProps {
12 | textInputStyle?: StyleProp;
13 | }
14 |
15 | const placeholder = Constants.expoConfig.extra?.messagesPlaceholder ?? "";
16 |
17 | export default function MessagesComponent({
18 | textInputStyle,
19 | }: MessagesComponentProps) {
20 | const dispatch = useDispatch();
21 | const messages = useSelector((state: RootState) => state.messages.messages);
22 | const isTyping = useSelector((state: RootState) => state.messages.isTyping);
23 |
24 | useEffect(() => {
25 | return () => {
26 | /* cancel API requests when component unmounts*/
27 | controller.abort();
28 | console.log("message component unmounted");
29 | };
30 | }, []);
31 |
32 | const onSend = useCallback((messages = []) => {
33 | dispatch({ type: sendMessage.toString(), payload: messages[0] });
34 | }, []);
35 |
36 | return (
37 |
45 | );
46 | }
47 |
--------------------------------------------------------------------------------
/app/features/messages/__tests__/MessagesSagas.ts:
--------------------------------------------------------------------------------
1 | import { put, call } from "redux-saga/effects";
2 |
3 | import { createReplyMessage, getReply } from "../messagesHelpers";
4 | import { sendMessageStart } from "../messagesSagas";
5 | import { setMessages, setIsTyping } from "../messagesSlice";
6 |
7 | describe("test messagesSagas", () => {
8 | it("Test saga sendMessageStart", () => {
9 | const testMessage = createReplyMessage("test");
10 | const generator = sendMessageStart({ payload: testMessage });
11 | expect(generator.next().value).toEqual(
12 | put({ type: setIsTyping, payload: true })
13 | );
14 | expect(generator.next().value).toEqual(
15 | put({ type: setMessages, payload: testMessage })
16 | );
17 | expect(generator.next().value).toEqual(call(getReply, testMessage));
18 | expect(generator.next().value).toEqual(
19 | put({ type: setMessages, payload: undefined })
20 | );
21 | expect(generator.next().value).toEqual(
22 | put({ type: setIsTyping, payload: false })
23 | );
24 | });
25 | });
26 |
--------------------------------------------------------------------------------
/app/features/messages/messagesHelpers.ts:
--------------------------------------------------------------------------------
1 | import { IMessage } from "react-native-gifted-chat";
2 |
3 | import { context } from "../../../assets/context";
4 | import { api } from "../../services/api";
5 | import { newId } from "../../utils/newId";
6 | import { chatbotUser } from "./messagesSlice";
7 |
8 | export const createReplyMessage = (reply: string) => {
9 | const replyMessage: IMessage = {
10 | _id: newId(),
11 | text: reply,
12 | createdAt: new Date(),
13 | user: chatbotUser,
14 | };
15 | return replyMessage;
16 | };
17 |
18 | export const getReply = async (message: IMessage) => {
19 | const body = {
20 | inputs: {
21 | question: message.text,
22 | context,
23 | },
24 | options: {
25 | wait_for_model: true,
26 | },
27 | };
28 | const replyResponse = await api.getAnswer(body);
29 |
30 | return createReplyMessage(replyResponse.answer);
31 | };
32 |
--------------------------------------------------------------------------------
/app/features/messages/messagesSagas.ts:
--------------------------------------------------------------------------------
1 | import Constants from "expo-constants";
2 | import { put, takeEvery, call } from "redux-saga/effects";
3 |
4 | import { getReply, createReplyMessage } from "./messagesHelpers";
5 | import { setMessages, sendMessage, setIsTyping } from "./messagesSlice";
6 |
7 | // Our worker Sagas
8 | function* sendMessageStart({ payload: message }) {
9 | yield put({ type: setIsTyping, payload: true });
10 | yield put({ type: setMessages, payload: message });
11 | try {
12 | const replyMessages = yield call(getReply, message);
13 | yield put({ type: setMessages, payload: replyMessages });
14 | } catch (error) {
15 | const errorMessage: string =
16 | Constants.expoConfig.extra?.messagesErrorMessage + error?.toString;
17 | yield put({ type: setMessages, payload: createReplyMessage(errorMessage) });
18 | }
19 | yield put({ type: setIsTyping, payload: false });
20 | }
21 |
22 | // Our watcher Sagas
23 | function* messagesSaga() {
24 | yield takeEvery(sendMessage, sendMessageStart);
25 | }
26 |
27 | export { messagesSaga, sendMessageStart };
28 |
--------------------------------------------------------------------------------
/app/features/messages/messagesSlice.ts:
--------------------------------------------------------------------------------
1 | import {
2 | createSlice,
3 | createAction,
4 | ActionCreatorWithPayload,
5 | } from "@reduxjs/toolkit";
6 | import type { PayloadAction } from "@reduxjs/toolkit";
7 | import { GiftedChat, User, IMessage } from "react-native-gifted-chat";
8 |
9 | export interface MessagesState {
10 | messages: IMessage[];
11 | isTyping: boolean;
12 | }
13 |
14 | export const defaultUser: User = {
15 | _id: 0,
16 | name: "User",
17 | avatar: "https://gravatar.com/avatar?d=wavatar",
18 | };
19 |
20 | export const chatbotUser: User = {
21 | _id: 1,
22 | name: "Chatbot",
23 | avatar: "https://gravatar.com/avatar?d=robohash",
24 | };
25 |
26 | const initialState: MessagesState = {
27 | messages: [],
28 | isTyping: false,
29 | };
30 |
31 | export const messagesSlice = createSlice({
32 | name: "messages",
33 | initialState,
34 | reducers: {
35 | setMessages: (state: MessagesState, action: PayloadAction) => {
36 | const newState = GiftedChat.append(state.messages, [action.payload]);
37 | state.messages = newState;
38 | },
39 | setIsTyping: (state: MessagesState, action: PayloadAction) => {
40 | state.isTyping = action.payload;
41 | },
42 | },
43 | });
44 |
45 | export const sendMessage: ActionCreatorWithPayload =
46 | createAction("SEND_MESSAGE");
47 |
48 | // Action creators are generated for each case reducer function
49 | export const { setMessages, setIsTyping } = messagesSlice.actions;
50 |
51 | export default messagesSlice.reducer;
52 |
--------------------------------------------------------------------------------
/app/screens/ErrorScreen/ErrorBoundary.tsx:
--------------------------------------------------------------------------------
1 | import React, { Component, ErrorInfo, ReactNode } from "react";
2 |
3 | import { ErrorDetails } from "./ErrorDetails";
4 |
5 | interface Props {
6 | children: ReactNode;
7 | catchErrors: "always" | "dev" | "prod" | "never";
8 | }
9 |
10 | interface State {
11 | error: Error | null;
12 | errorInfo: ErrorInfo | null;
13 | }
14 |
15 | /**
16 | * This component handles whenever the user encounters a JS error in the
17 | * app. It follows the "error boundary" pattern in React. We're using a
18 | * class component because according to the documentation, only class
19 | * components can be error boundaries.
20 | *
21 | * - [Documentation and Examples](https://github.com/infinitered/ignite/blob/master/docs/Error-Boundary.md)
22 | * - [React Error Boundaries](https://reactjs.org/docs/error-boundaries.html)
23 | */
24 | export class ErrorBoundary extends Component {
25 | state = { error: null, errorInfo: null };
26 |
27 | // If an error in a child is encountered, this will run
28 | componentDidCatch(error: Error, errorInfo: ErrorInfo) {
29 | // Catch errors in any components below and re-render with error message
30 | this.setState({
31 | error,
32 | errorInfo,
33 | });
34 |
35 | // You can also log error messages to an error reporting service here
36 | // This is a great place to put BugSnag, Sentry, crashlytics, etc:
37 | // reportCrash(error)
38 | }
39 |
40 | // Reset the error back to null
41 | resetError = () => {
42 | this.setState({ error: null, errorInfo: null });
43 | };
44 |
45 | // To avoid unnecessary re-renders
46 | shouldComponentUpdate(
47 | nextProps: Readonly,
48 | nextState: Readonly
49 | ): boolean {
50 | return nextState.error !== nextProps.error;
51 | }
52 |
53 | // Only enable if we're catching errors in the right environment
54 | isEnabled(): boolean {
55 | return (
56 | this.props.catchErrors === "always" ||
57 | (this.props.catchErrors === "dev" && __DEV__) ||
58 | (this.props.catchErrors === "prod" && !__DEV__)
59 | );
60 | }
61 |
62 | // Render an error UI if there's an error; otherwise, render children
63 | render() {
64 | return this.isEnabled() && this.state.error ? (
65 |
70 | ) : (
71 | this.props.children
72 | );
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/screens/ErrorScreen/ErrorDetails.tsx:
--------------------------------------------------------------------------------
1 | import React, { ErrorInfo } from "react";
2 | import { ScrollView, View, Text, Button } from "react-native";
3 |
4 | export interface ErrorDetailsProps {
5 | error: Error;
6 | errorInfo: ErrorInfo;
7 | onReset(): void;
8 | }
9 |
10 | export function ErrorDetails(props: ErrorDetailsProps) {
11 | return (
12 |
13 |
14 | {`${props.error}`.trim()}
15 | {`${props.errorInfo.componentStack}`.trim()}
16 |
17 |
18 |
19 |
20 | );
21 | }
22 |
--------------------------------------------------------------------------------
/app/screens/Main.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { StyleSheet, SafeAreaView } from "react-native";
3 |
4 | import MessagesComponent from "../features/messages/MessagesComponent";
5 |
6 | export default function Main() {
7 | return (
8 |
9 |
10 |
11 | );
12 | }
13 |
14 | const styles = StyleSheet.create({
15 | container: {
16 | flex: 1,
17 | },
18 | textInputStyle: {
19 | backgroundColor: "#FFFFF0",
20 | },
21 | });
22 |
--------------------------------------------------------------------------------
/app/services/api.ts:
--------------------------------------------------------------------------------
1 | import axios, { AxiosResponse, AxiosError } from "axios";
2 | import axiosRetry from "axios-retry";
3 | import Constants from "expo-constants";
4 |
5 | export interface QuestionAnswerArgs {
6 | inputs: {
7 | question: string;
8 | context: string;
9 | };
10 | options: {
11 | wait_for_model?: boolean;
12 | };
13 | }
14 |
15 | export interface QuestionAnswerReturn {
16 | /**
17 | * A string that’s the answer within the text.
18 | */
19 | answer: string;
20 | /**
21 | * A float that represents how likely that the answer is correct
22 | */
23 | score: number;
24 | /**
25 | * The index (string wise) of the start of the answer within context.
26 | */
27 | start: number;
28 | /**
29 | * The index (string wise) of the stop of the answer within context.
30 | */
31 | end: number;
32 | }
33 |
34 | export const controller = new AbortController();
35 |
36 | const instance = axios.create({
37 | baseURL: Constants.expoConfig.extra?.baseURL ?? "",
38 | headers: {
39 | Authorization: "Bearer " + Constants.expoConfig.extra?.huggingfaceKey,
40 | },
41 | signal: controller.signal,
42 | timeout: 20000, // 20 seconds
43 | validateStatus(status) {
44 | return status < 500; // Resolve only if the status code is less than 500
45 | },
46 | });
47 |
48 | const onRetry = (retryCount, error) => {
49 | console.log("retry", retryCount, error);
50 | };
51 |
52 | const retryDelay = () => 3000; // 3 seconds
53 |
54 | const retryCondition = () => true;
55 |
56 | axiosRetry(instance, {
57 | retries: 3,
58 | onRetry,
59 | retryDelay,
60 | retryCondition,
61 | });
62 |
63 | const responseBody = (response: AxiosResponse) => response.data;
64 |
65 | function handleError(error: Error | AxiosError) {
66 | console.log(error);
67 | const defaultResponse: QuestionAnswerReturn = {
68 | answer: `I don't know. My API feels fuzzy.`,
69 | score: 0.5,
70 | start: 0,
71 | end: 0,
72 | };
73 | return defaultResponse;
74 | }
75 |
76 | const requests = {
77 | post: (url: string, body: QuestionAnswerArgs) =>
78 | instance.post(url, body).then(responseBody).catch(handleError),
79 | };
80 |
81 | export const api = {
82 | getAnswer: (body): Promise => requests.post("", body),
83 | };
84 |
--------------------------------------------------------------------------------
/app/store/index.ts:
--------------------------------------------------------------------------------
1 | import { configureStore } from "@reduxjs/toolkit";
2 | import createSagaMiddleware from "redux-saga";
3 |
4 | import messagesReducer from "../features/messages/messagesSlice";
5 | import rootSaga from "./rootSaga";
6 |
7 | const sagaMiddleware = createSagaMiddleware();
8 |
9 | export const store = configureStore({
10 | reducer: {
11 | messages: messagesReducer,
12 | },
13 | middleware: (getDefaultMiddleware) => [
14 | ...getDefaultMiddleware({ thunk: false, serializableCheck: false }),
15 | sagaMiddleware,
16 | ],
17 | });
18 | sagaMiddleware.run(rootSaga);
19 |
20 | // Infer the `RootState` and `AppDispatch` types from the store itself
21 | export type RootState = ReturnType;
22 | // Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
23 | export type AppDispatch = typeof store.dispatch;
24 |
--------------------------------------------------------------------------------
/app/store/rootSaga.ts:
--------------------------------------------------------------------------------
1 | import { all } from "redux-saga/effects";
2 |
3 | import { messagesSaga } from "../features/messages/messagesSagas";
4 |
5 | export default function* rootSaga() {
6 | yield all([messagesSaga()]);
7 | }
8 |
--------------------------------------------------------------------------------
/app/utils/newId.ts:
--------------------------------------------------------------------------------
1 | let lastId: number = 0;
2 |
3 | export const newId = (prefix: string = "id") => {
4 | lastId++;
5 | const newId: string = `${prefix}${lastId}`;
6 | return newId;
7 | };
8 |
--------------------------------------------------------------------------------
/assets/adaptive-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kurtvandusen/React-Native-Easy-Chatbot/b40eeaa3ed602d7fe6de965b8765912b98abeb79/assets/adaptive-icon.png
--------------------------------------------------------------------------------
/assets/context.ts:
--------------------------------------------------------------------------------
1 | // from https://en.wikipedia.org/wiki/Nintendo
2 |
3 | export const context: string = `1973-1978: Early video games and Color TV-Game
4 |
5 | The growing demand for Nintendo's products led Yamauchi to further expand the offices, for which he acquired the surrounding land and assigned the production of cards to the original Nintendo building. Meanwhile, Yokoi, Uemura, and new employees such as Genyo Takeda, continued to develop innovative products for the company. The Laser Clay Shooting System was released in 1973 and managed to surpass bowling in popularity. Though Nintendo's toys continued to gain popularity, the 1973 oil crisis caused both a spike in the cost of plastics and a change in consumer priorities that put essential products over pastimes, and Nintendo lost several billion yen.
6 |
7 | In 1974, Nintendo released Wild Gunman, a skeet shooting arcade simulation consisting of a 16 mm image projector with a sensor that detects a beam from the player's light gun. Both the Laser Clay Shooting System and Wild Gunman were successfully exported to Europe and North America. However, Nintendo's production speeds were still slow compared to rival companies such as Bandai and Tomy, and their prices were high, which led to the discontinuation of some of their light gun products. The subsidiary Nintendo Leisure System Co., Ltd., which developed these products, was closed as a result of the economic impact dealt by the oil crisis.
8 |
9 | Yamauchi, motivated by the successes of Atari and Magnavox with their video game consoles, acquired the Japanese distribution rights for the Magnavox Odyssey in 1974, and reached an agreement with Mitsubishi Electric to develop similar products between 1975 and 1978, including the first microprocessor for video games systems, the Color TV-Game series, and an arcade game inspired by Othello. During this period, Takeda developed the video game EVR Race,and Shigeru Miyamoto joined Yokoi's team with the responsibility of designing the casing for the Color TV-Game consoles. In 1978, Nintendo's research and development department was split into two facilities, Nintendo Research & Development 1 and Nintendo Research & Development 2, respectively managed by Yokoi and Uemura.
10 |
11 | Shigeru Miyamoto brought distinctive sources of inspiration, including the natural environment and regional culture of Sonobe, popular culture influences like Westerns and detective fiction, along with folk Shinto practices and family media. These would each be seen in most of Nintendo's major franchises which developed following Miyamoto's creative leadership.
12 |
13 | 1979-1987: Game & Watch, arcade games, and Nintendo Entertainment System
14 | Further information: History of Game & Watch and History of Nintendo Entertainment System
15 |
16 | The Game & Watch, a Donkey Kong miniature arcade cabinet, and the NES
17 | Two key events in Nintendo's history occurred in 1979: its American subsidiary was opened in New York City, and a new department focused on arcade game development was created. In 1980, one of the first handheld video game systems, the Game & Watch, was created by Yokoi from the technology used in portable calculators. It became one of Nintendo's most successful products, with over 43.4 million units sold worldwide during its production period, and for which 59 games were made in total.
18 |
19 | Nintendo entered the arcade video game market with Sheriff and Radar Scope, released in Japan in 1979 and 1980 respectively. Sheriff, also known as Bandido in some regions, marked the first original video game made by Nintendo, was published by Sega and developed by Genyo Takeda and Shigeru Miyamoto. While Radar Scope, rivaled Galaxian in Japanese arcades but failed to find an audience overseas and created a financial crisis for the company. To try to find a more successful game, they put Miyamoto in charge of their next arcade game design, leading to the release of Donkey Kong in 1981, one of the first platform video games that allowed the player character to jump. The character, Jumpman, would later become Mario and Nintendo's official mascot. Mario was named after Mario Segale, the landlord of Nintendo's offices in Tukwila, Washington. Donkey Kong was a financial success for Nintendo both in Japan and overseas, and led Coleco to fight Atari for licensing rights for porting to home consoles and personal computers.
20 |
21 | In 1983, Nintendo opened a new production facility in Uji and was listed on the first section of the Tokyo Stock Exchange. Uemura, taking inspiration from the ColecoVision, began creating a new video game console that would incorporate a ROM cartridge format for video games as well as both a central processing unit and a picture processing unit. The Family Computer, or Famicom, was released in Japan in July 1983 along with three games adapted from their original arcade versions: Donkey Kong, Donkey Kong Jr. and Popeye. Its success was such that in 1984, it surpassed the market share held by Sega's SG-1000. At this time, Nintendo adopted a series of guidelines that involved the validation of each game produced for the Famicom before its distribution on the market, agreements with developers to ensure that no Famicom game would be adapted to other consoles within two years of its release, and restricting developers from producing more than five games per year for the Famicom.
22 |
23 | In the early 1980s, several video game consoles proliferated in the United States, as well as low-quality games produced by third-party developers, which oversaturated the market and led to the video game crash of 1983. Consequently, a recession hit the American video game industry, whose revenues went from over $3 billion to $100 million between 1983 and 1985. Nintendo's initiative to launch the Famicom in America was also impacted. To differentiate the Famicom from its competitors in America, Nintendo rebranded it as an entertainment system and its cartridges as Game Paks, and with a design reminiscent of a VCR. Nintendo implemented a lockout chip in the Game Paks for control on its third party library to avoid the market saturation that had occurred in the United States. The result is the Nintendo Entertainment System, or NES, which was released in North America in 1985. The landmark games Super Mario Bros. and The Legend of Zelda were produced by Miyamoto and Takashi Tezuka. Composer Koji Kondo reinforced the idea that musical themes could act as a complement to game mechanics rather than simply a miscellaneous element. Production of the NES lasted until 1995, and production of the Famicom lasted until 2003. In total, around 62 million Famicom and NES consoles were sold worldwide. During this period, Nintendo created a copyright infringement protection in the form of the Official Nintendo Seal of Quality, added to their products so that customers may recognize their authenticity in the market. By this time, Nintendo's network of electronic suppliers had extended to around thirty companies, including Ricoh (Nintendo's main source for semiconductors) and the Sharp Corporation.
24 |
25 | 1988-1992: Game Boy and Super Nintendo Entertainment System
26 | Further information: History of Game Boy and History of Super Nintendo Entertainment System
27 |
28 | The Game Boy and Super NES
29 | In 1988, Gunpei Yokoi and his team at Nintendo R&D1 conceived the Game Boy, the first handheld video game console made by Nintendo. Nintendo released the Game Boy in 1989. In North America, the Game Boy was bundled with the popular third-party game Tetris after a difficult negotiation process with Elektronorgtechnica. The Game Boy was a significant success. In its first two weeks of sale in Japan, its initial inventory of 300,000 units sold out, and in the United States, an additional 40,000 units were sold on its first day of distribution. Around this time, Nintendo entered an agreement with Sony to develop the Super Famicom CD-ROM Adapter, a peripheral for the upcoming Super Famicom capable of playing CD-ROMs. However, the collaboration did not last as Yamauchi preferred to continue developing the technology with Philips, which would result in the CD-i, and Sony's independent efforts resulted in the creation of the PlayStation console.
30 |
31 | The first issue of Nintendo Power magazine, which had an annual circulation of 1.5 million copies in the United States, was published in 1988. In July 1989, Nintendo held the first Nintendo Space World trade show with the name Shoshinkai for the purpose of announcing and demonstrating upcoming Nintendo products. That year, the first World of Nintendo stores-within-a-store, which carried official Nintendo merchandise, were opened in the United States. According to company information, more than 25% of homes in the United States had an NES in 1989.
32 |
33 | In the late 1980s, Nintendo's dominance slipped with the appearance of NEC's PC Engine and Sega's Mega Drive, 16-bit game consoles with improved graphics and audio compared to the NES. In response to the competition, Uemura designed the Super Famicom, which launched in 1990. The first batch of 300,000 consoles sold out in hours. The following year, as with the NES, Nintendo distributed a modified version of the Super Famicom to the United States market, titled the Super Nintendo Entertainment System. Launch games for the Super Famicom and Super NES include Super Mario World, F-Zero, Pilotwings, SimCity, and Gradius III. By mid-1992, over 46 million Super Famicom and Super NES consoles had been sold. The console's life cycle lasted until 1999 in the United States, and until 2003 in Japan.
34 |
35 | In March 1990, the first Nintendo World Championship was held, with participants from 29 American cities competing for the title of "best Nintendo player in the world". In June 1990, the subsidiary Nintendo of Europe was opened in Großostheim, Germany; in 1993, subsequent subsidiaries were established in the Netherlands (where Bandai had previously distributed Nintendo's products), France, the United Kingdom, Spain, Belgium, and Australia. In 1992, Nintendo acquired a majority stake in the Seattle Mariners baseball team, and sold most of its shares in 2016. Nintendo ceased manufacturing arcade games and systems in September 1992. In 1993, Star Fox was released, which marked an industry milestone by being the first video game to make use of the Super FX chip.
36 |
37 | The proliferation of graphically violent video games, such as Mortal Kombat, caused controversy and led to the creation of the Interactive Digital Software Association and the Entertainment Software Rating Board, in whose development Nintendo collaborated during 1994. These measures also encouraged Nintendo to abandon the content guidelines it had enforced since the release of the NES. Commercial strategies implemented by Nintendo during this time include the Nintendo Gateway System, an in-flight entertainment service available for airlines, cruise ships and hotels, and the "Play It Loud!" advertising campaign for Game Boys with different-colored casings. The Advanced Computer Modeling graphics used in Donkey Kong Country for the Super NES and Donkey Kong Land for the Game Boy were technologically innovative, as was the Satellaview satellite modem peripheral for the Super Famicom, which allowed the digital transmission of data via a communications satellite in space.
38 |
39 | 1993-1998: Nintendo 64, Virtual Boy, and Game Boy Color
40 | Further information: History of Nintendo 64, History of Virtual Boy, and History of Game Boy Color
41 |
42 | The Nintendo 64, Virtual Boy, and Game Boy Color
43 | In mid-1993, Nintendo and Silicon Graphics announced a strategic alliance to develop the Nintendo 64. NEC, Toshiba, and Sharp also contributed technology to the console. The Nintendo 64 was marketed as one of the first consoles to be designed with 64-bit architecture. As part of an agreement with Midway Games, the arcade games Killer Instinct and Cruis'n USA were ported to the console. Although the Nintendo 64 was planned for release in 1995, the production schedules of third-party developers influenced a delay, and the console was released in June and September 1996 in Japan and the United States respectively, and in March 1997 in Europe. By the end of its production in 2002, around 33 million Nintendo 64 consoles were sold worldwide, and it is considered one of the most recognized video game systems in history. 388 games were produced for the Nintendo 64 in total, some of which - particularly Super Mario 64, The Legend of Zelda: Ocarina of Time, and GoldenEye 007 - have been distinguished as some of the greatest of all time.
44 |
45 | In 1995, Nintendo released the Virtual Boy, a console designed by Gunpei Yokoi with stereoscopic graphics. Critics were generally disappointed with the quality of the games and red-colored graphics, and complained of gameplay-induced headaches. The system sold poorly and was quietly discontinued. Amid the system's failure, Yokoi formally retired from Nintendo. In February 1996, Pocket Monsters Red and Green, known internationally as Pokémon Red and Blue, developed by Game Freak was released in Japan for the Game Boy, and established the popular Pokémon franchise.:191 The game went on to sell 31.37 million units, with the video game series exceeding a total of 300 million units in sales as of 2017. In 1997, Nintendo released the Rumble Pak, a plug-in device that connects to the Nintendo 64 controller and produces a vibration during certain moments of a game.
46 |
47 | In 1998, the Game Boy Color was released. In addition to backward compatibility with Game Boy games, the console's similar capacity to the NES resulted in select adaptations of games from that library, such as Super Mario Bros. Deluxe. Since then, over 118.6 million Game Boy and Game Boy Color consoles have been sold worldwide.
48 |
49 | 1999-2003: Game Boy Advance and GameCube
50 | Further information: History of Game Boy Advance and History of GameCube
51 |
52 | The Game Boy Advance and GameCube
53 | In May 1999, with the advent of the PlayStation 2, Nintendo entered an agreement with IBM and Panasonic to develop the 128-bit Gekko processor and the DVD drive to be used in Nintendo's next home console. Meanwhile, a series of administrative changes occurred in 2000, when Nintendo's corporate offices were moved to the Minami-ku neighborhood in Kyoto, and Nintendo Benelux was established to manage the Dutch and Belgian territories.
54 |
55 | In 2001, two new Nintendo consoles were introduced: the Game Boy Advance, which was designed by Gwénaël Nicolas with stylistic departure from its predecessors, and the GameCube. During the first week of the Game Boy Advance's North American release in June 2001, over 500,000 units were sold, making it the fastest-selling video game console in the United States at the time. By the end of its production cycle in 2010, more than 81.5 million units had been sold worldwide. As for the GameCube, even with such distinguishing features as the miniDVD format of its games and Internet connectivity for a few games, its sales were lower than those of its predecessors, and during the six years of its production, 21.7 million units were sold worldwide. An innovative product developed by Nintendo during this time was the Nintendo e-Reader, a Game Boy Advance peripheral that allows the transfer of data stored on a series of cards to the console.
56 |
57 | In 2002, the Pokémon Mini was released. Its dimensions were smaller than that of the Game Boy Advance and it weighed 70 grams, making it the smallest video game console in history. Nintendo collaborated with Sega and Namco to develop Triforce, an arcade board to facilitate the conversion of arcade titles to the GameCube. Following the European release of the GameCube in May 2002, Hiroshi Yamauchi announced his resignation as the president of Nintendo, and Satoru Iwata was selected by the company as his successor. Yamauchi would remain as advisor and director of the company until 2005, and he died in 2013. Iwata's appointment as president ended the Yamauchi succession at the helm of the company, a practice that had been in place since its foundation.
58 |
59 | In 2003, Nintendo released the Game Boy Advance SP, an improved version of the Game Boy Advance with a foldable case, an illuminated display, and a rechargeable battery. By the end of its production cycle in 2010, over 43.5 million units had been sold worldwide. Nintendo also released the Game Boy Player, a peripheral that allows Game Boy and Game Boy Advance games to be played on the GameCube.
60 |
61 | 2004-2009: Nintendo DS and Wii
62 | Further information: History of Nintendo DS and History of Wii
63 |
64 | The Nintendo DS and Wii
65 | In 2004, the last remnants of Nintendo's original headquarters was reportedly demolished. Later that year, Nintendo released the Nintendo DS, which featured such innovations as dual screens - one of which being a touchscreen - and wireless connectivity for multiplayer play. Throughout its lifetime, more than 154 million units were sold, making it the most successful handheld console and the second best-selling console in history. In 2005, Nintendo released the Game Boy Micro, the last system in the Game Boy line. Sales did not meet Nintendo's expectations, with 2.5 million units being sold by 2007. In mid-2005, the Nintendo World Store was inaugurated in New York City.
66 |
67 | Nintendo's next home console was conceived in 2001, although development commenced in 2003, taking inspiration from the Nintendo DS. Nintendo also considered the relative failure of the GameCube, and instead opted to take a "blue ocean strategy" by developing a reduced performance console in contrast to the high-performance consoles of Sony and Microsoft to avoid directly competiting with them. The Wii was released in November 2006, with a total of 33 launch games. With the Wii, Nintendo sought to reach a broader demographic than its seventh-generation competitors, with the intention of also encompassing the "non-consumer" sector. To this end, Nintendo invested in a $200 million advertising campaign. The Wii's innovations include the Wii Remote controller, equipped with an accelerometer system and infrared sensors that allow it to detect its position in a three-dimensional environment with the aid of a sensor bar; the Nunchuk peripheral that includes an analog controller and an accelerometer; and the Wii MotionPlus expansion that increases the sensitivity of the main controller with the aid of gyroscopes. By 2016, more than 101 million Wii consoles had been sold worldwide, making it the most successful console of its generation, a distinction that Nintendo had not achieved since the 1990s with the Super NES.
68 |
69 | Several accessories were released for the Wii from 2007 to 2010, such as the Wii Balance Board, the Wii Wheel and the WiiWare download service. In 2009, Nintendo Iberica S.A. expanded its commercial operations to Portugal through a new office in Lisbon. By that year, Nintendo held a 68.3% share of the worldwide handheld gaming market. In 2010, Nintendo celebrated the 25th anniversary of Mario's debut appearance, for which certain allusive products were put on sale. The event included the release of Super Mario All-Stars 25th Anniversary Edition and special editions of the Nintendo DSi XL and Wii.
70 |
71 | 2010-2016: Nintendo 3DS, Wii U, and mobile ventures
72 | Further information: History of Nintendo 3DS, History of Wii U, and History of Nintendo mobile games
73 |
74 | The Nintendo 3DS, the Wii U, and a mobile phone with Pokémon Go in the sign-up menu
75 | Following an announcement in March 2010, Nintendo released the Nintendo 3DS in 2011. The console produces stereoscopic effects without 3D glasses. By 2018, more than 69 million units had been sold worldwide;] the figure increased to 75 million by the start of 2019. In 2011, Nintendo celebrated the 25th anniversary of The Legend of Zelda with the orchestra concert tour The Legend of Zelda: Symphony of the Goddesses and the video game The Legend of Zelda: Skyward Sword.
76 |
77 | In 2012 and 2013, two new Nintendo game consoles were introduced: the Wii U, with high-definition graphics and a GamePad controller with near-field communication technology, and the Nintendo 2DS, a version of the 3DS that lacks the clamshell design of Nintendo's previous handheld consoles and the stereoscopic effects of the 3DS. With 13.5 million units sold worldwide, the Wii U is the least successful video game console in Nintendo's history. In 2014, a new product line was released consisting of figures of Nintendo characters called amiibos.
78 |
79 | On 25 September 2013, Nintendo announced its acquisition of a 28% stake in PUX Corporation, a subsidiary of Panasonic, for the purpose of developing facial, voice, and text recognition for its video games. Due to a 30% decrease in company income between April and December 2013, Iwata announced a temporary 50% cut to his salary, with other executives seeing reductions by 20%-30%. In January 2015, Nintendo ceased operations in the Brazilian market due in part to high import duties. This did not affect the rest of Nintendo's Latin American market due to an alliance with Juegos de Video Latinoamérica. Nintendo reached an agreement with NC Games for Nintendo's products to resume distribution in Brazil by 2017, and by September 2020, the Switch was released in Brazil.
80 |
81 | On 11 July 2015, Iwata died of bile duct cancer, and after a couple of months in which Miyamoto and Takeda jointly operated the company, Tatsumi Kimishima was named as Iwata's successor on 16 September 2015. As part of the management's restructuring, Miyamoto and Takeda were respectively named creative and technological advisors.
82 |
83 | The financial losses caused by the Wii U, along with Sony's intention to release its video games to other platforms such as smart TVs, motivated Nintendo to rethink its strategy concerning the production and distribution of its properties. In 2015, Nintendo formalized agreements with DeNA and Universal Parks & Resorts to extend its presence to smart devices and amusement parks respectively. In March 2016, Nintendo's first mobile app for the iOS and Android systems, Miitomo, was released. Since then, Nintendo has produced other similar apps, such as Super Mario Run, Fire Emblem Heroes, Animal Crossing: Pocket Camp, Mario Kart Tour, and Pokémon Go, the last being developed by Niantic and having generated $115 million in revenue for Nintendo. The theme park area Super Nintendo World opened at Universal Studios Japan in 2020. In March 2016, the loyalty program My Nintendo replaced Club Nintendo.
84 |
85 | The NES Classic Edition was released in November 2016. The console is a version of the NES based on emulation, HDMI, and the Wii remote. Its successor, the Super NES Classic Edition, was released in September 2017. By October 2018, around ten million units of both consoles combined had been sold worldwide.
86 |
87 | 2017-present: Nintendo Switch and expansion to other media
88 | Further information: History of Nintendo Switch
89 |
90 | The Nintendo Switch
91 | The Wii U's successor in the eighth generation of video game consoles, the Nintendo Switch, was released in March 2017. The Switch features a hybrid design as a home and handheld console, Joy-Con controllers that each contain an accelerometer and gyroscope, and the simultaneous wireless networking of up to eight consoles. To expand its library, Nintendo entered alliances with several third-party and independent developers; by February 2019, more than 1,800 Switch games had been released. Worldwide sales of the Switch exceeded 55 million units by March 2020. In April 2018, the Nintendo Labo line was released, consisting of cardboard accessories that interact with the Switch and the Joy-Con controllers. More than one million units of the Nintendo Labo Variety Kit were sold in its first year on the market.
92 |
93 | In 2018, Shuntaro Furukawa replaced Kimishima as company president, and in 2019, Doug Bowser succeeded Nintendo of America president Reggie Fils-Aimé. In April 2019, Nintendo formed an alliance with Tencent to distribute the Nintendo Switch in China starting in December. In April 2020, ValueAct Capital Partners announced an acquisition of $1.1 billion in Nintendo stock purchases, giving them an overall stake of 2% in Nintendo. On 6 January 2020, hotel and restaurant development company Plan See Do announced that it would refurbish the former headquarters of Marufuku Nintendo Card Co. as a hotel, with plans to add 20 guest rooms, a restaurant, bar, and gym, with a planned opening date of mid 2021. The building belongs to Yamauchi Co., Ltd., an asset management company of Nintendo's founding family. It was further reported that the original 19th-century headquarters was apparently demolished and turned into a parking lot. Although the COVID-19 pandemic caused delays in the production and distribution of some of Nintendo's products, the situation "had limited impact on business results"; in May 2020, Nintendo reported a 75% increase in income compared to the previous fiscal year, mainly contributed by the Nintendo Switch Online service. In August 2020, Nintendo was named the richest company in Japan.
94 |
95 | Nintendo announced plans in June 2021 to convert its former Uji Ogura plant, where it had previously made playing and hanafuda cards, into a museum for the company to be completed by the 2023 fiscal year. The building has been vacant since these functions were transferred to a new Uji plant in 2016.
96 |
97 | Logo of Nintendo Pictures
98 | Nintendo is co-producing an animated film The Super Mario Bros. Movie alongside Universal Pictures and Illumination, with Miyamoto and Illumination CEO Chris Meledandri producing, set for release in April 2023. In 2021, Furukawa indicated Nintendo's plan to create more animated projects based on their work outside the Mario film, and by July, Melendandri joined the board of directors "as an independent and non-executive outside director", to help Nintendo produce further movies through his filmmaking experience, and Furukawa confirmed that work on other animated projects was currently underway. According to Furukawa, the company's expansion toward animated production is to keep " business thriving and growing", realizing the "need to create opportunities where even people who do not normally play on video game systems can come into contact with Nintendo characters". That day, Miyamoto said that " really came to understand the Nintendo point of view" and that "asking for input, as an expert with many years of experience in Hollywood, will be of great help to" Nintendo's transition into film production. Later, in July 2022, Nintendo acquired Dynamo Pictures, a Japanese CG company founded by Hiroshi Hirokawa on March 18, 2011. Dynamo had worked with Nintendo on digital shorts in the 2010s, including for the Pikmin series, and Nintendo said that Dynamo would continue their goal of expanding into animation. Following the completion of the acquisition in October 2022, Nintendo renamed Dynamo as Nintendo Pictures.
99 |
100 | In February 2022, Nintendo announced the acquisition of SRD Co., Ltd. (Systems Research and Development) after 40 years, a major contributor of Nintendo's first-party games such as Donkey Kong and The Legend of Zelda until the 1990s, and then support studio since.
101 |
102 | In May 2022, it was reported by Bloomberg that Saudi Arabia's Public Investment Fund had purchased a 5% stake in Nintendo.`;
103 |
--------------------------------------------------------------------------------
/assets/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kurtvandusen/React-Native-Easy-Chatbot/b40eeaa3ed602d7fe6de965b8765912b98abeb79/assets/favicon.png
--------------------------------------------------------------------------------
/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kurtvandusen/React-Native-Easy-Chatbot/b40eeaa3ed602d7fe6de965b8765912b98abeb79/assets/icon.png
--------------------------------------------------------------------------------
/assets/splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kurtvandusen/React-Native-Easy-Chatbot/b40eeaa3ed602d7fe6de965b8765912b98abeb79/assets/splash.png
--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = function (api) {
2 | api.cache(true);
3 | return {
4 | presets: ["babel-preset-expo"],
5 | };
6 | };
7 |
--------------------------------------------------------------------------------
/commitlint.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: ["@commitlint/config-conventional"],
3 | ignores: [(message) => message.includes("https://")],
4 | };
5 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "easy-chatbot",
3 | "version": "1.5.0",
4 | "main": "node_modules/expo/AppEntry.js",
5 | "scripts": {
6 | "start": "expo start",
7 | "android": "expo start --android",
8 | "ios": "expo start --ios",
9 | "web": "expo start --web",
10 | "prepare": "husky install",
11 | "test": "jest",
12 | "commit": "git-cz",
13 | "format": "prettier --write \"app/**/*.{js,jsx,json,md,ts,tsx}\"",
14 | "lint": "eslint App.js app --fix --ext .js,.ts,.tsx && npm run format"
15 | },
16 | "dependencies": {
17 | "@reduxjs/toolkit": "^1.9.0",
18 | "@types/react-native": "~0.70.6",
19 | "axios": "^1.1.3",
20 | "axios-retry": "^3.3.1",
21 | "dotenv": "^16.0.3",
22 | "expo": "~47.0.6",
23 | "expo-constants": "~14.0.2",
24 | "expo-status-bar": "~1.4.2",
25 | "react": "18.1.0",
26 | "react-native": "0.70.5",
27 | "react-native-gifted-chat": "^1.0.4",
28 | "react-redux": "^8.0.5",
29 | "redux": "^4.2.0",
30 | "redux-saga": "^1.2.1",
31 | "typescript": "^4.6.3"
32 | },
33 | "devDependencies": {
34 | "@babel/core": "^7.12.9",
35 | "@commitlint/cli": "^17.3.0",
36 | "@commitlint/config-conventional": "^17.3.0",
37 | "@semantic-release/changelog": "^6.0.2",
38 | "@semantic-release/git": "^10.0.1",
39 | "@typescript-eslint/eslint-plugin": "^5.44.0",
40 | "@typescript-eslint/parser": "^5.44.0",
41 | "commitizen": "^4.2.5",
42 | "cz-conventional-changelog": "^3.3.0",
43 | "eslint": "^8.28.0",
44 | "eslint-config-universe": "^11.1.1",
45 | "husky": "^8.0.2",
46 | "jest": "^29.3.1",
47 | "jest-expo": "^47.0.1",
48 | "jest-mock-axios": "^4.7.0-beta2",
49 | "prettier": "^2.8.0",
50 | "semantic-release": "^19.0.5"
51 | },
52 | "private": true,
53 | "config": {
54 | "commitizen": {
55 | "path": "./node_modules/cz-conventional-changelog"
56 | }
57 | },
58 | "jest": {
59 | "preset": "jest-expo",
60 | "transformIgnorePatterns": [
61 | "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)"
62 | ]
63 | },
64 | "husky": {
65 | "hooks": {
66 | "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/release.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | branches: [
3 | "main",
4 | {
5 | name: "staging",
6 | prerelease: true,
7 | },
8 | ],
9 | plugins: [
10 | "@semantic-release/commit-analyzer",
11 | "@semantic-release/release-notes-generator",
12 | [
13 | "@semantic-release/changelog",
14 | {
15 | changelogFile: "CHANGELOG.md",
16 | },
17 | ],
18 | "@semantic-release/npm",
19 | "@semantic-release/github",
20 | [
21 | "@semantic-release/git",
22 | {
23 | assets: ["CHANGELOG.md", "package.json", "package-lock.json"],
24 | message:
25 | "chore(release): set `package.json` to ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}",
26 | },
27 | ],
28 | ],
29 | };
30 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {},
3 | "extends": "expo/tsconfig.base"
4 | }
5 |
--------------------------------------------------------------------------------