Files
flipper/src/reducers/application.tsx
Pritesh Nandgaonkar 9ec4ef67ad Cache the text entered by the user
Summary:
This diff introduces the following improvements which I got as a feedback from the user

1) Before this diff the text entered used to vanish away when one switched tabs and came back to the support form. This diff takes care of that.
2) With this diff user can rexport the flipper trace to override the previous cached state too.
    - For this I had to update the UI to show flipper trace a separate input box, rather than appending it in the question field.
    - This avoided the the appending of the text in flipper trace and facilitated the easy override of the trace

3) With this diff one can also override commit_hash without appending multiple text.

WWW changes: D18250494, Do not land until this diff is landed.

Reviewed By: passy

Differential Revision: D18257524

fbshipit-source-id: 119edadf90ac95cb296c10520239513f1fef905d
2019-11-04 03:58:53 -08:00

394 lines
9.7 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {remote} from 'electron';
import uuidv1 from 'uuid/v1';
import {ReactElement} from 'react';
import CancellableExportStatus from '../chrome/CancellableExportStatus';
import {Actions} from './';
export const ACTIVE_SHEET_PLUGIN_SHEET: 'PLUGIN_SHEET' = 'PLUGIN_SHEET';
export const ACTIVE_SHEET_BUG_REPORTER: 'BUG_REPORTER' = 'BUG_REPORTER';
export const ACTIVE_SHEET_PLUGINS: 'PLUGINS' = 'PLUGINS';
export const ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT: 'SELECT_PLUGINS_TO_EXPORT' =
'SELECT_PLUGINS_TO_EXPORT';
export const ACTIVE_SHEET_SHARE_DATA: 'SHARE_DATA' = 'SHARE_DATA';
export const ACTIVE_SHEET_SIGN_IN: 'SIGN_IN' = 'SIGN_IN';
export const ACTIVE_SHEET_SETTINGS: 'SETTINGS' = 'SETTINGS';
export const ACTIVE_SHEET_SHARE_DATA_IN_FILE: 'SHARE_DATA_IN_FILE' =
'SHARE_DATA_IN_FILE';
export const SET_EXPORT_STATUS_MESSAGE: 'SET_EXPORT_STATUS_MESSAGE' =
'SET_EXPORT_STATUS_MESSAGE';
export const UNSET_SHARE: 'UNSET_SHARE' = 'UNSET_SHARE';
export type ActiveSheet =
| typeof ACTIVE_SHEET_PLUGIN_SHEET
| typeof ACTIVE_SHEET_BUG_REPORTER
| typeof ACTIVE_SHEET_PLUGINS
| typeof ACTIVE_SHEET_SHARE_DATA
| typeof ACTIVE_SHEET_SIGN_IN
| typeof ACTIVE_SHEET_SETTINGS
| typeof ACTIVE_SHEET_SHARE_DATA_IN_FILE
| typeof ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT
| null;
export type LauncherMsg = {
message: string;
severity: 'warning' | 'error';
};
export type ServerPorts = {
insecure: number;
secure: number;
};
export type StatusMessageType = {
msg: string;
sender: string;
};
type SubShareType =
| {
type: 'file';
file: string;
}
| {
type: 'link';
url?: string;
};
export type ShareType = {
statusComponent?: React.ReactNode;
closeOnFinish: boolean;
} & SubShareType;
export type NTUsersFormData = {
flipper_trace: string | null;
};
export type State = {
leftSidebarVisible: boolean;
rightSidebarVisible: boolean;
rightSidebarAvailable: boolean;
windowIsFocused: boolean;
activeSheet: ActiveSheet;
share: ShareType | null;
sessionId: string | null;
serverPorts: ServerPorts;
downloadingImportData: boolean;
launcherMsg: LauncherMsg;
flipperRating: number | null;
statusMessages: Array<string>;
xcodeCommandLineToolsDetected: boolean;
supportForm: {webState: NTUsersFormData} | null;
};
type BooleanActionType =
| 'leftSidebarVisible'
| 'rightSidebarVisible'
| 'rightSidebarAvailable'
| 'windowIsFocused'
| 'downloadingImportData';
export type Action =
| {
type: BooleanActionType;
payload?: boolean;
}
| {
type: 'SET_ACTIVE_SHEET';
payload: ActiveSheet;
}
| {
type: typeof ACTIVE_SHEET_SHARE_DATA_IN_FILE;
payload: {file: string; closeOnFinish: boolean};
}
| {
type: typeof ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT;
payload: ShareType;
}
| {
type: 'SET_SERVER_PORTS';
payload: {
insecure: number;
secure: number;
};
}
| {
type: 'LAUNCHER_MSG';
payload: {
severity: 'warning' | 'error';
message: string;
};
}
| {
type: 'SET_FLIPPER_RATING';
payload: {
rating: number;
};
}
| {
type: 'UNSET_SHARE';
}
| {
type: 'SET_EXPORT_STATUS_MESSAGE';
payload: React.ReactNode;
}
| {
type: 'SET_EXPORT_URL';
payload: string;
}
| {
type: 'ADD_STATUS_MSG';
payload: {msg: string; sender: string};
}
| {
type: 'REMOVE_STATUS_MSG';
payload: {msg: string; sender: string};
}
| {
type: 'SET_XCODE_DETECTED';
payload: {
isDetected: boolean;
};
}
| {
type: 'SET_SUPPORT_FORM_STATE';
payload: {
webState: NTUsersFormData;
} | null;
};
export const initialState: () => State = () => ({
leftSidebarVisible: true,
rightSidebarVisible: true,
rightSidebarAvailable: false,
windowIsFocused: remote.getCurrentWindow().isFocused(),
activeSheet: null,
share: null,
sessionId: uuidv1(),
serverPorts: {
insecure: 8089,
secure: 8088,
},
downloadingImportData: false,
launcherMsg: {
severity: 'warning',
message: '',
},
flipperRating: null,
statusMessages: [],
xcodeCommandLineToolsDetected: false,
supportForm: null,
});
function statusMessage(sender: string, msg: string): string {
const messageTrimmed = msg.trim();
const senderTrimmed = sender.trim();
let statusMessage = senderTrimmed.length > 0 ? senderTrimmed : '';
statusMessage =
statusMessage.length > 0 && messageTrimmed.length > 0
? `${statusMessage}: ${messageTrimmed}`
: '';
return statusMessage;
}
export default function reducer(
state: State | undefined,
action: Actions,
): State {
state = state || initialState();
if (
action.type === 'leftSidebarVisible' ||
action.type === 'rightSidebarVisible' ||
action.type === 'rightSidebarAvailable' ||
action.type === 'windowIsFocused' ||
action.type === 'downloadingImportData'
) {
const newValue =
typeof action.payload === 'undefined'
? !state[action.type]
: action.payload;
if (state[action.type] === newValue) {
// value hasn't changed
return state;
} else {
return {
...state,
[action.type]: newValue,
};
}
} else if (action.type === 'SET_ACTIVE_SHEET') {
return {
...state,
activeSheet: action.payload,
};
} else if (action.type === ACTIVE_SHEET_SHARE_DATA_IN_FILE) {
return {
...state,
activeSheet: ACTIVE_SHEET_SHARE_DATA_IN_FILE,
share: {
type: 'file',
file: action.payload.file,
closeOnFinish: action.payload.closeOnFinish,
},
};
} else if (action.type === ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT) {
return {
...state,
activeSheet: ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT,
share: action.payload,
};
} else if (action.type === 'SET_SERVER_PORTS') {
return {
...state,
serverPorts: action.payload,
};
} else if (action.type === 'LAUNCHER_MSG') {
return {
...state,
launcherMsg: action.payload,
};
} else if (action.type === 'SET_FLIPPER_RATING') {
return {
...state,
flipperRating: action.payload.rating,
};
} else if (action.type === 'SET_EXPORT_STATUS_MESSAGE') {
if (state.share) {
const {share} = state;
return {
...state,
share: {...share, statusComponent: action.payload},
};
}
return state;
} else if (action.type === 'UNSET_SHARE') {
return {...state, share: null};
} else if (action.type === 'SET_EXPORT_URL') {
const share = state.share;
if (share && share.type === 'link') {
return {...state, share: {...share, url: action.payload}};
}
return state;
} else if (action.type === 'ADD_STATUS_MSG') {
const {sender, msg} = action.payload;
const statusMsg = statusMessage(sender, msg);
if (statusMsg.length > 0) {
return {
...state,
statusMessages: [...state.statusMessages, statusMsg],
};
}
return state;
} else if (action.type === 'REMOVE_STATUS_MSG') {
const {sender, msg} = action.payload;
const statusMsg = statusMessage(sender, msg);
if (statusMsg.length > 0) {
const statusMessages = [...state.statusMessages];
statusMessages.splice(statusMessages.indexOf(statusMsg), 1);
return {...state, statusMessages};
}
return state;
} else if (action.type === 'SET_XCODE_DETECTED') {
return {...state, xcodeCommandLineToolsDetected: action.payload.isDetected};
} else if (action.type === 'SET_SUPPORT_FORM_STATE') {
return {...state, supportForm: action.payload};
} else {
return state;
}
}
export const toggleAction = (
type: BooleanActionType,
payload?: boolean,
): Action => ({
type,
payload,
});
export const unsetShare = (): Action => ({
type: UNSET_SHARE,
});
export const setExportStatusComponent = (
payload: ReactElement<typeof CancellableExportStatus>,
): Action => ({
type: SET_EXPORT_STATUS_MESSAGE,
payload,
});
export const setSelectPluginsToExportActiveSheet = (
payload: ShareType,
): Action => ({
type: ACTIVE_SHEET_SELECT_PLUGINS_TO_EXPORT,
payload,
});
export const setExportDataToFileActiveSheet = (payload: {
file: string;
closeOnFinish: boolean;
}): Action => ({
type: ACTIVE_SHEET_SHARE_DATA_IN_FILE,
payload: payload,
});
export const setActiveSheet = (payload: ActiveSheet): Action => ({
type: 'SET_ACTIVE_SHEET',
payload,
});
export const toggleLeftSidebarVisible = (payload?: boolean): Action => ({
type: 'leftSidebarVisible',
payload,
});
export const toggleRightSidebarVisible = (payload?: boolean): Action => ({
type: 'rightSidebarVisible',
payload,
});
export const toggleRightSidebarAvailable = (payload?: boolean): Action => ({
type: 'rightSidebarAvailable',
payload,
});
export const setFlipperRating = (rating: number): Action => ({
type: 'SET_FLIPPER_RATING',
payload: {
rating,
},
});
export const setExportURL = (result: string): Action => ({
type: 'SET_EXPORT_URL',
payload: result,
});
export const addStatusMessage = (payload: StatusMessageType): Action => ({
type: 'ADD_STATUS_MSG',
payload,
});
export const removeStatusMessage = (payload: StatusMessageType): Action => ({
type: 'REMOVE_STATUS_MSG',
payload,
});
export const setXcodeDetected = (isDetected: boolean): Action => ({
type: 'SET_XCODE_DETECTED',
payload: {isDetected},
});
export const setSupportFormState = (
payload: {webState: NTUsersFormData} | null,
): Action => ({
type: 'SET_SUPPORT_FORM_STATE',
payload,
});