Skip to content

Commit 62393f7

Browse files
feat: Migration to TS Components (#6700)
* feat: migrate to ts components * fixes * working changes * fix type errors * fix react import * Migrate to TS * CR Fixes * CR Fixes * CR Fixes * fix tests * remove coverage test * CR Changes * feat: Migration to TS Components * test fixes * lint fix * build fix * add allowpopups value --------- Co-authored-by: Amir Ghezelbash <[email protected]>
1 parent 584044b commit 62393f7

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+607
-293
lines changed

.eslintrc.json

+14-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@
2121
"rules": {
2222
"import/no-default-export": "off",
2323
"no-magic-numbers": "off",
24-
"no-undef": "off"
24+
"no-undef": "off",
25+
"jest/expect-expect": [
26+
"error",
27+
{
28+
"assertFunctionNames": ["expect", "fc.assert", "assert"]
29+
}
30+
]
31+
},
32+
"settings": {
33+
"import/resolver": {
34+
"node": {
35+
"extensions": [".js", ".jsx", ".ts", ".tsx"]
36+
}
37+
}
2538
}
2639
}

babel.config.js babel.config.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ const buildPresets = ({debug = false, modules = false}) => {
3939
},
4040
];
4141

42-
return ['@babel/preset-react', '@babel/preset-typescript', browserEnvPreset];
42+
return [['@babel/preset-react', {runtime: 'automatic'}], '@babel/preset-typescript', browserEnvPreset];
4343
};
4444

4545
/** @type {import('@babel/core').TransformOptions} */

bin/build-tools/build-cli.ts

-7
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,6 @@ import {buildMacOSConfig, buildMacOSWrapper} from './lib/build-macos';
2727
import {buildWindowsConfig, buildWindowsWrapper} from './lib/build-windows';
2828
import {buildWindowsInstaller, buildWindowsInstallerConfig} from './lib/build-windows-installer';
2929

30-
interface CommanderData {
31-
envFile: string;
32-
manualSign?: boolean;
33-
packageJson: string;
34-
wireJson: string;
35-
}
36-
3730
const toolName = path.basename(__filename).replace('.ts', '');
3831
const logger = LogFactory.getLogger(toolName, {forceEnable: true, namespace: '@wireapp/build-tools'});
3932
const appSource = path.join(__dirname, '../../');

electron/renderer/src/actions/AccountAction.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
*
1818
*/
1919

20-
import {EVENT_TYPE} from '../../../dist/lib/eventType';
21-
import {config} from '../../../dist/settings/config';
20+
import {EVENT_TYPE} from '../../../src/lib/eventType';
21+
import {config} from '../../../src/settings/config';
2222
import {AccountSelector} from '../selector/AccountSelector';
2323

2424
import {ActionType, initiateSSO} from './';

electron/renderer/src/actions/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export const deleteAccount = id => ({
5959
type: ActionType.DELETE_ACCOUNT,
6060
});
6161

62-
export const resetIdentity = (id = true) => ({
62+
export const resetIdentity = id => ({
6363
id,
6464
type: ActionType.RESET_IDENTITY,
6565
});

electron/renderer/src/components/AccountIcon.jsx electron/renderer/src/components/AccountIcon/AccountIcon.tsx

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

20-
import React from 'react';
21-
22-
import PropTypes from 'prop-types';
23-
2420
import './AccountIcon.css';
2521

26-
import {colorFromId} from '../lib/accentColor';
22+
import {colorFromId} from '../../lib/accentColor';
23+
import {Account} from '../../types/account';
2724

28-
const AccountIcon = ({account, ...props}) => {
25+
interface AccountIconProps {
26+
account: Account;
27+
}
28+
29+
export const AccountIcon = ({account, ...props}: AccountIconProps) => {
2930
const accountType = () => {
3031
if (!account.name) {
3132
return 'new';
@@ -49,6 +50,7 @@ const AccountIcon = ({account, ...props}) => {
4950
style={{borderColor: colorFromId(account.accentID)}}
5051
/>
5152
)}
53+
5254
<div className="AccountIcon-inner">
5355
{account.picture ? (
5456
<img src={account.picture} alt="Account Icon" />
@@ -59,9 +61,3 @@ const AccountIcon = ({account, ...props}) => {
5961
</div>
6062
);
6163
};
62-
63-
AccountIcon.propTypes = {
64-
account: PropTypes.object.isRequired,
65-
};
66-
67-
export default AccountIcon;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Wire
3+
* Copyright (C) 2023 Wire Swiss GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/.
17+
*
18+
*/
19+
20+
export * from './AccountIcon';

electron/renderer/src/components/App.jsx electron/renderer/src/components/App/App.tsx

+7-10
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,19 @@
1717
*
1818
*/
1919

20-
import React from 'react';
21-
2220
import {connect} from 'react-redux';
2321

24-
import {StyledApp} from '@wireapp/react-ui-kit';
25-
26-
import IsOnline from './IsOnline';
27-
import Sidebar from './Sidebar';
28-
import WebviewList from './WebviewList';
22+
import {StyledApp, THEME_ID} from '@wireapp/react-ui-kit';
2923

30-
import actionRoot from '../actions';
31-
import {AccountSelector} from '../selector/AccountSelector';
24+
import actionRoot from '../../actions';
25+
import {AccountSelector} from '../../selector/AccountSelector';
26+
import {IsOnline} from '../IsOnline';
27+
import Sidebar from '../Sidebar/Sidebar';
28+
import WebviewList from '../WebViewList/WebviewList';
3229

3330
const App = () => {
3431
return (
35-
<StyledApp style={{height: '100%'}}>
32+
<StyledApp style={{height: '100%'}} themeId={THEME_ID.DEFAULT}>
3633
<IsOnline>
3734
<div style={{display: 'flex', height: '100%', width: '100%'}}>
3835
<Sidebar />

electron/renderer/src/components/IsOnline.jsx electron/renderer/src/components/IsOnline/IsOnline.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@
1717
*
1818
*/
1919

20-
import React, {useEffect, useState} from 'react';
20+
import {useEffect, useState, ReactElement} from 'react';
2121

2222
import {Text, ContainerSM} from '@wireapp/react-ui-kit';
2323

24-
import {getText} from '../lib/locale';
24+
import {getText} from '../../lib/locale';
2525

26-
const IsOnline = ({children}) => {
26+
interface IsOnlineProps {
27+
children: ReactElement;
28+
}
29+
30+
export const IsOnline = ({children}: IsOnlineProps) => {
2731
const [isOnline, setIsOnline] = useState(navigator.onLine);
2832

2933
useEffect(() => {
@@ -46,5 +50,3 @@ const IsOnline = ({children}) => {
4650
</div>
4751
);
4852
};
49-
50-
export default IsOnline;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Wire
3+
* Copyright (C) 2023 Wire Swiss GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/.
17+
*
18+
*/
19+
20+
export * from './IsOnline';

electron/renderer/src/components/LoadingSpinner.jsx electron/renderer/src/components/LoadingSpinner/LoadingSpinner.tsx

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

20-
import React, {useEffect, useState} from 'react';
20+
import {useEffect, useState, MutableRefObject} from 'react';
2121

2222
import {FlexBox, Loading, COLOR} from '@wireapp/react-ui-kit';
2323

2424
import './LoadingSpinner.css';
2525

26+
type WebviewTag = Electron.WebviewTag;
27+
2628
const TRANSITION_GRACE_PERIOD_MS = 500;
2729

28-
const LoadingSpinner = ({visible, webviewRef}) => {
30+
interface LoadingSpinnerProps {
31+
visible: boolean;
32+
webviewRef: MutableRefObject<WebviewTag | null>;
33+
}
34+
35+
export const LoadingSpinner = ({visible, webviewRef}: LoadingSpinnerProps) => {
2936
const [isLoading, setIsLoading] = useState(true);
3037
const [isFinished, setIsFinished] = useState(false);
3138

@@ -39,11 +46,13 @@ const LoadingSpinner = ({visible, webviewRef}) => {
3946
webview.removeEventListener('did-finish-load', setLoading);
4047
};
4148
}
49+
50+
return () => undefined;
4251
});
4352

4453
useEffect(() => {
4554
if (!isLoading) {
46-
let timeout = setTimeout(() => {
55+
let timeout: NodeJS.Timeout | null = setTimeout(() => {
4756
timeout = null;
4857
setIsFinished(true);
4958
}, TRANSITION_GRACE_PERIOD_MS);
@@ -54,6 +63,8 @@ const LoadingSpinner = ({visible, webviewRef}) => {
5463
}
5564
};
5665
}
66+
67+
return () => undefined;
5768
}, [isLoading]);
5869

5970
if (!visible || isFinished) {
@@ -75,5 +86,3 @@ const LoadingSpinner = ({visible, webviewRef}) => {
7586
</div>
7687
);
7788
};
78-
79-
export default LoadingSpinner;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* Wire
3+
* Copyright (C) 2023 Wire Swiss GmbH
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see http://www.gnu.org/licenses/.
17+
*
18+
*/
19+
20+
export * from './LoadingSpinner';

electron/renderer/src/components/Sidebar.jsx electron/renderer/src/components/Sidebar/Sidebar.tsx

+41-15
Original file line numberDiff line numberDiff line change
@@ -21,36 +21,57 @@ import React from 'react';
2121

2222
import {connect} from 'react-redux';
2323

24-
import AccountIcon from './AccountIcon';
25-
import AddAccountTrigger from './context/AddAccountTrigger';
26-
import EditAccountMenu from './context/EditAccountMenu';
2724
import './Sidebar.css';
2825

29-
import {EVENT_TYPE} from '../../../dist/lib/eventType';
30-
import {addAccountWithSession, setAccountContextHidden, toggleEditAccountMenuVisibility} from '../actions';
31-
import {colorFromId} from '../lib/accentColor';
32-
import {isEnterKey} from '../lib/keyboardUtil';
33-
import {preventFocus} from '../lib/util';
34-
import {AccountSelector} from '../selector/AccountSelector';
35-
import {ContextMenuSelector} from '../selector/ContextMenuSelector';
26+
import {EVENT_TYPE} from '../../../../src/lib/eventType';
27+
import {addAccountWithSession, setAccountContextHidden, toggleEditAccountMenuVisibility} from '../../actions';
28+
import {colorFromId} from '../../lib/accentColor';
29+
import {isEnterKey} from '../../lib/keyboardUtil';
30+
import {preventFocus} from '../../lib/util';
31+
import {AccountSelector} from '../../selector/AccountSelector';
32+
import {ContextMenuSelector} from '../../selector/ContextMenuSelector';
33+
import {Account} from '../../types/account';
34+
import {AccountIcon} from '../AccountIcon';
35+
import AddAccountTrigger from '../context/AddAccountTrigger';
36+
import EditAccountMenu from '../context/EditAccountMenu';
3637

37-
const centerOfEventTarget = event => {
38+
const centerOfEventTarget = (event: React.MouseEvent<Element, MouseEvent>) => {
3839
const clientRectangle = event.currentTarget.getBoundingClientRect();
3940
const centerX = clientRectangle.left + clientRectangle.width / 2;
4041
const centerY = clientRectangle.top + clientRectangle.height / 2;
4142
return {centerX, centerY};
4243
};
4344

44-
const getClassName = account => {
45+
const getClassName = (account: Account) => {
4546
const showIconBadge = account.badgeCount > 0 ? ' Sidebar-icon-badge' : '';
4647
const showIconCursor = account.visible ? '' : ' Sidebar-icon-cursor';
4748
return `Sidebar-icon${showIconBadge}${showIconCursor}`;
4849
};
4950

50-
const handleSwitchAccount = accountIndex => {
51+
const handleSwitchAccount = (accountIndex: number) => {
5152
window.dispatchEvent(new CustomEvent(EVENT_TYPE.ACTION.SWITCH_ACCOUNT, {detail: {accountIndex: accountIndex}}));
5253
};
5354

55+
interface SidebarProps {
56+
accounts: Account[];
57+
currentAccentID: number;
58+
hasCreatedAccount: boolean;
59+
hasReachedLimitOfAccounts: boolean;
60+
isAddingAccount: boolean;
61+
isDarkMode: boolean;
62+
isEditAccountMenuVisible: boolean;
63+
setAccountContextHidden: () => void;
64+
toggleEditAccountMenuVisibility: (
65+
centerX: number,
66+
centerY: number,
67+
accountId: string,
68+
sessionID: string,
69+
lifecycle: string,
70+
isAtLeastAdmin: boolean,
71+
) => void;
72+
addAccountWithSession: () => void;
73+
}
74+
5475
const Sidebar = ({
5576
accounts,
5677
currentAccentID,
@@ -60,18 +81,22 @@ const Sidebar = ({
6081
isAddingAccount,
6182
isEditAccountMenuVisible,
6283
...connected
63-
}) => (
84+
}: SidebarProps) => (
6485
<div
86+
role="button"
87+
tabIndex={0}
6588
className={`${isDarkMode ? 'Sidebar theme-dark' : 'Sidebar theme-light'}`}
6689
style={!hasCreatedAccount ? {display: 'none'} : {}}
6790
onMouseDown={preventFocus()}
91+
onKeyDown={connected.setAccountContextHidden}
6892
onClick={connected.setAccountContextHidden}
6993
>
7094
{accounts.map(account => {
7195
const accountIndex = accounts.indexOf(account);
7296
return (
7397
<div className="Sidebar-cell" key={account.id}>
7498
<div
99+
role="button"
75100
style={{color: colorFromId(currentAccentID)}}
76101
className={getClassName(account)}
77102
tabIndex={0}
@@ -81,7 +106,7 @@ const Sidebar = ({
81106
handleSwitchAccount(accountIndex);
82107
}
83108
}}
84-
onContextMenu={preventFocus(event => {
109+
onContextMenu={preventFocus((event: React.MouseEvent<Element, MouseEvent>) => {
85110
const isAtLeastAdmin =
86111
account.teamRole === 'z.team.TeamRole.ROLE.OWNER' || account.teamRole === 'z.team.TeamRole.ROLE.ADMIN';
87112
const {centerX, centerY} = centerOfEventTarget(event);
@@ -101,6 +126,7 @@ const Sidebar = ({
101126
</div>
102127
);
103128
})}
129+
104130
{!isAddingAccount && !hasReachedLimitOfAccounts && (
105131
<AddAccountTrigger id="account" onClick={connected.addAccountWithSession} />
106132
)}

0 commit comments

Comments
 (0)