mirror of
https://github.com/quine-global/hyper.git
synced 2026-01-12 20:18:41 -09:00
Update state and reducer typings
This commit is contained in:
parent
6199f1b025
commit
aa9a50e8f9
8 changed files with 75 additions and 100 deletions
|
|
@ -11,7 +11,6 @@ import findBySession from '../utils/term-groups';
|
|||
import {getRootGroups} from '../selectors';
|
||||
import {setActiveSession, ptyExitSession, userExitSession} from './sessions';
|
||||
import {ITermState, ITermGroup, HyperState, HyperDispatch, HyperActions} from '../hyper';
|
||||
import {Immutable} from 'seamless-immutable';
|
||||
|
||||
function requestSplit(direction: 'VERTICAL' | 'HORIZONTAL') {
|
||||
return (activeUid: string) => (dispatch: HyperDispatch, getState: () => HyperState): void => {
|
||||
|
|
@ -67,7 +66,7 @@ export function setActiveGroup(uid: string) {
|
|||
// When we've found the next group which we want to
|
||||
// set as active (after closing something), we also need
|
||||
// to find the first child group which has a sessionUid.
|
||||
const findFirstSession = (state: Immutable<ITermState>, group: Immutable<ITermGroup>): string | undefined => {
|
||||
const findFirstSession = (state: ITermState, group: ITermGroup): string | undefined => {
|
||||
if (group.sessionUid) {
|
||||
return group.sessionUid;
|
||||
}
|
||||
|
|
@ -90,7 +89,7 @@ const findPrevious = <T>(list: T[], old: T) => {
|
|||
return index ? list[index - 1] : list[1];
|
||||
};
|
||||
|
||||
const findNextSessionUid = (state: Immutable<ITermState>, group: Immutable<ITermGroup>) => {
|
||||
const findNextSessionUid = (state: ITermState, group: ITermGroup) => {
|
||||
// If we're closing a root group (i.e. a whole tab),
|
||||
// the next group needs to be a root group as well:
|
||||
if (state.activeRootGroup === group.uid) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ import {
|
|||
|
||||
import {setActiveGroup} from './term-groups';
|
||||
import parseUrl from 'parse-url';
|
||||
import {HyperState, HyperDispatch, HyperActions} from '../hyper';
|
||||
import {HyperState, HyperDispatch, HyperActions, ITermGroups} from '../hyper';
|
||||
import {stat, Stats} from 'fs';
|
||||
|
||||
export function openContextMenu(uid: string, selection: any) {
|
||||
|
|
@ -110,7 +110,7 @@ export function windowGeometryUpdated(): HyperActions {
|
|||
|
||||
// Find all sessions that are below the given
|
||||
// termGroup uid in the hierarchy:
|
||||
const findChildSessions = (termGroups: HyperState['termGroups']['termGroups'], uid: string): string[] => {
|
||||
const findChildSessions = (termGroups: ITermGroups, uid: string): string[] => {
|
||||
const group = termGroups[uid];
|
||||
if (group.sessionUid) {
|
||||
return [uid];
|
||||
|
|
|
|||
38
lib/config.d.ts
vendored
38
lib/config.d.ts
vendored
|
|
@ -1,5 +1,24 @@
|
|||
import {FontWeight} from 'xterm';
|
||||
|
||||
export type ColorMap = {
|
||||
black: string;
|
||||
blue: string;
|
||||
cyan: string;
|
||||
green: string;
|
||||
lightBlack: string;
|
||||
lightBlue: string;
|
||||
lightCyan: string;
|
||||
lightGreen: string;
|
||||
lightMagenta: string;
|
||||
lightRed: string;
|
||||
lightWhite: string;
|
||||
lightYellow: string;
|
||||
magenta: string;
|
||||
red: string;
|
||||
white: string;
|
||||
yellow: string;
|
||||
};
|
||||
|
||||
export type configOptions = {
|
||||
autoUpdatePlugins: boolean | string;
|
||||
backgroundColor: string;
|
||||
|
|
@ -7,24 +26,7 @@ export type configOptions = {
|
|||
bellSound: string | null;
|
||||
bellSoundURL: string | null;
|
||||
borderColor: string;
|
||||
colors: {
|
||||
black: string;
|
||||
blue: string;
|
||||
cyan: string;
|
||||
green: string;
|
||||
lightBlack: string;
|
||||
lightBlue: string;
|
||||
lightCyan: string;
|
||||
lightGreen: string;
|
||||
lightMagenta: string;
|
||||
lightRed: string;
|
||||
lightWhite: string;
|
||||
lightYellow: string;
|
||||
magenta: string;
|
||||
red: string;
|
||||
white: string;
|
||||
yellow: string;
|
||||
};
|
||||
colors: ColorMap;
|
||||
copyOnSelect: boolean;
|
||||
css: string;
|
||||
cursorAccentColor: string;
|
||||
|
|
|
|||
69
lib/hyper.d.ts
vendored
69
lib/hyper.d.ts
vendored
|
|
@ -9,27 +9,28 @@ declare global {
|
|||
}
|
||||
}
|
||||
|
||||
export type ITermGroup = {
|
||||
export type ITermGroup = Immutable<{
|
||||
uid: string;
|
||||
sessionUid: string | null;
|
||||
parentUid: string | null;
|
||||
direction: 'HORIZONTAL' | 'VERTICAL' | null;
|
||||
sizes: number[] | null;
|
||||
children: string[];
|
||||
};
|
||||
}>;
|
||||
|
||||
export type ITermGroups = Record<string, ITermGroup>;
|
||||
export type ITermGroups = Immutable<Record<string, ITermGroup>>;
|
||||
|
||||
export type ITermState = {
|
||||
termGroups: ITermGroups;
|
||||
export type ITermState = Immutable<{
|
||||
termGroups: Mutable<ITermGroups>;
|
||||
activeSessions: Record<string, string>;
|
||||
activeRootGroup: string | null;
|
||||
};
|
||||
}>;
|
||||
|
||||
export type cursorShapes = 'BEAM' | 'UNDERLINE' | 'BLOCK';
|
||||
import {FontWeight, Terminal} from 'xterm';
|
||||
import {ColorMap} from './config';
|
||||
|
||||
export type uiState = {
|
||||
export type uiState = Immutable<{
|
||||
_lastUpdate: number | null;
|
||||
activeUid: string | null;
|
||||
activityMarkers: Record<string, boolean>;
|
||||
|
|
@ -38,24 +39,7 @@ export type uiState = {
|
|||
bellSoundURL: string | null;
|
||||
bellSound: string | null;
|
||||
borderColor: string;
|
||||
colors: {
|
||||
black: string;
|
||||
blue: string;
|
||||
cyan: string;
|
||||
green: string;
|
||||
lightBlack: string;
|
||||
lightBlue: string;
|
||||
lightCyan: string;
|
||||
lightGreen: string;
|
||||
lightMagenta: string;
|
||||
lightRed: string;
|
||||
lightWhite: string;
|
||||
lightYellow: string;
|
||||
magenta: string;
|
||||
red: string;
|
||||
white: string;
|
||||
yellow: string;
|
||||
};
|
||||
colors: ColorMap;
|
||||
cols: number | null;
|
||||
copyOnSelect: boolean;
|
||||
css: string;
|
||||
|
|
@ -107,7 +91,7 @@ export type uiState = {
|
|||
updateVersion: string | null;
|
||||
webGLRenderer: boolean;
|
||||
webLinksActivationKey: string;
|
||||
};
|
||||
}>;
|
||||
|
||||
export type session = {
|
||||
cleared: boolean;
|
||||
|
|
@ -123,22 +107,19 @@ export type session = {
|
|||
splitDirection?: 'HORIZONTAL' | 'VERTICAL';
|
||||
activeUid?: string;
|
||||
};
|
||||
export type sessionState = {
|
||||
export type sessionState = Immutable<{
|
||||
sessions: Record<string, session>;
|
||||
activeUid: string | null;
|
||||
write?: any;
|
||||
};
|
||||
}>;
|
||||
|
||||
export {ITermGroupReducer} from './reducers/term-groups';
|
||||
import {ITermGroupReducer} from './reducers/term-groups';
|
||||
export type ITermGroupReducer = Reducer<ITermState, HyperActions>;
|
||||
|
||||
export {IUiReducer} from './reducers/ui';
|
||||
import {IUiReducer} from './reducers/ui';
|
||||
export type IUiReducer = Reducer<uiState, HyperActions>;
|
||||
|
||||
export {ISessionReducer} from './reducers/sessions';
|
||||
import {ISessionReducer} from './reducers/sessions';
|
||||
export type ISessionReducer = Reducer<sessionState, HyperActions>;
|
||||
|
||||
import {Middleware} from 'redux';
|
||||
import {Middleware, Reducer} from 'redux';
|
||||
export type hyperPlugin = {
|
||||
getTabProps: any;
|
||||
getTabsProps: any;
|
||||
|
|
@ -163,9 +144,9 @@ export type hyperPlugin = {
|
|||
};
|
||||
|
||||
export type HyperState = {
|
||||
ui: Immutable<uiState>;
|
||||
sessions: Immutable<sessionState>;
|
||||
termGroups: Immutable<ITermState>;
|
||||
ui: uiState;
|
||||
sessions: sessionState;
|
||||
termGroups: ITermState;
|
||||
};
|
||||
|
||||
import {UIActions} from './constants/ui';
|
||||
|
|
@ -188,8 +169,6 @@ export type HyperActions = (
|
|||
| TabActions
|
||||
) & {effect?: () => void};
|
||||
|
||||
type immutableRecord<T> = {[k in keyof T]: Immutable<T[k]>};
|
||||
|
||||
import configureStore from './store/configure-store';
|
||||
export type HyperDispatch = ReturnType<typeof configureStore>['dispatch'];
|
||||
|
||||
|
|
@ -276,7 +255,7 @@ export type TermGroupOwnProps = {
|
|||
fontSmoothing?: string;
|
||||
parentProps: TermsProps;
|
||||
ref_: (uid: string, term: Term | null) => void;
|
||||
termGroup: Immutable<ITermGroup>;
|
||||
termGroup: ITermGroup;
|
||||
terms: Record<string, Term | null>;
|
||||
} & Pick<
|
||||
TermsProps,
|
||||
|
|
@ -336,7 +315,7 @@ export type TermProps = {
|
|||
bellSoundURL: string | null;
|
||||
borderColor: string;
|
||||
cleared: boolean;
|
||||
colors: uiState['colors'];
|
||||
colors: ColorMap;
|
||||
cols: number | null;
|
||||
copyOnSelect: boolean;
|
||||
cursorAccentColor?: string;
|
||||
|
|
@ -379,4 +358,10 @@ export type TermProps = {
|
|||
ref_: (uid: string, term: Term | null) => void;
|
||||
} & extensionProps;
|
||||
|
||||
// Utility types
|
||||
|
||||
export type Mutable<T> = T extends Immutable<infer U> ? (Exclude<U, T> extends never ? U : Exclude<U, T>) : T;
|
||||
|
||||
export type immutableRecord<T> = {[k in keyof T]: Immutable<T[k]>};
|
||||
|
||||
export type Assignable<T, U> = {[k in keyof U]: k extends keyof T ? T[k] : U[k]} & Partial<T>;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import Immutable, {Immutable as ImmutableType} from 'seamless-immutable';
|
||||
import Immutable from 'seamless-immutable';
|
||||
import {decorateSessionsReducer} from '../utils/plugins';
|
||||
import {
|
||||
SESSION_ADD,
|
||||
|
|
@ -13,10 +13,10 @@ import {
|
|||
SESSION_SEARCH,
|
||||
SESSION_SEARCH_CLOSE
|
||||
} from '../constants/sessions';
|
||||
import {sessionState, session, HyperActions} from '../hyper';
|
||||
import {sessionState, session, Mutable, ISessionReducer} from '../hyper';
|
||||
|
||||
const initialState: ImmutableType<sessionState> = Immutable({
|
||||
sessions: {} as Record<string, session>,
|
||||
const initialState: sessionState = Immutable<Mutable<sessionState>>({
|
||||
sessions: {},
|
||||
activeUid: null
|
||||
});
|
||||
|
||||
|
|
@ -35,7 +35,7 @@ function Session(obj: Immutable.DeepPartial<session>) {
|
|||
return Immutable(x).merge(obj);
|
||||
}
|
||||
|
||||
function deleteSession(state: ImmutableType<sessionState>, uid: string) {
|
||||
function deleteSession(state: sessionState, uid: string) {
|
||||
return state.updateIn(['sessions'], (sessions: typeof state['sessions']) => {
|
||||
const sessions_ = sessions.asMutable();
|
||||
delete sessions_[uid];
|
||||
|
|
@ -43,7 +43,7 @@ function deleteSession(state: ImmutableType<sessionState>, uid: string) {
|
|||
});
|
||||
}
|
||||
|
||||
const reducer = (state: ImmutableType<sessionState> = initialState, action: HyperActions) => {
|
||||
const reducer: ISessionReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case SESSION_ADD:
|
||||
return state.set('activeUid', action.uid).setIn(
|
||||
|
|
@ -134,6 +134,4 @@ const reducer = (state: ImmutableType<sessionState> = initialState, action: Hype
|
|||
}
|
||||
};
|
||||
|
||||
export type ISessionReducer = typeof reducer;
|
||||
|
||||
export default decorateSessionsReducer(reducer);
|
||||
|
|
|
|||
|
|
@ -4,17 +4,17 @@ import {TERM_GROUP_EXIT, TERM_GROUP_RESIZE} from '../constants/term-groups';
|
|||
import {SESSION_ADD, SESSION_SET_ACTIVE, SessionAddAction} from '../constants/sessions';
|
||||
import findBySession from '../utils/term-groups';
|
||||
import {decorateTermGroupsReducer} from '../utils/plugins';
|
||||
import {ITermGroup, ITermState, ITermGroups, HyperActions} from '../hyper';
|
||||
import {ITermGroup, ITermState, ITermGroups, ITermGroupReducer, Mutable} from '../hyper';
|
||||
|
||||
const MIN_SIZE = 0.05;
|
||||
const initialState = Immutable<ITermState>({
|
||||
const initialState: ITermState = Immutable<Mutable<ITermState>>({
|
||||
termGroups: {},
|
||||
activeSessions: {},
|
||||
activeRootGroup: null
|
||||
});
|
||||
|
||||
function TermGroup(obj: Immutable.DeepPartial<ITermGroup>) {
|
||||
const x: ITermGroup = {
|
||||
function TermGroup(obj: Immutable.DeepPartial<Mutable<ITermGroup>>) {
|
||||
const x: Mutable<ITermGroup> = {
|
||||
uid: '',
|
||||
sessionUid: null,
|
||||
parentUid: null,
|
||||
|
|
@ -26,7 +26,7 @@ function TermGroup(obj: Immutable.DeepPartial<ITermGroup>) {
|
|||
}
|
||||
|
||||
// Recurse upwards until we find a root term group (no parent).
|
||||
const findRootGroup = (termGroups: ImmutableType<ITermGroups>, uid: string): ImmutableType<ITermGroup> => {
|
||||
const findRootGroup = (termGroups: ITermGroups, uid: string): ITermGroup => {
|
||||
const current = termGroups[uid];
|
||||
if (!current.parentUid) {
|
||||
return current;
|
||||
|
|
@ -35,7 +35,7 @@ const findRootGroup = (termGroups: ImmutableType<ITermGroups>, uid: string): Imm
|
|||
return findRootGroup(termGroups, current.parentUid);
|
||||
};
|
||||
|
||||
const setActiveGroup = (state: ImmutableType<ITermState>, action: {uid: string}) => {
|
||||
const setActiveGroup = (state: ITermState, action: {uid: string}) => {
|
||||
if (!action.uid) {
|
||||
return state.set('activeRootGroup', null);
|
||||
}
|
||||
|
|
@ -66,7 +66,7 @@ const removalRebalance = (oldSizes: ImmutableType<number[]>, index: number) => {
|
|||
);
|
||||
};
|
||||
|
||||
const splitGroup = (state: ImmutableType<ITermState>, action: SessionAddAction) => {
|
||||
const splitGroup = (state: ITermState, action: SessionAddAction) => {
|
||||
const {splitDirection, uid, activeUid} = action;
|
||||
const activeGroup = findBySession(state, activeUid!)!;
|
||||
// If we're splitting in the same direction as the current active
|
||||
|
|
@ -132,11 +132,7 @@ const splitGroup = (state: ImmutableType<ITermState>, action: SessionAddAction)
|
|||
// Replace the parent by the given child in the tree,
|
||||
// used when we remove another child and we're left
|
||||
// with a one-to-one mapping between parent and child.
|
||||
const replaceParent = (
|
||||
state: ImmutableType<ITermState>,
|
||||
parent: ImmutableType<ITermGroup>,
|
||||
child: ImmutableType<ITermGroup>
|
||||
) => {
|
||||
const replaceParent = (state: ITermState, parent: ITermGroup, child: ITermGroup) => {
|
||||
if (parent.parentUid) {
|
||||
const parentParent = state.termGroups[parent.parentUid];
|
||||
// If the parent we're replacing has a parent,
|
||||
|
|
@ -161,7 +157,7 @@ const replaceParent = (
|
|||
.setIn(['termGroups', child.uid, 'parentUid'], parent.parentUid);
|
||||
};
|
||||
|
||||
const removeGroup = (state: ImmutableType<ITermState>, uid: string) => {
|
||||
const removeGroup = (state: ITermState, uid: string) => {
|
||||
const group = state.termGroups[uid];
|
||||
// when close tab with multiple panes, it remove group from parent to child. so maybe the parentUid exists but parent group have removed.
|
||||
// it's safe to remove the group.
|
||||
|
|
@ -188,7 +184,7 @@ const removeGroup = (state: ImmutableType<ITermState>, uid: string) => {
|
|||
.set('activeSessions', state.activeSessions.without(uid));
|
||||
};
|
||||
|
||||
const resizeGroup = (state: ImmutableType<ITermState>, uid: string, sizes: number[]) => {
|
||||
const resizeGroup = (state: ITermState, uid: string, sizes: number[]) => {
|
||||
// Make sure none of the sizes fall below MIN_SIZE:
|
||||
if (sizes.find((size) => size < MIN_SIZE)) {
|
||||
return state;
|
||||
|
|
@ -197,7 +193,7 @@ const resizeGroup = (state: ImmutableType<ITermState>, uid: string, sizes: numbe
|
|||
return state.setIn(['termGroups', uid, 'sizes'], sizes);
|
||||
};
|
||||
|
||||
const reducer = (state = initialState, action: HyperActions) => {
|
||||
const reducer: ITermGroupReducer = (state = initialState, action) => {
|
||||
switch (action.type) {
|
||||
case SESSION_ADD: {
|
||||
if (action.splitDirection) {
|
||||
|
|
@ -227,6 +223,4 @@ const reducer = (state = initialState, action: HyperActions) => {
|
|||
}
|
||||
};
|
||||
|
||||
export type ITermGroupReducer = typeof reducer;
|
||||
|
||||
export default decorateTermGroupsReducer(reducer);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import {
|
|||
SESSION_SET_CWD
|
||||
} from '../constants/sessions';
|
||||
import {UPDATE_AVAILABLE} from '../constants/updater';
|
||||
import {uiState, HyperActions} from '../hyper';
|
||||
import {uiState, Mutable, IUiReducer} from '../hyper';
|
||||
|
||||
const allowedCursorShapes = new Set(['BEAM', 'BLOCK', 'UNDERLINE']);
|
||||
const allowedCursorBlinkValues = new Set([true, false]);
|
||||
|
|
@ -33,7 +33,7 @@ const allowedHamburgerMenuValues = new Set([true, false]);
|
|||
const allowedWindowControlsValues = new Set([true, false, 'left']);
|
||||
|
||||
// Populate `config-default.js` from this :)
|
||||
const initial: ImmutableType<uiState> = Immutable({
|
||||
const initial: uiState = Immutable<Mutable<uiState>>({
|
||||
cols: null,
|
||||
rows: null,
|
||||
scrollback: 1000,
|
||||
|
|
@ -57,7 +57,7 @@ const initial: ImmutableType<uiState> = Immutable({
|
|||
letterSpacing: 0,
|
||||
css: '',
|
||||
termCSS: '',
|
||||
openAt: {} as Record<string, number>,
|
||||
openAt: {},
|
||||
resizeAt: 0,
|
||||
colors: {
|
||||
black: '#000000',
|
||||
|
|
@ -77,7 +77,7 @@ const initial: ImmutableType<uiState> = Immutable({
|
|||
lightCyan: '#68FDFE',
|
||||
lightWhite: '#FFFFFF'
|
||||
},
|
||||
activityMarkers: {} as Record<string, boolean>,
|
||||
activityMarkers: {},
|
||||
notifications: {
|
||||
font: false,
|
||||
resize: false,
|
||||
|
|
@ -115,7 +115,7 @@ const initial: ImmutableType<uiState> = Immutable({
|
|||
|
||||
const currentWindow = remote.getCurrentWindow();
|
||||
|
||||
const reducer = (state = initial, action: HyperActions) => {
|
||||
const reducer: IUiReducer = (state = initial, action) => {
|
||||
let state_ = state;
|
||||
let isMax;
|
||||
switch (action.type) {
|
||||
|
|
@ -127,7 +127,7 @@ const reducer = (state = initial, action: HyperActions) => {
|
|||
// font size changed from the config
|
||||
.merge(
|
||||
(() => {
|
||||
const ret: Immutable.DeepPartial<uiState> = {};
|
||||
const ret: Immutable.DeepPartial<Mutable<uiState>> = {};
|
||||
|
||||
if (config.scrollback) {
|
||||
ret.scrollback = config.scrollback;
|
||||
|
|
@ -452,6 +452,4 @@ const reducer = (state = initial, action: HyperActions) => {
|
|||
return state_;
|
||||
};
|
||||
|
||||
export type IUiReducer = typeof reducer;
|
||||
|
||||
export default decorateUIReducer(reducer);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import {ITermState} from '../hyper';
|
||||
import {Immutable} from 'seamless-immutable';
|
||||
|
||||
export default function findBySession(termGroupState: Immutable<ITermState>, sessionUid: string) {
|
||||
export default function findBySession(termGroupState: ITermState, sessionUid: string) {
|
||||
const {termGroups} = termGroupState;
|
||||
return Object.keys(termGroups)
|
||||
.map((uid) => termGroups[uid])
|
||||
|
|
|
|||
Loading…
Reference in a new issue