I am using react native with react-navigation v4
I have a home screen and a welcome screen. I am using redux to store the user that is logged in. In the welcome screen (before the user logs in), I reset the user to null like this:
useEffect(() => {
dispatch(updateCurrentUser(null));
});
On my home screen (after the user logs in), I navigate to the welcome screen with a logout button the following way:
<Button
title="Logout"
onPress={() => {
const resetAction = StackActions.reset({
index: 0,
actions: [
NavigationActions.navigate({routeName: "Welcome"}),
]
});
props.navigation.dispatch(resetAction);
// navigationData.navigation.pop();
// navigationData.navigation.navigate({routeName: "Welcome"});
}}
/>
After I run this, I get an error whenever i press the logout button
Since the user is now null and on the home screen I have the following code <Text style={styles.text}>Welcome, {currentUser.username}!</Text>, I am getting an error that null does not have the attribute username since currentUser is now null.
I do not understand why the home screen will not unmount and is being rendered when i reset the stack and navigated to the welcome screen. What could be the issue here?
You can just leave the stackaction and use switchnavigator and put these two screens in separate stacks. like
export default createAppContainer(createSwitchNavigator(
{
stack1:ScreenStack1,
App: AppTabs,
},
{
initialRouteName: 'AuthLoading',
}
));
so if I will navigation.navigate("App") from stack1 and at some point of time if I go back to stack1 from App navigation.navigate("stack1") here now all the screens of stack1 will behave like rendering fresh.
Related
I currently have a node bot embedded on my web app via direct line but I am struggling to attach:
Spotify Audio
I am trying to do so by using the URL attachment or an adaptive card, but the spotify embed doesn't play
Below is the code I use:
var send = {
text: "stuff",
attachments: [
contentType: "audio/ogg",
contentUrl: "spotifyEmbedUrl"
]
}
await stepContext.context.sendActivity(send);
I am unsure on how I can get spotify audio to play.
Is there a way I can return HTML code (and so get around it by adding an iframe into the chat etc?)
OR maybe I could create a modal popup that I could create the embed iframe?
Any help would be appreciated!
Unfortunately, you can't just send a file to a web page and it automatically start playing. Additionally, while Spotify provides embed URLs, which are not a direct link to an audio file, you can't simply tell the browser to play the file.
However, Spotify provides the embed code for displaying a play button that can be used in a page to play a song. Assuming you are using Web Chat in a web site (and even if you're not, this will give you an idea) and that, from the code you supplied, you are wanting to send the song in an activity, you can achieve this by sending the embed code in the activity, instead, via Web Chat's store. When the activity is received, the embed code is passed to a function to update the page and, thus, display the play button.
Be aware, the play button is essentially a UI widget, not a media player. There is no functionality available for telling the play button to auto play, stop, or anything else. The most you can do is display the button after which the user will be required to interact with it.
Also, this is a someone bare bones, simplified implementation. There are many things that aren't accounted for - please don't consider this a complete solution. There are aspects you will need to consider (e.g. multiple cards that utilize a postBack action).
In your bot: You want to send the embed code in an activity. Whether that is an event, message, or something else, is up to you. As you can see below, I have chosen to send a hero card that initiates a postBack when the button is pressed (a postBack sends data behind the scenes without displaying the action to the user).
const card = CardFactory.heroCard(
"Rome Wasn't Built in a Day",
null,
CardFactory.actions([
{
type: 'postBack',
title: 'Read more',
value: `<iframe src="https://open.spotify.com/embed/track/6lzd7dxYNuVSvh7sJDHIa3" width="300" height="380" frameborder="0" allowtransparency="true" allow="encrypted-media"></iframe>`
}
]),
{
subtitle: 'Artist: Morcheeba',
text: 'Album: Parts of the Process - released 2003'
}
);
await stepContext.context.sendActivity({ attachments: [card]});
Web Chat: First, use Web Chat's store to filter on incoming activities that include attachments where the button type (action) is postBack. When the condition is met, get the last card rendered and assign an event listener. When the card's button is clicked, get the 'spotify' container element and update the innerHTML with the embed code that was sent in the activity, thus displaying the play button.*
Please note, the setTimeout() used below is necessary for enabling the click action. Without the time out, the event listener being appended to the button would occur before the store finished processing the incoming activity.
<div id="webchat" role="main"></div>
<div class='spotify'></div>
[...]
const store = window.WebChat.createStore( {}, ( { dispatch } ) => next => action => {
if ( action.type === 'DIRECT_LINE/INCOMING_ACTIVITY' ) {
const activity = action.payload?.activity;
if (activity.attachments && activity.attachments[0].content.buttons[0]?.type === 'postBack') {
setTimeout(() => {
const spotifyIframe = activity.attachments[0].content.buttons[0].value
let cards = document.querySelectorAll( '.ac-adaptiveCard' )
let cardLength = cards.length;
let card = cards[ cardLength - 1 ];
card.querySelectorAll( 'button' ).forEach( button => {
button.addEventListener( 'click', ( e ) => {
e.preventDefault();
const spotifyContainer = document.querySelector( '.spotify' );
spotifyContainer.innerHTML = spotifyIframe
} )
} );
}, 300);
}
next( action );
} );
Hope of help!
I found a lot of website, that it allows me to change the website theme , without being logged in.
and when i refresh the page the theme doesn't reset. I was wondering how can i do that , or can someone put me on the right pass.
do i focus on the back-end , or it's only on front-end (client-side).
does it website to browser related. or it's something else ? i really looked a lot tried to save the the client choose into his db, but now when i see website that i can change it, without even being logged in so it's not related to db.
or is it session related ?
You can keep the theme information in localStorage in your users' browsers. When the app starts you can check if there is any theme information in the localStorage and use that, and when you update the theme you can set it in localStorage.
Example
class App extends React.Component {
state = {
theme: localStorage.getItem("theme") || "red"
};
toggleTheme = () => {
this.setState(
({ theme }) => ({
theme: theme === "red" ? "green" : "red"
}),
() => {
localStorage.setItem("theme", this.state.theme);
}
);
};
render() {
return (
<div style={{ backgroundColor: this.state.theme }}>
<div>Welcome to my website</div>
<button onClick={this.toggleTheme}> Toggle theme </button>
</div>
);
}
}
You can use something like this in Reactjs (obviously you would need to implement the MyTheme and SelectInput components yourself):
class MyReactComp extends React.Component {
setTheme(theme) {
localStorage.setItem('theme', selectedTheme);
}
render() {
<MyThemeLayout theme={localStorage.getItem('theme')} />
<MySelectInput onChange={theme => this.setTheme(theme)} />
}
}
Otherwise, you could send the theme choice to the backend, store it in MongoDB or something and then set an ID cookie so that the theme can be retrieved when the user next visits the site.
I have a React Navigation Tab Component like this:
const RootNavigator=TabNavigator({
Home:{
screen: Home,
navigationOptions:{
tabBarIcon: ({focused}) => (
<Icon
name={focused? 'ios-home':'ios-home-outline'}
style={{color: '#464646'}}
size={16}
/>
)
}
},
Notifications:{
screen: Notifications,
navigationOptions:{
tabBarIcon: ({focused}) => (
<TabNotifications focused={focused} />
)
}
}, {});
Is there a way to make a callback when leaving a screen?
In this case, I would like to perform a function when I leave the Notifications tab. Such as mark the notifications as seen and remove the badge indicator.
As of now, I am pulling the Notification icon from another component in order to show the number badge.
Thanks in advance.
One option is to use onNavigationStateChange to check the current change of the navigation and do the action you need to clear notifications etc.
onNavigationStateChange(prevState, newState, action)
Function that gets called every time navigation state managed by the
navigator changes. It receives the previous state, the new state of
the navigation and the action that issued state change. By default it
prints state changes to the console.
Another option is to use addListener. This way you can subscribe to willFocus/didFocus or willBlur/didBlur events and do the action you need.
addListener - Subscribe to updates to navigation lifecycle
React Navigation emits events to screen components that subscribe to
them:
willBlur - the screen will be unfocused
willFocus - the screen will focus
didFocus - the screen focused (if there was a transition, the transition completed)
didBlur - the screen unfocused (if there was a transition, the transition completed)
Example from the docs
const didBlurSubscription = this.props.navigation.addListener(
'didBlur',
payload => {
console.debug('didBlur', payload);
}
);
// Remove the listener when you are done
didBlurSubscription.remove();
// Payload
{
action: { type: 'Navigation/COMPLETE_TRANSITION', key: 'StackRouterRoot' },
context: 'id-1518521010538-2:Navigation/COMPLETE_TRANSITION_Root',
lastState: undefined,
state: undefined,
type: 'didBlur',
};
For those who want a third option, you could use the NavigationEvents component as suggested by the docs to listen to navigations hooks and to whatever you intended to do.
Edit: This is documentation for React Navigation 2.x, which is no
longer actively maintained. For up-to-date documentation, see the
latest version (6.x).
import React from 'react';
import { View } from 'react-native';
import { NavigationEvents } from 'react-navigation';
const MyScreen = () => (
<View>
<NavigationEvents
onWillFocus={payload => console.log('will focus',payload)}
onDidFocus={payload => console.log('did focus',payload)}
onWillBlur={payload => console.log('will blur',payload)}
onDidBlur={payload => console.log('did blur',payload)}
/>
{/*
Your view code
*/}
</View>
);
export default MyScreen;
I have the following template:
extends layout
block content
#wrapper
#logo
a(href='/')
p #{title}
#msg
| hi #{user}
#display
#register
----A registration form here----
#login
----A login form here-----
include footer
If the user opens this page via POST and I use a token to decide if he is logged in like so:
exports.home = function(req, res) {
// if user is not logged in, show both login and register forms
if (typeof req.session.username == 'undefined') {
res.render('home', { title: 'Online Coding Judge'});
}
// if user is logged in already, just say hi to him
else {
// what here???
}
};
How do I show different things on the page depending on whether he logged in or not?
EDIT: A more realistic example would be to show an error message if there was a failed login in the same UI I would need to conditionally show an error message.
Something like this should work:
EDIT: revised:
block content
#wrapper
#logo
a(href='/')
p #{title}
if {user}
#msg
| hi #{user}
#display
#register
----A registration form here----
#login
----A login form here-----
else
--- some other logic ---
include footer
I am writing a Chrome extension, in which there is a dialog-like window to let users input the username and password, which are then sent back to background page to make a request for the token in OAuth 2.0.
To send the username and password from dialog window back to background page, I used the following codes (inside the dialog window .html file):
<script>
function usrpwd(){
var up = {};
up.usr = document.login_form.usr.value;
up.pwd = document.login_form.pwd.value;
chrome.tabs.sendRequest(window.dialogArguments,up);
window.close();
}
</script>
where the window.dialogArguments is supposed to be the tab ID of the extension's background page.
And the dialog window is opened in background page by
chrome.contextMenus.create({
"title" : "show Modal Dialog",
"contexts" : ["all", "page"],
"onclick": handle_click
});
function handle_click(){
chrome.tabs.getSelected(null, function(tab){
console.log('tab ', tab);
window.showModalDialog("login_popup.html", tab.id, "dialogHeight:300px; dialogLeft:200px;");
});
}
The tab.id is supposed to be the ID of the background page, and it will be passed to dialog window and assigned to window.dialogArguments.
Also in the background page, the username and password are received by,
chrome.extension.onRequest.addListener(
function(request){
console.log("Username: ", request.usr);
console.log("Username: ", request.pwd);
}
);
However, console.log('tab ', tab) inside the handle_click function always shows that the getSelected tab is the tab where the context menu got clicked, not the background page. So I am wondering how to get the tab ID of the background page in this case. Or is there any other better ways to communicate between dialog window and background page?
Thanks a lot!
Background pages do not have a tabId, since they are not tabs.
To send a message to the background page, use chrome.extension.sendRequest (extension instead of tabs).
PS. Full demo