Skip to content

Commit

Permalink
feat(example): add chat ui
Browse files Browse the repository at this point in the history
* feat: add increased memory limit

* fix: include `bundle/` dir

* fix: disable new arch

* feat: add chat ui

* feat: add network state information
  • Loading branch information
szymonrybczak committed Jul 24, 2024
1 parent e87bebc commit 9295c10
Show file tree
Hide file tree
Showing 15 changed files with 635 additions and 103 deletions.
Binary file added example/assets/avatar.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions example/ios/AiExample.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
7699B88040F8A987B510C191 /* libPods-AiExample-AiExampleTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19F6CBCC0A4E27FBF8BF4A61 /* libPods-AiExample-AiExampleTests.a */; };
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
AC91505B2C4C37D100E4348A /* bundle in Resources */ = {isa = PBXBuildFile; fileRef = AC91505A2C4C37D100E4348A /* bundle */; };
FA9143FAE05E547962661C6F /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 1158F81499343192EE2DB0E3 /* PrivacyInfo.xcprivacy */; };
/* End PBXBuildFile section */

Expand Down Expand Up @@ -46,6 +47,8 @@
5DCACB8F33CDC322A6C60F78 /* libPods-AiExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AiExample.a"; sourceTree = BUILT_PRODUCTS_DIR; };
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = AiExample/LaunchScreen.storyboard; sourceTree = "<group>"; };
89C6BE57DB24E9ADA2F236DE /* Pods-AiExample-AiExampleTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AiExample-AiExampleTests.release.xcconfig"; path = "Target Support Files/Pods-AiExample-AiExampleTests/Pods-AiExample-AiExampleTests.release.xcconfig"; sourceTree = "<group>"; };
AC9150592C4C347200E4348A /* AiExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = AiExample.entitlements; path = AiExample/AiExample.entitlements; sourceTree = "<group>"; };
AC91505A2C4C37D100E4348A /* bundle */ = {isa = PBXFileReference; lastKnownFileType = folder; name = bundle; path = dist/bundle; sourceTree = "<group>"; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
/* End PBXFileReference section */

Expand Down Expand Up @@ -89,6 +92,7 @@
13B07FAE1A68108700A75B9A /* AiExample */ = {
isa = PBXGroup;
children = (
AC9150592C4C347200E4348A /* AiExample.entitlements */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
Expand Down Expand Up @@ -121,6 +125,7 @@
83CBB9F61A601CBA00E9B192 = {
isa = PBXGroup;
children = (
AC91505A2C4C37D100E4348A /* bundle */,
13B07FAE1A68108700A75B9A /* AiExample */,
832341AE1AAA6A7D00B99B32 /* Libraries */,
00E356EF1AD99517003FC87E /* AiExampleTests */,
Expand Down Expand Up @@ -246,6 +251,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
AC91505B2C4C37D100E4348A /* bundle in Resources */,
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
FA9143FAE05E547962661C6F /* PrivacyInfo.xcprivacy in Resources */,
Expand Down Expand Up @@ -471,6 +477,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = AiExample/AiExample.entitlements;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = ZK8L4ATDPD;
ENABLE_BITCODE = NO;
Expand Down Expand Up @@ -557,6 +564,7 @@
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = AiExample/AiExample.entitlements;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = ZK8L4ATDPD;
INFOPLIST_FILE = AiExample/Info.plist;
Expand Down
8 changes: 8 additions & 0 deletions example/ios/AiExample/AiExample.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.kernel.increased-memory-limit</key>
<true/>
</dict>
</plist>
2 changes: 1 addition & 1 deletion example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
ENV['RCT_NEW_ARCH_ENABLED'] = '1'
ENV['RCT_NEW_ARCH_ENABLED'] = '0'

# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
Expand Down
20 changes: 16 additions & 4 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,10 @@ PODS:
- ReactCommon/turbomodule/bridging
- ReactCommon/turbomodule/core
- Yoga
- react-native-get-random-values (1.11.0):
- React-Core
- react-native-netinfo (11.3.2):
- React-Core
- React-nativeconfig (0.74.2)
- React-NativeModulesApple (0.74.2):
- glog
Expand Down Expand Up @@ -1244,6 +1248,8 @@ DEPENDENCIES:
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
- React-Mapbuffer (from `../node_modules/react-native/ReactCommon`)
- react-native-ai (from `../..`)
- react-native-get-random-values (from `../node_modules/react-native-get-random-values`)
- "react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)"
- React-nativeconfig (from `../node_modules/react-native/ReactCommon`)
- React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`)
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
Expand Down Expand Up @@ -1337,6 +1343,10 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon"
react-native-ai:
:path: "../.."
react-native-get-random-values:
:path: "../node_modules/react-native-get-random-values"
react-native-netinfo:
:path: "../node_modules/@react-native-community/netinfo"
React-nativeconfig:
:path: "../node_modules/react-native/ReactCommon"
React-NativeModulesApple:
Expand Down Expand Up @@ -1417,15 +1427,17 @@ SPEC CHECKSUMS:
React-jsitracing: 0fa7f78d8fdda794667cb2e6f19c874c1cf31d7e
React-logger: 29fa3e048f5f67fe396bc08af7606426d9bd7b5d
React-Mapbuffer: bf56147c9775491e53122a94c423ac201417e326
react-native-ai: 4c526ef3a4ab811772b4ef0a3300f7d6b26cd0b4
react-native-ai: e1592baf0559a8b64e5f38dd2c0f2758ccea2d25
react-native-get-random-values: 21325b2244dfa6b58878f51f9aa42821e7ba3d06
react-native-netinfo: 076df4f9b07f6670acf4ce9a75aac8d34c2e2ccc
React-nativeconfig: 9f223cd321823afdecf59ed00861ab2d69ee0fc1
React-NativeModulesApple: ff7efaff7098639db5631236cfd91d60abff04c0
React-perflogger: 32ed45d9cee02cf6639acae34251590dccd30994
React-RCTActionSheet: 19f967ddaea258182b56ef11437133b056ba2adf
React-RCTAnimation: d7f4137fc44a08bba465267ea7cb1dbdb7c4ec87
React-RCTAppDelegate: dca95e1a6194f7ae06c2b5f1d5f891c61af00ec8
React-RCTAppDelegate: 2b3f4d8009796af209a0d496e73276b743acee08
React-RCTBlob: c6c3e1e0251700b7bea036b893913f22e2b9cb47
React-RCTFabric: a7874c54aea18f64677446efc5f839ec4fa5e931
React-RCTFabric: 93a3ea55169d19294f07092013c1c9ea7a015c9b
React-RCTImage: 40528ab74a4fef0f0e2ee797a074b26d120b6cc6
React-RCTLinking: 385b5beb96749aae9ae1606746e883e1c9f8a6a7
React-RCTNetwork: ffc9f05bd8fa5b3bce562199ba41235ad0af645c
Expand All @@ -1444,6 +1456,6 @@ SPEC CHECKSUMS:
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
Yoga: 2f71ecf38d934aecb366e686278102a51679c308

PODFILE CHECKSUM: bbc2c796a007c2b3b597f12669100724c622d914
PODFILE CHECKSUM: c1ce3fcc38763d2aab0f2e5c56e464d324db8386

COCOAPODS: 1.15.2
5 changes: 5 additions & 0 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,15 @@
"start": "react-native start"
},
"dependencies": {
"@react-native-community/netinfo": "^11.3.2",
"@types/uuid": "^10.0.0",
"ai": "^3.2.15",
"react": "18.2.0",
"react-native": "0.74.2",
"react-native-get-random-values": "^1.11.0",
"react-native-gifted-chat": "^2.4.0",
"text-encoding": "^0.7.0",
"uuid": "^10.0.0",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
7 changes: 7 additions & 0 deletions example/polyfills.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import 'react-native-get-random-values';

// @ts-ignore
import { polyfillGlobal } from 'react-native/Libraries/Utilities/PolyfillFunctions';
const webStreamPolyfills = require('web-streams-polyfill/ponyfill/es6');

polyfillGlobal('TextEncoder', () => require('text-encoding').TextEncoder);
polyfillGlobal('TextDecoder', () => require('text-encoding').TextDecoder);
polyfillGlobal('ReadableStream', () => webStreamPolyfills.ReadableStream);
polyfillGlobal('TransformStream', () => webStreamPolyfills.TransformStream);
polyfillGlobal('WritableStream', () => webStreamPolyfills.WritableStream);
polyfillGlobal('TextEncoderStream', () => webStreamPolyfills.TextEncoderStream);
79 changes: 58 additions & 21 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,32 +1,69 @@
import React from 'react';
import { StyleSheet, View, Text, TouchableOpacity } from 'react-native';
import { doGenerate } from 'react-native-ai';

export default function App() {
const askQuestion = async () => {
try {
const data = await doGenerate('ai', 'whats react native');
console.log(data);
} catch (e) {
console.error(e);
}
import React, { useState } from 'react';
import { SafeAreaView, StyleSheet } from 'react-native';
import { GiftedChat, type IMessage } from 'react-native-gifted-chat';
import { getModel } from 'react-native-ai';
import { generateText } from 'ai';
import { v4 as uuid } from 'uuid';
import NetworkInfo from './NetworkInfo';

const modelId = 'Phi-3-mini-4k-instruct-q4f16_1-MLC';

const aiBot = {
_id: 2,
name: 'AI Chat Bot',
avatar: require('./../assets/avatar.png'),
};

export default function Example() {
const [messages, setMessages] = useState<IMessage[]>([
{
_id: uuid(),
text: 'Hello! How can I help you today?',
createdAt: new Date(),
user: aiBot,
},
]);

const onSendMessage = async (prompt: string) => {
const { text } = await generateText({
model: getModel(modelId),
prompt,
});

setMessages((previousMessages) =>
GiftedChat.append(previousMessages, {
// @ts-ignore
_id: uuid(),
text,
createdAt: new Date(),
user: aiBot,
})
);
};

return (
<View style={styles.container}>
<TouchableOpacity style={styles.button} onPress={askQuestion}>
<Text>Ask a question</Text>
</TouchableOpacity>
</View>
<SafeAreaView style={styles.container}>
<NetworkInfo />
<GiftedChat
messages={messages}
onSend={(newMessage) => {
setMessages((previousMessages) =>
GiftedChat.append(previousMessages, newMessage)
);

onSendMessage(newMessage[0]!.text);
}}
user={{
_id: 1,
}}
/>
</SafeAreaView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: 'darkblue',
backgroundColor: '#fff',
},
button: { width: 200, height: 200, backgroundColor: 'red' },
});
56 changes: 56 additions & 0 deletions example/src/NetworkInfo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { useNetInfo } from '@react-native-community/netinfo';

const NetworkInfo = () => {
const netInfo = useNetInfo();

const getStatusColor = () => {
if (netInfo.isConnected) return styles.connected;
return styles.disconnected;
};

return (
<View style={styles.container}>
<View style={[styles.statusIndicator, getStatusColor()]} />
<Text style={styles.statusText}>
{netInfo.isConnected ? 'Connected ✅' : 'Disconnected ❌'}
</Text>
</View>
);
};

const styles = StyleSheet.create({
container: {
flexDirection: 'row',
alignItems: 'center',
padding: 10,
backgroundColor: '#f0f0f0',
borderRadius: 8,
},
statusIndicator: {
width: 12,
height: 12,
borderRadius: 6,
marginRight: 10,
},
connected: {
backgroundColor: '#4CAF50',
},
disconnected: {
backgroundColor: '#F44336',
},
textContainer: {
flex: 1,
},
statusText: {
fontSize: 16,
fontWeight: 'bold',
},
detailText: {
fontSize: 14,
color: '#666',
},
});

export default NetworkInfo;
5 changes: 3 additions & 2 deletions ios/Ai.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#import <React/RCTEventEmitter.h>

#ifdef RCT_NEW_ARCH_ENABLED
#import "RNAiSpec.h"

@interface Ai : NSObject <NativeAiSpec>
@interface Ai : RCTEventEmitter <NativeAiSpec>
#else
#import <React/RCTBridgeModule.h>

@interface Ai : NSObject <RCTBridgeModule>
@interface Ai : RCTEventEmitter <RCTBridgeModule>
#endif

@end
Loading

0 comments on commit 9295c10

Please sign in to comment.