summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorHank <hank@mullvad.net>2022-10-07 14:58:03 +0200
committerHank <hank@mullvad.net>2022-10-07 14:58:03 +0200
commitd5d97969cfc391a491c6aeb5c5826a95dcfa197a (patch)
tree5fec81c49b93e722ddaada635a28e967e62bf344 /gui/src
parente8ea2448b50d52026f3ccae7e84535911ea7b06b (diff)
parent48cf534d6610161e5db730dc91d187da79494aa7 (diff)
downloadmullvadvpn-d5d97969cfc391a491c6aeb5c5826a95dcfa197a.tar.xz
mullvadvpn-d5d97969cfc391a491c6aeb5c5826a95dcfa197a.zip
Merge branch 'update-packages'
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/main/ipc-event-channel.ts6
-rw-r--r--gui/src/renderer/.eslintignore1
-rw-r--r--gui/src/renderer/.eslintrc.js5
-rw-r--r--gui/src/renderer/components/AppButton.tsx5
-rw-r--r--gui/src/renderer/components/ErrorBoundary.tsx2
-rw-r--r--gui/src/renderer/components/LocationList.tsx2
-rw-r--r--gui/src/renderer/components/Login.tsx2
-rw-r--r--gui/src/renderer/components/ProblemReport.tsx2
-rw-r--r--gui/src/renderer/components/ScopeBar.tsx2
-rw-r--r--gui/src/renderer/components/SvgMap.tsx10
-rw-r--r--gui/src/renderer/components/TransitionContainer.tsx1
-rw-r--r--gui/src/renderer/context.tsx25
-rw-r--r--gui/src/renderer/index.ts5
-rw-r--r--gui/src/shared/ipc-helpers.ts4
14 files changed, 33 insertions, 39 deletions
diff --git a/gui/src/main/ipc-event-channel.ts b/gui/src/main/ipc-event-channel.ts
index d189634950..bae499910d 100644
--- a/gui/src/main/ipc-event-channel.ts
+++ b/gui/src/main/ipc-event-channel.ts
@@ -1,14 +1,14 @@
import { ipcMain, WebContents } from 'electron';
-import { createIpcMain, IpcMain, Schema } from '../shared/ipc-helpers';
+import { createIpcMain, IpcMain, Notifier, Schema } from '../shared/ipc-helpers';
import { ipcSchema } from '../shared/ipc-schema';
// Type where the notify functions have been replaced with either `undefined` if no `WebContents` is
// available, or with the function curried with the `WebContents`.
type IpcMainBootstrappedWithWebContents<S extends Schema> = {
[GK in keyof IpcMain<S>]: {
- [CK in keyof IpcMain<S>[GK]]: CK extends `notify${string}`
- ? undefined | ((arg: Parameters<IpcMain<S>[GK][CK]>[1]) => ReturnType<IpcMain<S>[GK][CK]>)
+ [CK in keyof IpcMain<S>[GK]]: IpcMain<S>[GK][CK] extends Notifier<infer T>
+ ? undefined | ((arg: T) => ReturnType<IpcMain<S>[GK][CK]>)
: IpcMain<S>[GK][CK];
};
};
diff --git a/gui/src/renderer/.eslintignore b/gui/src/renderer/.eslintignore
deleted file mode 100644
index a9ba028cee..0000000000
--- a/gui/src/renderer/.eslintignore
+++ /dev/null
@@ -1 +0,0 @@
-.eslintrc.js
diff --git a/gui/src/renderer/.eslintrc.js b/gui/src/renderer/.eslintrc.js
deleted file mode 100644
index c38aa97590..0000000000
--- a/gui/src/renderer/.eslintrc.js
+++ /dev/null
@@ -1,5 +0,0 @@
-module.exports = {
- env: {
- browser: true,
- },
-};
diff --git a/gui/src/renderer/components/AppButton.tsx b/gui/src/renderer/components/AppButton.tsx
index a3edc78ad3..45c93e1b2a 100644
--- a/gui/src/renderer/components/AppButton.tsx
+++ b/gui/src/renderer/components/AppButton.tsx
@@ -54,7 +54,10 @@ const BaseButton = React.memo(function BaseButtonT(props: IProps) {
if (groups.label === undefined && typeof child === 'string') {
return { ...groups, label: <Label textOffset={textOffset}>{child}</Label> };
} else if (React.isValidElement(child) && child.type === Label) {
- return { ...groups, label: React.cloneElement(child, { textOffset }) };
+ return {
+ ...groups,
+ label: React.cloneElement(child as React.ReactElement<ILabelProps>, { textOffset }),
+ };
} else if (groups.label === undefined) {
return { ...groups, left: [...groups.left, child] };
} else {
diff --git a/gui/src/renderer/components/ErrorBoundary.tsx b/gui/src/renderer/components/ErrorBoundary.tsx
index 7014175ffa..40615e44f4 100644
--- a/gui/src/renderer/components/ErrorBoundary.tsx
+++ b/gui/src/renderer/components/ErrorBoundary.tsx
@@ -33,7 +33,7 @@ export default class ErrorBoundary extends React.Component<IProps, IState> {
public render() {
if (this.state.hasError) {
- const reachBackMessage: React.ReactNodeArray =
+ const reachBackMessage: React.ReactNode[] =
// TRANSLATORS: The message displayed to the user in case of critical error in the GUI
// TRANSLATORS: Available placeholders:
// TRANSLATORS: %(email)s - support email
diff --git a/gui/src/renderer/components/LocationList.tsx b/gui/src/renderer/components/LocationList.tsx
index 729cb59f3c..19c3eca0a5 100644
--- a/gui/src/renderer/components/LocationList.tsx
+++ b/gui/src/renderer/components/LocationList.tsx
@@ -43,6 +43,7 @@ interface ILocationListProps<SpecialValueType> {
selectedValue?: LocationSelection<SpecialValueType>;
selectedElementRef?: React.Ref<React.ReactInstance>;
onSelect?: (value: LocationSelection<SpecialValueType>) => void;
+ children?: React.ReactNode;
}
export default class LocationList<SpecialValueType> extends React.Component<
@@ -244,6 +245,7 @@ interface ISpecialLocationProps<T> {
onSelect?: (value: T) => void;
info?: string;
forwardedRef?: React.Ref<HTMLButtonElement>;
+ children?: React.ReactNode;
}
export class SpecialLocation<T> extends React.Component<ISpecialLocationProps<T>> {
diff --git a/gui/src/renderer/components/Login.tsx b/gui/src/renderer/components/Login.tsx
index 0b30b1c167..6c69074a0c 100644
--- a/gui/src/renderer/components/Login.tsx
+++ b/gui/src/renderer/components/Login.tsx
@@ -379,7 +379,7 @@ function AccountDropdownItem(props: IAccountDropdownItemProps) {
}, [props.onSelect, props.value]);
const handleRemove = useCallback(
- (event) => {
+ (event: React.MouseEvent<HTMLButtonElement>) => {
// Prevent login form from submitting
event.preventDefault();
props.onRemove(props.value);
diff --git a/gui/src/renderer/components/ProblemReport.tsx b/gui/src/renderer/components/ProblemReport.tsx
index c2e501e109..aa89365fd5 100644
--- a/gui/src/renderer/components/ProblemReport.tsx
+++ b/gui/src/renderer/components/ProblemReport.tsx
@@ -385,7 +385,7 @@ export default class ProblemReport extends React.Component<
}
private renderSent() {
- const reachBackMessage: React.ReactNodeArray =
+ const reachBackMessage: React.ReactNode[] =
// TRANSLATORS: The message displayed to the user after submitting the problem report, given that the user left his or her email for us to reach back.
// TRANSLATORS: Available placeholders:
// TRANSLATORS: %(email)s
diff --git a/gui/src/renderer/components/ScopeBar.tsx b/gui/src/renderer/components/ScopeBar.tsx
index be5420b0b5..10b177c2c3 100644
--- a/gui/src/renderer/components/ScopeBar.tsx
+++ b/gui/src/renderer/components/ScopeBar.tsx
@@ -16,7 +16,7 @@ interface IScopeBarProps {
defaultSelectedIndex?: number;
onChange?: (selectedIndex: number) => void;
className?: string;
- children: React.ReactNode;
+ children: React.ReactElement<IScopeBarItemProps>[];
}
export function ScopeBar(props: IScopeBarProps) {
diff --git a/gui/src/renderer/components/SvgMap.tsx b/gui/src/renderer/components/SvgMap.tsx
index 00745bede2..680facb558 100644
--- a/gui/src/renderer/components/SvgMap.tsx
+++ b/gui/src/renderer/components/SvgMap.tsx
@@ -1,5 +1,5 @@
import { geoMercator, GeoProjection } from 'd3-geo';
-import rbush from 'rbush';
+import RBush, { BBox as RBushBBox } from 'rbush';
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import { ComposableMap, Geographies, Geography, Marker } from 'react-simple-maps';
@@ -8,16 +8,16 @@ import geometryTreeData from '../../../assets/geo/geometry.rbush.json';
import statesProvincesLinesData from '../../../assets/geo/states-provinces-lines.json';
import statesProvincesLinesTreeData from '../../../assets/geo/states-provinces-lines.rbush.json';
-interface IGeometryLeaf extends rbush.BBox {
+interface IGeometryLeaf extends RBushBBox {
id: string;
}
-interface IProvinceAndStateLineLeaf extends rbush.BBox {
+interface IProvinceAndStateLineLeaf extends RBushBBox {
id: string;
}
-const geometryTree = rbush<IGeometryLeaf>().fromJSON(geometryTreeData);
-const provincesStatesLinesTree = rbush<IProvinceAndStateLineLeaf>().fromJSON(
+const geometryTree = new RBush<IGeometryLeaf>().fromJSON(geometryTreeData);
+const provincesStatesLinesTree = new RBush<IProvinceAndStateLineLeaf>().fromJSON(
statesProvincesLinesTreeData,
);
diff --git a/gui/src/renderer/components/TransitionContainer.tsx b/gui/src/renderer/components/TransitionContainer.tsx
index 22ef1665eb..5fbfe61a55 100644
--- a/gui/src/renderer/components/TransitionContainer.tsx
+++ b/gui/src/renderer/components/TransitionContainer.tsx
@@ -6,6 +6,7 @@ import { WillExit } from '../lib/will-exit';
interface ITransitioningViewProps {
viewId: string;
+ children?: React.ReactNode;
}
type TransitioningView = React.ReactElement<ITransitioningViewProps>;
diff --git a/gui/src/renderer/context.tsx b/gui/src/renderer/context.tsx
index 0867618136..3b5fcc14fb 100644
--- a/gui/src/renderer/context.tsx
+++ b/gui/src/renderer/context.tsx
@@ -15,24 +15,15 @@ const missingContextError = new Error(
'The context value is empty. Make sure to wrap the component in AppContext.Provider.',
);
-export default function withAppContext<Props>(BaseComponent: React.ComponentType<Props>) {
- // Exclude the IAppContext from props since those are injected props
- const wrappedComponent = (props: Omit<Props, keyof IAppContext>) => {
- return (
- <AppContext.Consumer>
- {(context) => {
- if (context) {
- // Enforce type because Typescript does not recognize that
- // (Props ~ IAppContext & IAppContext) is identical to Props.
- const mergedProps = ({ ...props, ...context } as unknown) as Props;
+type PropsWithoutAppContext<Props> = Omit<Props, 'app'>;
- return <BaseComponent {...mergedProps} />;
- } else {
- throw missingContextError;
- }
- }}
- </AppContext.Consumer>
- );
+export default function withAppContext<Props>(
+ BaseComponent: React.ComponentType<PropsWithoutAppContext<Props> & IAppContext>,
+) {
+ // Exclude the IAppContext from props since those are injected props
+ const wrappedComponent = (props: PropsWithoutAppContext<Props>) => {
+ const appContext = useAppContext();
+ return <BaseComponent app={appContext} {...props} />;
};
if (window.env.development) {
diff --git a/gui/src/renderer/index.ts b/gui/src/renderer/index.ts
index 815095408f..fbf8ebcdba 100644
--- a/gui/src/renderer/index.ts
+++ b/gui/src/renderer/index.ts
@@ -1,7 +1,8 @@
-import ReactDOM from 'react-dom';
+import { createRoot } from 'react-dom/client';
import App from './app';
const app = new App();
const container = document.getElementById('app');
-ReactDOM.render(app.renderView(), container);
+const root = createRoot(container!);
+root.render(app.renderView());
diff --git a/gui/src/shared/ipc-helpers.ts b/gui/src/shared/ipc-helpers.ts
index 1680b45d11..fda5c2d3b5 100644
--- a/gui/src/shared/ipc-helpers.ts
+++ b/gui/src/shared/ipc-helpers.ts
@@ -5,7 +5,9 @@ import { capitalize } from './string-helpers';
type Handler<T, R> = (callback: (arg: T) => R) => void;
type Sender<T, R> = (arg: T) => R;
-type Notifier<T> = (webContents: WebContents | undefined, arg: T) => void;
+// Remove export after upgrading to Electron 21+ and removal of code to curry notifiers with
+// webContents in ../main/ipc-event-channel.ts.
+export type Notifier<T> = (webContents: WebContents | undefined, arg: T) => void;
type Listener<T> = (callback: (arg: T) => void) => void;
interface MainToRenderer<T> {