From 08c477729cf2b1108e5fdfc2e4ea06af10cfe3dc Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 09:59:43 +0100 Subject: [PATCH 01/15] Add radius token --- desktop/packages/mullvad-vpn/src/renderer/tokens/index.ts | 1 + desktop/packages/mullvad-vpn/src/renderer/tokens/radius.ts | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 desktop/packages/mullvad-vpn/src/renderer/tokens/radius.ts diff --git a/desktop/packages/mullvad-vpn/src/renderer/tokens/index.ts b/desktop/packages/mullvad-vpn/src/renderer/tokens/index.ts index 53555f1d5aef..6faa0dac5e6d 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/tokens/index.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/tokens/index.ts @@ -1,3 +1,4 @@ export * from './colors'; +export * from './radius'; export * from './spacings'; export * from './typography'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/tokens/radius.ts b/desktop/packages/mullvad-vpn/src/renderer/tokens/radius.ts new file mode 100644 index 000000000000..e73a2cb513a2 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/tokens/radius.ts @@ -0,0 +1,6 @@ +export enum Radius { + radius4 = '4px', + radius8 = '8px', + radius11 = '11px', + radius12 = '12px', +} From 94743c0618fcf7479f5944ff5952b78b6a10e578 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 10:00:17 +0100 Subject: [PATCH 02/15] Rename typography types --- .../mullvad-vpn/src/renderer/tokens/typography.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/desktop/packages/mullvad-vpn/src/renderer/tokens/typography.ts b/desktop/packages/mullvad-vpn/src/renderer/tokens/typography.ts index df7359b8f0ae..d647c8465a8e 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/tokens/typography.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/tokens/typography.ts @@ -34,23 +34,23 @@ export enum LineHeights { mini = '15px', } -interface Typography { +interface TypographyProperties { fontFamily: React.CSSProperties['fontFamily']; fontSize: React.CSSProperties['fontSize']; fontWeight: React.CSSProperties['fontWeight']; lineHeight: React.CSSProperties['lineHeight']; } -export const typography: Record< +export type Typography = | 'titleBig' | 'titleLarge' | 'titleMedium' | 'bodySmall' | 'bodySmallSemibold' | 'labelTiny' - | 'footnoteMini', - Typography -> = { + | 'footnoteMini'; + +export const typography: Record = { titleBig: { fontFamily: Fonts.title, fontWeight: FontWeights.bold, From b2fd21d2a395256c8e24bf9bf2bdb1a0474a7805 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:09:42 +0100 Subject: [PATCH 03/15] Add Button and IconButton components --- .../components/common/mixins/button-reset.ts | 10 ++ .../components/common/mixins/index.ts | 1 + .../components/common/molecules/Button.tsx | 105 ++++++++++++++++++ .../common/molecules/IconButton.tsx | 65 +++++++++++ .../components/common/molecules/index.ts | 2 + 5 files changed, 183 insertions(+) create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/common/mixins/button-reset.ts create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/common/mixins/index.ts create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/Button.tsx create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/IconButton.tsx create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/index.ts diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/mixins/button-reset.ts b/desktop/packages/mullvad-vpn/src/renderer/components/common/mixins/button-reset.ts new file mode 100644 index 000000000000..4ef5844150be --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/mixins/button-reset.ts @@ -0,0 +1,10 @@ +export const buttonReset = { + border: 'none', + padding: 0, + margin: 0, + font: 'inherit', + color: 'inherit', + textAlign: 'inherit', + lineHeight: 'inherit', + cursor: 'default', +} as React.CSSProperties; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/mixins/index.ts b/desktop/packages/mullvad-vpn/src/renderer/components/common/mixins/index.ts new file mode 100644 index 000000000000..c546f737b6ac --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/mixins/index.ts @@ -0,0 +1 @@ +export * from './button-reset'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/Button.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/Button.tsx new file mode 100644 index 000000000000..c4db496a2123 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/Button.tsx @@ -0,0 +1,105 @@ +import React, { forwardRef } from 'react'; +import styled from 'styled-components'; + +import { Colors, Radius, Spacings } from '../../../tokens'; +import { Flex } from '../layout'; +import { buttonReset } from '../mixins'; +import { BodySmallSemiBold } from '../text'; + +export interface ButtonProps extends React.ButtonHTMLAttributes { + variant?: 'primary' | 'success' | 'destructive'; + size?: 'tiny' | 'small' | 'regular' | 'full' | '1/2'; + leading?: React.ReactNode; + trailing?: React.ReactNode; +} + +const variants = { + primary: { + background: Colors.blue, + hover: Colors.blue60, + disabled: Colors.blue50, + }, + success: { + background: Colors.green, + hover: Colors.green90, + disabled: Colors.green40, + }, + destructive: { + background: Colors.red, + hover: Colors.red80, + disabled: Colors.red60, + }, +} as const; + +const sizes = { + tiny: '44px', + small: '60px', + regular: '272px', + full: '100%', + '1/2': '50%', +}; + +const StyledButton = styled.button({ + ...buttonReset, + + minHeight: '32px', + borderRadius: Radius.radius4, + width: 'var(--size)', + background: 'var(--background)', + '&:not(:disabled):hover': { + background: 'var(--hover)', + }, + '&:disabled': { + background: 'var(--disabled)', + }, + '&:focus-visible': { + outline: `2px solid ${Colors.white}`, + outlineOffset: '2px', + }, +}); + +export const Button = forwardRef( + ( + { variant = 'primary', size = 'regular', leading, trailing, children, disabled, ...props }, + ref, + ) => { + const styles = variants[variant]; + return ( + + + {leading} + + {typeof children === 'string' ? ( + + {children} + + ) : ( + children + )} + + {trailing} + + + ); + }, +); + +Button.displayName = 'Button'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/IconButton.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/IconButton.tsx new file mode 100644 index 000000000000..bdbe7ba8e442 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/IconButton.tsx @@ -0,0 +1,65 @@ +import React, { forwardRef } from 'react'; +import styled from 'styled-components'; + +import { Colors } from '../../../tokens'; +import ImageView from '../../ImageView'; +import { buttonReset } from '../mixins'; + +export interface IconButtonProps + extends Omit, 'children'> { + variant?: 'primary' | 'secondary'; + size?: 'small' | 'regular'; + icon: string; +} + +const variants = { + primary: { + background: Colors.white, + hover: Colors.white60, + disabled: Colors.white50, + }, + secondary: { + background: Colors.white60, + hover: Colors.white80, + disabled: Colors.white50, + }, +} as const; + +const sizes = { + small: 16, + regular: 24, +}; + +const StyledButton = styled.button({ + ...buttonReset, + + background: 'transparent', + height: 'var(--size)', + width: 'var(--size)', + '&:focus-visible': { + outline: `2px solid ${Colors.white}`, + outlineOffset: '2px', + borderRadius: '100%', + }, +}); + +export const IconButton = forwardRef( + ({ icon, variant = 'primary', size: sizeProp = 'regular', disabled, ...props }, ref) => { + const styles = variants[variant]; + const size = sizes[sizeProp]; + return ( + + + + ); + }, +); + +IconButton.displayName = 'Button'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/index.ts b/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/index.ts new file mode 100644 index 000000000000..66f0cf90a7d6 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/molecules/index.ts @@ -0,0 +1,2 @@ +export * from './Button'; +export * from './IconButton'; From 57e6703ce7bb0b73647c9b16ddd2e6c9e004fd8f Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:15:32 +0100 Subject: [PATCH 04/15] Add Link and update typography components --- .../renderer/components/SettingsHeader.tsx | 2 +- .../components/SplitTunnelingSettings.tsx | 2 +- .../src/renderer/components/cell/Footer.tsx | 2 +- .../components/common/text/BodySmall.tsx | 13 ++-- .../common/text/BodySmallSemiBold.tsx | 13 ++-- .../components/common/text/FootnoteMini.tsx | 13 ++-- .../components/common/text/LabelTiny.tsx | 14 ++--- .../renderer/components/common/text/Link.tsx | 62 +++++++++++++++++++ .../renderer/components/common/text/Text.tsx | 56 ++++++++++++++--- .../components/common/text/TitleBig.tsx | 14 ++--- .../components/common/text/TitleLarge.tsx | 13 ++-- .../components/common/text/TitleMedium.tsx | 14 ++--- .../renderer/components/common/text/index.ts | 1 + 13 files changed, 164 insertions(+), 55 deletions(-) create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/common/text/Link.tsx diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx index deac04b26bbe..643fb5da27a2 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SettingsHeader.tsx @@ -11,7 +11,7 @@ export const HeaderTitle = styled(TitleBig)({ }); export const HeaderSubTitle = styled(LabelTiny).attrs({ - $color: Colors.white60, + color: Colors.white60, })({}); interface SettingsHeaderProps { diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx index b2e25c9e63ee..fea4181624c6 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SplitTunnelingSettings.tsx @@ -551,7 +551,7 @@ function MacOsSplitTunnelingAvailability({ {messages.pgettext('split-tunneling-view', 'Open System Settings')} - + {messages.pgettext( 'split-tunneling-view', 'Enabled "Full disk access" and still having issues?', diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx index 245422563881..002aa86433d7 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/cell/Footer.tsx @@ -8,5 +8,5 @@ export const CellFooter = styled.div({ }); export const CellFooterText = styled(LabelTiny).attrs({ - $color: Colors.white60, + color: Colors.white60, })({}); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/BodySmall.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/BodySmall.tsx index 9cfe1bc9c041..18ab10e202e0 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/BodySmall.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/BodySmall.tsx @@ -1,8 +1,9 @@ -import styled from 'styled-components'; +import { Text, TextProps } from './Text'; -import { typography } from '../../../tokens'; -import { Text } from './Text'; +export type BodySmallProps = Omit; -export const BodySmall = styled(Text)({ - ...typography['bodySmall'], -}); +export const BodySmall = ({ children, ...props }: BodySmallProps) => ( + + {children} + +); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/BodySmallSemiBold.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/BodySmallSemiBold.tsx index 705a939e5d48..f70a2c7b11eb 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/BodySmallSemiBold.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/BodySmallSemiBold.tsx @@ -1,8 +1,9 @@ -import styled from 'styled-components'; +import { Text, TextProps } from './Text'; -import { typography } from '../../../tokens'; -import { Text } from './Text'; +export type BodySmallSemiBoldProps = Omit; -export const BodySmallSemiBold = styled(Text)({ - ...typography['bodySmallSemibold'], -}); +export const BodySmallSemiBold = ({ children, ...props }: BodySmallSemiBoldProps) => ( + + {children} + +); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/FootnoteMini.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/FootnoteMini.tsx index adbafb90d129..77d563e03c9f 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/FootnoteMini.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/FootnoteMini.tsx @@ -1,8 +1,9 @@ -import styled from 'styled-components'; +import { Text, TextProps } from './Text'; -import { typography } from '../../../tokens'; -import { Text } from './Text'; +export type FoonoteMiniProps = Omit; -export const FootnoteMini = styled(Text)({ - ...typography['footnoteMini'], -}); +export const FootnoteMini = ({ children, ...props }: FoonoteMiniProps) => ( + + {children} + +); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/LabelTiny.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/LabelTiny.tsx index 9f6f8a143c42..f7a952e67e6d 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/LabelTiny.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/LabelTiny.tsx @@ -1,8 +1,8 @@ -import styled from 'styled-components'; +import { Text, TextProps } from './Text'; +export type LabelTinyProps = Omit; -import { typography } from '../../../tokens'; -import { Text } from './Text'; - -export const LabelTiny = styled(Text)({ - ...typography['labelTiny'], -}); +export const LabelTiny = ({ children, ...props }: LabelTinyProps) => ( + + {children} + +); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/Link.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/Link.tsx new file mode 100644 index 000000000000..f2ea457fe3e4 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/Link.tsx @@ -0,0 +1,62 @@ +import React, { useCallback } from 'react'; +import styled from 'styled-components'; + +import { useHistory } from '../../../lib/history'; +import { RoutePath } from '../../../lib/routes'; +import { Colors, Radius } from '../../../tokens'; +import { buttonReset } from '../mixins'; +import { Text, TextProps } from './Text'; + +export interface LinkProps extends TextProps, Omit, 'color'> { + to: RoutePath; +} + +const StyledText = styled(Text)<{ + $hoverColor: Colors | undefined; +}>((props) => ({ + ...buttonReset, + background: 'transparent', + + '&:hover': { + textDecorationLine: 'underline', + textUnderlineOffset: '2px', + color: props.$hoverColor, + }, + '&:focus-visible': { + borderRadius: Radius.radius4, + outline: `2px solid ${Colors.white}`, + outlineOffset: '2px', + }, +})); + +const getHoverColor = (color: Colors | undefined) => { + switch (color) { + case Colors.white60: + return Colors.white; + default: + return undefined; + } +}; + +export const Link = ({ to, children, color, onClick, ...props }: LinkProps) => { + const history = useHistory(); + const navigate = useCallback( + (e: React.MouseEvent<'button'>) => { + if (onClick) { + onClick(e); + } + return history.push(to); + }, + [history, to, onClick], + ); + return ( + + {children} + + ); +}; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/Text.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/Text.tsx index f4b32d988d08..3ea195725a70 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/Text.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/Text.tsx @@ -1,11 +1,53 @@ +import { forwardRef } from 'react'; import styled from 'styled-components'; -import { Colors } from '../../../tokens'; +import { Colors, Typography, typography } from '../../../tokens'; -interface TextProps { - $color?: Colors; -} +export type TextProps = React.PropsWithChildren<{ + variant?: Typography; + color?: Colors; + as?: React.ElementType; + style?: React.CSSProperties; +}>; -export const Text = styled.div(({ $color }) => ({ - color: $color ? $color : Colors.white, -})); +export const StyledText = styled.span({ + color: 'var(--color)', + fontFamily: 'var(--fontFamily)', + fontWeight: 'var(--fontWeight)', + fontSize: 'var(--fontSize)', + lineHeight: 'var(--lineHeight)', +}); + +export const Text = forwardRef( + ( + { + variant = 'bodySmall', + color = Colors.white, + children, + style, + ...props + }: React.PropsWithChildren, + ref, + ) => { + const { fontFamily, fontSize, fontWeight, lineHeight } = typography[variant]; + return ( + + {children} + + ); + }, +); + +Text.displayName = 'Text'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleBig.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleBig.tsx index 16d76c04ef82..4b3b1d84efab 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleBig.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleBig.tsx @@ -1,8 +1,8 @@ -import styled from 'styled-components'; +import { Text, TextProps } from './Text'; +export type TitleBigProps = Omit; -import { typography } from '../../../tokens'; -import { Text } from './Text'; - -export const TitleBig = styled(Text)({ - ...typography['titleBig'], -}); +export const TitleBig = ({ children, ...props }: TitleBigProps) => ( + + {children} + +); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleLarge.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleLarge.tsx index e939b099fc05..c80814362ec8 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleLarge.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleLarge.tsx @@ -1,7 +1,8 @@ -import styled from 'styled-components'; +import { Text, TextProps } from './Text'; +export type TitleLargeProps = Omit; -import { typography } from '../../../tokens'; -import { Text } from './Text'; -export const TitleLarge = styled(Text)({ - ...typography['titleLarge'], -}); +export const TitleLarge = ({ children, ...props }: TitleLargeProps) => ( + + {children} + +); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleMedium.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleMedium.tsx index 578d435ef373..5e188698a42a 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleMedium.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/TitleMedium.tsx @@ -1,8 +1,8 @@ -import styled from 'styled-components'; +import { Text, TextProps } from './Text'; +export type TitleMediumProps = Omit; -import { typography } from '../../../tokens'; -import { Text } from './Text'; - -export const TitleMedium = styled(Text)({ - ...typography['titleMedium'], -}); +export const TitleMedium = ({ children, ...props }: TitleMediumProps) => ( + + {children} + +); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/index.ts b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/index.ts index 56db1927fc80..542c9d564273 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/text/index.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/text/index.ts @@ -6,3 +6,4 @@ export * from './Text'; export * from './TitleBig'; export * from './TitleLarge'; export * from './TitleMedium'; +export * from './Link'; From 7bdf5fb81845e60545d3bea70ddf273c2eeca756 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:17:38 +0100 Subject: [PATCH 05/15] Add Container component --- .../components/common/layout/Container.tsx | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/common/layout/Container.tsx diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/layout/Container.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/layout/Container.tsx new file mode 100644 index 000000000000..839f9a8f577e --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/layout/Container.tsx @@ -0,0 +1,28 @@ +import React from 'react'; +import styled from 'styled-components'; + +import { Spacings } from '../../../tokens'; +import { Flex, FlexProps } from './Flex'; + +export interface ContainerProps extends FlexProps { + size?: '3' | '4'; + children: React.ReactNode; +} + +const sizes: Record<'3' | '4', string> = { + '3': `calc(100% - ${Spacings.spacing6} * 2)`, + '4': `calc(100% - ${Spacings.spacing5} * 2)`, +}; + +const StyledFlex = styled(Flex)<{ $size: string }>((props) => ({ + width: props.$size, + margin: 'auto', +})); + +export const Container = React.forwardRef( + ({ size = '4', ...props }, ref) => { + return ; + }, +); + +Container.displayName = 'Container'; From 09f99fce88500ceac8a21d100f2304a53d85fa4d Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:17:53 +0100 Subject: [PATCH 06/15] Add flex basis to Flex component --- .../src/renderer/components/common/layout/Flex.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/common/layout/Flex.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/common/layout/Flex.tsx index ede836194ba1..32d7f4f30b41 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/common/layout/Flex.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/common/layout/Flex.tsx @@ -12,11 +12,21 @@ export interface FlexProps extends LayoutProps { $justifyContent?: React.CSSProperties['justifyContent']; $flexGrow?: React.CSSProperties['flexGrow']; $flexShrink?: React.CSSProperties['flexShrink']; + $flexBasis?: React.CSSProperties['flexBasis']; children?: React.ReactNode; } export const Flex = styled(Layout)( - ({ $gap, $flex, $flexDirection, $alignItems, $justifyContent, $flexGrow, $flexShrink }) => ({ + ({ + $gap, + $flex, + $flexDirection, + $alignItems, + $justifyContent, + $flexGrow, + $flexShrink, + $flexBasis, + }) => ({ display: 'flex', gap: $gap, flex: $flex, @@ -25,5 +35,6 @@ export const Flex = styled(Layout)( justifyContent: $justifyContent, flexGrow: $flexGrow, flexShrink: $flexShrink, + flexBasis: $flexBasis, }), ); From 4b1fa106298aab339e917755f07a87c54450c930 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:21:04 +0100 Subject: [PATCH 07/15] Add app info and changelog views --- .../src/renderer/components/AppRouter.tsx | 3 + .../components/views/app-info/AppInfoView.tsx | 48 ++++++++ .../components/AppVersionListItem.tsx | 65 +++++++++++ .../app-info/components/ChangelogListItem.tsx | 17 +++ .../views/app-info/components/index.ts | 2 + .../components/views/app-info/index.ts | 1 + .../views/changelog/ChangelogView.tsx | 106 ++++++++++++++++++ .../components/views/changelog/index.ts | 1 + .../src/renderer/components/views/index.ts | 2 + .../mullvad-vpn/src/renderer/lib/routes.ts | 2 + .../src/shared/localization-contexts.ts | 4 +- 11 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/AppVersionListItem.tsx create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/ChangelogListItem.tsx create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/index.ts create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/index.ts create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/index.ts create mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/views/index.ts diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/AppRouter.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/AppRouter.tsx index 3541c095d69a..6ad0a9e199e8 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/AppRouter.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/AppRouter.tsx @@ -38,6 +38,7 @@ import TooManyDevices from './TooManyDevices'; import TransitionContainer, { TransitionView } from './TransitionContainer'; import UdpOverTcp from './UdpOverTcp'; import UserInterfaceSettings from './UserInterfaceSettings'; +import { AppInfoView, ChangelogView } from './views'; import VpnSettings from './VpnSettings'; import WireguardSettings from './WireguardSettings'; @@ -103,6 +104,8 @@ export default function AppRouter() { + + diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx new file mode 100644 index 000000000000..41671c46a9bd --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/AppInfoView.tsx @@ -0,0 +1,48 @@ +import { messages } from '../../../../shared/gettext'; +import { useHistory } from '../../../lib/history'; +import { BackAction } from '../../KeyboardNavigation'; +import { Layout, SettingsContainer, SettingsGroup, SettingsStack } from '../../Layout'; +import { + NavigationBar, + NavigationContainer, + NavigationItems, + NavigationScrollbars, + TitleBarItem, +} from '../../NavigationBar'; +import SettingsHeader, { HeaderTitle } from '../../SettingsHeader'; +import { AppVersionListItem, ChangelogListItem } from './components'; + +export const AppInfoView = () => { + const { pop } = useHistory(); + return ( + + + + + + + {messages.pgettext('app-info-view', 'App info')} + + + + + + {messages.pgettext('app-info-view', 'App info')} + + + + + + + + + + + + + + + + + ); +}; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/AppVersionListItem.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/AppVersionListItem.tsx new file mode 100644 index 000000000000..64605157917d --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/AppVersionListItem.tsx @@ -0,0 +1,65 @@ +import { useCallback } from 'react'; + +import { messages } from '../../../../../shared/gettext'; +import { getDownloadUrl } from '../../../../../shared/version'; +import { useAppContext } from '../../../../context'; +import { useSelector } from '../../../../redux/store'; +import { Colors } from '../../../../tokens'; +import * as Cell from '../../../cell'; +import { LabelStack } from '../../../Layout'; + +export function AppVersionListItem() { + const appVersion = useSelector((state) => state.version.current); + const consistentVersion = useSelector((state) => state.version.consistent); + const upToDateVersion = useSelector((state) => (state.version.suggestedUpgrade ? false : true)); + const suggestedIsBeta = useSelector((state) => state.version.suggestedIsBeta ?? false); + const isOffline = useSelector((state) => state.connection.isBlocked); + + const { openUrl } = useAppContext(); + const openDownloadLink = useCallback( + () => openUrl(getDownloadUrl(suggestedIsBeta)), + [openUrl, suggestedIsBeta], + ); + + let alertIcon; + let footer; + if (!consistentVersion || !upToDateVersion) { + const inconsistentVersionMessage = messages.pgettext( + 'app-info-view', + 'App is out of sync. Please quit and restart.', + ); + + const updateAvailableMessage = messages.pgettext( + 'app-info-view', + 'Update available. Install the latest app version to stay up to date.', + ); + + const message = !consistentVersion ? inconsistentVersionMessage : updateAvailableMessage; + + alertIcon = ; + footer = ( + + {message} + + ); + } + + return ( + <> + + + {alertIcon} + {messages.pgettext('app-info-view', 'App version')} + + {appVersion} + + {footer} + + ); +} diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/ChangelogListItem.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/ChangelogListItem.tsx new file mode 100644 index 000000000000..c05b0286b6b1 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/ChangelogListItem.tsx @@ -0,0 +1,17 @@ +import { useCallback } from 'react'; + +import { messages } from '../../../../../shared/gettext'; +import { useHistory } from '../../../../lib/history'; +import { RoutePath } from '../../../../lib/routes'; +import * as Cell from '../../../cell'; + +export function ChangelogListItem() { + const history = useHistory(); + const navigate = useCallback(() => history.push(RoutePath.changelog), [history]); + + return ( + + {messages.pgettext('settings-view', "What's new")} + + ); +} diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/index.ts b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/index.ts new file mode 100644 index 000000000000..905bc4539720 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/components/index.ts @@ -0,0 +1,2 @@ +export * from './AppVersionListItem'; +export * from './ChangelogListItem'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/index.ts b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/index.ts new file mode 100644 index 000000000000..afbe9686f695 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/app-info/index.ts @@ -0,0 +1 @@ +export * from './AppInfoView'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx new file mode 100644 index 000000000000..dd81c8556870 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx @@ -0,0 +1,106 @@ +import { useCallback } from 'react'; +import styled from 'styled-components'; + +import { links } from '../../../../config.json'; +import { messages } from '../../../../shared/gettext'; +import { useAppContext } from '../../../context'; +import { useHistory } from '../../../lib/history'; +import { useSelector } from '../../../redux/store'; +import { Colors, Spacings } from '../../../tokens'; +import { Flex } from '../../common/layout'; +import { Container } from '../../common/layout/Container'; +import { Button } from '../../common/molecules/Button'; +import { BodySmall, TitleBig, TitleLarge } from '../../common/text'; +import ImageView from '../../ImageView'; +import { BackAction } from '../../KeyboardNavigation'; +import { Layout, SettingsContainer } from '../../Layout'; +import { + NavigationBar, + NavigationContainer, + NavigationItems, + NavigationScrollbars, + TitleBarItem, +} from '../../NavigationBar'; +import SettingsHeader from '../../SettingsHeader'; + +const StyledList = styled(Flex)({ + listStyleType: 'disc', + paddingLeft: 0, + li: { + marginLeft: '1.5em', + }, +}); + +const StyledFooter = styled(Flex)({ + position: 'sticky', + minHeight: '64px', + bottom: 0, + background: Colors.darkBlue, +}); + +export const ChangelogView = () => { + const { pop } = useHistory(); + const { openUrl } = useAppContext(); + const changelog = useSelector((state) => state.userInterface.changelog); + const version = useSelector((state) => state.version.current); + + const url = links.download; + const openDownloadLink = useCallback(() => openUrl(url), [openUrl, url]); + return ( + + + + + + + {messages.pgettext('changelog-view', "What's new")} + + + + + + {messages.pgettext('changelog-view', "What's new")} + + + + {version} + + + {!changelog.length ? ( + + {changelog.map((item, i) => ( + + {item} + + ))} + + ) : ( + + {messages.pgettext( + 'changelog-view', + 'No updates or changes were made in this release for this platform.', + )} + + )} + + + + + + + + + + + ); +}; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/index.ts b/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/index.ts new file mode 100644 index 000000000000..2c823d4f13fd --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/index.ts @@ -0,0 +1 @@ +export * from './ChangelogView'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/index.ts b/desktop/packages/mullvad-vpn/src/renderer/components/views/index.ts new file mode 100644 index 000000000000..dff5aa7a90ba --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/index.ts @@ -0,0 +1,2 @@ +export * from './app-info'; +export * from './changelog'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/routes.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/routes.ts index 89b50c1fb0e0..73f510ea3ac5 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/lib/routes.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/routes.ts @@ -31,4 +31,6 @@ export enum RoutePath { selectLocation = '/select-location', editCustomBridge = '/select-location/edit-custom-bridge', filter = '/select-location/filter', + appInfo = '/settings/app-info', + changelog = '/settings/changelog', } diff --git a/desktop/packages/mullvad-vpn/src/shared/localization-contexts.ts b/desktop/packages/mullvad-vpn/src/shared/localization-contexts.ts index f30212025cea..c4d47b1afa7a 100644 --- a/desktop/packages/mullvad-vpn/src/shared/localization-contexts.ts +++ b/desktop/packages/mullvad-vpn/src/shared/localization-contexts.ts @@ -37,4 +37,6 @@ export type LocalizationContexts = | 'select-language-nav' | 'tray-icon-context-menu' | 'tray-icon-tooltip' - | 'troubleshoot'; + | 'troubleshoot' + | 'app-info-view' + | 'changelog-view'; From 0edea8cc7659a18f9c321e3b2a6fa8ced2144cea Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:25:11 +0100 Subject: [PATCH 08/15] Use Button component in connection panel --- .../src/renderer/components/MultiButton.tsx | 31 ++++++++---------- .../main-view/ConnectionActionButton.tsx | 17 ++++------ .../main-view/SelectLocationButton.tsx | 32 ++++++------------- 3 files changed, 30 insertions(+), 50 deletions(-) diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/MultiButton.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/MultiButton.tsx index 3129abcbb220..ef002c023d9b 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/MultiButton.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/MultiButton.tsx @@ -1,42 +1,39 @@ import React from 'react'; import styled from 'styled-components'; -const SIDE_BUTTON_WIDTH = 44; +import { ButtonProps } from './common/molecules'; const ButtonRow = styled.div({ display: 'flex', - flexDirection: 'row', + gap: '1px', }); const MainButton = styled.button({ - display: 'flex', - flex: 1, borderTopRightRadius: 0, borderBottomRightRadius: 0, + paddingLeft: '44px', + '&:focus-visible': { + zIndex: 10, + }, }); const SideButton = styled.button({ - display: 'flex', borderTopLeftRadius: 0, borderBottomLeftRadius: 0, - width: SIDE_BUTTON_WIDTH, - marginLeft: '1px !important', + '&:focus-visible': { + zIndex: 10, + }, }); -export interface MultiButtonCompatibleProps { - className?: string; - textOffset?: number; -} - -interface IMultiButtonProps { - mainButton: React.ComponentType; - sideButton: React.ComponentType; +interface MultiButtonProps { + mainButton: React.ComponentType; + sideButton: React.ComponentType; } -export function MultiButton(props: IMultiButtonProps) { +export function MultiButton(props: MultiButtonProps) { return ( - + ); diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/main-view/ConnectionActionButton.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/main-view/ConnectionActionButton.tsx index 437fa933216a..b0466d0d0772 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/main-view/ConnectionActionButton.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/main-view/ConnectionActionButton.tsx @@ -1,15 +1,10 @@ import { useCallback } from 'react'; -import styled from 'styled-components'; import { messages } from '../../../shared/gettext'; import log from '../../../shared/logging'; import { useAppContext } from '../../context'; import { useSelector } from '../../redux/store'; -import { SmallButton, SmallButtonColor } from '../SmallButton'; - -const StyledConnectionButton = styled(SmallButton)({ - margin: 0, -}); +import { Button } from '../common/molecules/Button'; export default function ConnectionActionButton() { const tunnelState = useSelector((state) => state.connection.status.state); @@ -21,7 +16,7 @@ export default function ConnectionActionButton() { } } -function ConnectButton(props: Partial[0]>) { +function ConnectButton(props: Partial[0]>) { const { connectTunnel } = useAppContext(); const onConnect = useCallback(async () => { @@ -34,9 +29,9 @@ function ConnectButton(props: Partial[0]>) { }, [connectTunnel]); return ( - + ); } @@ -56,8 +51,8 @@ function DisconnectButton() { const displayAsCancel = tunnelState !== 'connected'; return ( - + ); } diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/main-view/SelectLocationButton.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/main-view/SelectLocationButton.tsx index 50508a319270..7a6ab7d9687c 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/main-view/SelectLocationButton.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/main-view/SelectLocationButton.tsx @@ -1,6 +1,5 @@ import { useCallback, useMemo } from 'react'; import { sprintf } from 'sprintf-js'; -import styled from 'styled-components'; import { ICustomList } from '../../../shared/daemon-rpc-types'; import { messages, relayLocations } from '../../../shared/gettext'; @@ -10,17 +9,9 @@ import { transitions, useHistory } from '../../lib/history'; import { RoutePath } from '../../lib/routes'; import { IRelayLocationCountryRedux, RelaySettingsRedux } from '../../redux/settings/reducers'; import { useSelector } from '../../redux/store'; +import { Button, ButtonProps } from '../common/molecules'; import ImageView from '../ImageView'; -import { MultiButton, MultiButtonCompatibleProps } from '../MultiButton'; -import { SmallButton, SmallButtonColor } from '../SmallButton'; - -const StyledSmallButton = styled(SmallButton)({ - margin: 0, -}); - -const StyledReconnectButton = styled(StyledSmallButton)({ - padding: '4px 8px 4px 8px', -}); +import { MultiButton } from '../MultiButton'; export default function SelectLocationButtons() { const tunnelState = useSelector((state) => state.connection.status.state); @@ -32,7 +23,7 @@ export default function SelectLocationButtons() { } } -function SelectLocationButton(props: MultiButtonCompatibleProps) { +function SelectLocationButton(props: ButtonProps) { const { push } = useHistory(); const tunnelState = useSelector((state) => state.connection.status.state); @@ -50,8 +41,9 @@ function SelectLocationButton(props: MultiButtonCompatibleProps) { }, [push]); return ( - + ); } @@ -119,7 +111,7 @@ function getRelayName( } } -function ReconnectButton(props: MultiButtonCompatibleProps) { +function ReconnectButton(props: ButtonProps) { const { reconnectTunnel } = useAppContext(); const onReconnect = useCallback(async () => { @@ -132,12 +124,8 @@ function ReconnectButton(props: MultiButtonCompatibleProps) { }, [reconnectTunnel]); return ( - + ); } From 94b7493066a7c6b3167873d67133b8f5c13f42c8 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:27:16 +0100 Subject: [PATCH 09/15] Show notification instead of dialog when new version installed --- .../packages/mullvad-vpn/src/main/account.ts | 2 +- .../packages/mullvad-vpn/src/main/index.ts | 1 + .../src/main/notification-controller.ts | 2 +- .../packages/mullvad-vpn/src/main/version.ts | 2 +- .../renderer/components/NotificationArea.tsx | 39 +++++++++-- .../components/NotificationBanner.tsx | 11 +-- .../src/renderer/components/Settings.tsx | 68 +++---------------- .../src/renderer/components/SmallButton.tsx | 6 +- .../src/shared/notifications/index.ts | 14 ++++ .../src/shared/notifications/new-version.ts | 44 ++++++++++++ .../src/shared/notifications/notification.ts | 22 +++--- .../test/unit/notification-evaluation.spec.ts | 2 +- 12 files changed, 128 insertions(+), 85 deletions(-) create mode 100644 desktop/packages/mullvad-vpn/src/shared/notifications/index.ts create mode 100644 desktop/packages/mullvad-vpn/src/shared/notifications/new-version.ts diff --git a/desktop/packages/mullvad-vpn/src/main/account.ts b/desktop/packages/mullvad-vpn/src/main/account.ts index 024e4a7208aa..7fc6b48d4700 100644 --- a/desktop/packages/mullvad-vpn/src/main/account.ts +++ b/desktop/packages/mullvad-vpn/src/main/account.ts @@ -13,7 +13,7 @@ import { AccountExpiredNotificationProvider, CloseToAccountExpiryNotificationProvider, SystemNotificationCategory, -} from '../shared/notifications/notification'; +} from '../shared/notifications'; import { Scheduler } from '../shared/scheduler'; import AccountDataCache from './account-data-cache'; import { DaemonRpc } from './daemon-rpc'; diff --git a/desktop/packages/mullvad-vpn/src/main/index.ts b/desktop/packages/mullvad-vpn/src/main/index.ts index ea2f12199c1c..efbd5e1654ae 100644 --- a/desktop/packages/mullvad-vpn/src/main/index.ts +++ b/desktop/packages/mullvad-vpn/src/main/index.ts @@ -363,6 +363,7 @@ class ApplicationMain this.daemonRpc.disconnect(); } + this.settings.gui.changelogDisplayedForVersion = this.version.currentVersion.gui; for (const logger of [log, this.rendererLog]) { try { logger?.disposeDisposableOutputs(); diff --git a/desktop/packages/mullvad-vpn/src/main/notification-controller.ts b/desktop/packages/mullvad-vpn/src/main/notification-controller.ts index 925bff081246..664f10270909 100644 --- a/desktop/packages/mullvad-vpn/src/main/notification-controller.ts +++ b/desktop/packages/mullvad-vpn/src/main/notification-controller.ts @@ -16,7 +16,7 @@ import { SystemNotificationCategory, SystemNotificationProvider, SystemNotificationSeverityType, -} from '../shared/notifications/notification'; +} from '../shared/notifications'; import { Scheduler } from '../shared/scheduler'; const THROTTLE_DELAY = 500; diff --git a/desktop/packages/mullvad-vpn/src/main/version.ts b/desktop/packages/mullvad-vpn/src/main/version.ts index 1bab7728b414..676391e15069 100644 --- a/desktop/packages/mullvad-vpn/src/main/version.ts +++ b/desktop/packages/mullvad-vpn/src/main/version.ts @@ -8,7 +8,7 @@ import { SystemNotificationCategory, UnsupportedVersionNotificationProvider, UpdateAvailableNotificationProvider, -} from '../shared/notifications/notification'; +} from '../shared/notifications'; import { DaemonRpc } from './daemon-rpc'; import { IpcMainEventChannel } from './ipc-event-channel'; import { NotificationSender } from './notification-controller'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx index dac62db192e6..6aac11c9d519 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx @@ -1,9 +1,7 @@ import { useCallback, useState } from 'react'; -import { useSelector } from 'react-redux'; import { messages } from '../../shared/gettext'; import log from '../../shared/logging'; -import { NewDeviceNotificationProvider } from '../../shared/notifications/new-device'; import { BlockWhenDisconnectedNotificationProvider, CloseToAccountExpiryNotificationProvider, @@ -13,18 +11,22 @@ import { InAppNotificationProvider, InAppNotificationTroubleshootInfo, InconsistentVersionNotificationProvider, + NewVersionNotificationProvider, ReconnectingNotificationProvider, UnsupportedVersionNotificationProvider, UpdateAvailableNotificationProvider, -} from '../../shared/notifications/notification'; +} from '../../shared/notifications'; +import { NewDeviceNotificationProvider } from '../../shared/notifications/new-device'; import { useAppContext } from '../context'; import useActions from '../lib/actionsHook'; import { transitions, useHistory } from '../lib/history'; import { formatHtml } from '../lib/html-formatter'; import { RoutePath } from '../lib/routes'; import accountActions from '../redux/account/actions'; -import { IReduxState } from '../redux/store'; +import { IReduxState, useSelector } from '../redux/store'; +import { Colors } from '../tokens'; import * as AppButton from './AppButton'; +import { Link } from './common/text'; import { ModalAlert, ModalAlertType, ModalMessage, ModalMessageList } from './Modal'; import { NotificationActions, @@ -59,6 +61,18 @@ export default function NotificationArea(props: IProps) { const { hideNewDeviceBanner } = useActions(accountActions); + const { setDisplayedChangelog } = useAppContext(); + + const currentVersion = useSelector((state) => state.version.current); + const displayedForVersion = useSelector( + (state) => state.settings.guiSettings.changelogDisplayedForVersion, + ); + const changelog = useSelector((state) => state.userInterface.changelog); + + const close = useCallback(() => { + setDisplayedChangelog(); + }, [setDisplayedChangelog]); + const notificationProviders: InAppNotificationProvider[] = [ new ConnectingNotificationProvider({ tunnelState }), new ReconnectingNotificationProvider(tunnelState), @@ -84,6 +98,12 @@ export default function NotificationArea(props: IProps) { deviceName: account.deviceName ?? '', close: hideNewDeviceBanner, }), + new NewVersionNotificationProvider({ + currentVersion, + displayedForVersion, + changelog, + close, + }), new UpdateAvailableNotificationProvider(version), ); @@ -106,7 +126,16 @@ export default function NotificationArea(props: IProps) { {notification.title} - {formatHtml(notification.subtitle ?? '')} + {notification.subtitleAction?.type === 'navigate' ? ( + + {formatHtml(notification.subtitle ?? '')} + + ) : ( + formatHtml(notification.subtitle ?? '') + )} {notification.action && } diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationBanner.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationBanner.tsx index 924f65ff9914..12f9fbef6e35 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationBanner.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationBanner.tsx @@ -6,6 +6,7 @@ import { messages } from '../../shared/gettext'; import { InAppNotificationIndicatorType } from '../../shared/notifications/notification'; import { useEffectEvent, useLastDefinedValue, useStyledRef } from '../lib/utility-hooks'; import * as AppButton from './AppButton'; +import { IconButton } from './common/molecules'; import { tinyText } from './common-styles'; import ImageView from './ImageView'; @@ -81,12 +82,14 @@ export function NotificationTroubleshootDialogAction(props: NotificationActionPr export function NotificationCloseAction(props: NotificationActionProps) { return ( - - - + onClick={props.onClick} + icon="icon-close" + size="small" + variant="secondary" + /> ); } diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx index 15f760941f32..2bc05a5f0445 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/Settings.tsx @@ -2,20 +2,17 @@ import { useCallback } from 'react'; import { strings } from '../../config.json'; import { messages } from '../../shared/gettext'; -import { getDownloadUrl } from '../../shared/version'; import { useAppContext } from '../context'; import { useHistory } from '../lib/history'; import { RoutePath } from '../lib/routes'; import { useSelector } from '../redux/store'; -import { Colors } from '../tokens'; -import { RedButton } from './AppButton'; import * as Cell from './cell'; +import { Button } from './common/molecules/Button'; import { TitleBig } from './common/text'; import { BackAction } from './KeyboardNavigation'; import { ButtonStack, Footer, - LabelStack, Layout, SettingsContainer, SettingsContent, @@ -86,7 +83,7 @@ export default function Support() { - + {window.env.development && ( @@ -204,59 +201,16 @@ function ApiAccessMethodsButton() { ); } -function AppVersionButton() { +function AppInfoButton() { + const history = useHistory(); + const navigate = useCallback(() => history.push(RoutePath.appInfo), [history]); const appVersion = useSelector((state) => state.version.current); - const consistentVersion = useSelector((state) => state.version.consistent); - const upToDateVersion = useSelector((state) => (state.version.suggestedUpgrade ? false : true)); - const suggestedIsBeta = useSelector((state) => state.version.suggestedIsBeta ?? false); - const isOffline = useSelector((state) => state.connection.isBlocked); - - const { openUrl } = useAppContext(); - const openDownloadLink = useCallback( - () => openUrl(getDownloadUrl(suggestedIsBeta)), - [openUrl, suggestedIsBeta], - ); - - let alertIcon; - let footer; - if (!consistentVersion || !upToDateVersion) { - const inconsistentVersionMessage = messages.pgettext( - 'settings-view', - 'App is out of sync. Please quit and restart.', - ); - - const updateAvailableMessage = messages.pgettext( - 'settings-view', - 'Update available. Install the latest app version to stay up to date.', - ); - - const message = !consistentVersion ? inconsistentVersionMessage : updateAvailableMessage; - - alertIcon = ; - footer = ( - - {message} - - ); - } return ( - <> - - - {alertIcon} - {messages.pgettext('settings-view', 'App version')} - - {appVersion} - - {footer} - + + {messages.pgettext('settings-view', 'App info')} + {appVersion} + ); } @@ -287,10 +241,10 @@ function QuitButton() { const tunnelState = useSelector((state) => state.connection.status); return ( - + ); } diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/SmallButton.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/SmallButton.tsx index c91fbbdb204c..b9ce4a6a59c7 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/SmallButton.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/SmallButton.tsx @@ -3,7 +3,6 @@ import styled from 'styled-components'; import { colors } from '../../config.json'; import { smallText } from './common-styles'; -import { MultiButtonCompatibleProps } from './MultiButton'; export enum SmallButtonColor { blue, @@ -84,6 +83,11 @@ const StyledTextOffset = styled.span<{ $width: number }>((props) => ({ flex: `0 1 ${props.$width}px`, })); +export interface MultiButtonCompatibleProps { + className?: string; + textOffset?: number; +} + interface SmallButtonProps extends Omit, 'onClick' | 'color'>, MultiButtonCompatibleProps { diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/index.ts b/desktop/packages/mullvad-vpn/src/shared/notifications/index.ts new file mode 100644 index 000000000000..615ce4225023 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/shared/notifications/index.ts @@ -0,0 +1,14 @@ +export * from './account-expired'; +export * from './close-to-account-expiry'; +export * from './block-when-disconnected'; +export * from './connected'; +export * from './connecting'; +export * from './disconnected'; +export * from './daemon-disconnected'; +export * from './error'; +export * from './inconsistent-version'; +export * from './new-version'; +export * from './notification'; +export * from './reconnecting'; +export * from './unsupported-version'; +export * from './update-available'; diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/new-version.ts b/desktop/packages/mullvad-vpn/src/shared/notifications/new-version.ts new file mode 100644 index 000000000000..991266adbe59 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/shared/notifications/new-version.ts @@ -0,0 +1,44 @@ +import { RoutePath } from '../../renderer/lib/routes'; +import { messages } from '../gettext'; +import { IChangelog } from '../ipc-types'; +import { InAppNotification, InAppNotificationProvider } from './notification'; + +interface NewVersionNotificationContext { + currentVersion: string; + displayedForVersion: string; + changelog: IChangelog; + close: () => void; +} + +export class NewVersionNotificationProvider implements InAppNotificationProvider { + public constructor(private context: NewVersionNotificationContext) {} + + public mayDisplay = () => { + return ( + this.context.displayedForVersion !== this.context.currentVersion && + this.context.changelog.length > 0 + ); + }; + + public getInAppNotification(): InAppNotification { + const title = messages.pgettext('in-app-notifications', 'NEW VERSION INSTALLED'); + const subtitle = messages.pgettext('in-app-notifications', "Click here to see what's new."); + return { + indicator: 'success', + action: { type: 'close', close: this.context.close }, + title, + subtitle, + subtitleAction: { + type: 'navigate', + link: { + to: RoutePath.changelog, + onClick: this.context.close, + 'aria-label': messages.pgettext( + 'accessibility', + 'New version installed, click here to see the changelog', + ), + }, + }, + }; + } +} diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/notification.ts b/desktop/packages/mullvad-vpn/src/shared/notifications/notification.ts index 87166aab4d57..96754811a644 100644 --- a/desktop/packages/mullvad-vpn/src/shared/notifications/notification.ts +++ b/desktop/packages/mullvad-vpn/src/shared/notifications/notification.ts @@ -1,3 +1,5 @@ +import { LinkProps } from '../../renderer/components/common/text'; + export type NotificationAction = { type: 'open-url'; url: string; @@ -25,6 +27,10 @@ export type InAppNotificationAction = | { type: 'close'; close: () => void; + } + | { + type: 'navigate'; + link: Pick; }; export type InAppNotificationIndicatorType = 'success' | 'warning' | 'error'; @@ -59,9 +65,10 @@ export interface SystemNotification { export interface InAppNotification { indicator?: InAppNotificationIndicatorType; + action?: InAppNotificationAction; title: string; subtitle?: string; - action?: InAppNotificationAction; + subtitleAction?: InAppNotificationAction; } export interface SystemNotificationProvider extends NotificationProvider { @@ -71,16 +78,3 @@ export interface SystemNotificationProvider extends NotificationProvider { export interface InAppNotificationProvider extends NotificationProvider { getInAppNotification(): InAppNotification | undefined; } - -export * from './account-expired'; -export * from './close-to-account-expiry'; -export * from './block-when-disconnected'; -export * from './connected'; -export * from './connecting'; -export * from './disconnected'; -export * from './daemon-disconnected'; -export * from './error'; -export * from './inconsistent-version'; -export * from './reconnecting'; -export * from './unsupported-version'; -export * from './update-available'; diff --git a/desktop/packages/mullvad-vpn/test/unit/notification-evaluation.spec.ts b/desktop/packages/mullvad-vpn/test/unit/notification-evaluation.spec.ts index d05e967efc55..50acda1393d7 100644 --- a/desktop/packages/mullvad-vpn/test/unit/notification-evaluation.spec.ts +++ b/desktop/packages/mullvad-vpn/test/unit/notification-evaluation.spec.ts @@ -9,7 +9,7 @@ import { FirewallPolicyErrorType } from '../../src/shared/daemon-rpc-types'; import { UnsupportedVersionNotificationProvider, UpdateAvailableNotificationProvider, -} from '../../src/shared/notifications/notification'; +} from '../../src/shared/notifications'; function createController() { return new NotificationController({ From fc4394b9188893faf67e2ea4c5894639e1d1bfc5 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:32:52 +0100 Subject: [PATCH 10/15] Hide inconsistent version notification in development --- .../src/shared/notifications/inconsistent-version.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/inconsistent-version.ts b/desktop/packages/mullvad-vpn/src/shared/notifications/inconsistent-version.ts index e4f7a8ddc10d..4cfed9f77701 100644 --- a/desktop/packages/mullvad-vpn/src/shared/notifications/inconsistent-version.ts +++ b/desktop/packages/mullvad-vpn/src/shared/notifications/inconsistent-version.ts @@ -17,7 +17,10 @@ export class InconsistentVersionNotificationProvider { public constructor(private context: InconsistentVersionNotificationContext) {} - public mayDisplay = () => !this.context.consistent; + public mayDisplay = () => + !this.context.consistent && + process.env.NODE_ENV !== undefined && + process.env.NODE_ENV !== 'development'; public getSystemNotification(): SystemNotification { return { From 78164ab65ead6857cc061e1b10d805e1e996d359 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:45:39 +0100 Subject: [PATCH 11/15] Remove Changelog component --- .../packages/mullvad-vpn/src/renderer/app.tsx | 2 - .../src/renderer/components/Changelog.tsx | 78 ------------------- 2 files changed, 80 deletions(-) delete mode 100644 desktop/packages/mullvad-vpn/src/renderer/components/Changelog.tsx diff --git a/desktop/packages/mullvad-vpn/src/renderer/app.tsx b/desktop/packages/mullvad-vpn/src/renderer/app.tsx index 7c7b0edbfaac..243cce4633c2 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/app.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/app.tsx @@ -39,7 +39,6 @@ import log, { ConsoleOutput } from '../shared/logging'; import { LogLevel } from '../shared/logging-types'; import { Scheduler } from '../shared/scheduler'; import AppRouter from './components/AppRouter'; -import { Changelog } from './components/Changelog'; import ErrorBoundary from './components/ErrorBoundary'; import KeyboardNavigation from './components/KeyboardNavigation'; import Lang from './components/Lang'; @@ -297,7 +296,6 @@ export default class AppRenderer { - {window.env.platform === 'darwin' && } diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/Changelog.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/Changelog.tsx deleted file mode 100644 index ea1b42f5c229..000000000000 --- a/desktop/packages/mullvad-vpn/src/renderer/components/Changelog.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { useCallback } from 'react'; -import styled from 'styled-components'; - -import { messages } from '../../shared/gettext'; -import { useAppContext } from '../context'; -import { useBoolean } from '../lib/utility-hooks'; -import { useSelector } from '../redux/store'; -import * as AppButton from './AppButton'; -import { hugeText, smallText } from './common-styles'; -import { ModalAlert, ModalMessage } from './Modal'; - -const StyledTitle = styled.h1(hugeText, { - textAlign: 'center', - margin: '7px 0 4px', -}); - -const StyledSubTitle = styled.span(smallText, { - marginTop: '10px', - fontWeight: 700, -}); - -const StyledList = styled.ul({ - listStyle: 'disc outside', - marginLeft: '20px', -}); - -const StyledMessage = styled(ModalMessage)({ - fontSize: '12px', - marginTop: '6px', -}); - -export function Changelog() { - const currentVersion = useSelector((state) => state.version.current); - const changelogDisplayedForVersion = useSelector( - (state) => state.settings.guiSettings.changelogDisplayedForVersion, - ); - const changelog = useSelector((state) => state.userInterface.changelog); - const initialForceShowChanges = useSelector((state) => state.userInterface.forceShowChanges); - - const { setDisplayedChangelog } = useAppContext(); - - const [forceShowChanges, , stopForceShowChanges] = useBoolean(initialForceShowChanges); - - const close = useCallback(() => { - setDisplayedChangelog(); - stopForceShowChanges(); - }, [setDisplayedChangelog, stopForceShowChanges]); - - const visible = - forceShowChanges || - (changelogDisplayedForVersion !== currentVersion && - changelog.length > 0 && - !window.env.development && - !/-dev-[0-9a-f]{6}$/.test(currentVersion)); - - return ( - - { - // TRANSLATORS: This is a button which closes a dialog. - messages.gettext('Got it!') - } - , - ]}> - {currentVersion} - {messages.pgettext('changelog', 'Changes in this version:')} - - - {changelog.map((item, i) => ( -
  • {item}
  • - ))} -
    -
    -
    - ); -} From 5dd382c8284df89c049ec75f81aa8b279a25cfde Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:51:59 +0100 Subject: [PATCH 12/15] Remove forceShowChanges and related logic --- desktop/packages/mullvad-vpn/src/main/index.ts | 1 - desktop/packages/mullvad-vpn/src/renderer/app.tsx | 5 ++--- .../src/renderer/redux/userinterface/actions.ts | 14 -------------- .../src/renderer/redux/userinterface/reducers.ts | 8 -------- .../packages/mullvad-vpn/src/shared/ipc-schema.ts | 1 - .../packages/mullvad-vpn/test/e2e/setup/main.ts | 1 - 6 files changed, 2 insertions(+), 28 deletions(-) diff --git a/desktop/packages/mullvad-vpn/src/main/index.ts b/desktop/packages/mullvad-vpn/src/main/index.ts index efbd5e1654ae..f855278ba922 100644 --- a/desktop/packages/mullvad-vpn/src/main/index.ts +++ b/desktop/packages/mullvad-vpn/src/main/index.ts @@ -787,7 +787,6 @@ class ApplicationMain splitTunnelingApplications: this.splitTunnelingApplications, macOsScrollbarVisibility: this.macOsScrollbarVisibility, changelog: this.changelog ?? [], - forceShowChanges: CommandLineOptions.showChanges.match, navigationHistory: this.navigationHistory, currentApiAccessMethod: this.currentApiAccessMethod, isMacOs13OrNewer: isMacOs13OrNewer(), diff --git a/desktop/packages/mullvad-vpn/src/renderer/app.tsx b/desktop/packages/mullvad-vpn/src/renderer/app.tsx index 243cce4633c2..a71df61f56f7 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/app.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/app.tsx @@ -242,7 +242,7 @@ export default class AppRenderer { this.setUpgradeVersion(initialState.upgradeVersion); this.setGuiSettings(initialState.guiSettings); this.storeAutoStart(initialState.autoStart); - this.setChangelog(initialState.changelog, initialState.forceShowChanges); + this.setChangelog(initialState.changelog); this.setCurrentApiAccessMethod(initialState.currentApiAccessMethod); this.reduxActions.userInterface.setIsMacOs13OrNewer(initialState.isMacOs13OrNewer); @@ -1000,9 +1000,8 @@ export default class AppRenderer { this.reduxActions.settings.updateAutoStart(autoStart); } - private setChangelog(changelog: IChangelog, forceShowChanges: boolean) { + private setChangelog(changelog: IChangelog) { this.reduxActions.userInterface.setChangelog(changelog); - this.reduxActions.userInterface.setForceShowChanges(forceShowChanges); } private updateLocation() { diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts index 238835318e3a..83c0252452b1 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/actions.ts @@ -41,11 +41,6 @@ export interface ISetChangelog { changelog: IChangelog; } -export interface ISetForceShowChanges { - type: 'SET_FORCE_SHOW_CHANGES'; - forceShowChanges: boolean; -} - export interface ISetIsPerformingPostUpgrade { type: 'SET_IS_PERFORMING_POST_UPGRADE'; isPerformingPostUpgrade: boolean; @@ -70,7 +65,6 @@ export type UserInterfaceAction = | ISetConnectedToDaemon | ISetDaemonAllowed | ISetChangelog - | ISetForceShowChanges | ISetIsPerformingPostUpgrade | ISetSelectLocationView | ISetIsMacOs13OrNewer; @@ -132,13 +126,6 @@ function setChangelog(changelog: IChangelog): ISetChangelog { }; } -function setForceShowChanges(forceShowChanges: boolean): ISetForceShowChanges { - return { - type: 'SET_FORCE_SHOW_CHANGES', - forceShowChanges, - }; -} - function setIsPerformingPostUpgrade(isPerformingPostUpgrade: boolean): ISetIsPerformingPostUpgrade { return { type: 'SET_IS_PERFORMING_POST_UPGRADE', @@ -169,7 +156,6 @@ export default { setConnectedToDaemon, setDaemonAllowed, setChangelog, - setForceShowChanges, setIsPerformingPostUpgrade, setSelectLocationView, setIsMacOs13OrNewer, diff --git a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts index 89427e9b06e4..46bdfc630851 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/redux/userinterface/reducers.ts @@ -12,7 +12,6 @@ export interface IUserInterfaceReduxState { connectedToDaemon: boolean; daemonAllowed?: boolean; changelog: IChangelog; - forceShowChanges: boolean; isPerformingPostUpgrade: boolean; selectLocationView: LocationType; isMacOs13OrNewer: boolean; @@ -26,7 +25,6 @@ const initialState: IUserInterfaceReduxState = { connectedToDaemon: false, daemonAllowed: undefined, changelog: [], - forceShowChanges: false, isPerformingPostUpgrade: false, selectLocationView: LocationType.exit, isMacOs13OrNewer: true, @@ -64,12 +62,6 @@ export default function ( changelog: action.changelog, }; - case 'SET_FORCE_SHOW_CHANGES': - return { - ...state, - forceShowChanges: action.forceShowChanges, - }; - case 'SET_IS_PERFORMING_POST_UPGRADE': return { ...state, diff --git a/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts b/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts index 856239c0f556..3580c679f30e 100644 --- a/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts +++ b/desktop/packages/mullvad-vpn/src/shared/ipc-schema.ts @@ -73,7 +73,6 @@ export interface IAppStateSnapshot { splitTunnelingApplications?: ISplitTunnelingApplication[]; macOsScrollbarVisibility?: MacOsScrollbarVisibility; changelog: IChangelog; - forceShowChanges: boolean; navigationHistory?: IHistoryObject; currentApiAccessMethod?: AccessMethodSetting; isMacOs13OrNewer: boolean; diff --git a/desktop/packages/mullvad-vpn/test/e2e/setup/main.ts b/desktop/packages/mullvad-vpn/test/e2e/setup/main.ts index d8f3ceee48f4..1795451046a9 100644 --- a/desktop/packages/mullvad-vpn/test/e2e/setup/main.ts +++ b/desktop/packages/mullvad-vpn/test/e2e/setup/main.ts @@ -171,7 +171,6 @@ class ApplicationMain { splitTunnelingApplications: [], macOsScrollbarVisibility: MacOsScrollbarVisibility.whenScrolling, changelog: [], - forceShowChanges: false, navigationHistory: undefined, scrollPositions: {}, isMacOs13OrNewer: true, From cf8c066f1d542c6317869ca60c7984226ef80330 Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 14:56:59 +0100 Subject: [PATCH 13/15] Add link to changelog --- desktop/packages/mullvad-vpn/src/config.json | 3 ++- .../src/renderer/components/views/changelog/ChangelogView.tsx | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/desktop/packages/mullvad-vpn/src/config.json b/desktop/packages/mullvad-vpn/src/config.json index a77c47de4501..43229834cae4 100644 --- a/desktop/packages/mullvad-vpn/src/config.json +++ b/desktop/packages/mullvad-vpn/src/config.json @@ -4,7 +4,8 @@ "purchase": "https://mullvad.net/account/", "faq": "https://mullvad.net/help/tag/mullvad-app/", "privacyGuide": "https://mullvad.net/help/first-steps-towards-online-privacy/", - "download": "https://mullvad.net/download/vpn/" + "download": "https://mullvad.net/download/vpn/", + "changelog": "https://github.com/mullvad/mullvadvpn-app/blob/main/CHANGELOG.md" }, "colors": { "darkerBlue": "rgba(25, 38, 56, 0.95)", diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx index dd81c8556870..262f7c4bafd5 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/views/changelog/ChangelogView.tsx @@ -44,7 +44,7 @@ export const ChangelogView = () => { const changelog = useSelector((state) => state.userInterface.changelog); const version = useSelector((state) => state.version.current); - const url = links.download; + const url = links.changelog; const openDownloadLink = useCallback(() => openUrl(url), [openUrl, url]); return ( From ed613617eedd739f06183617fa8f423e5b5b260d Mon Sep 17 00:00:00 2001 From: Oliver Date: Tue, 10 Dec 2024 17:03:27 +0100 Subject: [PATCH 14/15] Update translations --- .../packages/mullvad-vpn/locales/messages.pot | 59 ++++++++++++++----- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/desktop/packages/mullvad-vpn/locales/messages.pot b/desktop/packages/mullvad-vpn/locales/messages.pot index 9e311321aeae..9b10ccf527d7 100644 --- a/desktop/packages/mullvad-vpn/locales/messages.pot +++ b/desktop/packages/mullvad-vpn/locales/messages.pot @@ -167,7 +167,6 @@ msgstr "" msgid "Go to System Settings" msgstr "" -#. This is a button which closes a dialog. msgid "Got it!" msgstr "" @@ -342,6 +341,10 @@ msgctxt "accessibility" msgid "More information" msgstr "" +msgctxt "accessibility" +msgid "New version installed, click here to see the changelog" +msgstr "" + msgctxt "accessibility" msgid "Opens externally" msgstr "" @@ -578,6 +581,22 @@ msgctxt "api-access-methods-view" msgid "With the “Mullvad bridges” method, the app communicates with a Mullvad API server via a Mullvad bridge server. It does this by sending the traffic obfuscated by Shadowsocks." msgstr "" +msgctxt "app-info-view" +msgid "App info" +msgstr "" + +msgctxt "app-info-view" +msgid "App is out of sync. Please quit and restart." +msgstr "" + +msgctxt "app-info-view" +msgid "App version" +msgstr "" + +msgctxt "app-info-view" +msgid "Update available. Install the latest app version to stay up to date." +msgstr "" + msgctxt "auth-failure" msgid "Blocking internet: account is out of time" msgstr "" @@ -595,7 +614,15 @@ msgid "You are logged in with an invalid account number. Please log out and try msgstr "" msgctxt "changelog" -msgid "Changes in this version:" +msgid "See full changelog" +msgstr "" + +msgctxt "changelog-view" +msgid "No updates or changes were made in this release for this platform." +msgstr "" + +msgctxt "changelog-view" +msgid "What's new" msgstr "" #. The selected location label displayed on the main view, when a user selected a specific host to connect to. @@ -884,6 +911,10 @@ msgctxt "in-app-notifications" msgid "BLOCKING INTERNET" msgstr "" +msgctxt "in-app-notifications" +msgid "Click here to see what's new." +msgstr "" + #. The in-app banner displayed to the user when the app update is available. msgctxt "in-app-notifications" msgid "Install the latest app version to stay up to date." @@ -897,6 +928,10 @@ msgctxt "in-app-notifications" msgid "NEW DEVICE CREATED" msgstr "" +msgctxt "in-app-notifications" +msgid "NEW VERSION INSTALLED" +msgstr "" + msgctxt "in-app-notifications" msgid "Please quit and restart the app." msgstr "" @@ -1522,11 +1557,7 @@ msgid "API access" msgstr "" msgctxt "settings-view" -msgid "App is out of sync. Please quit and restart." -msgstr "" - -msgctxt "settings-view" -msgid "App version" +msgid "App info" msgstr "" msgctxt "settings-view" @@ -1537,10 +1568,6 @@ msgctxt "settings-view" msgid "Support" msgstr "" -msgctxt "settings-view" -msgid "Update available. Install the latest app version to stay up to date." -msgstr "" - #. Navigation button to the 'User interface settings' view msgctxt "settings-view" msgid "User interface settings" @@ -1551,6 +1578,10 @@ msgctxt "settings-view" msgid "VPN settings" msgstr "" +msgctxt "settings-view" +msgid "What's new" +msgstr "" + msgctxt "split-tunneling-view" msgid "%(applicationName)s is problematic and can’t be excluded from the VPN tunnel." msgstr "" @@ -2305,9 +2336,6 @@ msgstr "" msgid "Always-on VPN assigned to other VPN" msgstr "" -msgid "App info" -msgstr "" - msgid "At least one method needs to be enabled" msgstr "" @@ -2344,6 +2372,9 @@ msgstr "" msgid "Changelog" msgstr "" +msgid "Changes in this version:" +msgstr "" + msgid "Changes to DNS related settings might not go into effect immediately due to cached results." msgstr "" From ad65eb5288fc659d268014767eee8fb251feea91 Mon Sep 17 00:00:00 2001 From: Oliver Date: Wed, 11 Dec 2024 16:14:49 +0100 Subject: [PATCH 15/15] Move renderer specific notifications to renderer folder --- .../src/renderer/components/NotificationArea.tsx | 6 ++++-- .../mullvad-vpn/src/renderer/lib/notifications/index.ts | 2 ++ .../{shared => renderer/lib}/notifications/new-device.ts | 6 +++--- .../{shared => renderer/lib}/notifications/new-version.ts | 8 ++++---- .../mullvad-vpn/src/shared/notifications/index.ts | 1 - 5 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 desktop/packages/mullvad-vpn/src/renderer/lib/notifications/index.ts rename desktop/packages/mullvad-vpn/src/{shared => renderer/lib}/notifications/new-device.ts (80%) rename desktop/packages/mullvad-vpn/src/{shared => renderer/lib}/notifications/new-version.ts (82%) diff --git a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx index 6aac11c9d519..002f23598f41 100644 --- a/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx +++ b/desktop/packages/mullvad-vpn/src/renderer/components/NotificationArea.tsx @@ -11,16 +11,18 @@ import { InAppNotificationProvider, InAppNotificationTroubleshootInfo, InconsistentVersionNotificationProvider, - NewVersionNotificationProvider, ReconnectingNotificationProvider, UnsupportedVersionNotificationProvider, UpdateAvailableNotificationProvider, } from '../../shared/notifications'; -import { NewDeviceNotificationProvider } from '../../shared/notifications/new-device'; import { useAppContext } from '../context'; import useActions from '../lib/actionsHook'; import { transitions, useHistory } from '../lib/history'; import { formatHtml } from '../lib/html-formatter'; +import { + NewDeviceNotificationProvider, + NewVersionNotificationProvider, +} from '../lib/notifications'; import { RoutePath } from '../lib/routes'; import accountActions from '../redux/account/actions'; import { IReduxState, useSelector } from '../redux/store'; diff --git a/desktop/packages/mullvad-vpn/src/renderer/lib/notifications/index.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/notifications/index.ts new file mode 100644 index 000000000000..a03af00d0622 --- /dev/null +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/notifications/index.ts @@ -0,0 +1,2 @@ +export * from './new-device'; +export * from './new-version'; diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/new-device.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/notifications/new-device.ts similarity index 80% rename from desktop/packages/mullvad-vpn/src/shared/notifications/new-device.ts rename to desktop/packages/mullvad-vpn/src/renderer/lib/notifications/new-device.ts index 7d0fe9f29951..f5bd085d89ac 100644 --- a/desktop/packages/mullvad-vpn/src/shared/notifications/new-device.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/notifications/new-device.ts @@ -1,8 +1,8 @@ import { sprintf } from 'sprintf-js'; -import { messages } from '../../shared/gettext'; -import { capitalizeEveryWord } from '../string-helpers'; -import { InAppNotification, InAppNotificationProvider } from './notification'; +import { messages } from '../../../shared/gettext'; +import { InAppNotification, InAppNotificationProvider } from '../../../shared/notifications'; +import { capitalizeEveryWord } from '../../../shared/string-helpers'; interface NewDeviceNotificationContext { shouldDisplay: boolean; diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/new-version.ts b/desktop/packages/mullvad-vpn/src/renderer/lib/notifications/new-version.ts similarity index 82% rename from desktop/packages/mullvad-vpn/src/shared/notifications/new-version.ts rename to desktop/packages/mullvad-vpn/src/renderer/lib/notifications/new-version.ts index 991266adbe59..73ccf615258e 100644 --- a/desktop/packages/mullvad-vpn/src/shared/notifications/new-version.ts +++ b/desktop/packages/mullvad-vpn/src/renderer/lib/notifications/new-version.ts @@ -1,7 +1,7 @@ -import { RoutePath } from '../../renderer/lib/routes'; -import { messages } from '../gettext'; -import { IChangelog } from '../ipc-types'; -import { InAppNotification, InAppNotificationProvider } from './notification'; +import { messages } from '../../../shared/gettext'; +import { IChangelog } from '../../../shared/ipc-types'; +import { InAppNotification, InAppNotificationProvider } from '../../../shared/notifications'; +import { RoutePath } from '../routes'; interface NewVersionNotificationContext { currentVersion: string; diff --git a/desktop/packages/mullvad-vpn/src/shared/notifications/index.ts b/desktop/packages/mullvad-vpn/src/shared/notifications/index.ts index 615ce4225023..5321917af6f3 100644 --- a/desktop/packages/mullvad-vpn/src/shared/notifications/index.ts +++ b/desktop/packages/mullvad-vpn/src/shared/notifications/index.ts @@ -7,7 +7,6 @@ export * from './disconnected'; export * from './daemon-disconnected'; export * from './error'; export * from './inconsistent-version'; -export * from './new-version'; export * from './notification'; export * from './reconnecting'; export * from './unsupported-version';