react-native-gifted-chat Video message is not displayed -Video not not implemented by GiftedChat - react-native-gifted-chat

Video is not being displayed in the message.
Got message " Video is not implemented by GiftedChat. You need to provide your own implementation by using renderMessageVideo prop.
Message[] has the following values:
_id:
text:
createdAt:
user:{
_id:
name:
avatar:
},
image:
video:
<GiftedChat
messages={this.state.messages}
onSend={this.onSend.bind(this)}
user={{
_id: this.state.LoggedinuserID,
}}
/>
Please help what am I doing wrong

What its saying that you need to provide your custom component to wrap the video into
In your case you are rendering the messages directly to the GiftedChat so we will pass our custom video component to GiftedChat as below
Reference: https://github.com/FaridSafi/react-native-gifted-chat/#react-native-video-and-expo-av
import { Video,Audio } from 'expo-av';
const renderMessageVideo = (props: any) => {
const { currentMessage } = props;
return (
<View style={{ padding: 20 }}>
<Video
resizeMode="contain"
useNativeControls
shouldPlay={false}
source={{ uri: currentMessage.video }}
style={styles.video}
/>
</View>
);
};
<GiftedChat
messages={this.state.messages}
onSend={this.onSend.bind(this)}
renderMessageVideo={renderMessageVideo}
user={{
_id: this.state.LoggedinuserID,
}}
/>

Related

How to provide live alerts to multiple phones with React Native

I coded an app that will create a modal that gives the option to alert reception that a customer is coming. However, when running the app on two phones, all changes are local. Why is that? I want to be able to "Alert Reception" and have reception receive a notification of the customer and be able to click More Info and see all the details about it.
We scan a customer QR code, and allow the security guard to validate and then alert reception and send the info to them.
Any ideas? We are using AWS and React Native. I would like to alert everyone and then be able to have the reception see the customer is coming and get the info.
import { StyleSheet, Text, View, Image, Button, Modal, Platform, ScrollView } from 'react-native';
import { BarCodeScanner } from 'expo-barcode-scanner';
import Constants from 'expo-constants';
import * as Notifications from 'expo-notifications';
import { Audio, Video } from 'expo-av';
//For push notifications
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: true,
shouldSetBadge: false,
}),
});
export default function App() {
//QR Scanner
const [hasPermission, setHasPermission] = useState(null);
const [scanned, setScanned] = useState(false);
const [newData, setNewData] = useState('');
//Modal Views
const [homeScreenVisible, setHomeScreenVisible] = useState(true);
const [customerModalVisible, setCustomerModalVisible] = useState(false);
const [customerModalDetailedVisible, setCustomerModalDetailedVisible] = useState(false);
const [qrScannerVisible, setQRScannerVisible] = useState(false);
//Push notifications
const [expoPushToken, setExpoPushToken] = useState('');
const [notification, setNotification] = useState(false);
const notificationListener = useRef();
const responseListener = useRef();
//useEffects are rendered upon app start. We use the [] to make sure they are only rendered once. If you want them to update, add in the array / state var and upon update the useEffect will run again.
//For Bar Code Scanner
useEffect(() => {
(async () => {
const { status } = await BarCodeScanner.requestPermissionsAsync();
setHasPermission(status === 'granted');
})();
}, []);
//For Push Notifications
useEffect(() => {
registerForPushNotificationsAsync().then(token => setExpoPushToken(token));
// This listener is fired whenever a notification is received while the app is foregrounded
notificationListener.current = Notifications.addNotificationReceivedListener(notification => {
setNotification(notification);
});
// This listener is fired whenever a user taps on or interacts with a notification (works when app is foregrounded, backgrounded, or killed)
responseListener.current = Notifications.addNotificationResponseReceivedListener(response => {
console.log(response);
console.log('Someone clicked on the push notification')
});
return () => {
Notifications.removeNotificationSubscription(notificationListener.current);
Notifications.removeNotificationSubscription(responseListener.current);
};
}, []);
//Bar Code scanner function, reads the data (which is a aws s3 endpoint served through cloudfront), then I run a fetch on the url (aka data), and then turn the string response into a json. Then I set newData equal to the JSON object via React Hooks. Then I turn the QR scanner visible off, and then open the customer modal.
const handleBarCodeScanned = ({ type, data }) => {
setScanned(true);
console.log(data) // Should be the url JSON endpoint
fetch(data)
.then(response => response.json())
.then(response => {
console.log(response)
setNewData(response)
});
setQRScannerVisible(false);
setCustomerModalVisible(true);
// const playbackObject = new Audio.Sound();
};
if (hasPermission === null) {
return <Text>Requesting for camera permission</Text>;
}
if (hasPermission === false) {
return <Text>No access to camera</Text>;
}
// We are returning a View with multiple JS {} fragments that turn off and on depending on state. There is an issue with setScanned(false) that sometimes the scanner is not set to false and it will not rescan. If you run into that problem, try adding setScanned(false).
return (
<ScrollView style={{flex: 1, backgroundColor: 'black'}}>
<View id="view" style={styles.container}>
{homeScreenVisible &&
<>
<Image
source={{
uri: "https://d1s68zh8fdz4eb.cloudfront.net/logo.png"
}}
style={{
height: 500,
width: '100%',
// borderWidth: 5,
// borderColor: '#fff',
marginTop: 30,
marginBottom: 20
}}
/>
<Button title="Scan QR Code" style={styles.moreInfo} onPress={() => {
setScanned(false)
setHomeScreenVisible(false)
setQRScannerVisible(true)
}} />
</>
}
{qrScannerVisible &&
<>
<Image
source={{
uri: "https://d1s68zh8fdz4eb.cloudfront.net/logo.png"
}}
style={{
height: 100,
width: 100,
borderWidth: 5,
marginBottom: 60
}}
/>
<BarCodeScanner
onBarCodeScanned={scanned ? undefined : handleBarCodeScanned}
// style={StyleSheet.absoluteFillObject}
style={{width: 300, height: 300, borderWidth: 5, borderColor: '#fff'}}
//If you want to switch to a absolute fill object, add the target area on the screen for scanning and try to add a sound.
// If you want to use the front facing or rear facing, include type={'front'} or put 'back'
/>
<Text style={{color: '#fff', fontSize: 30, marginTop: 30, marginBottom: 30}}>Scan QR Code</Text>
<Button title="Home" onPress={() => {
setHomeScreenVisible(true)
setQRScannerVisible(false)
setScanned(false)
}} />
</>
}
{/* Used for re scanning things. It is commented out because someoen can always go back to home and rescan. However, if you want to reintroduce a rescan button, you can do it with the below code.*/}
{/* {scanned && <Button title={'Tap to Scan Again'} onPress={() => {
setScanned(false)
}} />}
*/}
{customerModalVisible &&
<Modal style={styles.modal}>
<View style={styles.modalView}>
<Image
source={{
uri: "https://d1s68zh8fdz4eb.cloudfront.net/logo.png"
}}
style={{
height: 100,
width: 100,
borderWidth: 5,
marginBottom: 60
}}
/>
<View style={styles.modalInside}>
<Image
style={{
height: 300,
width: 300,
marginBottom: 20,
borderWidth: 5,
borderColor: 'gold'
}}
source={{
uri: newData.photo,
}}
/>
<Text style={styles.modalTextName}>{newData.name}</Text>
<Text style={styles.modalTextSecondary}>Favorite Drink: {newData.favoriteDrink}</Text>
<Text style={styles.modalTextSecondary}>Lead Contact: Leah</Text>
</View>
<Button title="Alert Reception" style={styles.closeButton} onPress={async () => {
await sendPushNotification(expoPushToken);
alert('Reception has been notified.')
}} />
<Button title="More Info" style={styles.moreInfo} onPress={() => {
// PushCustomerStatus();
setCustomerModalDetailedVisible(true)
setCustomerModalVisible(false)
setScanned(false)
setQRScannerVisible(false)
// Add modal # 2 or page navigation here
}} />
<Button title="Close" style={styles.closeButton} onPress={() => {
setHomeScreenVisible(true)
setCustomerModalVisible(false)
setScanned(false)
setQRScannerVisible(false)
}} />
</View>
</Modal>}
{customerModalDetailedVisible &&
<>
<Image
source={{
uri: "https://d1s68zh8fdz4eb.cloudfront.net/logo.png"
}}
style={{
height: 100,
width: 100,
// borderWidth: 5,
// borderColor: '#fff'
}}
/>
<View
style={{
flex: 1,
alignItems: 'center',
justifyContent: 'space-around',
width: '95%',
borderWidth: 5,
borderColor: 'gold',
}}>
{/* <Text>Your expo push token: {expoPushToken}</Text> */}
<View style={{ alignItems: 'flex-start', justifyContent: 'center', backgroundColor: '#fff', flex: 1, width: '100%', padding: 15}}>
<Image
style={{
height: 300,
width: 300,
marginBottom: 20,
// borderWidth: 5,
// borderColor: 'gold'
}}
source={{
uri: newData.photo,
}}
/>
<Text>Customer: {newData.name}</Text>
<Text>Arm Length: {newData.armLength}</Text>
<Text>Address: {newData.address}</Text>
<Text>Phone: {newData.phone}</Text>
<Text>Email: {newData.email}</Text>
<Text>Favorite Drink: {newData.favoriteDrink}</Text>
<Text>Height: {newData.height}</Text>
<Text>Inseam: {newData.inseam}</Text>
<Text>Neck Length: {newData.neckLength}</Text>
<Text>Customer: {newData.name}</Text>
<Text>Arm Length: {newData.armLength}</Text>
<Text>Address: {newData.address}</Text>
<Text>Phone: {newData.phone}</Text>
<Text>Email: {newData.email}</Text>
<Text>Favorite Drink: {newData.favoriteDrink}</Text>
<Text>Height: {newData.height}</Text>
<Text>Inseam: {newData.inseam}</Text>
<Text>Neck Length: {newData.neckLength}</Text>
<Text>Customer: {newData.name}</Text>
<Text>Arm Length: {newData.armLength}</Text>
<Text>Address: {newData.address}</Text>
<Text>Phone: {newData.phone}</Text>
<Text>Email: {newData.email}</Text>
<Text>Favorite Drink: {newData.favoriteDrink}</Text>
<Text>Height: {newData.height}</Text>
<Text>Inseam: {newData.inseam}</Text>
<Text>Neck Length: {newData.neckLength}</Text>
<Text>Customer: {newData.name}</Text>
<Text>Arm Length: {newData.armLength}</Text>
<Text>Address: {newData.address}</Text>
<Text>Phone: {newData.phone}</Text>
<Text>Email: {newData.email}</Text>
<Text>Favorite Drink: {newData.favoriteDrink}</Text>
<Text>Height: {newData.height}</Text>
<Text>Inseam: {newData.inseam}</Text>
<Text>Neck Length: {newData.neckLength}</Text>
{/* I can return it as an object above and use dot notation or do something similar below but use a string */}
{/* <Text>Data: {notification && JSON.stringify(notification.request.content.data)}</Text> */}
<Button
title="Press to Send Notification"
onPress={async () => {
await sendPushNotification(expoPushToken);
}}
/>
<Button
title="Home"
onPress={() => {
setHomeScreenVisible(true)
setScanned(false)
setCustomerModalDetailedVisible(false)
setQRScannerVisible(false)
}}
/>
</View>
</View>
</>
}
</View>
</ScrollView>
);
}
// Can use this function below, OR use Expo's Push Notification Tool-> https://expo.io/notifications
async function sendPushNotification(expoPushToken) {
const message = {
to: expoPushToken,
sound: 'default',
title: 'Customer Arriving!',
body: 'Please greet them at the door.',
};
await fetch('https://exp.host/--/api/v2/push/send', {
method: 'POST',
headers: {
Accept: 'application/json',
'Accept-encoding': 'gzip, deflate',
'Content-Type': 'application/json',
},
body: JSON.stringify(message),
});
}
async function registerForPushNotificationsAsync() {
let token;
if (Constants.isDevice) {
const { status: existingStatus } = await Notifications.getPermissionsAsync();
let finalStatus = existingStatus;
if (existingStatus !== 'granted') {
const { status } = await Notifications.requestPermissionsAsync();
finalStatus = status;
}
if (finalStatus !== 'granted') {
alert('Failed to get push token for push notification!');
return;
}
token = (await Notifications.getExpoPushTokenAsync()).data;
console.log(token);
} else {
alert('Must use physical device for Push Notifications');
}
if (Platform.OS === 'android') {
Notifications.setNotificationChannelAsync('default', {
name: 'default',
importance: Notifications.AndroidImportance.MAX,
vibrationPattern: [0, 250, 250, 250],
lightColor: '#FF231F7C',
});
}
return token;
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'flex-start',
alignItems: 'center',
backgroundColor: 'black',
paddingTop: 60,
},
modal: {
// marginTop: 100,
},
modalView: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'black'
},
modalInside: {
justifyContent: 'space-between',
alignItems: 'center',
marginBottom: 20
},
modalTextName: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 5,
color: 'white'
},
modalTextSecondary: {
color: '#fff',
marginBottom: 5,
},
closeButton: {
marginTop: 100,
},
moreInfo: {
marginTop: 100,
}
});
By live alerts, I assume you mean text notifications. One way to push out text notifications using AWS is using the Simple Notification Service. Because you are using a React app, use the AWS SDK for JavaScript. Using the SDK, you can create app logic to fire off text notifications in response to certain events.
You can find examples here:
https://github.com/awsdocs/aws-doc-sdk-examples/tree/master/javascriptv3/example_code/sns/src

In Android Modal - wrapping content in GestureHandlerRootView not fixing react-native-gesture-handler

I am using expo ^40.0.0.
I am trying to get react-native-gesture-handler components to work in a <Modal> from react-native in Android. I followed docs here - https://docs.swmansion.com/react-native-gesture-handler/docs/#for-library-authors
It stays to wrap in <GestureHandlerRootView>, I did this but it doesn't fix the issue.
I created a snack demo of issue - https://snack.expo.io/#noitidart/frisky-carrot
Here you see a "Tapped here count: 0". Please try tapping it, you will see it doesn't increment the counter.
You will see a "RN BUTTON" this works but it is not from react-native-gesture-handler.
Here is my code from the snack:
import * as React from 'react';
import { Text, View, Modal, Button as RNButton } from 'react-native';
import {
BaseButton,
GestureHandlerRootView
} from 'react-native-gesture-handler';
export default function App() {
return (
<Modal animationType="slide" transparent={false}>
<Example />
</Modal>
);
}
const Example = function () {
const [cnt, setCnt] = React.useState(0);
return (
<View style={{ justifyContent: 'center', flex: 1 }}>
<RNButton title="rn button" onPress={() => alert('hi')} />
<GestureHandlerRootView>
<BaseButton
onPress={() => {
// alert('pressed');
setCnt(cnt + 1);
}}
>
<View style={{ backgroundColor: 'steelblue', height: 100 }}>
<Text>Tapped here count: {cnt}</Text>
</View>
</BaseButton>
</GestureHandlerRootView>
</View>
);
};

Creating list in Vue.js with Vuetify --> Error: avoid using JavaScript keyword as "v-on"

Just want to create a simple list in Vue.js with Vuetify. I got an error like: Avoid using JavaScript keyword as "v-on" value: "" vue/valid-v-on. Please be specific in your possible answer, since I'm a beginner with Vuetify and Vue.js.
This is my template code:
<template>
<v-container grid-list-md >
<v-card-title class="pa-0 pb-2">Tracks</v-card-title>
<v-list>
<v-list-item
v-for="(item, index) in items"
:key="index"
#click=""
>
<v-list-item-avatar>
<v-icon
class="grey lighten-1 white--text"
v-text="'folder'"
></v-icon>
</v-list-item-avatar>
<v-list-item-content>
<v-list-item-title v-text="item.name"></v-list-item-title>
<v-list-item-subtitle v-text="item.artist"></v-list-item-subtitle>
</v-list-item-content>
<v-list-item-action>
<v-btn icon>
<v-icon color="grey lighten-1">mdi-information</v-icon>
</v-btn>
</v-list-item-action>
</v-list-item>
</v-list>
</v-container>
</template>
And this is my script code:
export default {
name: "Home",
data: () => ({
items: [
{ name: 'Test1', artist: 'Artist1' },
{ name: 'Test2', artist: 'Artist2' },
{ name: 'Test3', artist: 'Artist3' },
]
}),
}
make sure #click has a method inside it
don't just put #click=""
well put #click="test" , where test is an explicit method in the methods object

Error: Invalid hook call when using with redux

Sorry if I am asking a beginner's level question. I am new to React.js and recently I have been trying to grasps the concepts by following this tutorial:
JustDjango
What I am trying to accomplish is creating a login form which uses redux to store the states, my code is as follows :
import React from 'react';
import { Form, Icon, Input, Button, Spin } from 'antd/lib';
import { connect } from 'react-redux';
import { NavLink } from 'react-router-dom';
import * as actions from '../store/actions/auth';
const FormItem = Form.Item;
const antIcon = <Icon type="loading" style={{ fontSize: 24 }} spin />;
class NormalLoginForm extends React.Component {
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (!err) {
this.props.onAuth(values.userName, values.password);
this.props.history.push('/');
}
});
}
render() {
let errorMessage = null;
if (this.props.error) {
errorMessage = (
<p>{this.props.error.message}</p>
);
}
const { getFieldDecorator } = this.props.form;
return (
<div>
{errorMessage}
{
this.props.loading ?
<Spin indicator={antIcon} />
:
<Form onSubmit={this.handleSubmit} className="login-form">
<FormItem>
{getFieldDecorator('userName', {
rules: [{ required: true, message: 'Please input your username!' }],
})(
<Input prefix={<Icon type="user" style={{ color: 'rgba(0,0,0,.25)' }} />} placeholder="Username" />
)}
</FormItem>
<FormItem>
{getFieldDecorator('password', {
rules: [{ required: true, message: 'Please input your Password!' }],
})(
<Input prefix={<Icon type="lock" style={{ color: 'rgba(0,0,0,.25)' }} />} type="password" placeholder="Password" />
)}
</FormItem>
<FormItem>
<Button type="primary" htmlType="submit" style={{marginRight: '10px'}}>
Login
</Button>
Or
<NavLink
style={{marginRight: '10px'}}
to='/signup/'> signup
</NavLink>
</FormItem>
</Form>
}
</div>
);
}
}
const WrappedNormalLoginForm = Form.useForm()(NormalLoginForm);
const mapStateToProps = (state) => {
return {
loading: state.loading,
error: state.error
}
}
const mapDispatchToProps = dispatch => {
return {
onAuth: (username, password) => dispatch(actions.authLogin(username, password))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(WrappedNormalLoginForm);
The error traceback shows that the error is coming from :
76 | const WrappedNormalLoginForm = Form.useForm()(NormalLoginForm);
77 |
78 | const mapStateToProps = (state) => {
79 | return {
Some google search on this particular error shows that this error has something to do with hooks being defined in a classed based component , however i do not understand why :
const mapStateToProps = (state) => {......
is considered a hook
Will greatly appreciate anybody's help!
React hooks only used by functional components. You used class components.
Shortly, Form.useForm() the method is only used functional components, you can read it from this link below:
https://ant.design/components/form/

Quick reply in react native gifted chat not showing

I have the following setup done in my code, however the quick replies are not showing. Below shown is my state object and render code. [The quick reply is not showing, am i missing something in the code ? 1
state = {
messages : [
{
_id: 1,
text: 'My message',
"quickReplies":[
{
"contentType":"text",
"title":"Yes",
"imageUrl":"http://example.com/img/yes.png"
},
{
"contentType":"text",
"title":"No",
"imageUrl":"http://example.com/img/no.png"
}
]
}],
}
My Render method is as follows
render() {
return (
<View style={{ flex: 1, backgroundColor: '#fff' }}>
<HeaderIconExample color ='#1976d2' title ={"Digital Assistant"} />
<GiftedChat
messages={this.state.messages}
onSend={messages => this.onSend(messages)}
onQuickReply={quickReply => this.onQuickReply(quickReply)}
user={{
_id: 1
}}
/>
<KeyboardSpacer />
</View>
);
}
However when the app executes, only the text property of the message object is shown. Please see below image for more details.
The format of quick reply is wrong:
You should change it to something like this
message: [{
_id: 1,
text: "text",
createdAt: new Date(),
user: user,
quickReplies: {
type: 'radio' // or 'checkbox'
values: [{
title: "yes"
value: "yes"
},{
title: "no"
value: "no"
}]
}
}]