Skip to content

Commit f83b86b

Browse files
feat: Migrate Redux to TS (#6655)
* feat: migrate to ts components * fixes * working changes * fix type errors * fix react import * Migrate to TS * CR Fixes * CR Fixes * feat: migrate lib js files to ts * CR Fixes * CR Fixes * revert changes * feat: Migrate Redux to TS * remove unecessary code * prepare * fix tests * remove coverage test * CR Changes * fixes * fix * fixes * fixes * fix tests * fix switching webview * fixes * lint fixes * logs tests * temporary fix * temporary fix * looking for issue * fixes * test custom variables * rename variables * fix * fixes * checking different tsconfig * fix: Make sure env is setup * persistToFile * change app name * remove extra fix * change app name * fixes? * fixes? * fixes * restore package.json * prepare tsconfig for build and development * eslint fix * remove unecessary comments, add bin to exclude * build fixes * revert files in tsconfig * CR Changes --------- Co-authored-by: Amir Ghezelbash <[email protected]>
1 parent d401eb3 commit f83b86b

34 files changed

+615
-412
lines changed

.eslintrc.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
}
1616
],
1717
"parserOptions": {
18-
"project": ["./tsconfig.json", "./tsconfig.bin.json", "./tsconfig.mocha.json"]
18+
"project": ["./tsconfig.json", "./tsconfig.mocha.json", "./tsconfig.bin.json"]
1919
},
2020
"plugins": ["jasmine"],
2121
"rules": {

electron/renderer/src/actions/AccountAction.js electron/renderer/src/actions/AccountAction.ts

+31-10
Original file line numberDiff line numberDiff line change
@@ -19,42 +19,58 @@
1919

2020
import {EVENT_TYPE} from '../../../src/lib/eventType';
2121
import {config} from '../../../src/settings/config';
22+
import {AppDispatch, State} from '../index';
23+
import {SwitchAccount} from '../reducers/accountReducer';
2224
import {AccountSelector} from '../selector/AccountSelector';
2325

24-
import {ActionType, initiateSSO} from './';
26+
import {ACCOUNT_ACTION, initiateSSO} from './index';
27+
28+
type WebviewTag = Electron.WebviewTag;
2529

2630
/**
2731
* Don't use this method directly, use `switchWebview` instead.
2832
*
2933
* @param {string} id - Account ID
30-
* @returns {{id: string, type: ActionType.SWITCH_ACCOUNT}} - Account switch action
34+
* @returns {{id: string, type: ACCOUNT_ACTION.SWITCH_ACCOUNT}} - Account switch action
3135
*/
32-
export const switchAccount = id => ({
36+
export const switchAccount = (id: string): SwitchAccount => ({
3337
id,
34-
type: ActionType.SWITCH_ACCOUNT,
38+
type: ACCOUNT_ACTION.SWITCH_ACCOUNT,
3539
});
3640

41+
export type AccountActionTypes = {
42+
startSSO: (ssoCode: string) => void;
43+
switchWebview: (accountIndex: number) => Promise<void>;
44+
};
45+
3746
export class AccountAction {
38-
startSSO = ssoCode => {
39-
return async (dispatch, getState, {actions: {accountAction}}) => {
47+
startSSO = (ssoCode: string) => {
48+
return async (
49+
dispatch: AppDispatch,
50+
getState: () => State,
51+
{actions: {accountAction}}: {actions: {accountAction: AccountActionTypes}},
52+
) => {
4053
try {
4154
const accounts = AccountSelector.getAccounts(getState());
4255
const loggedOutWebviews = accounts.filter(account => account.userID === undefined);
4356

4457
if (loggedOutWebviews.length > 0) {
58+
// @ts-ignore
4559
dispatch(accountAction.switchWebview(accounts.indexOf(loggedOutWebviews[0])));
4660

4761
const accountId = loggedOutWebviews[0].id;
4862
dispatch(initiateSSO(accountId, ssoCode, accounts.length == 1));
4963
} else {
5064
if (accounts.length >= config.maximumAccounts) {
51-
return window.dispatchEvent(
65+
window.dispatchEvent(
5266
new CustomEvent(EVENT_TYPE.ACTION.CREATE_SSO_ACCOUNT_RESPONSE, {
5367
detail: {
5468
reachedMaximumAccounts: true,
5569
},
5670
}),
5771
);
72+
73+
return;
5874
}
5975
// All accounts are logged in, create a new one
6076
dispatch(initiateSSO(undefined, ssoCode, true));
@@ -66,17 +82,22 @@ export class AccountAction {
6682
};
6783
};
6884

69-
switchWebview = accountIndex => {
70-
return async (dispatch, getState) => {
85+
switchWebview = (accountIndex: number) => {
86+
return async (dispatch: AppDispatch, getState: () => State) => {
7187
const account = AccountSelector.getAccounts(getState())[Math.max(accountIndex, 0)];
88+
89+
if (!account.id) {
90+
return;
91+
}
92+
7293
dispatch(switchAccount(account.id));
7394

7495
// Note: We need to focus window first to properly set focus
7596
// on the webview with shortcuts like Cmd+1/2/3
7697
window.blur();
7798
window.focus();
7899

79-
const webview = document.querySelector(`.Webview[data-accountid='${account.id}']`);
100+
const webview = document.querySelector(`.Webview[data-accountid='${account.id}']`) as WebviewTag;
80101
if (webview) {
81102
webview.blur();
82103
webview.focus();

electron/renderer/src/actions/__tests__/actions.spec.js electron/renderer/src/actions/__tests__/actions.spec.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717
*
1818
*/
1919

20-
import {ActionType, addAccount, deleteAccount, updateAccount, updateAccountBadge} from '../';
20+
import {ACCOUNT_ACTION, addAccount, deleteAccount, updateAccount, updateAccountBadge} from '../';
2121
import {generateUUID} from '../../lib/util';
2222
import {switchAccount} from '../AccountAction';
2323

2424
describe('action creators', () => {
2525
describe('addAccount', () => {
2626
it('should create action to add account with session', () => {
2727
const action = addAccount();
28-
expect(action.type).toEqual(ActionType.ADD_ACCOUNT);
28+
expect(action.type).toEqual(ACCOUNT_ACTION.ADD_ACCOUNT);
2929
expect(action.sessionID).toEqual(expect.any(String));
3030
});
3131
});
@@ -37,7 +37,7 @@ describe('action creators', () => {
3737
const action = {
3838
data,
3939
id,
40-
type: ActionType.UPDATE_ACCOUNT,
40+
type: ACCOUNT_ACTION.UPDATE_ACCOUNT,
4141
};
4242
expect(updateAccount(id, data)).toEqual(action);
4343
});
@@ -48,7 +48,7 @@ describe('action creators', () => {
4848
const id = generateUUID();
4949
const action = {
5050
id,
51-
type: ActionType.SWITCH_ACCOUNT,
51+
type: ACCOUNT_ACTION.SWITCH_ACCOUNT,
5252
};
5353
expect(switchAccount(id)).toEqual(action);
5454
});
@@ -61,7 +61,7 @@ describe('action creators', () => {
6161
const action = {
6262
count,
6363
id,
64-
type: ActionType.UPDATE_ACCOUNT_BADGE,
64+
type: ACCOUNT_ACTION.UPDATE_ACCOUNT_BADGE,
6565
};
6666
expect(updateAccountBadge(id, count)).toEqual(action);
6767
});
@@ -72,7 +72,7 @@ describe('action creators', () => {
7272
const id = generateUUID();
7373
const action = {
7474
id,
75-
type: ActionType.DELETE_ACCOUNT,
75+
type: ACCOUNT_ACTION.DELETE_ACCOUNT,
7676
};
7777
expect(deleteAccount(id)).toEqual(action);
7878
});

electron/renderer/src/actions/index.js electron/renderer/src/actions/index.ts

+72-57
Original file line numberDiff line numberDiff line change
@@ -21,98 +21,107 @@ import * as Joi from '@hapi/joi';
2121

2222
import {Availability} from '@wireapp/protocol-messaging';
2323

24-
import {accountAction} from './AccountAction';
24+
import {AccountAction, accountAction} from './AccountAction';
2525

26+
import {AppDispatch, State} from '../index';
2627
import {generateUUID} from '../lib/util';
28+
import {
29+
AddAccount,
30+
DeleteAccount,
31+
InitiateSSO,
32+
ResetIdentity,
33+
SetConversationJoinData,
34+
UpdateAccount,
35+
UpdateAccountBadge,
36+
UpdateAccountDarkMode,
37+
UpdateAccountLifeCycle,
38+
} from '../reducers/accountReducer';
39+
import {HideContextMenus, ToggleEditAccountVisibility} from '../reducers/contextMenuReducer';
2740
import {AccountSelector} from '../selector/AccountSelector';
28-
29-
export const ActionType = {
30-
ADD_ACCOUNT: 'ADD_ACCOUNT',
31-
DELETE_ACCOUNT: 'DELETE_ACCOUNT',
32-
HIDE_CONTEXT_MENUS: 'HIDE_CONTEXT_MENUS',
33-
INITIATE_SSO: 'INITIATE_SSO',
34-
RESET_IDENTITY: 'RESET_IDENTITY',
35-
SET_CONVERSATION_JOIN_DATA: 'SET_CONVERSATION_JOIN_DATA',
36-
SWITCH_ACCOUNT: 'SWITCH_ACCOUNT',
37-
TOGGLE_ADD_ACCOUNT_VISIBILITY: 'TOGGLE_ADD_ACCOUNT_VISIBILITY',
38-
TOGGLE_EDIT_ACCOUNT_VISIBILITY: 'TOGGLE_EDIT_ACCOUNT_VISIBILITY',
39-
UPDATE_ACCOUNT: 'UPDATE_ACCOUNT',
40-
UPDATE_ACCOUNT_BADGE: 'UPDATE_ACCOUNT_BADGE',
41-
UPDATE_ACCOUNT_DARK_MODE: 'UPDATE_ACCOUNT_DARK_MODE',
42-
UPDATE_ACCOUNT_LIFECYCLE: 'UPDATE_ACCOUNT_LIFECYCLE',
43-
};
44-
45-
export const addAccount = (withSession = true) => ({
41+
import {Account, ConversationJoinData} from '../types/account';
42+
import {ContextMenuState} from '../types/contextMenuState';
43+
44+
export enum ACCOUNT_ACTION {
45+
ADD_ACCOUNT = 'ADD_ACCOUNT',
46+
DELETE_ACCOUNT = 'DELETE_ACCOUNT',
47+
HIDE_CONTEXT_MENUS = 'HIDE_CONTEXT_MENUS',
48+
INITIATE_SSO = 'INITIATE_SSO',
49+
RESET_IDENTITY = 'RESET_IDENTITY',
50+
SET_CONVERSATION_JOIN_DATA = 'SET_CONVERSATION_JOIN_DATA',
51+
SWITCH_ACCOUNT = 'SWITCH_ACCOUNT',
52+
TOGGLE_ADD_ACCOUNT_VISIBILITY = 'TOGGLE_ADD_ACCOUNT_VISIBILITY',
53+
TOGGLE_EDIT_ACCOUNT_VISIBILITY = 'TOGGLE_EDIT_ACCOUNT_VISIBILITY',
54+
UPDATE_ACCOUNT = 'UPDATE_ACCOUNT',
55+
UPDATE_ACCOUNT_BADGE = 'UPDATE_ACCOUNT_BADGE',
56+
UPDATE_ACCOUNT_DARK_MODE = 'UPDATE_ACCOUNT_DARK_MODE',
57+
UPDATE_ACCOUNT_LIFECYCLE = 'UPDATE_ACCOUNT_LIFECYCLE',
58+
}
59+
60+
export const addAccount = (withSession = true): AddAccount => ({
4661
sessionID: withSession ? generateUUID() : undefined,
47-
type: ActionType.ADD_ACCOUNT,
62+
type: ACCOUNT_ACTION.ADD_ACCOUNT,
4863
});
4964

50-
export const initiateSSO = (id, ssoCode = undefined, withSession = true) => ({
65+
export const initiateSSO = (id: string | undefined, ssoCode: string, withSession = true): InitiateSSO => ({
5166
id,
5267
sessionID: withSession ? generateUUID() : undefined,
5368
ssoCode,
54-
type: ActionType.INITIATE_SSO,
69+
type: ACCOUNT_ACTION.INITIATE_SSO,
5570
});
5671

57-
export const deleteAccount = id => ({
72+
export const deleteAccount = (id: string): DeleteAccount => ({
5873
id,
59-
type: ActionType.DELETE_ACCOUNT,
74+
type: ACCOUNT_ACTION.DELETE_ACCOUNT,
6075
});
6176

62-
export const resetIdentity = id => ({
77+
export const resetIdentity = (id: string): ResetIdentity => ({
6378
id,
64-
type: ActionType.RESET_IDENTITY,
79+
type: ACCOUNT_ACTION.RESET_IDENTITY,
6580
});
6681

67-
export const updateAccount = (id, data) => ({
82+
export const updateAccount = (id: string, data: Partial<Account>): UpdateAccount => ({
6883
data,
6984
id,
70-
type: ActionType.UPDATE_ACCOUNT,
85+
type: ACCOUNT_ACTION.UPDATE_ACCOUNT,
7186
});
7287

73-
export const updateAccountLifecycle = (id, channel) => {
88+
export const updateAccountLifecycle = (id: string, channel: string): UpdateAccountLifeCycle => {
7489
return {
75-
data: channel,
90+
channel,
7691
id,
77-
type: ActionType.UPDATE_ACCOUNT_LIFECYCLE,
92+
type: ACCOUNT_ACTION.UPDATE_ACCOUNT_LIFECYCLE,
7893
};
7994
};
8095

81-
export const setConversationJoinData = (id, data) => ({
96+
export const setConversationJoinData = (id: string, data?: ConversationJoinData): SetConversationJoinData => ({
8297
data,
8398
id,
84-
type: ActionType.SET_CONVERSATION_JOIN_DATA,
99+
type: ACCOUNT_ACTION.SET_CONVERSATION_JOIN_DATA,
85100
});
86101

87-
export const updateAccountBadge = (id, count) => ({
102+
export const updateAccountBadge = (id: string, count: number): UpdateAccountBadge => ({
88103
count,
89104
id,
90-
type: ActionType.UPDATE_ACCOUNT_BADGE,
105+
type: ACCOUNT_ACTION.UPDATE_ACCOUNT_BADGE,
91106
});
92107

93-
export const updateAccountDarkMode = (id, darkMode) => ({
108+
export const updateAccountDarkMode = (id: string, darkMode: boolean): UpdateAccountDarkMode => ({
94109
darkMode,
95110
id,
96-
type: ActionType.UPDATE_ACCOUNT_DARK_MODE,
111+
type: ACCOUNT_ACTION.UPDATE_ACCOUNT_DARK_MODE,
97112
});
98113

99-
export const setAccountContextHidden = () => ({
100-
type: ActionType.HIDE_CONTEXT_MENUS,
114+
export const setAccountContextHidden = (): HideContextMenus => ({
115+
type: ACCOUNT_ACTION.HIDE_CONTEXT_MENUS,
101116
});
102117

103-
export const toggleEditAccountMenuVisibility = (centerX, centerY, accountId, sessionId, lifecycle, isAtLeastAdmin) => ({
104-
payload: {
105-
accountId,
106-
isAtLeastAdmin,
107-
lifecycle,
108-
position: {centerX, centerY},
109-
sessionId,
110-
},
111-
type: ActionType.TOGGLE_EDIT_ACCOUNT_VISIBILITY,
118+
export const toggleEditAccountMenuVisibility = (payload: ContextMenuState): ToggleEditAccountVisibility => ({
119+
payload,
120+
type: ACCOUNT_ACTION.TOGGLE_EDIT_ACCOUNT_VISIBILITY,
112121
});
113122

114-
export const abortAccountCreation = id => {
115-
return (dispatch, getState) => {
123+
export const abortAccountCreation = (id: string) => {
124+
return (dispatch: AppDispatch, getState: () => State) => {
116125
// Note: It's not guaranteed that the dispatched action "deleteAccount" generates a new state without the deleted account
117126
const accounts = AccountSelector.getAccounts(getState()).filter(account => account.id !== id);
118127
const lastAccount = accounts[accounts.length - 1];
@@ -121,6 +130,7 @@ export const abortAccountCreation = id => {
121130

122131
if (lastAccount) {
123132
const accountIndex = AccountSelector.getAccountIndex(getState(), lastAccount.id);
133+
// @ts-ignore
124134
dispatch(accountAction.switchWebview(accountIndex));
125135
} else {
126136
dispatch(addAccount(false));
@@ -129,12 +139,13 @@ export const abortAccountCreation = id => {
129139
};
130140

131141
export const addAccountWithSession = () => {
132-
return (dispatch, getState) => {
142+
return (dispatch: AppDispatch, getState: () => State) => {
133143
const hasReachedAccountLimit = AccountSelector.hasReachedLimitOfAccounts(getState());
134144
const unboundAccount = AccountSelector.getUnboundAccount(getState());
135145

136146
if (!!unboundAccount) {
137147
const unboundAccountIndex = AccountSelector.getAccountIndex(getState(), unboundAccount.id);
148+
// @ts-ignore
138149
dispatch(accountAction.switchWebview(unboundAccountIndex));
139150
return;
140151
}
@@ -147,7 +158,7 @@ export const addAccountWithSession = () => {
147158
};
148159
};
149160

150-
export const updateAccountData = (id, data) => {
161+
export const updateAccountData = (id: string, data: Partial<Account>) => {
151162
const accountDataSchema = Joi.object({
152163
accentID: Joi.number(),
153164
availability: Joi.number().optional(),
@@ -160,7 +171,7 @@ export const updateAccountData = (id, data) => {
160171
webappUrl: Joi.string(),
161172
}).unknown(true);
162173

163-
return dispatch => {
174+
return (dispatch: AppDispatch) => {
164175
const validatedAccountData = accountDataSchema.validate(data);
165176

166177
if (!validatedAccountData.error) {
@@ -171,14 +182,14 @@ export const updateAccountData = (id, data) => {
171182
};
172183
};
173184

174-
export const updateAccountBadgeCount = (id, count) => {
175-
return (dispatch, getState) => {
185+
export const updateAccountBadgeCount = (id: string, count: number) => {
186+
return (dispatch: AppDispatch, getState: () => State) => {
176187
const accounts = getState().accounts;
177188
const account = getState().accounts.find(acc => acc.id === id);
178189
const accumulatedCount = accounts.reduce((accumulated, account) => {
179190
return accumulated + (account.id === id ? count : account.badgeCount);
180191
}, 0);
181-
const ignoreFlash = account.availability === Availability.Type.BUSY;
192+
const ignoreFlash = account?.availability === Availability.Type.BUSY;
182193

183194
window.sendBadgeCount(accumulatedCount, ignoreFlash);
184195

@@ -193,7 +204,11 @@ export const updateAccountBadgeCount = (id, count) => {
193204
};
194205
};
195206

196-
const actionRoot = {
207+
export interface ActionRoot {
208+
accountAction: AccountAction;
209+
}
210+
211+
const actionRoot: ActionRoot = {
197212
accountAction,
198213
};
199214

0 commit comments

Comments
 (0)