Improve containers typings and add prop types

This commit is contained in:
Labhansh Agrawal 2020-02-19 21:11:29 +05:30 committed by Benjamin Staneck
parent d0ce94ce8e
commit c337288efa
5 changed files with 249 additions and 250 deletions

View file

@ -5,8 +5,7 @@ import Header from '../components/header';
import {closeTab, changeTab, maximize, openHamburgerMenu, unmaximize, minimize, close} from '../actions/header'; import {closeTab, changeTab, maximize, openHamburgerMenu, unmaximize, minimize, close} from '../actions/header';
import {connect} from '../utils/plugins'; import {connect} from '../utils/plugins';
import {getRootGroups} from '../selectors'; import {getRootGroups} from '../selectors';
import {HyperState} from '../hyper'; import {HyperState, HyperDispatch} from '../hyper';
import {Dispatch} from 'redux';
const isMac = /Mac/.test(navigator.userAgent); const isMac = /Mac/.test(navigator.userAgent);
@ -29,51 +28,53 @@ const getTabs = createSelector(
}) })
); );
export const HeaderContainer = connect( const mapStateToProps = (state: HyperState) => {
(state: HyperState) => { return {
return { // active is an index
// active is an index isMac,
isMac, tabs: getTabs(state),
tabs: getTabs(state), activeMarkers: state.ui.activityMarkers,
activeMarkers: state.ui.activityMarkers, borderColor: state.ui.borderColor,
borderColor: state.ui.borderColor, backgroundColor: state.ui.backgroundColor,
backgroundColor: state.ui.backgroundColor, maximized: state.ui.maximized,
maximized: state.ui.maximized, fullScreen: state.ui.fullScreen,
fullScreen: state.ui.fullScreen, showHamburgerMenu: state.ui.showHamburgerMenu,
showHamburgerMenu: state.ui.showHamburgerMenu, showWindowControls: state.ui.showWindowControls
showWindowControls: state.ui.showWindowControls };
}; };
},
(dispatch: Dispatch<any>) => {
return {
onCloseTab: (i: string) => {
dispatch(closeTab(i));
},
onChangeTab: (i: string) => { const mapDispatchToProps = (dispatch: HyperDispatch) => {
dispatch(changeTab(i)); return {
}, onCloseTab: (i: string) => {
dispatch(closeTab(i));
},
maximize: () => { onChangeTab: (i: string) => {
dispatch(maximize()); dispatch(changeTab(i));
}, },
unmaximize: () => { maximize: () => {
dispatch(unmaximize()); dispatch(maximize());
}, },
openHamburgerMenu: (coordinates: {x: number; y: number}) => { unmaximize: () => {
dispatch(openHamburgerMenu(coordinates)); dispatch(unmaximize());
}, },
minimize: () => { openHamburgerMenu: (coordinates: {x: number; y: number}) => {
dispatch(minimize()); dispatch(openHamburgerMenu(coordinates));
}, },
close: () => { minimize: () => {
dispatch(close()); dispatch(minimize());
} },
};
}, close: () => {
null dispatch(close());
)(Header, 'Header'); }
};
};
export const HeaderContainer = connect(mapStateToProps, mapDispatchToProps, null)(Header, 'Header');
export type HeaderConnectedProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;

View file

@ -11,12 +11,11 @@ import stylis from 'stylis';
import {HeaderContainer} from './header'; import {HeaderContainer} from './header';
import TermsContainer from './terms'; import TermsContainer from './terms';
import NotificationsContainer from './notifications'; import NotificationsContainer from './notifications';
import {HyperState} from '../hyper'; import {HyperState, HyperProps, HyperDispatch} from '../hyper';
import {Dispatch} from 'redux';
const isMac = /Mac/.test(navigator.userAgent); const isMac = /Mac/.test(navigator.userAgent);
class Hyper extends React.PureComponent<any, any> { class Hyper extends React.PureComponent<HyperProps, {lastConfigUpdate: number}> {
mousetrap!: MousetrapInstance; mousetrap!: MousetrapInstance;
terms: any; terms: any;
constructor(props: any) { constructor(props: any) {
@ -26,7 +25,7 @@ class Hyper extends React.PureComponent<any, any> {
}; };
} }
//TODO: Remove usage of legacy and soon deprecated lifecycle methods //TODO: Remove usage of legacy and soon deprecated lifecycle methods
UNSAFE_componentWillReceiveProps(next: any) { UNSAFE_componentWillReceiveProps(next: HyperProps) {
if (this.props.backgroundColor !== next.backgroundColor) { if (this.props.backgroundColor !== next.backgroundColor) {
// this can be removed when `setBackgroundColor` in electron // this can be removed when `setBackgroundColor` in electron
// starts working again // starts working again
@ -90,9 +89,9 @@ class Hyper extends React.PureComponent<any, any> {
window.focusActiveTerm = this.handleFocusActive; window.focusActiveTerm = this.handleFocusActive;
}; };
componentDidUpdate(prev: any) { componentDidUpdate(prev: HyperProps) {
if (prev.activeSession !== this.props.activeSession) { if (prev.activeSession !== this.props.activeSession) {
this.handleFocusActive(this.props.activeSession); this.handleFocusActive(this.props.activeSession!);
} }
} }
@ -147,29 +146,30 @@ class Hyper extends React.PureComponent<any, any> {
} }
} }
const HyperContainer = connect( const mapStateToProps = (state: HyperState) => {
(state: HyperState) => { return {
return { isMac,
isMac, customCSS: state.ui.css,
customCSS: state.ui.css, uiFontFamily: state.ui.uiFontFamily,
uiFontFamily: state.ui.uiFontFamily, borderColor: state.ui.borderColor,
borderColor: state.ui.borderColor, activeSession: state.sessions.activeUid,
activeSession: state.sessions.activeUid, backgroundColor: state.ui.backgroundColor,
backgroundColor: state.ui.backgroundColor, maximized: state.ui.maximized,
maximized: state.ui.maximized, fullScreen: state.ui.fullScreen,
fullScreen: state.ui.fullScreen, lastConfigUpdate: state.ui._lastUpdate
lastConfigUpdate: state.ui._lastUpdate };
}; };
},
(dispatch: Dispatch<any>) => { const mapDispatchToProps = (dispatch: HyperDispatch) => {
return { return {
execCommand: (command: any, fn: any, e: any) => { execCommand: (command: any, fn: any, e: any) => {
dispatch(uiActions.execCommand(command, fn, e)); dispatch(uiActions.execCommand(command, fn, e));
} }
}; };
}, };
null,
{forwardRef: true} const HyperContainer = connect(mapStateToProps, mapDispatchToProps, null, {forwardRef: true})(Hyper, 'Hyper');
)(Hyper, 'Hyper');
export default HyperContainer; export default HyperContainer;
export type HyperConnectedProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;

View file

@ -2,75 +2,96 @@ import Notifications from '../components/notifications';
import {installUpdate} from '../actions/updater'; import {installUpdate} from '../actions/updater';
import {connect} from '../utils/plugins'; import {connect} from '../utils/plugins';
import {dismissNotification} from '../actions/notifications'; import {dismissNotification} from '../actions/notifications';
import {HyperState} from '../hyper'; import {HyperState, HyperDispatch} from '../hyper';
import {Dispatch} from 'redux';
const NotificationsContainer = connect( const mapStateToProps = (state: HyperState) => {
(state: HyperState) => { const {ui} = state;
const {ui} = state; const {notifications} = ui;
const {notifications} = ui; let state_: Partial<{
const state_ = {}; fontShowing: boolean;
fontSize: number;
fontText: string;
resizeShowing: boolean;
cols: number | null;
rows: number | null;
updateShowing: boolean;
updateVersion: string | null;
updateNote: string | null;
updateReleaseUrl: string | null;
updateCanInstall: boolean | null;
messageShowing: boolean;
messageText: string | null;
messageURL: string | null;
messageDismissable: boolean | null;
}> = {};
if (notifications.font) { if (notifications.font) {
const fontSize = ui.fontSizeOverride || ui.fontSize; const fontSize = ui.fontSizeOverride || ui.fontSize;
Object.assign(state_, { state_ = {
fontShowing: true, ...state_,
fontSize, fontShowing: true,
fontText: `${fontSize}px` fontSize,
}); fontText: `${fontSize}px`
}
if (notifications.resize) {
const cols = ui.cols;
const rows = ui.rows;
Object.assign(state_, {
resizeShowing: true,
cols,
rows
});
}
if (notifications.updates) {
Object.assign(state_, {
updateShowing: true,
updateVersion: ui.updateVersion,
updateNote: ui.updateNotes!.split('\n')[0],
updateReleaseUrl: ui.updateReleaseUrl,
updateCanInstall: ui.updateCanInstall
});
} else if (notifications.message) {
Object.assign(state_, {
messageShowing: true,
messageText: ui.messageText,
messageURL: ui.messageURL,
messageDismissable: ui.messageDismissable
});
}
return state_;
},
(dispatch: Dispatch<any>) => {
return {
onDismissFont: () => {
dispatch(dismissNotification('font'));
},
onDismissResize: () => {
dispatch(dismissNotification('resize'));
},
onDismissUpdate: () => {
dispatch(dismissNotification('updates'));
},
onDismissMessage: () => {
dispatch(dismissNotification('message'));
},
onUpdateInstall: () => {
dispatch(installUpdate());
}
}; };
}, }
null
)(Notifications, 'Notifications'); if (notifications.resize) {
const cols = ui.cols;
const rows = ui.rows;
state_ = {
...state_,
resizeShowing: true,
cols,
rows
};
}
if (notifications.updates) {
state_ = {
...state_,
updateShowing: true,
updateVersion: ui.updateVersion,
updateNote: ui.updateNotes!.split('\n')[0],
updateReleaseUrl: ui.updateReleaseUrl,
updateCanInstall: ui.updateCanInstall
};
} else if (notifications.message) {
state_ = {
...state_,
messageShowing: true,
messageText: ui.messageText,
messageURL: ui.messageURL,
messageDismissable: ui.messageDismissable
};
}
return state_;
};
const mapDispatchToProps = (dispatch: HyperDispatch) => {
return {
onDismissFont: () => {
dispatch(dismissNotification('font'));
},
onDismissResize: () => {
dispatch(dismissNotification('resize'));
},
onDismissUpdate: () => {
dispatch(dismissNotification('updates'));
},
onDismissMessage: () => {
dispatch(dismissNotification('message'));
},
onUpdateInstall: () => {
dispatch(installUpdate());
}
};
};
const NotificationsContainer = connect(mapStateToProps, mapDispatchToProps, null)(Notifications, 'Notifications');
export default NotificationsContainer; export default NotificationsContainer;
export type NotificationsConnectedProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;

View file

@ -4,80 +4,80 @@ import {resizeSession, sendSessionData, setSessionXtermTitle, setActiveSession,
import {openContextMenu} from '../actions/ui'; import {openContextMenu} from '../actions/ui';
import {getRootGroups} from '../selectors'; import {getRootGroups} from '../selectors';
import {HyperState, TermsProps} from '../hyper'; import {HyperState, HyperDispatch} from '../hyper';
import {Dispatch} from 'redux';
const TermsContainer = connect( const mapStateToProps = (state: HyperState) => {
(state: HyperState): TermsProps => { const {sessions} = state.sessions;
const {sessions} = state.sessions; return {
return { sessions,
sessions, cols: state.ui.cols,
cols: state.ui.cols, rows: state.ui.rows,
rows: state.ui.rows, scrollback: state.ui.scrollback,
scrollback: state.ui.scrollback, termGroups: getRootGroups(state),
termGroups: getRootGroups(state), activeRootGroup: state.termGroups.activeRootGroup,
activeRootGroup: state.termGroups.activeRootGroup, activeSession: state.sessions.activeUid,
activeSession: state.sessions.activeUid, customCSS: state.ui.termCSS,
customCSS: state.ui.termCSS, write: state.sessions.write,
write: state.sessions.write, fontSize: state.ui.fontSizeOverride ? state.ui.fontSizeOverride : state.ui.fontSize,
fontSize: state.ui.fontSizeOverride ? state.ui.fontSizeOverride : state.ui.fontSize, fontFamily: state.ui.fontFamily,
fontFamily: state.ui.fontFamily, fontWeight: state.ui.fontWeight,
fontWeight: state.ui.fontWeight, fontWeightBold: state.ui.fontWeightBold,
fontWeightBold: state.ui.fontWeightBold, lineHeight: state.ui.lineHeight,
lineHeight: state.ui.lineHeight, letterSpacing: state.ui.letterSpacing,
letterSpacing: state.ui.letterSpacing, uiFontFamily: state.ui.uiFontFamily,
uiFontFamily: state.ui.uiFontFamily, fontSmoothing: state.ui.fontSmoothingOverride,
fontSmoothing: state.ui.fontSmoothingOverride, padding: state.ui.padding,
padding: state.ui.padding, cursorColor: state.ui.cursorColor,
cursorColor: state.ui.cursorColor, cursorAccentColor: state.ui.cursorAccentColor,
cursorAccentColor: state.ui.cursorAccentColor, cursorShape: state.ui.cursorShape,
cursorShape: state.ui.cursorShape, cursorBlink: state.ui.cursorBlink,
cursorBlink: state.ui.cursorBlink, borderColor: state.ui.borderColor,
borderColor: state.ui.borderColor, selectionColor: state.ui.selectionColor,
selectionColor: state.ui.selectionColor, colors: state.ui.colors,
colors: state.ui.colors, foregroundColor: state.ui.foregroundColor,
foregroundColor: state.ui.foregroundColor, backgroundColor: state.ui.backgroundColor,
backgroundColor: state.ui.backgroundColor, bell: state.ui.bell,
bell: state.ui.bell, bellSoundURL: state.ui.bellSoundURL,
bellSoundURL: state.ui.bellSoundURL, bellSound: state.ui.bellSound,
bellSound: state.ui.bellSound, copyOnSelect: state.ui.copyOnSelect,
copyOnSelect: state.ui.copyOnSelect, modifierKeys: state.ui.modifierKeys,
modifierKeys: state.ui.modifierKeys, quickEdit: state.ui.quickEdit,
quickEdit: state.ui.quickEdit, webGLRenderer: state.ui.webGLRenderer,
webGLRenderer: state.ui.webGLRenderer, macOptionSelectionMode: state.ui.macOptionSelectionMode,
macOptionSelectionMode: state.ui.macOptionSelectionMode, disableLigatures: state.ui.disableLigatures
disableLigatures: state.ui.disableLigatures };
}; };
},
(dispatch: Dispatch<any>) => {
return {
onData(uid: string, data: any) {
dispatch(sendSessionData(uid, data));
},
onTitle(uid: string, title: string) { const mapDispatchToProps = (dispatch: HyperDispatch) => {
dispatch(setSessionXtermTitle(uid, title)); return {
}, onData(uid: string, data: any) {
dispatch(sendSessionData(uid, data));
},
onResize(uid: string, cols: number, rows: number) { onTitle(uid: string, title: string) {
dispatch(resizeSession(uid, cols, rows)); dispatch(setSessionXtermTitle(uid, title));
}, },
onActive(uid: string) { onResize(uid: string, cols: number, rows: number) {
dispatch(setActiveSession(uid)); dispatch(resizeSession(uid, cols, rows));
}, },
toggleSearch(uid: string) {
dispatch(onSearch(uid));
},
onContextMenu(uid: string, selection: any) { onActive(uid: string) {
dispatch(setActiveSession(uid)); dispatch(setActiveSession(uid));
dispatch(openContextMenu(uid, selection)); },
} toggleSearch(uid: string) {
}; dispatch(onSearch(uid));
}, },
null,
{forwardRef: true} onContextMenu(uid: string, selection: any) {
)(Terms, 'Terms'); dispatch(setActiveSession(uid));
dispatch(openContextMenu(uid, selection));
}
};
};
const TermsContainer = connect(mapStateToProps, mapDispatchToProps, null, {forwardRef: true})(Terms, 'Terms');
export default TermsContainer; export default TermsContainer;
export type TermsConnectedProps = ReturnType<typeof mapStateToProps> & ReturnType<typeof mapDispatchToProps>;

57
lib/hyper.d.ts vendored
View file

@ -185,44 +185,21 @@ import configureStore from './store/configure-store';
export type HyperThunkDispatch = ThunkDispatch<HyperState, undefined, HyperActions>; export type HyperThunkDispatch = ThunkDispatch<HyperState, undefined, HyperActions>;
export type HyperDispatch = ReturnType<typeof configureStore>['dispatch']; export type HyperDispatch = ReturnType<typeof configureStore>['dispatch'];
export type TermsProps = { type extensionProps = Partial<{
activeRootGroup: string | null; customChildren: any;
activeSession: string | null; customChildrenBefore: any;
customCSS: string; customCSS: string;
fontSmoothing: string; customInnerChildren: any;
termGroups: Immutable<ITermGroup>[]; }>;
} & immutableRecord<
Pick< import {HeaderConnectedProps} from './containers/header';
uiState, export type HeaderProps = HeaderConnectedProps & extensionProps;
| 'backgroundColor'
| 'bell' import {HyperConnectedProps} from './containers/hyper';
| 'bellSound' export type HyperProps = HyperConnectedProps & extensionProps;
| 'bellSoundURL'
| 'borderColor' import {NotificationsConnectedProps} from './containers/notifications';
| 'colors' export type NotificationsProps = NotificationsConnectedProps & extensionProps;
| 'cols'
| 'copyOnSelect' import {TermsConnectedProps} from './containers/terms';
| 'cursorAccentColor' export type TermsProps = TermsConnectedProps & extensionProps & {ref_: any};
| 'cursorBlink'
| 'cursorColor'
| 'cursorShape'
| 'disableLigatures'
| 'fontFamily'
| 'fontSize'
| 'fontWeight'
| 'fontWeightBold'
| 'foregroundColor'
| 'letterSpacing'
| 'lineHeight'
| 'macOptionSelectionMode'
| 'modifierKeys'
| 'padding'
| 'quickEdit'
| 'rows'
| 'scrollback'
| 'selectionColor'
| 'uiFontFamily'
| 'webGLRenderer'
>
> &
immutableRecord<Pick<sessionState, 'sessions' | 'write'>>;