React Native Appearance.addChangeListener() does nothing - themes

I am writing my first react-native app and would like to switch themes like GMail does.
Indeed GMail get darker colors when we change the theme mode, or set automatic dark theme during nights, into the phone settings.
So I try to implement the Appearance.addChangeListener as explained in the doc but unfortunately the feature doesn't work.
I am trying on Android 10.
How can I, without restarting the app, update the color of my application when the phone theme change ?
useEffect(() => {
dispatch(changeTheme(Appearance.getColorScheme()));
Appearance.addChangeListener(onThemeChange);
return () => Appearance.removeChangeListener(onThemeChange);
}, []);
// This function is never call
const onThemeChange = ({ colorScheme }) => {
console.log("onThemeChange", colorScheme)
dispatch(changeTheme(colorScheme));
}

I resolved this problem by adding this code to MainActivity.java:
import android.content.res.Configuration;
#Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getReactInstanceManager().onConfigurationChanged(this, newConfig);
}
and for testing this feature, you can change DarkTheme in Android 10 and above ON/OFF.

useColorScheme
you can use useColorScheme, it will update automatically.
first
import {useColorScheme} from 'react-native;
then, in you functional component
const colorScheme = useColorScheme();
I also suggest to write your own custom hook to update StatusBar and NavigationBar on colorScheme changed

use useColorScheme
It will change the dark and light mode automatically
import {useColorScheme} from 'react-native;
then,for class component
componentDidMount() {
Appearance.getColorScheme()=='dark'?this.setState({ theme: true }): this.setState({ theme: false});
}
componentDidUpdate(){
this.listener =Appearance.addChangeListener((theme) => {
// console.log("theme", theme);
theme.colorScheme == "dark"
? this.setState({ theme: true })
: this.setState({ theme: false });
});
}

Related

Dialog does not close on web version of Outlook

I have an add-in that opens a dialog box using Office.context.ui.displayDialogAsync() with displayInIframe: true
When I click the 'X' close button in the top righthand corner nothing happens.
Similarly, when I call dialog.close() or Office.context.ui.closeContainer() nothing happens.
I have tested this on chrome and edge, both have this issue (I have not tested other browsers).
On the desktop app this works without any issues.
Simplified code for displaying the dialog window:
Office.context.ui.displayDialogAsync(url, { height: 60, width: 60, displayInIframe: true }, asyncResult => {
if (handleError(asyncResult)) return;
dialog = asyncResult.value;
const dialogClosed = async (_: any): Promise<void> => {
console.log("dialogClosed");
};
dialog.addEventHandler(Office.EventType.DialogEventReceived, dialogClosed);
dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
const promises = [];
{working business logic}
Promise.all(promises).then(values => {
{working business logic}
event.completed();
});
});
If I add an event handler for DialogEventRecieved, as far as I can tell this is never triggered on web.
Any suggestion would be appreciated. Thanks.
The problem can be related to the following part of your code:
const promises = [];
{working business logic}
Promise.all(promises).then(values => {
{working business logic}
event.completed();
});
Try to remove any extra code for promises and just use something like that:
let dialog;
Office.context.ui.displayDialogAsync('https://myDomain/myDialog.html',
function (asyncResult) {
dialog = asyncResult.value;
dialog.addEventHandler(Office.EventType.DialogMessageReceived, processMessage);
}
);
function processMessage(arg) {
dialog.close();
// message processing code goes here;
}
Read more about that in the Use the Office dialog API in Office Add-ins article.

Reset react navigation stack history

Update
Changed to use DrawerNavigator as the root for now, but would still like to know if it's possible to use StackNavigator as root but behavior like tabs, or drawers.
Am using reactnavigation v5.
I have the following setup:
<RootStack.Navigator initialRouteName={'SplashNavigator'}>
<RootStack.Screen name={'SplashNavigator'} component={SplashStackNavigator} options={{headerShown: false}} />
<RootStack.Screen name={'DrawerNavigator'} component={DrawerNavigator} />
</RootStack.Navigator>
From SplashNavigator I do a navigation.navigate('DrawerNavigator', {screen:'Home'})
However, the header has a back button that navigates back to the splash screen.
Is there a way to reset the history so it'll take the DrawerNavigator as the main navigator?
Have tried StackActions.replace in HomeScreen but somehow it doesn't recognise the screen.
const HomeScreen = ({navigation}) => {
useEffect(() => {
navigation.dispatch(state => {
console.log(state);
return StackActions.replace('Home')
});
}, []);
...
ExceptionsManager.js:173 The action 'REPLACE' with payload {"name":"Home"} was not handled by any navigator.
Yet I do see the route in the state
"routeNames": [
"Home",
"Promotions"
],
Have tried CommonActions.reset() too but it didn't change anything.
const HomeScreen = ({navigation}) => {
useEffect(() => {
navigation.dispatch(state => {
console.log(state);
return CommonActions.reset({...state, key:null})
});

PhotoEditorSDK Uncaught TypeError: Cannot read property 'export' of null

Currently using photoeditorsdk#4.3.1
With pure JS example, export image works just fine.
window.onload = () => {
const container = document.getElementById('app')
const editor = new PhotoEditorSDK.UI.ReactUI({
container,
license: JSON.stringify(PESDK_LICENSE),
assets: {
baseUrl:'/assets'
},
})
window.editor = editor
}
When try to wrap photoeditorsdk into a React Component as following
class Editor extends Component {
constructor (props) {
super(props)
}
componentDidMount () {
const container = this.refs.pesdk
const editor = new PhotoEditorSDK.UI.ReactUI({
container,
license: JSON.stringify(PESDK_LICENSE),
assets: {
baseUrl: '/assets'
},
title: 'Photo Editor'
})
window.editor = editor
}
render () {
return (
<div ref='pesdk'></div>
)
}
}
export default Editor
and export image using
editor.export(false).then(image => document.body.append(image))
from window.editor will encounter the errror
react-dom.development.js:5622 Uncaught TypeError: Cannot read property 'export' of null
at t.export (react-dom.development.js:5622)
at <anonymous>:1:14
I'm not able to reproduce this here. Can you give more details? E.g., where and when are you calling editor.export from. Also, are you passing an image to the editor as an option?

How to change the direction of the animation in StackNavigator?

How to change the direction of the animation in StackNavigator?
Current Behavior
When user goes to another screen, the screen flies from bottom to top.
Expected Behavior
When user goes to another screen, the screen flies from right to left. (Like Facebook or Instagram!)
StackNavigator Code
export default StackNavigator ({
Main: {
screen: MainScreen,
},
...
}, {
navigationOptions: ({navigation, screenProps}) => ({
tabBarOnPress: blahblaj
}),
lazy: true
// I guess we can do something here
});
If we can set the animation time, it will be even better! Currently it looks like the screen flies from middle of the screen to top. I want natural animation like Facebook or Instagram :)
Thanks in advance,
For react navigation > 5.0:
import {
CardStyleInterpolators,
createStackNavigator,
} from '#react-navigation/stack';
const Stack = createStackNavigator();
export default () => (
<Stack.Navigator
screenOptions={{
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS
}}
>
<Stack.Screen name="Screen 1" component={ScreenComponent1} />
<Stack.Screen name="Screen 2" component={ScreenComponent2} />
</Stack.Navigator>
);
You may also want to use headerStyleInterpolator: HeaderStyleInterpolators.forUIKit
More info here: https://reactnavigation.org/docs/stack-navigator/#pre-made-configs
For react navigation < 5.0
On iOS it's standard behavior. Android requires a little bit of configuration. There are two options you can use to set screen transitions: mode and transitionConfig. In this case transitionConfig will work:
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStack/CardStackStyleInterpolator';
// this path can be different depending on react-navigation version, this one is for #1.0.0-beta.15
export default StackNavigator ({
Main: {
screen: MainScreen,
},
...
}, {
transitionConfig: () => ({
screenInterpolator: CardStackStyleInterpolator.forHorizontal,
}),
})
We use CardStackStyleInterpolator from react-navigation source, but you can provide custom transition if you want, here is how to make one or here or this article.
mode is more for default behavior:
export default StackNavigator ({
Main: {
screen: MainScreen,
},
...
}, {
mode: 'card',
navigationOptions: ({navigation, screenProps}) => ({
tabBarOnPress: blahblaj
}),
lazy: true
});
mode can have only two values:
card - Use the standard iOS (right to left) and Android (bottom to
top) screen transitions. This is the default.
modal - Make the screens slide in from the bottom which is a common
iOS pattern. Only works on iOS, has no effect on Android.
For react navigation >= 5.0:
import {
CardStyleInterpolators,
createStackNavigator,
} from '#react-navigation/stack';
const Stack = createStackNavigator();
export default () => (
<Stack.Navigator
screenOptions={{
cardStyleInterpolator: CardStyleInterpolators.forHorizontalIOS
}}
>
<Stack.Screen name="Screen 1" component={ScreenComponent1} />
<Stack.Screen name="Screen 2" component={ScreenComponent2} />
</Stack.Navigator>
);
You may also want to use headerStyleInterpolator: HeaderStyleInterpolators.forUIKit
More info here: https://reactnavigation.org/docs/stack-navigator/#pre-made-configs
Updated answer:
import ReactNavigation from "react-navigation";
createStackNavigator({...},{
transitionConfig: () =>
ReactNavigation.StackViewTransitionConfigs.SlideFromRightIOS
})
Here,I just post my answer so that you can change the direction of the animation! That's all! The answer you have accepted is just default!
import CardStackStyleInterpolator from 'react-navigation/src/views/CardStackStyleInterpolator';
export default StackNavigator ({
Main: {
screen: MainScreen,
},
...
}, {
transitionConfig: () => ({
screenInterpolator: CardStackStyleInterpolator.forHorizontal,
}),
});
In this way, the screen transitions will become right to left on both two platforms!
What you need to pay more attention to is you can set any screen transitions whatever you want by using transitionConfig props!
The solution is very simple. In React navigation 4.x you can do like this
import { createAppContainer } from 'react-navigation'
import { createStackNavigator, StackViewTransitionConfigs } from 'react-navigation-stack';
const Navigation = createStackNavigator({
screenA: ComponentA,
screenB: ComponentB,
}, {
mode: 'card',
transitionConfig: () => StackViewTransitionConfigs.SlideFromRightIOS,
}
export const AppNavigation = createAppContainer(Navigation)
Note: You can achieve like this transition in previous react navigation versions also, but you have to change the import
animation​
How the screen should animate when pushed or popped.
Supported values:
default: use the platform default animation
fade: fade screen in or out
fade_from_bottom: fade the new screen from bottom
flip: flip the screen, requires stackPresentation: "modal" (iOS only)
simple_push: default animation, but without shadow and native header transition (iOS only, uses default animation on Android)
slide_from_bottom: slide in the new screen from bottom
slide_from_right: slide in the new screen from right (Android only, uses default animation on iOS)
slide_from_left: slide in the new screen from left (Android only, uses default animation on iOS)
none: don't animate the screen
Only supported on Android and iOS.

How to create a toolbar on firefox?

I need to create two toolbar on Firefox : one is horizontal on top and the other vertical on right side of the browser. But the sdk lib to firefox dont have resources to do it. Any sugestion ?
This might help, pretty simple guide laid out for easy reading:
http://www.borngeek.com/firefox/toolbar-tutorial/
Since version 1.15 the Addon SDK allows you to create toolbars and add buttons to it. I don't think it's possible to create a vertical toolbar, only horizontal ones.
There's a nice example on how to do it in the Addon SDK official repository:
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
const { Toolbar } = require("sdk/ui/toolbar");
const { Frame } = require("sdk/ui/frame");
const { Button } = require("sdk/ui/button");
let button = new Button({
id: "button",
label: "send!",
icon: "./favicon.ico",
onClick: () => {
frame.postMessage({
hello: "content"
});
}
});
let frame = new Frame({
url: "./index.html",
onAttach: () => {
console.log("frame was attached");
},
onReady: () => {
console.log("frame document was loaded");
},
onLoad: () => {
console.log("frame load complete");
},
onMessage: (event) => {
console.log("got message from frame content", event);
if (event.data === "ping!")
event.source.postMessage("pong!", event.source.origin);
}
});
let toolbar = new Toolbar({
items: [frame],
title: "Addon Demo",
hidden: false,
onShow: () => {
console.log("toolbar was shown");
},
onHide: () => {
console.log("toolbar was hidden");
}
});
Also, there's an older SO thread explaining how to do it on older versions of the Addon SDK and for XUL-based addons.
The code above only works on Firefox Australis (upcomming version 29.0). You can use a Jetpack module like toolbarwidget-jplib by Rob--W.
So you can add widgets on the navigation bar:
require("toolbarwidget").ToolbarWidget({
toolbarID: "nav-bar", // <-- Place widget on Navigation bar
id: "mozilla-icon",
label: "My Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico"
});

Resources