diff --git a/flow-typed/npm/redux_v3.x.x.js b/flow-typed/npm/redux_v3.x.x.js index f6445d9..a4aecbf 100644 --- a/flow-typed/npm/redux_v3.x.x.js +++ b/flow-typed/npm/redux_v3.x.x.js @@ -2,90 +2,134 @@ // flow-typed version: a165222d28/redux_v3.x.x/flow_>=v0.33.x declare module 'redux' { - /* S = State A = Action D = Dispatch + R = Result of a thunk action */ + declare type GetState = () => S; + declare type ThunkAction = ( + dispatch: Dispatch, + GetState, + ) => R; + declare type ThunkDispatch = (action: ThunkAction) => R; declare type DispatchAPI = (action: A) => A; - declare type Dispatch }> = DispatchAPI; + declare type PlainDispatch}> = DispatchAPI; + declare type Dispatch = PlainDispatch & ThunkDispatch; - declare type MiddlewareAPI> = { - dispatch: D; - getState(): S; + declare type MiddlewareAPI> = { + dispatch: D, + getState(): S, }; - declare type Store> = { + declare type Store> = { // rewrite MiddlewareAPI members in order to get nicer error messages (intersections produce long messages) - dispatch: D; - getState(): S; - subscribe(listener: () => void): () => void; - replaceReducer(nextReducer: Reducer): void + dispatch: D, + getState(): S, + subscribe(listener: () => void): () => void, + replaceReducer(nextReducer: Reducer): void, }; declare type Reducer = (state: S, action: A) => S; - declare type CombinedReducer = (state: $Shape & {} | void, action: A) => S; + declare type CombinedReducer = ( + state: ($Shape & {}) | void, + action: A, + ) => S; - declare type Middleware> = - (api: MiddlewareAPI) => - (next: D) => D; + declare type Middleware> = ( + api: MiddlewareAPI, + ) => (next: D) => D; - declare type StoreCreator> = { - (reducer: Reducer, enhancer?: StoreEnhancer): Store; - (reducer: Reducer, preloadedState: S, enhancer?: StoreEnhancer): Store; + declare type StoreCreator> = { + (reducer: Reducer, enhancer?: StoreEnhancer): Store, + ( + reducer: Reducer, + preloadedState: S, + enhancer?: StoreEnhancer, + ): Store, }; - declare type StoreEnhancer> = (next: StoreCreator) => StoreCreator; + declare type StoreEnhancer> = ( + next: StoreCreator, + ) => StoreCreator; - declare function createStore(reducer: Reducer, enhancer?: StoreEnhancer): Store; - declare function createStore(reducer: Reducer, preloadedState: S, enhancer?: StoreEnhancer): Store; + declare function createStore( + reducer: Reducer, + enhancer?: StoreEnhancer, + ): Store; + declare function createStore( + reducer: Reducer, + preloadedState: S, + enhancer?: StoreEnhancer, + ): Store; - declare function applyMiddleware(...middlewares: Array>): StoreEnhancer; + declare function applyMiddleware( + ...middlewares: Array> + ): StoreEnhancer; declare type ActionCreator = (...args: Array) => A; - declare type ActionCreators = { [key: K]: ActionCreator }; + declare type ActionCreators = {[key: K]: ActionCreator}; - declare function bindActionCreators, D: DispatchAPI>(actionCreator: C, dispatch: D): C; - declare function bindActionCreators, D: DispatchAPI>(actionCreators: C, dispatch: D): C; + declare function bindActionCreators< + S, + A, + C: ActionCreator, + D: DispatchAPI, + >( + actionCreator: C, + dispatch: D, + ): C; + declare function bindActionCreators< + S, + A, + K, + C: ActionCreators, + D: DispatchAPI, + >( + actionCreators: C, + dispatch: D, + ): C; - declare function combineReducers(reducers: O): CombinedReducer<$ObjMap(r: Reducer) => S>, A>; + declare function combineReducers( + reducers: O, + ): CombinedReducer<$ObjMap(r: Reducer) => S>, A>; - declare function compose(ab: (a: A) => B): (a: A) => B + declare function compose(ab: (a: A) => B): (a: A) => B; declare function compose( bc: (b: B) => C, - ab: (a: A) => B - ): (a: A) => C + ab: (a: A) => B, + ): (a: A) => C; declare function compose( cd: (c: C) => D, bc: (b: B) => C, - ab: (a: A) => B - ): (a: A) => D + ab: (a: A) => B, + ): (a: A) => D; declare function compose( de: (d: D) => E, cd: (c: C) => D, bc: (b: B) => C, - ab: (a: A) => B - ): (a: A) => E + ab: (a: A) => B, + ): (a: A) => E; declare function compose( ef: (e: E) => F, de: (d: D) => E, cd: (c: C) => D, bc: (b: B) => C, - ab: (a: A) => B - ): (a: A) => F + ab: (a: A) => B, + ): (a: A) => F; declare function compose( fg: (f: F) => G, ef: (e: E) => F, de: (d: D) => E, cd: (c: C) => D, bc: (b: B) => C, - ab: (a: A) => B - ): (a: A) => G + ab: (a: A) => B, + ): (a: A) => G; declare function compose( gh: (g: G) => H, fg: (f: F) => G, @@ -93,8 +137,8 @@ declare module 'redux' { de: (d: D) => E, cd: (c: C) => D, bc: (b: B) => C, - ab: (a: A) => B - ): (a: A) => H + ab: (a: A) => B, + ): (a: A) => H; declare function compose( hi: (h: H) => I, gh: (g: G) => H, @@ -103,7 +147,6 @@ declare module 'redux' { de: (d: D) => E, cd: (c: C) => D, bc: (b: B) => C, - ab: (a: A) => B - ): (a: A) => I - + ab: (a: A) => B, + ): (a: A) => I; } diff --git a/src/App.js b/src/App.js index 97bf4b1..a90a916 100644 --- a/src/App.js +++ b/src/App.js @@ -12,7 +12,13 @@ import { localUrlFromVersion, requestOngoingVersions, } from './actions.js'; -import type {Dispatch, OngoingVersions, Status, Statuses} from './types.js'; +import type { + Dispatch, + OngoingVersions, + State, + Status, + Statuses, +} from './types.js'; function requestNotificationPermission(): void { if ( @@ -43,7 +49,7 @@ const parseUrl = ( class ConnectedApp extends React.Component<{dispatch: Dispatch}, void> { refreshIntervalId: ?number; - constructor(props): void { + constructor(props: {dispatch: Dispatch}): void { super(props); this.refreshIntervalId = null; } @@ -107,28 +113,24 @@ const App = connect()(ConnectedApp); const VersionInput = connect( // mapStateToProps - state => { - return { - value: state.versionInput, - }; - }, + (state: State) => ({ + value: state.versionInput, + }), // mapDispatchToProps - dispatch => { - return { - onSubmit: (e: SyntheticEvent): void => { - e.preventDefault(); - dispatch(submitVersion()); - dispatch(updateUrl()); - }, - handleSearchBoxChange: (e: SyntheticEvent): void => { - dispatch(updateVersionInput(e.currentTarget.value)); - }, - handleDismissSearchBoxVersion: (): void => { - window.location.hash = ''; - dispatch(setVersion('')); - }, - }; - }, + (dispatch: Dispatch) => ({ + onSubmit: (e: SyntheticEvent): void => { + e.preventDefault(); + dispatch(submitVersion()); + dispatch(updateUrl()); + }, + handleSearchBoxChange: (e: SyntheticEvent): void => { + dispatch(updateVersionInput(e.currentTarget.value)); + }, + handleDismissSearchBoxVersion: (): void => { + window.location.hash = ''; + dispatch(setVersion('')); + }, + }), )(SearchForm); type SearchFormProps = { @@ -188,11 +190,9 @@ function Spinner() { const SideBar = connect( // mapStateToProps - state => { - return { - versions: state.latestChannelVersions, - }; - }, + (state: State) => ({ + versions: state.latestChannelVersions, + }), // mapDispatchToProps null, )(ReleasesMenu); @@ -225,12 +225,10 @@ function ReleaseItem({title, version}: {title: string, version: string}) { const CurrentRelease = connect( // mapStateToProps - state => { - return { - statuses: state.statuses, - version: state.version, - }; - }, + (state: State) => ({ + statuses: state.statuses, + version: state.version, + }), // mapDispatchToProps null, )(Dashboard); diff --git a/src/actions.js b/src/actions.js index 57848d8..6e4ce80 100644 --- a/src/actions.js +++ b/src/actions.js @@ -14,6 +14,7 @@ import type { SetVersion, Statuses, SubmitVersion, + ThunkAction, UpdateLatestChannelVersions, UpdateStatuses, UpdateVersionInput, @@ -73,7 +74,7 @@ function fetchStatus(version: string): Promise<*> { ); } -export function requestStatus(version: ?string) { +export function requestStatus(version: ?string): ThunkAction { const notifyChanges = changed => { // $FlowFixMe if (Notification.permission === 'granted') { @@ -131,7 +132,7 @@ export function requestOngoingVersions() { // We do that in a thunk action to have access to the state via "getState". export const localUrlFromVersion = (version: string) => `#pollbot/firefox/${version}`; -export function updateUrl() { +export function updateUrl(): ThunkAction { return function(dispatch: Dispatch, getState: GetState) { window.location.hash = localUrlFromVersion(getState().version); }; diff --git a/src/types.js b/src/types.js index e32f759..4212538 100644 --- a/src/types.js +++ b/src/types.js @@ -1,5 +1,10 @@ // @flow -import type {Store as ReduxStore, Dispatch as ReduxDispatch} from 'redux'; +import type { + Store as ReduxStore, + ThunkAction as ReduxThunkAction, + Dispatch as ReduxDispatch, + GetState as ReduxGetState, +} from 'redux'; /* * state types @@ -68,9 +73,9 @@ export type Action = | UpdateStatuses; /* - * types + * Redux types */ -export type GetState = () => State; +export type GetState = ReduxGetState; +export type ThunkAction = ReduxThunkAction; export type Store = ReduxStore; -export type Dispatch = ReduxDispatch & Thunk; -export type Thunk = ((Dispatch, GetState) => Promise | void) => A; +export type Dispatch = ReduxDispatch;