ConnectyCube expo react native support for RNChat - react-native

Is there a chance to get an RNChat example which runs on latest expo react native for supporting the great expo plugins like expo av player or expo haptics?
Edit:
Build fails
=== BUILD TARGET React-Codegen OF PROJECT Pods WITH CONFIGURATION Debug ===
Check dependencies
** BUILD FAILED **
The following build commands failed:
CompileSwiftSources normal x86_64 com.apple.xcode.tools.swift.compiler
CompileSwift normal x86_64
(2 failures)
I get tons of errors using the expo and expo-modules-core like:
expo-modules-core/ Class Components Factories swift:71:52: error: unknown attribute '_implicitSelfCapture'
OR
expo-modules-core/ios/Swift/DynamicTypes/DynamicEnumType.swift:7:22: error: expected declaration
let innerType: any Enumerable.Type

Unfortunately, we don't have the chat app example for Expo. Errors you've provided aren't related to ConnectyCube's services.
You can make chat app using our ConnectyCube SDK. The SDK supports Expo except WebRTC (video/audio calls).
See docs how to use ConnectyCube's API and chat for React Native here
Try simple code how to use ConnectyCube SDK with Expo:
npx create-expo-app ExpoConnectyCube
cd ExpoConnectyCube
yarn add react-native-connectycube
yarn ios
import { StatusBar } from "expo-status-bar";
import { useEffect, useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import ConnectyCube from "react-native-connectycube";
const creds = {
appId: 385,
authKey: "DFBMs5-dKBBCXcd",
authSecret: "SkCW-ThdnmRg9Za",
};
const conf = {
debug: { mode: 1 },
};
const user = {
id: 72780,
login: "videouser1",
password: "videouser1",
};
export default function App() {
const [session, setSession] = useState("empty");
const [chat, setChat] = useState(false);
const [message, setMessage] = useState("");
const initConnectyCube = () => {
ConnectyCube.init(creds, conf);
};
const createAuthSession = () => {
ConnectyCube.createSession({ login: user.login, password: user.password })
.then((result) => {
setSession(result);
})
.catch((sessionError) => setChat(sessionError));
};
const chatConnect = () => {
ConnectyCube.chat.onMessageListener = (user, message) => {
setMessage({ user, message });
};
ConnectyCube.chat
.connect({ userId: user.id, password: user.password })
.then(() => {
setChat(true);
ConnectyCube.chat.send(user.id, { body: "Hello", type: "chat" });
})
.catch((chatError) => setChat(chatError));
};
useEffect(() => {
initConnectyCube();
createAuthSession();
chatConnect();
}, []);
return (
<View style={styles.container}>
<Text>{`Session: ${JSON.stringify(session)} \n`}</Text>
<Text>{`Chat connected: ${chat} \n`}</Text>
<Text>{`onMessage: ${JSON.stringify(message)} \n`}</Text>
<StatusBar style="auto" />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
justifyContent: "center",
},
});

Related

Issue sending & receiving streams between two clients in LiveKit's React Native SDK

I'm trying to build on the example app provided by livekit, so far I've implemented everything like the example app and I've been successful with connecting to a room on example website, I recieve audio from website, but I don't read the video stream, and I also can't send audio or video at all.
Steps to reproduce the behavior:
add the following to index.js
import { registerRootComponent } from "expo";
import { registerGlobals } from "livekit-react-native";
import App from "./App";
registerRootComponent(App);
registerGlobals();
Rendering the following component in App.tsx
import { Participant, Room, Track } from "livekit-client";
import {
useRoom,
useParticipant,
AudioSession,
VideoView,
} from "livekit-react-native";
import { useEffect, useState } from "react";
import { Text, ListRenderItem, StyleSheet, FlatList, View } from "react-native";
import { ParticipantView } from "./ParticipantView";
import { RoomControls } from "./RoomControls";
import type { TrackPublication } from "livekit-client";
const App = () => {
// Create a room state
const [, setIsConnected] = useState(false);
const [room] = useState(
() =>
new Room({
publishDefaults: { simulcast: false },
adaptiveStream: true,
})
);
// Get the participants from the room
const { participants } = useRoom(room);
const url = "[hard-coded-url]";
const token =
"[hard-coded-token";
useEffect(() => {
let connect = async () => {
// If you wish to configure audio, uncomment the following:
await AudioSession.configureAudio({
android: {
preferredOutputList: ["speaker"],
},
ios: {
defaultOutput: "speaker",
},
});
await AudioSession.startAudioSession();
await room.connect(url, token, {});
await room.localParticipant.setCameraEnabled(true);
await room.localParticipant.setMicrophoneEnabled(true);
await room.localParticipant.enableCameraAndMicrophone();
console.log("connected to ", url);
setIsConnected(true);
};
connect();
return () => {
room.disconnect();
AudioSession.stopAudioSession();
};
}, [url, token, room]);
// Setup views.
const stageView = participants.length > 0 && (
<ParticipantView participant={participants[0]} style={styles.stage} />
);
const renderParticipant: ListRenderItem<Participant> = ({ item }) => {
return (
<ParticipantView participant={item} style={styles.otherParticipantView} />
);
};
const otherParticipantsView = participants.length > 0 && (
<FlatList
data={participants}
renderItem={renderParticipant}
keyExtractor={(item) => item.sid}
horizontal={true}
style={styles.otherParticipantsList}
/>
);
const { cameraPublication, microphonePublication } = useParticipant(
room.localParticipant
);
return (
<View style={styles.container}>
{stageView}
{otherParticipantsView}
<RoomControls
micEnabled={isTrackEnabled(microphonePublication)}
setMicEnabled={(enabled: boolean) => {
room.localParticipant.setMicrophoneEnabled(enabled);
}}
cameraEnabled={isTrackEnabled(cameraPublication)}
setCameraEnabled={(enabled: boolean) => {
room.localParticipant.setCameraEnabled(enabled);
}}
onDisconnectClick={() => {
// navigation.pop();
console.log("disconnected");
}}
/>
</View>
);
};
function isTrackEnabled(pub?: TrackPublication): boolean {
return !(pub?.isMuted ?? true);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: "center",
justifyContent: "center",
},
stage: {
flex: 1,
width: "100%",
},
otherParticipantsList: {
width: "100%",
height: 150,
flexGrow: 0,
},
otherParticipantView: {
width: 150,
height: 150,
},
});
export default App;
the components used here are mostly the same as what's in the example, I've removed the screensharing logic and the messages
5. I run the app using an expo development build
6. it will log that it's connected, you'll be able to hear sound from the remote participant, but not see any video or send any sound.
7. if i try to add
await room.localParticipant.enableCameraAndMicrophone();
in the useEffect, I get the following error:
Possible Unhandled Promise Rejection (id: 0):
Error: Not implemented.
getSettings#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:103733:24
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:120307:109
generatorResume#[native code]
asyncGeneratorStep#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21908:26
_next#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21927:29
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21932:14
tryCallTwo#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26656:9
doResolve#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26788:25
Promise#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26675:14
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21924:25
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:120173:52
generatorResume#[native code]
asyncGeneratorStep#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21908:26
_next#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21927:29
tryCallOne#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26648:16
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:26729:27
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27687:26
_callTimer#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27602:17
_callReactNativeMicrotasksPass#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27635:17
callReactNativeMicrotasks#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:27799:44
__callReactNativeMicrotasks#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:21006:46
#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20806:45
__guard#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20986:15
flushedQueue#http://192.168.1.150:8081/index.bundle?platform=ios&dev=true&hot=false:20805:21
flushedQueue#[native code]
Expected behavior
This should both receive & send video and audio streams between the two clients

unable to display expo push token on apk

I am using react native expo bare workflow
When I open the app on expo client I am able to see the device token on screen but when I convert it to apk
by using
expo build:android
It doesn't show token.
This is my code.
import React, { useEffect, useState } from "react";
import { StyleSheet, Text, View } from "react-native";
import * as Notifications from "expo-notifications";
import * as Permissions from "expo-permissions";
import { TextInput } from "react-native";
export default function App() {
const [token, setToken] = useState("");
const [value, onChangeText] = React.useState("Useless Placeholder");
useEffect(() => {
getPushNotificationPermissions();
});
getPushNotificationPermissions = async () => {
const { status: existingStatus } = await Permissions.getAsync(
Permissions.NOTIFICATIONS,
);
let finalStatus = existingStatus;
// only ask if permissions have not already been determined, because
// iOS won't necessarily prompt the user a second time.
if (existingStatus !== "granted") {
// Android remote notification permissions are granted during the app
// install, so this will only ask on iOS
const { status } = await Permissions.askAsync(Permissions.NOTIFICATIONS);
finalStatus = status;
}
// Stop here if the user did not grant permissions
if (finalStatus !== "granted") {
return;
}
console.log(finalStatus);
// Get the token that uniquely identifies this device
console.log(
"Notification Token: ",
(await Notifications.getExpoPushTokenAsync()).data,
);
setToken((await Notifications.getExpoPushTokenAsync()).data);
};
return (
<View style={styles.container}>
<Text>{token}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
alignItems: "center",
justifyContent: "center",
},
});
And also i don't get a push notification on apk but it works on expo client.
Since you're using bare workflow, You should pass your experienceId in an object to getExpoPushTokenAsync, the value of your experienceId is #your-username/your-project-slug

Data lost with last version of react-native and AsyncStorage

When I try to update my application (android/ios) with react-native and expo my data is lost and i don't know why :
old version :
"react-native": "0.51.0",
"redux-persist": "4.8.2",
new version :
"redux-persist": "4.8.2",
"react-native": "~0.61.5",
"expo": "^37.0.12",
Build with expo for the newer version
How I persist the data. The code hasn't changed between versions.
useEffect(() => {
persistStore(
store,
{
storage: AsyncStorage,
whitelist: ['data', 'data2' ],
transforms: [
createTransform(
state => state,
state => ({
...state,
infosOpened: false,
}),
{
whitelist: 'app',
}
),
],
},
() => {
setRehydrated(true)
}
)
}, [])
AsyncStorage is imported from react-native and I keep react-native with expo. #react-native-community/async-storage isn't compatible.
As what I saw inside the older version data is persisted with SQLlite format 3 inside "data user". Data appears to be always here with the newer version but it is no longer recovered.
I don't know if there is some braking changes react-native from version 51 to 61. I see nothing inside github release tags.
Edit1: OK so it seems that the problem is that RN use RCTAsyncLocalStorage_V1 folder and expo RCTAsyncLocalStorage. How I can fix that with the easiest way for IOS and Android ? Is it better to eject expo app or to add migration code ?
Edit2: Finally I opted for an RN version with react-native-unimodules like that I have no problem with path storage and I can use some dependencies from expo. (https://blog.expo.io/you-can-now-use-expo-apis-in-any-react-native-app-7c3a93041331)
Maybe the solution under works... I didn't test it
Another possible solution here. I didn't test it too :
https://github.com/expo/expo/issues/8220#issuecomment-656300244
You can find the sample code for migration in the snippet. This snippet is migration from Expo to pure RN. You will only have to reverse migration.
import React, { Component } from 'react';
import { View, ActivityIndicator, AsyncStorage } from 'react-native';
import PropTypes from 'prop-types';
import RNFS from 'react-native-fs';
export default class WalletMigrate extends Component {
componentDidMount() {
this.migrateDataFromExpo();
}
migrationComplete() {
console.log('Migration was successful. Exiting migration...')
this.props.onComplete();
}
// Migrate Document directory from Expo
async migrateDataFromExpo() {
const expoDirectoryExists = await RNFS.exists(RNFS.DocumentDirectoryPath + '/ExponentExperienceData');
if (!expoDirectoryExists) {
console.log('Expo data was previously migrated. Exiting migration...');
this.props.onComplete();
return;
}
try {
await RNFS.unlink(RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1')
console.log('/RCTAsyncLocalStorage_V1 has been deleted. Continuing...')
} catch {
console.log('/RCTAsyncLocalStorage_V1 does not exist. Continuing...')
}
RNFS.copyFile(
RNFS.DocumentDirectoryPath + '/ExponentExperienceData/%40USERNAME%2FAPPNAME/RCTAsyncLocalStorage',
RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1',
)
.then(() => {
RNFS.readDir(RNFS.DocumentDirectoryPath + '/RCTAsyncLocalStorage_V1').then(files => {
files.forEach(file => {
if (file.name !== 'manifest.json') {
RNFS.readFile(file.path).then(fileContents => {
AsyncStorage.setItem('data', fileContents)
.then(() => {
RNFS.unlink(RNFS.DocumentDirectoryPath + '/ExponentExperienceData').then(() => this.migrationComplete());
})
.catch(() => {
console.log('An error was encountered when trying to delete /ExponentExperienceData. Exiting migration...');
this.props.onComplete();
})
.then(() => this.migrationComplete())
});
}
});
})
.catch(error => {
console.log('An error was encountered when trying to read the /RTCAsyncLocalStorage_V1 directory. Exiting migration...');
console.log(error);
this.props.onComplete();
});
})
.catch(_error => this.props.onComplete());
}
render() {
return (
<View style={{ flex: 1, justifyContent: 'center', alignContent: 'center' }}>
<ActivityIndicator />
</View>
);
}
}
WalletMigrate.propTypes = {
onComplete: PropTypes.func,
};

Dialogflow API Chatbot for React Native in Expo

I am learning react native as beginner.
I want to create a chatbot using Dialogflow in react native in Expo.
I have searched all the forums and googled , but did not find any reference of using Dialogflow specifically to Expo though found reference to React Native CLI.
In this context, can anyone please guide me how to create a chatbot using Dialogflow in Expo React Native
Here you will have a great tutorial!
https://blog.jscrambler.com/build-a-chatbot-with-dialogflow-and-react-native/
if this help you please check it as correct answer...
here bellow some code:
import React, { Component } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import { GiftedChat } from 'react-native-gifted-chat';
import { Dialogflow_V2 } from 'react-native-dialogflow';
import { dialogflowConfig } from './env';
const BOT_USER = {
_id: 2,
name: 'FAQ Bot',
avatar: 'https://i.imgur.com/7k12EPD.png'
};
class App extends Component {
state = {
messages: [
{
_id: 1,
text: `Hi! I am the FAQ bot 🤖 from Jscrambler.\n\nHow may I help you with today?
`,
createdAt: new Date(),
user: BOT_USER
}
]
};
componentDidMount() {
Dialogflow_V2.setConfiguration(
dialogflowConfig.client_email,
dialogflowConfig.private_key,
Dialogflow_V2.LANG_ENGLISH_US,
dialogflowConfig.project_id
);
}
handleGoogleResponse(result) {
let text = result.queryResult.fulfillmentMessages[0].text.text[0];
this.sendBotResponse(text);
}
onSend(messages = []) {
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, messages)
}));
let message = messages[0].text;
Dialogflow_V2.requestQuery(
message,
result => this.handleGoogleResponse(result),
error => console.log(error)
);
}
sendBotResponse(text) {
let msg = {
_id: this.state.messages.length + 1,
text,
createdAt: new Date(),
user: BOT_USER
};
this.setState(previousState => ({
messages: GiftedChat.append(previousState.messages, [msg])
}));
}
render() {
return (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<GiftedChat
messages={this.state.messages}
onSend={messages => this.onSend(messages)}
user={{
_id: 1
}}
/>
</View>
);
}
}
export default App;

expo-av bare Error: Missing audio recording permissions

Was looking to use the recently available expo packages for detached or "bare" apps in react-native.
Running into the following error:
Error: Missing audio recording permissions.
however I have already called the expo-permissions library to ensure RecordAudio permissions are obtained.
See https://github.com/Glorifundel/bareaudio for full example project
App.js
import React, { Component } from 'react';
import { Platform, StyleSheet, Text, View, Button } from 'react-native';
import * as Permissions from 'expo-permissions';
import { Audio } from 'expo-av';
export default class App extends Component {
render() {
return (
<View style={{ flex: 1 }}>
<Text style={styles.welcome}>Welcome to React Native!</Text>
<Button title="Get Permission" onPress={this.onPressPermission} />
<Button title="Record" onPress={this.onPressRecord} />
</View>
);
}
onPressPermission = async () => {
const { status, expires, permissions } = await Permissions.askAsync(
Permissions.CAMERA_ROLL,
Permissions.AUDIO_RECORDING
);
alert(`permission: ${status}`);
};
onPressRecord = async () => {
const recording = new Audio.Recording();
try {
await recording.prepareToRecordAsync(
Audio.RECORDING_OPTIONS_PRESET_LOW_QUALITY
);
await recording.startAsync();
alert(`onPressRecord recording!`);
} catch (error) {
alert(`onPressRecord error: ${error}`);
}
};
}
Pressing the "Get Permission" button reports an alert "permissions: granted", following that up with pressing the "Record" button results in an alert "onPressRecord error: Error: Missing audio recording permissions."
Any insight is appreciated,
Environment details: I am running on windows 10, on an android emulator running android API 27 (8.1 Oreo). Did a fresh Node v10.15.3 install as well as a fresh react-native-cli expo-cli install and generated the project with expo init --template bare-minimum. followed up with yarn add expo-av and yarn add expo-permissions, followed the instructions found on the readme for the two packages.
async function startRecording() {
try {
console.log('Requesting permissions..');
await Audio.requestPermissionsAsync().then(() => {
console.log('Permission granted!');
})
.catch(error => {
console.log(error);
});
await Audio.setAudioModeAsync({
allowsRecordingIOS: true,
playsInSilentModeIOS: true,
});
console.log('Starting recording..');
const { recording } = await Audio.Recording.createAsync(
Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY
);
setRecording(recording);
console.log('Recording started');
} catch (err) {
console.error('Failed to start recording', err);
}
}