Skip to content
This repository has been archived by the owner on Nov 11, 2024. It is now read-only.

Commit

Permalink
feat: add "AppState.windows" and new AppState events
Browse files Browse the repository at this point in the history
The new events are: "rootViewWillAppear" and "windowDidChangeScreen"
  • Loading branch information
aleclarson committed Oct 16, 2019
1 parent 221b429 commit edcc0dc
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 14 deletions.
21 changes: 18 additions & 3 deletions @types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6863,22 +6863,37 @@ export interface AlertIOSStatic {
*
* @see https://facebook.github.io/react-native/docs/appstateios.html#content
*/
export type AppStateEvent = "change" | "memoryWarning";
export type AppStateEvent = "change" | "memoryWarning" | "rootViewWillAppear" | "windowDidChangeScreen";
export type AppStateStatus = "active" | "background" | "inactive";

export interface AppStateStatic {
currentState: AppStateStatus;
windows: { [rootTag: number]: WindowState };

/**
* Add a handler to AppState changes by listening to the change event
* type and providing the handler
*/
addEventListener(type: AppStateEvent, listener: (state: AppStateStatus) => void): void;
addEventListener(type: 'change', listener: (state: AppStateStatus) => void): void;
addEventListener(type: 'memoryWarning', listener: () => void): void;
addEventListener(type: 'rootViewWillAppear', listener: (state: WindowState) => void): void;
addEventListener(type: 'windowDidChangeScreen', listener: (state: WindowState) => void): void;

/**
* Remove a handler by passing the change event type and the handler
*/
removeEventListener(type: AppStateEvent, listener: (state: AppStateStatus) => void): void;
removeEventListener(type: AppStateEvent, listener: Function): void;
}

export interface WindowState {
rootTag: number;
screen: Screen;
}

export interface Screen {
id: number;
scale: number;
layout: LayoutRectangle;
}

/**
Expand Down
42 changes: 31 additions & 11 deletions Libraries/AppState/AppState.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@ const RCTAppState = NativeModules.AppState;
const logError = require('logError');
const invariant = require('fbjs/lib/invariant');

import type {Layout} from 'CoreEventTypes';

type Screen = {|
+rootTag: number,
+bounds: Layout,
+scale: number,
|};

const eventTypes = ['change', 'memoryWarning', 'rootViewWillAppear', 'windowDidChangeScreen'];

/**
* `AppState` can tell you if the app is in the foreground or background,
* and notify you when the state changes.
Expand All @@ -30,15 +40,16 @@ class AppState extends NativeEventEmitter {
_eventHandlers: Object;
currentState: ?string;
isAvailable: boolean = true;
windows: { [rootTag: number]: Screen };

constructor() {
super(RCTAppState);

this.isAvailable = true;
this._eventHandlers = {
change: new Map(),
memoryWarning: new Map(),
};
this._eventHandlers = eventTypes.reduce((out, type) => {
out[type] = new Map();
return out;
}, {});

// TODO: Remove the 'active' fallback after `initialAppState` is exported by
// the Android implementation.
Expand All @@ -58,6 +69,18 @@ class AppState extends NativeEventEmitter {
}
);

this.windows = RCTAppState.windows.reduce((acc, state) => {
acc[state.rootTag] = state;
return acc;
}, {});

const onWindowChange = state => {
this.windows[state.rootTag] = state;
}

this.addListener('rootViewWillAppear', onWindowChange);
this.addListener('windowDidChangeScreen', onWindowChange);

// TODO: see above - this request just populates the value of `currentState`
// when the module is first initialized. Would be better to get rid of the
// prop and expose `getCurrentAppState` method directly.
Expand Down Expand Up @@ -87,7 +110,7 @@ class AppState extends NativeEventEmitter {
handler: Function
) {
invariant(
['change', 'memoryWarning'].indexOf(type) !== -1,
eventTypes.indexOf(type) !== -1,
'Trying to subscribe to unknown event: "%s"', type
);
if (type === 'change') {
Expand All @@ -97,11 +120,8 @@ class AppState extends NativeEventEmitter {
handler(appStateData.app_state);
}
));
} else if (type === 'memoryWarning') {
this._eventHandlers[type].set(handler, this.addListener(
'memoryWarning',
handler
));
} else {
this._eventHandlers[type].set(handler, this.addListener(type, handler));
}
}

Expand All @@ -115,7 +135,7 @@ class AppState extends NativeEventEmitter {
handler: Function
) {
invariant(
['change', 'memoryWarning'].indexOf(type) !== -1,
eventTypes.indexOf(type) !== -1,
'Trying to remove listener for unknown event: "%s"', type
);
if (!this._eventHandlers[type].has(handler)) {
Expand Down

0 comments on commit edcc0dc

Please sign in to comment.