Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 76 additions & 20 deletions Libraries/Components/StatusBar/StatusBar.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,34 @@ function createStackEntry(props: any): any {
*
* ### Imperative API
*
* For cases where using a component is not ideal, there is also an imperative
* API exposed as static functions on the component. It is however not recommended
* to use the static API and the component for the same prop because any value
* set by the static API will get overriden by the one set by the component in
* the next render.
* For cases where using a component is not ideal, there are static methods
* to manipulate the `StatusBar` display stack. These methods have the same
* behavior as mounting and unmounting a `StatusBar` component.
*
* For example, you can call `StatusBar.pushStackEntry` to update the status bar
* before launching a third-party native UI component, and then call
* `StatusBar.popStackEntry` when completed.
*
* ```
* const openThirdPartyBugReporter = async () => {
* // The bug reporter has a dark background, so we push a new status bar style.
* const stackEntry = StatusBar.pushStackEntry({barStyle: 'light-content'});
*
* // `open` returns a promise that resolves when the UI is dismissed.
* await BugReporter.open();
*
* // Don't forget to call `popStackEntry` when you're done.
* StatusBar.popStackEntry(stackEntry);
* };
* ```
*
* There is legacy imperative API that enables you to manually update the
* status bar styles. However, the legacy API does not update the internal
* `StatusBar` diaplay stack, which means that any changes will be overridden
* whenever a `StatusBar` component is mounted or unmounted.
*
* It is strongly advised that you use `pushStackEntry`, `popStackEntry`, or
* `replaceStackEntry` instead of the static methods beginning with `set`.
*
* ### Constants
*
Expand Down Expand Up @@ -261,6 +284,48 @@ class StatusBar extends React.Component<{
StatusBarManager.setTranslucent(translucent);
}

/**
* Push a StatusBar entry onto the stack.
* The return value should be passed to `popStackEntry` when complete.
*
* @param props Object containing the StatusBar props to use in the stack entry.
*/
Comment thread
jamesreggio marked this conversation as resolved.
Resolved
static pushStackEntry(props) {
const entry = createStackEntry(props);
StatusBar._propsStack.push(entry);
StatusBar._updatePropsStack();
return entry;
}

/**
* Pop a StatusBar entry from the stack.
*
* @param entry Entry returned from `pushStackEntry`.
*/
Comment thread
jamesreggio marked this conversation as resolved.
Resolved
static popStackEntry(entry) {
const index = StatusBar._propsStack.indexOf(entry);
if (index !== -1) {
StatusBar._propsStack.splice(index, 1);
}
StatusBar._updatePropsStack();
}

/**
* Replace an existing StatusBar stack entry with new props.
*
* @param entry Entry returned from `pushStackEntry` to replace.
* @param props Object containing the StatusBar props to use in the replacement stack entry.
*/
Comment thread
jamesreggio marked this conversation as resolved.
Resolved
Comment thread
jamesreggio marked this conversation as resolved.
Resolved
static replaceStackEntry(entry, props) {
const newEntry = createStackEntry(props);
const index = StatusBar._propsStack.indexOf(entry);
if (index !== -1) {
StatusBar._propsStack[index] = newEntry;
}
StatusBar._updatePropsStack();
return newEntry;
}

static propTypes = {
/**
* If the status bar is hidden.
Expand Down Expand Up @@ -314,33 +379,24 @@ class StatusBar extends React.Component<{
// Every time a StatusBar component is mounted, we push it's prop to a stack
// and always update the native status bar with the props from the top of then
// stack. This allows having multiple StatusBar components and the one that is
// added last or is deeper in the view hierarchy will have priority.
this._stackEntry = createStackEntry(this.props);
StatusBar._propsStack.push(this._stackEntry);
this._updatePropsStack();
// added last or is deeper in the view hierachy will have priority.
this._stackEntry = StatusBar.pushStackEntry(this.props);
}

componentWillUnmount() {
// When a StatusBar is unmounted, remove itself from the stack and update
// the native bar with the next props.
const index = StatusBar._propsStack.indexOf(this._stackEntry);
StatusBar._propsStack.splice(index, 1);

this._updatePropsStack();
StatusBar.popStackEntry(this._stackEntry);
}

componentDidUpdate() {
const index = StatusBar._propsStack.indexOf(this._stackEntry);
this._stackEntry = createStackEntry(this.props);
StatusBar._propsStack[index] = this._stackEntry;

Comment thread
jamesreggio marked this conversation as resolved.
Resolved
this._updatePropsStack();
this._stackEntry = StatusBar.replaceStackEntry(this._stackEntry, this.props);
}

/**
* Updates the native status bar with the props from the stack.
*/
_updatePropsStack = () => {
static _updatePropsStack = () => {
// Send the update to the native module only once at the end of the frame.
clearImmediate(StatusBar._updateImmediate);
StatusBar._updateImmediate = setImmediate(() => {
Expand All @@ -358,7 +414,7 @@ class StatusBar extends React.Component<{
) {
StatusBarManager.setStyle(
mergedProps.barStyle.value,
mergedProps.barStyle.animated,
mergedProps.barStyle.animated || false,
);
}
if (!oldProps || oldProps.hidden.value !== mergedProps.hidden.value) {
Expand Down