React-native: how to save webview state on minimize - react-native

I'm trying to use WebView in my react-native app (Android).
When i press home button and when start app again webview doesn't save his state.
I read some articles and my code now is:
var freetime = React.createClass({
getInitialState: function() {
return {
url: DEFAULT_URL,
backButtonEnabled: false,
forwardButtonEnabled: false,
loading: true,
scalesPageToFit: true,
};
},
render: function() {
return(
<WebView
url={this.state.url}
onNavigationStateChange={this.onNavStateChanged}/>
);
},
onNavStateChanged: function(navState) {
console.log("Url: " + navState.url);
console.log("Source: " + navState.source);
this.setState({
url: navState.url,
status: navState.title,
scalesPageToFit: true
});
}
});
But it didn't work too.

Related

How to stop audio file and automatically play next file in expo app in react native?

I am testing my react native app on my iPhone with Expo audio and am having some issues.
I have multiple audio files here:
constructor(props) {
super(props);
this.sets = [
{
'name': 'Get started',
'image': 'https://media2.giphy.com/media/L3txcnbi3ODhV8XbcC/giphy.gif?cid=ecf05e4753ab0311a208263dfa2f06b292304586b6968cd5&rid=giphy.gif',
'audio_file': 'https://www.buzzsprout.com/919750/2968663-rowing-test-2.mp3'
},
{
'name': '5 pushups',
'image': 'https://media3.giphy.com/media/3ohze1qkqPZHMrEuwo/giphy.gif?cid=ecf05e477ee256ccf5c259848c5d44eb07cea572a4b05e29&rid=giphy.gif',
'audio_file': 'https://www.buzzsprout.com/919750/2946361.mp3'
},
{
'name': '10 burpees',
'image': 'https://media1.giphy.com/media/23hPPMRgPxbNBlPQe3/giphy.gif?cid=ecf05e476831df96aaeea2281fa09fb198d9ca8b14f8405c&rid=giphy.gif',
'audio_file': 'https://www.buzzsprout.com/919750/2946361.mp3'
}
]
this.state = {
index: 0,
isPlaying: false,
playbackInstance: null,
currentIndex: 0,
volume: 1.0,
isBuffering: false,
value:0,
isLooping: true
}
}
I have a play button that should play the current file. When pressed, the pause button shows and then pauses the audio file. This functionality works fine.
However, I also want the user to be able to go to the next track. When the user presses the next button, I'd like for the current audio to stop, go to the next track, and start the track immediately. I am having trouble doing this. Currently what happens is I hit next, the same audio continues to play and then when I press play again, the next audio file plays on top of the original file. How do I address this?
nextWorkout = async () => {
const { isPlaying, playbackInstance } = this.state
isPlaying
? await playbackInstance.pauseAsync()
: await playbackInstance.playAsync()
// go to next track
this.setState({
isPlaying: !isPlaying,
index:this.state.index + 1
})
// load next audio file
this.loadAudio()
.then(playbackInstance.playAsync());
// play next audio file
// playbackInstance.playAsync();
// scroll to image in horizontal flatlist
// this.flatListRef.scrollToIndex({animated: true, index: this.state.index});
}
async componentDidMount() {
_isMounted = true;
try {
await Audio.setAudioModeAsync({
allowsRecordingIOS: false,
interruptionModeIOS: Audio.INTERRUPTION_MODE_IOS_MIX_WITH_OTHERS,
playsInSilentModeIOS: true,
interruptionModeAndroid: Audio.INTERRUPTION_MODE_ANDROID_DUCK_OTHERS,
shouldDuckAndroid: true,
staysActiveInBackground: true, // https://github.com/expo/expo/issues/5472
playThroughEarpieceAndroid: true
})
this.loadAudio()
} catch (e) {
console.log(e)
}
}
async componentWillUnmount() {
_isMounted = false;
this.state.playbackInstance.unloadAsync();
}
async loadAudio() {
const {currentIndex, isPlaying, volume} = this.state
try {
const playbackInstance = new Audio.Sound()
const source = {
uri: this.sets[this.state.index].audio_file
}
const status = {
shouldPlay: isPlaying,
volume
}
playbackInstance.setOnPlaybackStatusUpdate(this.onPlaybackStatusUpdate)
await playbackInstance.loadAsync(source, status, false)
this.setState({playbackInstance})
} catch (e) {
console.log(e)
}
}
onPlaybackStatusUpdate = status => {
this.setState({
isBuffering: status.isBuffering
})
}
handlePlayPause = async () => {
const { isPlaying, playbackInstance } = this.state
isPlaying
? await playbackInstance.pauseAsync()
: await playbackInstance.playAsync()
this.setState({
isPlaying: !isPlaying
})
}
try {
await this.state.playbackInstance.unloadAsync()
await this.state.playbackInstance.loadAsync({uri: this.sets[this.state.index].audio_file});
await this.state.playbackInstance.playAsync();
await this.setState({
isPlaying: true
})
} catch (err) {
console.warn("Couldn't Play audio", err)
}

how to redirect to a screen when app is opened from push notification in react native

I am working on a react native app with aws-amplify library https://aws-amplify.github.io/docs/js/push-notifications .When I click on push notification, my app should redirect to notification screen.I am not getting the navigation props when i open the app from notification , So I am using this to work without prop https://reactnavigation.org/docs/en/navigating-without-navigation-prop.html but still I am getting this error "undefined is not an object (evaluating 't.dispatch')".I am using react-navigation in my app
import PushNotification from '#aws-amplify/pushnotification';
import NotificationList from './NotificationList';
import NavigationService from './NavigationService';
Analytics.configure(awsmobile);
PushNotification.configure(awsmobile);
if(Platform.OS === 'android'){
PushNotification.onNotification((notification) => {
// console.log('in app notification : Outside App', notification);
Auth.currentAuthenticatedUser({
bypassCache: false // Optional, By default is false. If set to true, this call will send a request to Cognito to get the latest user data
}).then(user => {
console.log('Current user : Outside App', user.attributes.sub)
const currentDate = new Date();
const todayDate = moment(currentDate).format("YYYY-MM-DD")
var todayTime = moment().format('HH:mm:ss')
const notificationDetails = {
userId: user.attributes.sub,
userTitle: notification.title,
userBody: notification.body,
userDate: todayDate,
userTime: todayTime,
};
console.log("notificationDetails outside", notificationDetails)
API.graphql(graphqlOperation(createUserNotification, { input: notificationDetails }))
.then(response => {
console.log(JSON.stringify(response, null, 2));
})
.catch(err => {
console.log('Error Saving Details...', err);
this.setState({ showActivityIndicator: false });
});
});
});
PushNotification.onNotificationOpened((notification) => {
const b = new Home();
console.log('onNotificationOpened 1');
b._handleNotificationOpen(notification)
});
}
class Home extends React.Component {
constructor(props) {
super(props);
global.ShowRecordVar = "12"
this._handleNotificationOpen =
this._handleNotificationOpen.bind(this);
this.state = {
apiResponse: 0,
loading: true,
}
}
_handleNotificationOpen = (notification) => {
if (notification["pinpoint.deeplink"]) {
NavigationService.navigate('NotificationList',{notification});
}
}
//Some More Codes
}

how to fix blank page if i am using vue router with electron js?

I'm trying to use vue router with an application on an Electron JS. If I use a router on the render page, then the router work done. But I do not understand how to make the transition to the page, for example,- 'Settings' using the Tray. At attempt of transition the empty page opens.
I have prepared a working example of the project. This problem exists only build project. In development mode all work well.
This is my work example on github. Please need help.
git clone https://github.com/DmtryJS/electron-vue-example.git
cd electron-vue-example
npm install
npm run build
and run dist\win-unpacked\example_for_stackoverflow.exe
my main.js file
'use strict'
import { app, protocol, BrowserWindow, Menu, ipcMain, Tray } from 'electron'
import { format as formatUrl } from 'url'
const electron = require('electron');
const path = require('path');
const isDevelopment = process.env.NODE_ENV !== 'production';
let imgBasePath;
if(isDevelopment) {
imgBasePath = path.join('src','assets', 'img');
} else {
imgBasePath = path.join(path.dirname(__dirname), 'extraResources', 'img');
}
let win;
let tray;
protocol.registerStandardSchemes(['app'], { secure: true })
const trayIcon = path.join(__static, 'img', 'icon.png');
function createWindow () {
win = new BrowserWindow({
width: 800,
height: 600,
icon: trayIcon
})
routeTo(win, "")
win.on('closed', () => {
win = null
})
//убрать меню
win.setMenuBarVisibility(true)
win.on('show', function() {
tray.setHighlightMode('always')
})
win.on('hide', function() {
tray.setHighlightMode('never')
})
}
// Quit when all windows are closed.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
app.on('activate', () => {
if (win === null) {
createWindow()
}
})
app.on('ready', () => {
createWindow()
win.webContents.openDevTools(); //открыть dev tools
createTray()
})
// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
if (process.platform === 'win32') {
process.on('message', data => {
if (data === 'graceful-exit') {
app.quit()
}
})
} else {
process.on('SIGTERM', () => {
app.quit()
})
}
}
function createTray()
{
let traiIconPath = path.join(imgBasePath, 'preloader_tray_icon.png')
tray = new Tray(traiIconPath)
const contextMenu = Menu.buildFromTemplate(
[
{
label: 'Settings',
type: 'normal',
click: function()
{
routeTo(win, "/settings")
let contents = win.webContents
contents.on('dom-ready', function()
{
if(!win.isVisible())
{
showWindow()
}
})
}
},
{
label: 'Exit',
type: 'normal',
click: function()
{
win = null
app.quit()
}
}
])
tray.setContextMenu(contextMenu)
tray.on('click', function() {
toggleWindow();
})
}
function showWindow() {
var position = getPosition();
win.setPosition(position.x, position.y, false)
win.show()
win.focus()
}
ipcMain.on('routerEvent', function(event, arg) {
routeTo(win, arg)
})
function routeTo(win, to) {
if (isDevelopment) {
win.loadURL(`http://localhost:${process.env.ELECTRON_WEBPACK_WDS_PORT}` + to)
} else {
win.loadURL(formatUrl({
pathname: path.join(__dirname, 'index.html' + to);,
protocol: 'file',
slashes: true
}))
}
}
And
router.js
import Vue from 'vue'
import Router from 'vue-router'
import Main from './../views/Main.vue'
import Settings from './../views/Settings.vue'
Vue.use(Router)
export default new Router({
//mode: 'history',
routes: [
{
path: '/',
name: 'home',
component: Main
},
{
path: '/settings',
name: 'settings',
component: Settings
}
]
})
You need to add created to the main Vue app check docs
// src/main.js
new Vue({
router,
render: h => h(App),
created() {
// Prevent blank screen in Electron builds
this.$router.push('/')
}
}).$mount('#app')
The solution for me was to remove the history mode in the vue router.
Sorry, but after one day of googling, I just found a solution. The case turned out to be
win.loadURL(formatUrl({
pathname: path.join(__dirname, 'index.html' + to);,
protocol: 'file',
slashes: true
}))
I delete formaUrl and everything works well
win.loadURL(path.join(__dirname, 'index.html' + to));
For me solution was this:
Check if app is running at addresses like this:
Local: http://x86_64-apple-darwin13.4.0:8080/
Network: http://localhost:8080/
Check if you can access x86_64..url in browser. If you are not seeing a webpage but can see it from localhost, then map 127.0.0.1 to x86_64-apple-darwin13.4.0 in hosts file. in mac its located in /etc/hosts in windows its in system32/drivers/etc.

Automatically closing Drawer when view width is decreasing

I'm trying to make a view like Firebase's console with React and material-ui.
How can I build a Drawer that will automatically close when view(browser) width is decreasing.
Quite easy, you can hook up the listener on resize event on your react class:
var RootPage = React.createClass({
render: function() {
return <Drawer refs={'drawer'} />;
},
// we trigger our drawer here
componentWillUpdate: function(nextProp, nextState) {
if(nextState.width < this.state.width) {
this.refs.drawer.open = false;
}
},
windowOnResize: function() {
var width = $(window).width();
this.setState({ width: width });
},
componentWillMount: function() {
this.windowOnResize();
},
componentDidMount: function() {
window.addEventListener("resize", this.windowOnResize);
},
componentWillUnmount: function() {
window.removeEventListener("resize", this.windowOnResize);
}
});

How to avoid refetching data in React-native

I am using react-native-navigation-drawer. I fetch data from url (inside componentDidMount) to render first page. Then I go to second/third (other) pages. When I reselect/choose First Page again. It refetch data from url. How I can keep that data so that I can avoid fetching url again and again until user click on refresh button. Any help, please. I tried fetching data in parent view and passProps but if I do so, I can't refresh data.
getInitialState: function() {
return {
dataSource: null,
loaded: false,
networkError : false,
};
},
componentDidMount: function() {
if(this.props.firstTime){//This is used to fetch data only the in first time.
this.fetchData(); //call function to fetch data from url
}
console.log("Issue View First Time :: " + this.props.firstTime);
},
fetchData: function() {
fetch(REQUEST_URL)
.then((response) => response.json())
.then((responseData) => {
this.setState({
dataSource: responseData, //Want to keep this information to render again.
loaded: true,
});
})
.catch((error) => {
console.warn('error ::: ' + error);
this.setState({
networkError: true, //used to render error View
});
})
.done(()=> {
});
},
This is a dump question. I figured it out.
I declare a variable and set state of dataSource with that variable.
var KEEPED_DATA = [];
var FirstView = React.createClass({
getInitialState: function() {
return {
dataSource: KEEPED_DATA,
networkError : false,
};
},
componentWillMount: function() {
if(!KEEPED_DATA.length){
this.fetchData();
}
},
fetchData: function() {
//Fetching data from url
KEEPED_DATA = responseData;
},
render: function() {
//render
});