diff --git a/lib/reducers/foreground-reducer.js b/lib/reducers/foreground-reducer.js index e3d8b123b..59e45a923 100644 --- a/lib/reducers/foreground-reducer.js +++ b/lib/reducers/foreground-reducer.js @@ -1,22 +1,22 @@ // @flow import type { BaseAction } from '../types/redux-types'; -export const backgroundActionType = 'BACKGROUND'; -export const foregroundActionType = 'FOREGROUND'; export const unsupervisedBackgroundActionType = 'UNSUPERVISED_BACKGROUND'; +export const updateLifecycleStateActionType = 'UPDATE_LIFECYCLE_STATE'; export default function reduceForeground( state: boolean, action: BaseAction, ): boolean { - if ( - action.type === backgroundActionType || - action.type === unsupervisedBackgroundActionType - ) { + if (action.type === unsupervisedBackgroundActionType) { return false; - } else if (action.type === foregroundActionType) { - return true; + } else if (action.type === updateLifecycleStateActionType) { + if (action.payload === 'active') { + return true; + } else if (action.payload === 'background') { + return false; + } } return state; } diff --git a/lib/types/lifecycle-state-types.js b/lib/types/lifecycle-state-types.js new file mode 100644 index 000000000..1351b1600 --- /dev/null +++ b/lib/types/lifecycle-state-types.js @@ -0,0 +1,3 @@ +// @flow + +export type LifecycleState = 'active' | 'inactive' | 'background' | 'unknown'; diff --git a/lib/types/redux-types.js b/lib/types/redux-types.js index 739c360f4..b3bdc2c40 100644 --- a/lib/types/redux-types.js +++ b/lib/types/redux-types.js @@ -1,831 +1,828 @@ // @flow import type { LogOutResult, LogInStartingPayload, LogInResult, RegisterResult, } from './account-types'; import type { ActivityUpdateSuccessPayload, QueueActivityUpdatesPayload, SetThreadUnreadStatusPayload, } from './activity-types'; import type { RawEntryInfo, EntryStore, CalendarQuery, SaveEntryPayload, CreateEntryPayload, DeleteEntryResponse, RestoreEntryPayload, FetchEntryInfosResult, CalendarQueryUpdateResult, CalendarQueryUpdateStartingPayload, } from './entry-types'; import type { CalendarFilter, CalendarThreadFilter, SetCalendarDeletedFilterPayload, } from './filter-types'; +import type { LifecycleState } from './lifecycle-state-types'; import type { LoadingStatus, LoadingInfo } from './loading-types'; import type { UpdateMultimediaMessageMediaPayload } from './media-types'; import type { MessageStore, RawMultimediaMessageInfo, FetchMessageInfosPayload, SendMessagePayload, SaveMessagesPayload, NewMessagesPayload, MessageStorePrunePayload, LocallyComposedMessageInfo, } from './message-types'; import type { RawTextMessageInfo } from './messages/text'; import type { BaseNavInfo } from './nav-types'; import type { ClearDeliveredReportsPayload, ClientReportCreationRequest, QueueReportsPayload, } from './report-types'; import type { ProcessServerRequestsPayload } from './request-types'; import type { UserSearchResult } from './search-types'; import type { SetSessionPayload } from './session-types'; import type { ConnectionInfo, StateSyncFullActionPayload, StateSyncIncrementalActionPayload, UpdateConnectionStatusPayload, SetLateResponsePayload, UpdateDisconnectedBarPayload, } from './socket-types'; import type { SubscriptionUpdateResult } from './subscription-types'; import type { ThreadStore, ChangeThreadSettingsPayload, LeaveThreadPayload, NewThreadResult, ThreadJoinPayload, } from './thread-types'; import type { UpdatesResultWithUserInfos } from './update-types'; import type { CurrentUserInfo, UserStore } from './user-types'; export type BaseAppState = { navInfo: NavInfo, currentUserInfo: ?CurrentUserInfo, entryStore: EntryStore, threadStore: ThreadStore, userStore: UserStore, messageStore: MessageStore, updatesCurrentAsOf: number, // millisecond timestamp loadingStatuses: { [key: string]: { [idx: number]: LoadingStatus } }, calendarFilters: $ReadOnlyArray, urlPrefix: string, connection: ConnectionInfo, watchedThreadIDs: $ReadOnlyArray, foreground: boolean, nextLocalID: number, queuedReports: $ReadOnlyArray, dataLoaded: boolean, }; // Web JS runtime doesn't have access to the cookie for security reasons. // Native JS doesn't have a sessionID because the cookieID is used instead. // Web JS doesn't have a device token because it's not a device... export type NativeAppState = BaseAppState<*> & { sessionID?: void, deviceToken: ?string, cookie: ?string, }; export type WebAppState = BaseAppState<*> & { sessionID: ?string, deviceToken?: void, cookie?: void, }; export type AppState = NativeAppState | WebAppState; export type BaseAction = | {| - type: '@@redux/INIT', - payload?: void, + +type: '@@redux/INIT', + +payload?: void, |} | {| - type: 'FETCH_ENTRIES_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'FETCH_ENTRIES_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_ENTRIES_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'FETCH_ENTRIES_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_ENTRIES_SUCCESS', - payload: FetchEntryInfosResult, - loadingInfo: LoadingInfo, + +type: 'FETCH_ENTRIES_SUCCESS', + +payload: FetchEntryInfosResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'LOG_OUT_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'LOG_OUT_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'LOG_OUT_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'LOG_OUT_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'LOG_OUT_SUCCESS', - payload: LogOutResult, - loadingInfo: LoadingInfo, + +type: 'LOG_OUT_SUCCESS', + +payload: LogOutResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'DELETE_ACCOUNT_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'DELETE_ACCOUNT_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'DELETE_ACCOUNT_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'DELETE_ACCOUNT_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'DELETE_ACCOUNT_SUCCESS', - payload: LogOutResult, - loadingInfo: LoadingInfo, + +type: 'DELETE_ACCOUNT_SUCCESS', + +payload: LogOutResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'CREATE_LOCAL_ENTRY', - payload: RawEntryInfo, + +type: 'CREATE_LOCAL_ENTRY', + +payload: RawEntryInfo, |} | {| - type: 'CREATE_ENTRY_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'CREATE_ENTRY_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'CREATE_ENTRY_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'CREATE_ENTRY_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'CREATE_ENTRY_SUCCESS', - payload: CreateEntryPayload, - loadingInfo: LoadingInfo, + +type: 'CREATE_ENTRY_SUCCESS', + +payload: CreateEntryPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'SAVE_ENTRY_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'SAVE_ENTRY_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'SAVE_ENTRY_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'SAVE_ENTRY_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'SAVE_ENTRY_SUCCESS', - payload: SaveEntryPayload, - loadingInfo: LoadingInfo, + +type: 'SAVE_ENTRY_SUCCESS', + +payload: SaveEntryPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'CONCURRENT_MODIFICATION_RESET', - payload: {| - id: string, - dbText: string, + +type: 'CONCURRENT_MODIFICATION_RESET', + +payload: {| + +id: string, + +dbText: string, |}, |} | {| - type: 'DELETE_ENTRY_STARTED', - loadingInfo: LoadingInfo, - payload: {| - localID: ?string, - serverID: ?string, + +type: 'DELETE_ENTRY_STARTED', + +loadingInfo: LoadingInfo, + +payload: {| + +localID: ?string, + +serverID: ?string, |}, |} | {| - type: 'DELETE_ENTRY_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'DELETE_ENTRY_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'DELETE_ENTRY_SUCCESS', - payload: ?DeleteEntryResponse, - loadingInfo: LoadingInfo, + +type: 'DELETE_ENTRY_SUCCESS', + +payload: ?DeleteEntryResponse, + +loadingInfo: LoadingInfo, |} | {| - type: 'LOG_IN_STARTED', - loadingInfo: LoadingInfo, - payload: LogInStartingPayload, + +type: 'LOG_IN_STARTED', + +loadingInfo: LoadingInfo, + +payload: LogInStartingPayload, |} | {| - type: 'LOG_IN_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'LOG_IN_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'LOG_IN_SUCCESS', - payload: LogInResult, - loadingInfo: LoadingInfo, + +type: 'LOG_IN_SUCCESS', + +payload: LogInResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'REGISTER_STARTED', - loadingInfo: LoadingInfo, - payload: LogInStartingPayload, + +type: 'REGISTER_STARTED', + +loadingInfo: LoadingInfo, + +payload: LogInStartingPayload, |} | {| - type: 'REGISTER_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'REGISTER_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'REGISTER_SUCCESS', - payload: RegisterResult, - loadingInfo: LoadingInfo, + +type: 'REGISTER_SUCCESS', + +payload: RegisterResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESET_PASSWORD_STARTED', - payload: {| calendarQuery: CalendarQuery |}, - loadingInfo: LoadingInfo, + +type: 'RESET_PASSWORD_STARTED', + +payload: {| calendarQuery: CalendarQuery |}, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESET_PASSWORD_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'RESET_PASSWORD_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESET_PASSWORD_SUCCESS', - payload: LogInResult, - loadingInfo: LoadingInfo, + +type: 'RESET_PASSWORD_SUCCESS', + +payload: LogInResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'FORGOT_PASSWORD_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'FORGOT_PASSWORD_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'FORGOT_PASSWORD_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'FORGOT_PASSWORD_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'FORGOT_PASSWORD_SUCCESS', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'FORGOT_PASSWORD_SUCCESS', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_USER_SETTINGS_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'CHANGE_USER_SETTINGS_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_USER_SETTINGS_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'CHANGE_USER_SETTINGS_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_USER_SETTINGS_SUCCESS', - payload: {| - email: string, + +type: 'CHANGE_USER_SETTINGS_SUCCESS', + +payload: {| + +email: string, |}, - loadingInfo: LoadingInfo, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESEND_VERIFICATION_EMAIL_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'RESEND_VERIFICATION_EMAIL_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESEND_VERIFICATION_EMAIL_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'RESEND_VERIFICATION_EMAIL_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESEND_VERIFICATION_EMAIL_SUCCESS', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'RESEND_VERIFICATION_EMAIL_SUCCESS', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_THREAD_SETTINGS_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'CHANGE_THREAD_SETTINGS_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_THREAD_SETTINGS_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'CHANGE_THREAD_SETTINGS_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_THREAD_SETTINGS_SUCCESS', - payload: ChangeThreadSettingsPayload, - loadingInfo: LoadingInfo, + +type: 'CHANGE_THREAD_SETTINGS_SUCCESS', + +payload: ChangeThreadSettingsPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'DELETE_THREAD_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'DELETE_THREAD_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'DELETE_THREAD_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'DELETE_THREAD_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'DELETE_THREAD_SUCCESS', - payload: LeaveThreadPayload, - loadingInfo: LoadingInfo, + +type: 'DELETE_THREAD_SUCCESS', + +payload: LeaveThreadPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'NEW_THREAD_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'NEW_THREAD_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'NEW_THREAD_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'NEW_THREAD_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'NEW_THREAD_SUCCESS', - payload: NewThreadResult, - loadingInfo: LoadingInfo, + +type: 'NEW_THREAD_SUCCESS', + +payload: NewThreadResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'REMOVE_USERS_FROM_THREAD_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'REMOVE_USERS_FROM_THREAD_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'REMOVE_USERS_FROM_THREAD_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'REMOVE_USERS_FROM_THREAD_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'REMOVE_USERS_FROM_THREAD_SUCCESS', - payload: ChangeThreadSettingsPayload, - loadingInfo: LoadingInfo, + +type: 'REMOVE_USERS_FROM_THREAD_SUCCESS', + +payload: ChangeThreadSettingsPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_THREAD_MEMBER_ROLES_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'CHANGE_THREAD_MEMBER_ROLES_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_THREAD_MEMBER_ROLES_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'CHANGE_THREAD_MEMBER_ROLES_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'CHANGE_THREAD_MEMBER_ROLES_SUCCESS', - payload: ChangeThreadSettingsPayload, - loadingInfo: LoadingInfo, + +type: 'CHANGE_THREAD_MEMBER_ROLES_SUCCESS', + +payload: ChangeThreadSettingsPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_REVISIONS_FOR_ENTRY_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'FETCH_REVISIONS_FOR_ENTRY_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_REVISIONS_FOR_ENTRY_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'FETCH_REVISIONS_FOR_ENTRY_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_REVISIONS_FOR_ENTRY_SUCCESS', - payload: {| - entryID: string, - text: string, - deleted: boolean, + +type: 'FETCH_REVISIONS_FOR_ENTRY_SUCCESS', + +payload: {| + +entryID: string, + +text: string, + +deleted: boolean, |}, - loadingInfo: LoadingInfo, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESTORE_ENTRY_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'RESTORE_ENTRY_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESTORE_ENTRY_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'RESTORE_ENTRY_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'RESTORE_ENTRY_SUCCESS', - payload: RestoreEntryPayload, - loadingInfo: LoadingInfo, + +type: 'RESTORE_ENTRY_SUCCESS', + +payload: RestoreEntryPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'JOIN_THREAD_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'JOIN_THREAD_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'JOIN_THREAD_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'JOIN_THREAD_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'JOIN_THREAD_SUCCESS', - payload: ThreadJoinPayload, - loadingInfo: LoadingInfo, + +type: 'JOIN_THREAD_SUCCESS', + +payload: ThreadJoinPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'LEAVE_THREAD_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'LEAVE_THREAD_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'LEAVE_THREAD_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'LEAVE_THREAD_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'LEAVE_THREAD_SUCCESS', - payload: LeaveThreadPayload, - loadingInfo: LoadingInfo, + +type: 'LEAVE_THREAD_SUCCESS', + +payload: LeaveThreadPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'SET_NEW_SESSION', - payload: SetSessionPayload, + +type: 'SET_NEW_SESSION', + +payload: SetSessionPayload, |} | {| - type: 'persist/REHYDRATE', - payload: ?BaseAppState<*>, + +type: 'persist/REHYDRATE', + +payload: ?BaseAppState<*>, |} | {| - type: 'FETCH_MESSAGES_BEFORE_CURSOR_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'FETCH_MESSAGES_BEFORE_CURSOR_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_MESSAGES_BEFORE_CURSOR_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'FETCH_MESSAGES_BEFORE_CURSOR_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_MESSAGES_BEFORE_CURSOR_SUCCESS', - payload: FetchMessageInfosPayload, - loadingInfo: LoadingInfo, + +type: 'FETCH_MESSAGES_BEFORE_CURSOR_SUCCESS', + +payload: FetchMessageInfosPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_MOST_RECENT_MESSAGES_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'FETCH_MOST_RECENT_MESSAGES_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_MOST_RECENT_MESSAGES_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'FETCH_MOST_RECENT_MESSAGES_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'FETCH_MOST_RECENT_MESSAGES_SUCCESS', - payload: FetchMessageInfosPayload, - loadingInfo: LoadingInfo, + +type: 'FETCH_MOST_RECENT_MESSAGES_SUCCESS', + +payload: FetchMessageInfosPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_TEXT_MESSAGE_STARTED', - loadingInfo: LoadingInfo, - payload: RawTextMessageInfo, + +type: 'SEND_TEXT_MESSAGE_STARTED', + +loadingInfo: LoadingInfo, + +payload: RawTextMessageInfo, |} | {| - type: 'SEND_TEXT_MESSAGE_FAILED', - error: true, - payload: Error & { - localID: string, - threadID: string, + +type: 'SEND_TEXT_MESSAGE_FAILED', + +error: true, + +payload: Error & { + +localID: string, + +threadID: string, }, - loadingInfo: LoadingInfo, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_TEXT_MESSAGE_SUCCESS', - payload: SendMessagePayload, - loadingInfo: LoadingInfo, + +type: 'SEND_TEXT_MESSAGE_SUCCESS', + +payload: SendMessagePayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_MULTIMEDIA_MESSAGE_STARTED', - loadingInfo: LoadingInfo, - payload: RawMultimediaMessageInfo, + +type: 'SEND_MULTIMEDIA_MESSAGE_STARTED', + +loadingInfo: LoadingInfo, + +payload: RawMultimediaMessageInfo, |} | {| - type: 'SEND_MULTIMEDIA_MESSAGE_FAILED', - error: true, - payload: Error & { - localID: string, - threadID: string, + +type: 'SEND_MULTIMEDIA_MESSAGE_FAILED', + +error: true, + +payload: Error & { + +localID: string, + +threadID: string, }, - loadingInfo: LoadingInfo, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_MULTIMEDIA_MESSAGE_SUCCESS', - payload: SendMessagePayload, - loadingInfo: LoadingInfo, + +type: 'SEND_MULTIMEDIA_MESSAGE_SUCCESS', + +payload: SendMessagePayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEARCH_USERS_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'SEARCH_USERS_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEARCH_USERS_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'SEARCH_USERS_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEARCH_USERS_SUCCESS', - payload: UserSearchResult, - loadingInfo: LoadingInfo, + +type: 'SEARCH_USERS_SUCCESS', + +payload: UserSearchResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'SAVE_DRAFT', - payload: { - key: string, - draft: string, + +type: 'SAVE_DRAFT', + +payload: { + +key: string, + +draft: string, }, |} | {| - type: 'UPDATE_ACTIVITY_STARTED', - payload?: void, - loadingInfo: LoadingInfo, - |} - | {| - type: 'UPDATE_ACTIVITY_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'UPDATE_ACTIVITY_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'UPDATE_ACTIVITY_SUCCESS', - payload: ActivityUpdateSuccessPayload, - loadingInfo: LoadingInfo, + +type: 'UPDATE_ACTIVITY_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'SET_DEVICE_TOKEN_STARTED', - payload: string, - loadingInfo: LoadingInfo, + +type: 'UPDATE_ACTIVITY_SUCCESS', + +payload: ActivityUpdateSuccessPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'SET_DEVICE_TOKEN_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'SET_DEVICE_TOKEN_STARTED', + +payload: string, + +loadingInfo: LoadingInfo, |} | {| - type: 'SET_DEVICE_TOKEN_SUCCESS', - payload: string, - loadingInfo: LoadingInfo, + +type: 'SET_DEVICE_TOKEN_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'HANDLE_VERIFICATION_CODE_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'SET_DEVICE_TOKEN_SUCCESS', + +payload: string, + +loadingInfo: LoadingInfo, |} | {| - type: 'HANDLE_VERIFICATION_CODE_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'HANDLE_VERIFICATION_CODE_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'HANDLE_VERIFICATION_CODE_SUCCESS', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'HANDLE_VERIFICATION_CODE_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_REPORT_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'HANDLE_VERIFICATION_CODE_SUCCESS', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_REPORT_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'SEND_REPORT_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_REPORT_SUCCESS', - payload?: ClearDeliveredReportsPayload, - loadingInfo: LoadingInfo, + +type: 'SEND_REPORT_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_REPORTS_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'SEND_REPORT_SUCCESS', + +payload?: ClearDeliveredReportsPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_REPORTS_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'SEND_REPORTS_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'SEND_REPORTS_SUCCESS', - payload?: ClearDeliveredReportsPayload, - loadingInfo: LoadingInfo, + +type: 'SEND_REPORTS_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'QUEUE_REPORTS', - payload: QueueReportsPayload, + +type: 'SEND_REPORTS_SUCCESS', + +payload?: ClearDeliveredReportsPayload, + +loadingInfo: LoadingInfo, |} | {| - type: 'SET_URL_PREFIX', - payload: string, + +type: 'QUEUE_REPORTS', + +payload: QueueReportsPayload, |} | {| - type: 'SAVE_MESSAGES', - payload: SaveMessagesPayload, + +type: 'SET_URL_PREFIX', + +payload: string, |} | {| - type: 'UPDATE_CALENDAR_THREAD_FILTER', - payload: CalendarThreadFilter, + +type: 'SAVE_MESSAGES', + +payload: SaveMessagesPayload, |} | {| - type: 'CLEAR_CALENDAR_THREAD_FILTER', - payload?: void, + +type: 'UPDATE_CALENDAR_THREAD_FILTER', + +payload: CalendarThreadFilter, |} | {| - type: 'SET_CALENDAR_DELETED_FILTER', - payload: SetCalendarDeletedFilterPayload, + +type: 'CLEAR_CALENDAR_THREAD_FILTER', + +payload?: void, |} | {| - type: 'UPDATE_SUBSCRIPTION_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'SET_CALENDAR_DELETED_FILTER', + +payload: SetCalendarDeletedFilterPayload, |} | {| - type: 'UPDATE_SUBSCRIPTION_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'UPDATE_SUBSCRIPTION_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'UPDATE_SUBSCRIPTION_SUCCESS', - payload: SubscriptionUpdateResult, - loadingInfo: LoadingInfo, + +type: 'UPDATE_SUBSCRIPTION_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'UPDATE_CALENDAR_QUERY_STARTED', - loadingInfo: LoadingInfo, - payload?: CalendarQueryUpdateStartingPayload, + +type: 'UPDATE_SUBSCRIPTION_SUCCESS', + +payload: SubscriptionUpdateResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'UPDATE_CALENDAR_QUERY_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'UPDATE_CALENDAR_QUERY_STARTED', + +loadingInfo: LoadingInfo, + +payload?: CalendarQueryUpdateStartingPayload, |} | {| - type: 'UPDATE_CALENDAR_QUERY_SUCCESS', - payload: CalendarQueryUpdateResult, - loadingInfo: LoadingInfo, + +type: 'UPDATE_CALENDAR_QUERY_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'FULL_STATE_SYNC', - payload: StateSyncFullActionPayload, + +type: 'UPDATE_CALENDAR_QUERY_SUCCESS', + +payload: CalendarQueryUpdateResult, + +loadingInfo: LoadingInfo, |} | {| - type: 'INCREMENTAL_STATE_SYNC', - payload: StateSyncIncrementalActionPayload, + +type: 'FULL_STATE_SYNC', + +payload: StateSyncFullActionPayload, |} | {| - type: 'PROCESS_SERVER_REQUESTS', - payload: ProcessServerRequestsPayload, + +type: 'INCREMENTAL_STATE_SYNC', + +payload: StateSyncIncrementalActionPayload, |} | {| - type: 'UPDATE_CONNECTION_STATUS', - payload: UpdateConnectionStatusPayload, + +type: 'PROCESS_SERVER_REQUESTS', + +payload: ProcessServerRequestsPayload, |} | {| - type: 'QUEUE_ACTIVITY_UPDATES', - payload: QueueActivityUpdatesPayload, + +type: 'UPDATE_CONNECTION_STATUS', + +payload: UpdateConnectionStatusPayload, |} | {| - type: 'FOREGROUND', - payload?: void, + +type: 'QUEUE_ACTIVITY_UPDATES', + +payload: QueueActivityUpdatesPayload, |} | {| - type: 'BACKGROUND', - payload?: void, + +type: 'UNSUPERVISED_BACKGROUND', + +payload?: void, |} | {| - type: 'UNSUPERVISED_BACKGROUND', - payload?: void, + +type: 'UPDATE_LIFECYCLE_STATE', + +payload: LifecycleState, |} | {| - type: 'PROCESS_UPDATES', - payload: UpdatesResultWithUserInfos, + +type: 'PROCESS_UPDATES', + +payload: UpdatesResultWithUserInfos, |} | {| - type: 'PROCESS_MESSAGES', - payload: NewMessagesPayload, + +type: 'PROCESS_MESSAGES', + +payload: NewMessagesPayload, |} | {| - type: 'MESSAGE_STORE_PRUNE', - payload: MessageStorePrunePayload, + +type: 'MESSAGE_STORE_PRUNE', + +payload: MessageStorePrunePayload, |} | {| - type: 'SET_LATE_RESPONSE', - payload: SetLateResponsePayload, + +type: 'SET_LATE_RESPONSE', + +payload: SetLateResponsePayload, |} | {| - type: 'UPDATE_DISCONNECTED_BAR', - payload: UpdateDisconnectedBarPayload, + +type: 'UPDATE_DISCONNECTED_BAR', + +payload: UpdateDisconnectedBarPayload, |} | {| - type: 'REQUEST_ACCESS_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'REQUEST_ACCESS_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'REQUEST_ACCESS_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'REQUEST_ACCESS_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'REQUEST_ACCESS_SUCCESS', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'REQUEST_ACCESS_SUCCESS', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'UPDATE_MULTIMEDIA_MESSAGE_MEDIA', - payload: UpdateMultimediaMessageMediaPayload, + +type: 'UPDATE_MULTIMEDIA_MESSAGE_MEDIA', + +payload: UpdateMultimediaMessageMediaPayload, |} | {| - type: 'CREATE_LOCAL_MESSAGE', - payload: LocallyComposedMessageInfo, + +type: 'CREATE_LOCAL_MESSAGE', + +payload: LocallyComposedMessageInfo, |} | {| - type: 'UPDATE_RELATIONSHIPS_STARTED', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'UPDATE_RELATIONSHIPS_STARTED', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| - type: 'UPDATE_RELATIONSHIPS_FAILED', - error: true, - payload: Error, - loadingInfo: LoadingInfo, + +type: 'UPDATE_RELATIONSHIPS_FAILED', + +error: true, + +payload: Error, + +loadingInfo: LoadingInfo, |} | {| - type: 'UPDATE_RELATIONSHIPS_SUCCESS', - payload?: void, - loadingInfo: LoadingInfo, + +type: 'UPDATE_RELATIONSHIPS_SUCCESS', + +payload?: void, + +loadingInfo: LoadingInfo, |} | {| +type: 'SET_THREAD_UNREAD_STATUS_STARTED', +payload: {| +threadID: string, +unread: boolean, |}, +loadingInfo: LoadingInfo, |} | {| +type: 'SET_THREAD_UNREAD_STATUS_FAILED', +error: true, +payload: Error, +loadingInfo: LoadingInfo, |} | {| +type: 'SET_THREAD_UNREAD_STATUS_SUCCESS', +payload: SetThreadUnreadStatusPayload, |}; export type ActionPayload = ?(Object | Array<*> | $ReadOnlyArray<*> | string); export type SuperAction = { type: string, payload?: ActionPayload, loadingInfo?: LoadingInfo, error?: boolean, }; type ThunkedAction = (dispatch: Dispatch) => void; export type PromisedAction = (dispatch: Dispatch) => Promise; export type Dispatch = ((promisedAction: PromisedAction) => Promise) & ((thunkedAction: ThunkedAction) => void) & ((action: SuperAction) => boolean); // This is lifted from redux-persist/lib/constants.js // I don't want to add redux-persist to the web/server bundles... // import { REHYDRATE } from 'redux-persist'; export const rehydrateActionType = 'persist/REHYDRATE'; diff --git a/native/lifecycle/lifecycle-event-emitter.js b/native/lifecycle/lifecycle-event-emitter.js index 2c2e8b069..4140d0f1f 100644 --- a/native/lifecycle/lifecycle-event-emitter.js +++ b/native/lifecycle/lifecycle-event-emitter.js @@ -1,52 +1,53 @@ // @flow import invariant from 'invariant'; import { Platform } from 'react-native'; import NativeEventEmitter from 'react-native/Libraries/EventEmitter/NativeEventEmitter'; import type { TurboModule } from 'react-native/Libraries/TurboModule/RCTExport'; import * as TurboModuleRegistry from 'react-native/Libraries/TurboModule/TurboModuleRegistry'; -// eslint-disable-next-line import/default + +import type { LifecycleState } from 'lib/types/lifecycle-state-types'; interface Spec extends TurboModule { +getConstants: () => {| initialStatus: string, |}; +addListener: (eventName: string) => void; +removeListeners: (count: number) => void; } const AndroidLifecycle = (TurboModuleRegistry.getEnforcing( 'AndroidLifecycle', ): Spec); class LifecycleEventEmitter extends NativeEventEmitter { currentLifecycleStatus: ?string; constructor() { super(AndroidLifecycle); this.currentLifecycleStatus = AndroidLifecycle.getConstants().initialStatus; this.addLifecycleListener((state) => { this.currentAndroidLifecycle = state; }); } - addLifecycleListener = (listener: (state: ?string) => mixed) => { + addLifecycleListener = (listener: (state: ?LifecycleState) => mixed) => { return this.addListener('LIFECYCLE_CHANGE', (event) => { listener(event.status); }); }; } let lifecycleEventEmitter; function getLifecycleEventEmitter() { if (lifecycleEventEmitter) { return lifecycleEventEmitter; } invariant( Platform.OS === 'android', 'LifecycleEventEmitter only works on Android', ); lifecycleEventEmitter = new LifecycleEventEmitter(); return lifecycleEventEmitter; } export { getLifecycleEventEmitter }; diff --git a/native/lifecycle/lifecycle-handler.react.js b/native/lifecycle/lifecycle-handler.react.js index 819a0f731..c5abcbf55 100644 --- a/native/lifecycle/lifecycle-handler.react.js +++ b/native/lifecycle/lifecycle-handler.react.js @@ -1,44 +1,45 @@ // @flow import * as React from 'react'; import { useDispatch } from 'react-redux'; -import { - backgroundActionType, - foregroundActionType, -} from 'lib/reducers/foreground-reducer'; +import { updateLifecycleStateActionType } from 'lib/reducers/foreground-reducer'; +import type { LifecycleState } from 'lib/types/lifecycle-state-types'; import { appBecameInactive } from '../redux/redux-setup'; import { addLifecycleListener } from './lifecycle'; const LifecycleHandler = React.memo<{||}>(() => { const dispatch = useDispatch(); const lastStateRef = React.useRef(); const onLifecycleChange = React.useCallback( - (nextState: ?string) => { + (nextState: ?LifecycleState) => { if (!nextState || nextState === 'unknown') { return; } const lastState = lastStateRef.current; lastStateRef.current = nextState; if (lastState === 'background' && nextState === 'active') { - dispatch({ type: foregroundActionType, payload: null }); + dispatch({ type: updateLifecycleStateActionType, payload: 'active' }); } else if (lastState !== 'background' && nextState === 'background') { - dispatch({ type: backgroundActionType, payload: null }); + dispatch({ + type: updateLifecycleStateActionType, + payload: 'background', + }); appBecameInactive(); } }, [lastStateRef, dispatch], ); React.useEffect(() => { const subscription = addLifecycleListener(onLifecycleChange); return () => subscription.remove(); }, [onLifecycleChange]); return null; }); LifecycleHandler.displayName = 'LifecycleHandler'; export default LifecycleHandler; diff --git a/native/lifecycle/lifecycle.js b/native/lifecycle/lifecycle.js index 45284cbd5..486f5333e 100644 --- a/native/lifecycle/lifecycle.js +++ b/native/lifecycle/lifecycle.js @@ -1,26 +1,28 @@ // @flow import { Platform, AppState as NativeAppState } from 'react-native'; +import { type LifecycleState } from 'lib/types/lifecycle-state-types'; + import { getLifecycleEventEmitter } from './lifecycle-event-emitter'; -function addLifecycleListener(listener: (state: ?string) => mixed) { +function addLifecycleListener(listener: (state: ?LifecycleState) => mixed) { if (Platform.OS === 'android') { return getLifecycleEventEmitter().addLifecycleListener(listener); } NativeAppState.addEventListener('change', listener); return { remove: () => { NativeAppState.removeEventListener('change', listener); }, }; } function getCurrentLifecycleState() { return Platform.OS === 'android' ? getLifecycleEventEmitter().currentLifecycleStatus : NativeAppState.currentState; } export { addLifecycleListener, getCurrentLifecycleState }; diff --git a/web/redux/visibility-handler.react.js b/web/redux/visibility-handler.react.js index eae5377a6..73afa5a32 100644 --- a/web/redux/visibility-handler.react.js +++ b/web/redux/visibility-handler.react.js @@ -1,57 +1,57 @@ // @flow import * as React from 'react'; import { useDispatch } from 'react-redux'; -import { - backgroundActionType, - foregroundActionType, -} from 'lib/reducers/foreground-reducer'; +import { updateLifecycleStateActionType } from 'lib/reducers/foreground-reducer'; import { useIsAppForegrounded } from 'lib/shared/lifecycle-utils'; import { useVisibility } from './visibility'; function VisibilityHandler() { const visibility = useVisibility(); const [visible, setVisible] = React.useState(!visibility.hidden()); const onVisibilityChange = React.useCallback((event, state: string) => { setVisible(state === 'visible'); }, []); React.useEffect(() => { const listener = visibility.change(onVisibilityChange); return () => { visibility.unbind(listener); }; }, [visibility, onVisibilityChange]); const dispatch = useDispatch(); const curForeground = useIsAppForegrounded(); const updateRedux = React.useCallback( (foreground) => { if (foreground === curForeground) { return; } if (foreground) { - dispatch({ type: foregroundActionType, payload: null }); + dispatch({ type: updateLifecycleStateActionType, payload: 'active' }); } else { - dispatch({ type: backgroundActionType, payload: null }); + dispatch({ + type: updateLifecycleStateActionType, + payload: 'background', + }); } }, [dispatch, curForeground], ); const prevVisibleRef = React.useRef(curForeground); React.useEffect(() => { const prevVisible = prevVisibleRef.current; if (visible && !prevVisible) { updateRedux(true); } else if (!visible && prevVisible) { updateRedux(false); } prevVisibleRef.current = visible; }, [visible, updateRedux]); return null; } export default VisibilityHandler;