diff options
Diffstat (limited to 'gui/src')
| -rw-r--r-- | gui/src/main/daemon-rpc.ts | 4 | ||||
| -rw-r--r-- | gui/src/main/default-settings.ts | 1 | ||||
| -rw-r--r-- | gui/src/main/index.ts | 3 | ||||
| -rw-r--r-- | gui/src/main/platform-version.ts | 15 | ||||
| -rw-r--r-- | gui/src/main/settings.ts | 6 | ||||
| -rw-r--r-- | gui/src/renderer/app.tsx | 4 | ||||
| -rw-r--r-- | gui/src/renderer/components/Settings.tsx | 68 | ||||
| -rw-r--r-- | gui/src/renderer/redux/settings/actions.ts | 14 | ||||
| -rw-r--r-- | gui/src/renderer/redux/settings/reducers.ts | 8 | ||||
| -rw-r--r-- | gui/src/renderer/redux/userinterface/actions.ts | 16 | ||||
| -rw-r--r-- | gui/src/renderer/redux/userinterface/reducers.ts | 8 | ||||
| -rw-r--r-- | gui/src/shared/daemon-rpc-types.ts | 1 | ||||
| -rw-r--r-- | gui/src/shared/ipc-schema.ts | 2 |
13 files changed, 143 insertions, 7 deletions
diff --git a/gui/src/main/daemon-rpc.ts b/gui/src/main/daemon-rpc.ts index 1c96be12bb..c09ee1b40a 100644 --- a/gui/src/main/daemon-rpc.ts +++ b/gui/src/main/daemon-rpc.ts @@ -546,6 +546,10 @@ export class DaemonRpc { await this.call<grpcTypes.DnsOptions, Empty>(this.client.setDnsOptions, dnsOptions); } + public async setAppleServicesBypass(enabled: boolean): Promise<void> { + await this.callBool<Empty>(this.client.setAppleServicesBypass, enabled); + } + public async getVersionInfo(): Promise<IAppVersionInfo> { const response = await this.callEmpty<grpcTypes.AppVersionInfo>(this.client.getVersionInfo); return response.toObject(); diff --git a/gui/src/main/default-settings.ts b/gui/src/main/default-settings.ts index e11a7434e1..62f60cf65b 100644 --- a/gui/src/main/default-settings.ts +++ b/gui/src/main/default-settings.ts @@ -81,6 +81,7 @@ export function getDefaultSettings(): ISettings { customLists: [], apiAccessMethods: getDefaultApiAccessMethods(), relayOverrides: [], + appleServicesBypass: false, }; } diff --git a/gui/src/main/index.ts b/gui/src/main/index.ts index be6c6609a0..2401e70b69 100644 --- a/gui/src/main/index.ts +++ b/gui/src/main/index.ts @@ -55,7 +55,7 @@ import NotificationController, { NotificationControllerDelegate, NotificationSender, } from './notification-controller'; -import { isMacOs13OrNewer } from './platform-version'; +import { isMacOs13OrNewer, isMacOs14p6OrNewer } from './platform-version'; import * as problemReport from './problem-report'; import { resolveBin } from './proc'; import ReconnectionBackoff from './reconnection-backoff'; @@ -774,6 +774,7 @@ class ApplicationMain navigationHistory: this.navigationHistory, currentApiAccessMethod: this.currentApiAccessMethod, isMacOs13OrNewer: isMacOs13OrNewer(), + isMacOs14p6OrNewer: isMacOs14p6OrNewer(), })); IpcMainEventChannel.map.handleGetData(async () => ({ diff --git a/gui/src/main/platform-version.ts b/gui/src/main/platform-version.ts index 027434d8d9..9b483fed65 100644 --- a/gui/src/main/platform-version.ts +++ b/gui/src/main/platform-version.ts @@ -1,24 +1,31 @@ import os from 'os'; -export function isMacOs11OrNewer() { +export function isMacOs11OrNewer(): boolean { const [major] = parseVersion(); return process.platform === 'darwin' && major >= 20; } -export function isMacOs13OrNewer() { +export function isMacOs13OrNewer(): boolean { const [major] = parseVersion(); return process.platform === 'darwin' && major >= 22; } +export function isMacOs14p6OrNewer(): boolean { + const [major, minor] = parseVersion(); + const darwin24 = major >= 24; + const darwin236 = major == 23 && minor >= 6; // 23.6 is used by macOS 14.6 + return process.platform === 'darwin' && (darwin236 || darwin24); +} + // Windows 11 has the internal version 10.0.22000+. -export function isWindows11OrNewer() { +export function isWindows11OrNewer(): boolean { const [major, minor, patch] = parseVersion(); return ( process.platform === 'win32' && (major > 10 || (major === 10 && (minor > 0 || patch >= 22000))) ); } -function parseVersion() { +function parseVersion(): number[] { return os .release() .split('.') diff --git a/gui/src/main/settings.ts b/gui/src/main/settings.ts index 03537ba581..d53219ec6d 100644 --- a/gui/src/main/settings.ts +++ b/gui/src/main/settings.ts @@ -72,6 +72,9 @@ export default class Settings implements Readonly<ISettings> { IpcMainEventChannel.settings.handleSetDnsOptions((dns) => { return this.daemonRpc.setDnsOptions(dns); }); + IpcMainEventChannel.settings.handleSetAppleServicesBypass((enabled) => { + return this.daemonRpc.setAppleServicesBypass(enabled); + }); IpcMainEventChannel.autoStart.handleSet((autoStart: boolean) => { return this.setAutoStart(autoStart); }); @@ -187,6 +190,9 @@ export default class Settings implements Readonly<ISettings> { public get relayOverrides() { return this.settingsValue.relayOverrides; } + public get appleServicesBypass() { + return this.settingsValue.appleServicesBypass; + } public get gui() { return this.guiSettings; diff --git a/gui/src/renderer/app.tsx b/gui/src/renderer/app.tsx index c961d07258..563899000e 100644 --- a/gui/src/renderer/app.tsx +++ b/gui/src/renderer/app.tsx @@ -245,6 +245,7 @@ export default class AppRenderer { this.setChangelog(initialState.changelog, initialState.forceShowChanges); this.setCurrentApiAccessMethod(initialState.currentApiAccessMethod); this.reduxActions.userInterface.setIsMacOs13OrNewer(initialState.isMacOs13OrNewer); + this.reduxActions.userInterface.setIsMacOs14p6OrNewer(initialState.isMacOs14p6OrNewer); if (initialState.macOsScrollbarVisibility !== undefined) { this.reduxActions.userInterface.setMacOsScrollbarVisibility( @@ -321,6 +322,8 @@ export default class AppRenderer { IpcRendererEventChannel.settings.updateBridgeSettings(bridgeSettings); public setDnsOptions = (dnsOptions: IDnsOptions) => IpcRendererEventChannel.settings.setDnsOptions(dnsOptions); + public setAppleServicesBypass = (enabled: boolean) => + IpcRendererEventChannel.settings.setAppleServicesBypass(enabled); public clearAccountHistory = () => IpcRendererEventChannel.accountHistory.clear(); public setAutoConnect = (value: boolean) => IpcRendererEventChannel.guiSettings.setAutoConnect(value); @@ -826,6 +829,7 @@ export default class AppRenderer { reduxSettings.updateWireguardDaita(newSettings.tunnelOptions.wireguard.daita); reduxSettings.updateBridgeState(newSettings.bridgeState); reduxSettings.updateDnsOptions(newSettings.tunnelOptions.dns); + reduxSettings.updateAppleServicesBypass(newSettings.appleServicesBypass); reduxSettings.updateSplitTunnelingState(newSettings.splitTunnel.enableExclusions); reduxSettings.updateObfuscationSettings(newSettings.obfuscationSettings); reduxSettings.updateCustomLists(newSettings.customLists); diff --git a/gui/src/renderer/components/Settings.tsx b/gui/src/renderer/components/Settings.tsx index 211679a76c..98d36fb9fd 100644 --- a/gui/src/renderer/components/Settings.tsx +++ b/gui/src/renderer/components/Settings.tsx @@ -7,10 +7,20 @@ import { useAppContext } from '../context'; import { useHistory } from '../lib/history'; import { RoutePath } from '../lib/routes'; import { useSelector } from '../redux/store'; -import { AriaDescribed, AriaDescription, AriaDescriptionGroup } from './AriaGroup'; +import { + AriaDescribed, + AriaDescription, + AriaDescriptionGroup, + AriaDetails, + AriaInput, + AriaInputGroup, + AriaLabel, +} from './AriaGroup'; import * as Cell from './cell'; +import InfoButton from './InfoButton'; import { BackAction } from './KeyboardNavigation'; import { Layout, SettingsContainer } from './Layout'; +import { ModalMessage } from './Modal'; import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar'; import SettingsHeader, { HeaderTitle } from './SettingsHeader'; import { @@ -28,6 +38,8 @@ export default function Support() { const connectedToDaemon = useSelector((state) => state.userInterface.connectedToDaemon); const isMacOs13OrNewer = useSelector((state) => state.userInterface.isMacOs13OrNewer); + const isMacOs14p6OrNewer = useSelector((state) => state.userInterface.isMacOs14p6OrNewer); + const showSubSettings = loginState.type === 'ok' && connectedToDaemon; const showSplitTunneling = window.env.platform !== 'darwin' || isMacOs13OrNewer; @@ -77,6 +89,12 @@ export default function Support() { <ApiAccessMethodsButton /> </Cell.Group> + {isMacOs14p6OrNewer ? ( + <Cell.Group> + <AppleServicesBypass /> + </Cell.Group> + ) : null} + <Cell.Group> <SupportButton /> <AppVersionButton /> @@ -227,6 +245,54 @@ function SupportButton() { ); } +function AppleServicesBypass() { + const { setAppleServicesBypass } = useAppContext(); + const appleServicesBypass = useSelector((state) => state.settings.appleServicesBypass); + + return ( + <AriaInputGroup> + <Cell.Container> + <AriaLabel> + <Cell.InputLabel> + {messages.pgettext('settings-view', 'Apple services bypass')} + </Cell.InputLabel> + </AriaLabel> + <AriaDetails> + <InfoButton> + <ModalMessage> + {messages.pgettext( + 'settings-view', + 'Some Apple services have an issue where the network settings set by Mullvad get ignored, this in turn blocks certain apps.', + )} + </ModalMessage> + <ModalMessage> + {messages.pgettext( + 'settings-view', + 'Enabling this setting allows traffic to specific Apple-owned networks to go outside of the VPN tunnel, allowing services like iMessage and FaceTime to work whilst using Mullvad.', + )} + </ModalMessage> + <ModalMessage> + {messages.pgettext( + 'settings-view', + 'Attention: this traffic will go outside of the VPN tunnel. Any application that tries to can bypass the VPN tunnel and send traffic to these Apple networks.', + )} + </ModalMessage> + <ModalMessage> + {messages.pgettext( + 'settings-view', + 'This a temporary fix and we are currently working on a long-term solution.', + )} + </ModalMessage> + </InfoButton> + </AriaDetails> + <AriaInput> + <Cell.Switch isOn={appleServicesBypass} onChange={setAppleServicesBypass} /> + </AriaInput> + </Cell.Container> + </AriaInputGroup> + ); +} + function DebugButton() { const history = useHistory(); const navigate = useCallback(() => history.push(RoutePath.debug), [history]); diff --git a/gui/src/renderer/redux/settings/actions.ts b/gui/src/renderer/redux/settings/actions.ts index d2a3fb1c4a..80ac3707c1 100644 --- a/gui/src/renderer/redux/settings/actions.ts +++ b/gui/src/renderer/redux/settings/actions.ts @@ -93,6 +93,11 @@ export interface IUpdateDnsOptionsAction { dns: IDnsOptions; } +export interface ISetAppleServicesBypass { + type: 'SET_APPLE_SERVICES_BYPASS'; + enabled: boolean; +} + export interface IUpdateSplitTunnelingStateAction { type: 'UPDATE_SPLIT_TUNNELING_STATE'; enabled: boolean; @@ -145,6 +150,7 @@ export type SettingsAction = | IUpdateWireguardDaitaAction | IUpdateAutoStartAction | IUpdateDnsOptionsAction + | ISetAppleServicesBypass | IUpdateSplitTunnelingStateAction | ISetSplitTunnelingApplicationsAction | ISetObfuscationSettings @@ -273,6 +279,13 @@ function updateDnsOptions(dns: IDnsOptions): IUpdateDnsOptionsAction { }; } +function updateAppleServicesBypass(enabled: boolean): ISetAppleServicesBypass { + return { + type: 'SET_APPLE_SERVICES_BYPASS', + enabled, + }; +} + function updateSplitTunnelingState(enabled: boolean): IUpdateSplitTunnelingStateAction { return { type: 'UPDATE_SPLIT_TUNNELING_STATE', @@ -343,6 +356,7 @@ export default { updateWireguardDaita, updateAutoStart, updateDnsOptions, + updateAppleServicesBypass, updateSplitTunnelingState, setSplitTunnelingApplications, updateObfuscationSettings, diff --git a/gui/src/renderer/redux/settings/reducers.ts b/gui/src/renderer/redux/settings/reducers.ts index 6eb595467b..7f806c248c 100644 --- a/gui/src/renderer/redux/settings/reducers.ts +++ b/gui/src/renderer/redux/settings/reducers.ts @@ -114,6 +114,7 @@ export interface ISettingsReduxState { daita?: IDaitaSettings; }; dns: IDnsOptions; + appleServicesBypass: boolean; splitTunneling: boolean; splitTunnelingApplications: ISplitTunnelingApplication[]; obfuscationSettings: ObfuscationSettings; @@ -181,6 +182,7 @@ const initialState: ISettingsReduxState = { addresses: [], }, }, + appleServicesBypass: false, splitTunneling: false, splitTunnelingApplications: [], obfuscationSettings: { @@ -310,6 +312,12 @@ export default function ( dns: action.dns, }; + case 'SET_APPLE_SERVICES_BYPASS': + return { + ...state, + appleServicesBypass: action.enabled, + }; + case 'UPDATE_SPLIT_TUNNELING_STATE': return { ...state, diff --git a/gui/src/renderer/redux/userinterface/actions.ts b/gui/src/renderer/redux/userinterface/actions.ts index 238835318e..a5ee138464 100644 --- a/gui/src/renderer/redux/userinterface/actions.ts +++ b/gui/src/renderer/redux/userinterface/actions.ts @@ -61,6 +61,11 @@ export interface ISetIsMacOs13OrNewer { isMacOs13OrNewer: boolean; } +export interface ISetIsMacOs14p6OrNewer { + type: 'SET_IS_MACOS14_6_OR_NEWER'; + isMacOs14p6OrNewer: boolean; +} + export type UserInterfaceAction = | IUpdateLocaleAction | IUpdateWindowArrowPositionAction @@ -73,7 +78,8 @@ export type UserInterfaceAction = | ISetForceShowChanges | ISetIsPerformingPostUpgrade | ISetSelectLocationView - | ISetIsMacOs13OrNewer; + | ISetIsMacOs13OrNewer + | ISetIsMacOs14p6OrNewer; function updateLocale(locale: string): IUpdateLocaleAction { return { @@ -160,6 +166,13 @@ function setIsMacOs13OrNewer(isMacOs13OrNewer: boolean): ISetIsMacOs13OrNewer { }; } +function setIsMacOs14p6OrNewer(isMacOs14p6OrNewer: boolean): ISetIsMacOs14p6OrNewer { + return { + type: 'SET_IS_MACOS14_6_OR_NEWER', + isMacOs14p6OrNewer, + }; +} + export default { updateLocale, updateWindowArrowPosition, @@ -173,4 +186,5 @@ export default { setIsPerformingPostUpgrade, setSelectLocationView, setIsMacOs13OrNewer, + setIsMacOs14p6OrNewer, }; diff --git a/gui/src/renderer/redux/userinterface/reducers.ts b/gui/src/renderer/redux/userinterface/reducers.ts index 89427e9b06..b245522cec 100644 --- a/gui/src/renderer/redux/userinterface/reducers.ts +++ b/gui/src/renderer/redux/userinterface/reducers.ts @@ -16,6 +16,7 @@ export interface IUserInterfaceReduxState { isPerformingPostUpgrade: boolean; selectLocationView: LocationType; isMacOs13OrNewer: boolean; + isMacOs14p6OrNewer: boolean; } const initialState: IUserInterfaceReduxState = { @@ -30,6 +31,7 @@ const initialState: IUserInterfaceReduxState = { isPerformingPostUpgrade: false, selectLocationView: LocationType.exit, isMacOs13OrNewer: true, + isMacOs14p6OrNewer: true, }; export default function ( @@ -88,6 +90,12 @@ export default function ( isMacOs13OrNewer: action.isMacOs13OrNewer, }; + case 'SET_IS_MACOS14_6_OR_NEWER': + return { + ...state, + isMacOs14p6OrNewer: action.isMacOs14p6OrNewer, + }; + default: return state; } diff --git a/gui/src/shared/daemon-rpc-types.ts b/gui/src/shared/daemon-rpc-types.ts index 33ff6bb8ce..4943bee933 100644 --- a/gui/src/shared/daemon-rpc-types.ts +++ b/gui/src/shared/daemon-rpc-types.ts @@ -439,6 +439,7 @@ export interface ISettings { customLists: CustomLists; apiAccessMethods: ApiAccessMethodSettings; relayOverrides: Array<RelayOverride>; + appleServicesBypass: boolean; } export type BridgeState = 'auto' | 'on' | 'off'; diff --git a/gui/src/shared/ipc-schema.ts b/gui/src/shared/ipc-schema.ts index 4e08e7109d..8fa7c8c306 100644 --- a/gui/src/shared/ipc-schema.ts +++ b/gui/src/shared/ipc-schema.ts @@ -77,6 +77,7 @@ export interface IAppStateSnapshot { navigationHistory?: IHistoryObject; currentApiAccessMethod?: AccessMethodSetting; isMacOs13OrNewer: boolean; + isMacOs14p6OrNewer: boolean; } // The different types of requests are: @@ -186,6 +187,7 @@ export const ipcSchema = { setRelaySettings: invoke<RelaySettings, void>(), updateBridgeSettings: invoke<BridgeSettings, void>(), setDnsOptions: invoke<IDnsOptions, void>(), + setAppleServicesBypass: invoke<boolean, void>(), setObfuscationSettings: invoke<ObfuscationSettings, void>(), addApiAccessMethod: invoke<NewAccessMethodSetting, string>(), updateApiAccessMethod: invoke<AccessMethodSetting, void>(), |
