
Security News
/Research
Wallet-Draining npm Package Impersonates Nodemailer to Hijack Crypto Transactions
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
@busfor/react-native-navigation-appearance
Advanced tools
Appearance Module built on top of wix/react-native-navigation
Make sure that your are using supported versions of react-native-navigation and react-native:
1.x |
---|
react-native-navigation >= 6.4.0; react-native: >=0.62 |
Make sure that you have installed @react-native-community/async-storage
dependency or install it using:
$ yarn add @react-native-community/async-storage
Install this module using:
$ yarn add @busfor/react-native-navigation-appearance
MainActivity.java
This file is located in android/app/src/main/java/com/<yourproject>/MainActivity.java
.
+import android.os.Bundle;
+import androidx.annotation.Nullable;
+import com.busfor.rnnappearance.RNNAppearanceModuleKt;
public class MainActivity extends NavigationActivity {
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ RNNAppearanceModuleKt.setThemeResId(R.style.AppTheme);
+ }
}
This file is located in android/app/src/main/res/values/styles.xml
.
<resources>
+
+ <style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat.Light" />
<!-- Base application theme. -->
- <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
+ <style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:textColor">#000000</item>
</style>
</resources>
This file should be located in android/app/src/main/res/values-night/styles.xml
.
<resources>
<style name="Theme.AppCompat.DayNight" parent="Theme.AppCompat" />
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
<!-- Customize your theme here. -->
<item name="android:textColor">#FFFFFF</item>
</style>
</resources>
Make sure you don't have UIUserInterfaceStyle
in Info.plist
createTheme
function:import { createTheme } from '@busfor/react-native-navigation-appearance'
export const theme = createTheme({
dark: {
backgroundColor: '#121212',
textColor: '#fff',
primaryColor: 'blue',
},
light: {
backgroundColor: '#fff',
textColor: '#121212',
primaryColor: 'red',
},
})
createDefaultOptions
function:import { createDefaultOptions, Appearance } from '@busfor/react-native-navigation-appearance'
import { theme } from './theme'
export const defaultOptions = createDefaultOptions(({ appearance }) => ({
statusBar: {
style: appearance === Appearance.dark ? 'light' : 'dark',
backgroundColor: theme[appearance].backgroundColor,
},
navigationBar: {
backgroundColor: theme[appearance].backgroundColor,
},
topBar: {
background: {
color: theme[appearance].backgroundColor,
},
title: {
color: theme[appearance].textColor,
},
},
}))
ThemeProvider
to register and init module with defaultOptions
that we have created:NOTE: Make sure that you are running initAppearanceModule
inside Navigation.events().registerAppLaunchedListener
callback and before Navigation.setRoot
function!
import { ThemeProvider, initAppearanceModule } from '@busfor/react-native-navigation-appearance'
Navigation.registerComponent(
'AppScreen',
() => (props) => (
<ThemeProvider>
<AppScreen {...props} />
</ThemeProvider>
),
() => AppScreen
)
Navigation.events().registerAppLaunchedListener(async () => {
await initAppearanceModule(defaultOptions)
Navigation.setRoot({ ... })
})
createOptions
and defaultOptions
functions:This file should be located in /AppScreen/options.js
import { createOptions } from '@busfor/react-native-navigation-appearance'
import { defaultOptions } from '../defaultOptions'
export default createOptions((props) =>
defaultOptions(props, {
// props contains the current appearance and passed props to the screen
topBar: {
title: {
text: props.appearance,
},
},
})
)
createStyles
function:This file should be located in /AppScreen/styles.js
import { createStyles } from '@busfor/react-native-navigation-appearance'
import { theme } from '../theme'
export default createStyles(({ appearance }) => ({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
backgroundColor: theme[appearance].backgroundColor,
},
text: {
color: theme[appearance].textColor,
paddingVertical: 8,
textAlign: 'center',
},
}))
useThemedOptions
, initialOptions
to define screen options and use useStyles
hook to provide styles:This file should be located in /AppScreen/index.js
import React from 'react'
import { Text, SafeAreaView } from 'react-native'
import { useStyles, initialOptions, useThemedOptions } from '@busfor/react-native-navigation-appearance'
import stylesCreator from './styles'
import options from './options'
const AppScreen = ({ componentId }) => {
useThemedOptions({}, options, componentId)
const styles = useStyles(stylesCreator)
return (
<SafeAreaView style={styles.container}>
<Text>Hello world!</Text>
</SafeAreaView>
)
}
AppScreen.options = initialOptions(options)
export default AppScreen
Also you can open the example project to see how it works in the real case.
You can set appearance manually using useThemeControls
hook:
import { useThemeControls, AppearanceMode } from '@busfor/react-native-navigation-appearance'
const App = () => {
const { currentApearanceMode, setAppearanceMode } = useThemeControls()
return (
<>
<Text>Current mode: {currentApearanceMode}</Text>
<Button title='Dark' onPress={() => setAppearanceMode(AppearanceMode.dark)} />
<Button title='Light' onPress={() => setAppearanceMode(AppearanceMode.light)} />
<Button title='System' onPress={() => setAppearanceMode(AppearanceMode.system)} />
</>
)
}
You can get current appearance using useAppearance
hook:
import { useAppearance, Appearance } from '@busfor/react-native-navigation-appearance'
const App = () => {
const appearance = useAppearance()
return <Text>Current appearance: {appearance}</Text>
}
You can get any value for current appearance using useThemedValue
hook:
import { useThemedValue } from '@busfor/react-native-navigation-appearance'
const lightLogoSource = require('./lightLogo.png')
const darkLogoSource = require('./darkLogo.png')
const App = () => {
const logoSource = useThemedValue({ light: lightLogoSource, dark: darkLogoSource })
return <Image source={logoSource} />
}
With this function, you can select specific unique styles and options per appearance (like Platform.select
)
import { createOptions, appearanceSelect } from '@busfor/react-native-navigation-appearance'
import { defaultOptions } from '../defaultOptions'
export default createOptions((props) =>
defaultOptions(props, {
topBar: {
title: {
text: appearanceSelect(props.appearance, {
light: 'This is text for the light appearance',
dark: 'This is text for the dark appearance',
}),
},
},
})
)
import mockAsyncStorage from '@react-native-community/async-storage/jest/async-storage-mock'
import '@busfor/react-native-navigation-appearance/jest/rnn-appearance-mock'
jest.mock('@react-native-community/async-storage', () => mockAsyncStorage)
jest.useFakeTimers()
setDarkModeMock
in your test cases:import { setDarkModeMock } from '@busfor/react-native-navigation-appearance'
describe('Theming', () => {
afterEach(() => {
setDarkModeMock(false)
})
it(`dark theme`, () => {
setDarkModeMock(true)
...
})s
it(`light theme`, () => {
...
})
})
FAQs
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.
Security News
/Research
Malicious Nx npm versions stole secrets and wallet info using AI CLI tools; Socket’s AI scanner detected the supply chain attack and flagged the malware.