Skip to content
This repository has been archived by the owner on Oct 4, 2023. It is now read-only.

Commit

Permalink
[C-1349] Improve StatusBar colors (#2175)
Browse files Browse the repository at this point in the history
* Set status bar color on android

* Manage StatusBar colors during and after SplashScreen

* Fix lint

* Fix types

* Fix types 2
  • Loading branch information
sliptype authored Oct 26, 2022
1 parent ba80376 commit 089b283
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 18 deletions.
32 changes: 29 additions & 3 deletions packages/mobile/src/screens/splash-screen/SplashScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
import { useRef, useState, useEffect, useCallback } from 'react'

import { accountSelectors, Status } from '@audius/common'
import { accountSelectors, themeSelectors, Status } from '@audius/common'
import LottieView from 'lottie-react-native'
import { StyleSheet, Animated } from 'react-native'
import { StyleSheet, Animated, StatusBar, Platform } from 'react-native'
import { useSelector } from 'react-redux'
import { useEffectOnce } from 'react-use'

import { updateStatusBarTheme } from 'app/utils/theme'

const { getAccountStatus } = accountSelectors
const { getTheme, getSystemAppearance } = themeSelectors

const SCALE_TO = 1.2
const ANIM_DURATION_MS = 2000
Expand All @@ -30,8 +34,23 @@ const styles = StyleSheet.create({
export const SplashScreen = () => {
const [animationFinished, setAnimationFinished] = useState(false)
const accountStatus = useSelector(getAccountStatus)
const theme = useSelector(getTheme)
const systemAppearance = useSelector(getSystemAppearance)
const backgroundOpacityAnim = useRef(new Animated.Value(1))

useEffectOnce(() => {
if (Platform.OS === 'ios') {
// Hide the StatusBar on ios
updateStatusBarTheme(theme, systemAppearance)
StatusBar.setHidden(true)
} else {
// Make the StatusBar translucent on android
// (hiding it on android causes the app to shift when it's unhidden)
StatusBar.setBackgroundColor('transparent')
StatusBar.setTranslucent(true)
}
})

useEffect(() => {
if (![Status.IDLE, Status.LOADING].includes(accountStatus)) {
if (animationRef.current) {
Expand Down Expand Up @@ -66,8 +85,15 @@ export const SplashScreen = () => {
}, [scaleAnim])

const onAnimationFinish = useCallback(() => {
if (Platform.OS === 'ios') {
// Unhide the StatusBar on ios
StatusBar.setHidden(false, 'fade')
} else {
// Make the StatusBar opaque on android
updateStatusBarTheme(theme, systemAppearance)
}
setAnimationFinished(true)
}, [setAnimationFinished])
}, [setAnimationFinished, theme, systemAppearance])

const animationRef = useRef<LottieView | null>(null)

Expand Down
11 changes: 8 additions & 3 deletions packages/mobile/src/store/theme/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { eventEmitter, initialMode } from 'react-native-dark-mode'
import { put, call, spawn, takeEvery, select } from 'typed-redux-saga'

import { localStorage } from 'app/services/local-storage'
import { handleThemeChange } from 'app/utils/theme'
import { updateStatusBarTheme, setStatusBarTheme } from 'app/utils/theme'
const { setTheme, setSystemAppearance } = themeActions
const { getSystemAppearance } = themeSelectors
const { getTheme, getSystemAppearance } = themeSelectors

const waitForSystemAppearanceChange = async () => {
let listener
Expand All @@ -27,6 +27,7 @@ const waitForSystemAppearanceChange = async () => {
function* watchSystemAppearanceChange() {
while (true) {
const systemAppearance = yield* select(getSystemAppearance)
const theme = yield* select(getTheme)
if (!systemAppearance) {
yield* put(
setSystemAppearance({
Expand All @@ -35,14 +36,18 @@ function* watchSystemAppearanceChange() {
)
} else {
const systemAppearance = yield* call(waitForSystemAppearanceChange)
if (theme === Theme.AUTO) {
setStatusBarTheme(systemAppearance)
}
yield* put(setSystemAppearance({ systemAppearance }))
}
}
}

function* setThemeAsync(action: PayloadAction<{ theme: Theme }>) {
const systemAppearance = yield* select(getSystemAppearance)
const { theme } = action.payload
handleThemeChange(theme)
updateStatusBarTheme(theme, systemAppearance)

yield* call([localStorage, 'setItem'], 'theme', theme)
}
Expand Down
35 changes: 23 additions & 12 deletions packages/mobile/src/utils/theme.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { SystemAppearance, Nullable } from '@audius/common'
import { themeSelectors } from '@audius/common'
import { StatusBar } from 'react-native'
import { useSelector } from 'react-redux'
Expand All @@ -11,29 +12,39 @@ export enum Theme {
MATRIX = 'matrix'
}

export const handleThemeChange = (theme: Theme) => {
/**
* Set status bar theme in a cross-platform way
*/
export const setStatusBarTheme = (theme: 'light' | 'dark') => {
if (theme === 'light') {
StatusBar.setBarStyle('dark-content')
StatusBar.setBackgroundColor(defaultTheme.white)
} else {
StatusBar.setBarStyle('light-content')
StatusBar.setBackgroundColor(darkTheme.white)
}
}

export const updateStatusBarTheme = (
theme: Nullable<Theme>,
systemAppearance: Nullable<SystemAppearance>
) => {
switch (theme) {
case Theme.DEFAULT: {
StatusBar.setBarStyle('dark-content')
setStatusBarTheme('light')
break
}
case Theme.DARK: {
StatusBar.setBarStyle('light-content')
setStatusBarTheme('dark')
break
}
case Theme.AUTO: {
StatusBar.setBarStyle('default')
if (systemAppearance) {
setStatusBarTheme(systemAppearance)
}
break
}
}

// Fade in status bar after we
// get our first update, after a
// slight delay to allow Splash Screen
// to animate out.
setTimeout(() => {
StatusBar.setHidden(false, 'fade')
}, 500)
}

export const defaultTheme = {
Expand Down

0 comments on commit 089b283

Please sign in to comment.