diff --git a/patches/protonmail/proton-account.patch b/patches/protonmail/app-account.patch
similarity index 95%
rename from patches/protonmail/proton-account.patch
rename to patches/protonmail/app-account.patch
index 2c4dd3f7..1ddb1d2b 100644
--- a/patches/protonmail/proton-account.patch
+++ b/patches/protonmail/app-account.patch
@@ -51,11 +51,11 @@ index 8f5e56ef0..a40d9dc17 100644
export default Setup;
diff --git a/applications/account/src/app/content/MainContainer.tsx b/applications/account/src/app/content/MainContainer.tsx
-index 575b59dcec..5e774e01a1 100644
+index 8009f7f074..1938e387fb 100644
--- a/applications/account/src/app/content/MainContainer.tsx
+++ b/applications/account/src/app/content/MainContainer.tsx
-@@ -132,7 +132,7 @@ const MainContainer = () => {
- const loadingFeatures = featuresFlags.some(({ loading }) => loading) || loadingDataRecovery;
+@@ -137,7 +137,7 @@ const MainContainer = () => {
+ const loadingFeatures = featuresFlags.some(({ loading }) => loading);
const recoveryNotification = useRecoveryNotification(false);
- const appFromPathname = getAppFromPathnameSafe(location.pathname);
@@ -63,3 +63,4 @@ index 575b59dcec..5e774e01a1 100644
const app = appFromPathname || getToApp(undefined, user);
const appSlug = getSlugFromApp(app);
+
diff --git a/patches/protonmail/proton-calendar.patch b/patches/protonmail/app-calendar.patch
similarity index 100%
rename from patches/protonmail/proton-calendar.patch
rename to patches/protonmail/app-calendar.patch
diff --git a/patches/protonmail/proton-drive.patch b/patches/protonmail/app-drive.patch
similarity index 95%
rename from patches/protonmail/proton-drive.patch
rename to patches/protonmail/app-drive.patch
index b159afc4..6118b4ff 100644
--- a/patches/protonmail/proton-drive.patch
+++ b/patches/protonmail/app-drive.patch
@@ -1,21 +1,20 @@
diff --git a/applications/drive/src/.htaccess b/applications/drive/src/.htaccess
-index 5b522f3deb..5523b5a5dc 100644
+index b0b25a5fae..11d4e4af0f 100644
--- a/applications/drive/src/.htaccess
+++ b/applications/drive/src/.htaccess
-@@ -39,11 +39,13 @@ ErrorDocument 404 /assets/404.html
- Header set X-Robots-Tag "noindex"
+@@ -40,10 +40,12 @@ ErrorDocument 404 /assets/404.html
-+#
# The download service worker gets chunk hash appended to the end of the filename
++#
Header set Service-Worker-Allowed "/"
Header set Service-Worker "script"
+#
-
- AddType application/font-woff2 .woff2
+
+ AddOutputFilter INCLUDES;DEFLATE svg
diff --git a/applications/drive/src/app/store/_downloads/fileSaver/download.ts b/applications/drive/src/app/store/_downloads/fileSaver/download.ts
index 66a9aba1cc..2a7ab63889 100644
diff --git a/patches/protonmail/proton-mail.patch b/patches/protonmail/app-mail.patch
similarity index 86%
rename from patches/protonmail/proton-mail.patch
rename to patches/protonmail/app-mail.patch
index 1b9f960e..d730c859 100644
--- a/patches/protonmail/proton-mail.patch
+++ b/patches/protonmail/app-mail.patch
@@ -149,27 +149,55 @@ index 4c16c85b5..8b93c6084 100644
+}; /* */
diff --git a/packages/components/hooks/useGetEncryptionPreferences.ts b/packages/components/hooks/useGetEncryptionPreferences.ts
-index fe83b9e8c..b944a61e8 100644
+index dae0d635c7..6308e24fa9 100644
--- a/packages/components/hooks/useGetEncryptionPreferences.ts
+++ b/packages/components/hooks/useGetEncryptionPreferences.ts
-@@ -24,7 +24,7 @@ const DEFAULT_LIFETIME = 5 * MINUTE;
- * The logic for how those preferences are determined is laid out in the
- * Confluence document 'Encryption preferences for outgoing email'
+@@ -5,7 +5,7 @@ import { MINUTE, RECIPIENT_TYPES } from '@proton/shared/lib/constants';
+ import { getSelfSendAddresses } from '@proton/shared/lib/helpers/address';
+ import { canonicalizeEmail, canonicalizeInternalEmail } from '@proton/shared/lib/helpers/email';
+ import { KT_VERIFICATION_STATUS } from '@proton/shared/lib/interfaces';
+-import { GetEncryptionPreferences } from '@proton/shared/lib/interfaces/hooks/GetEncryptionPreferences';
++import { GetEncryptionPreferences } from '@proton/shared/lib/interfaces/hooks/GetEncryptionPreferences'; /* TODO "GetEncryptionPreferences" is used as a method signature */
+ import { getKeyHasFlagsToEncrypt } from '@proton/shared/lib/keys';
+ import { getActiveKeys } from '@proton/shared/lib/keys/getActiveKeys';
+ import { splitKeys } from '@proton/shared/lib/keys/keys';
+@@ -31,7 +31,7 @@ const DEFAULT_LIFETIME = 5 * MINUTE;
+ * Confluence document 'Encryption preferences for outgoing email'.
+ * NB: the current logic does not handle internal address keys belonging to external accounts, since these keys are not used by Inbox.
*/
-const useGetEncryptionPreferences = () => {
-+const useGetEncryptionPreferences = () => { /* */
++const useGetEncryptionPreferences = () => { /* TODO "GetEncryptionPreferences" is used as a method signature */
const api = useApi();
const cache = useCache();
const getAddresses = useGetAddresses();
-@@ -87,6 +87,6 @@ const useGetEncryptionPreferences = () => {
+@@ -109,6 +109,6 @@ const useGetEncryptionPreferences = () => {
},
[cache, getEncryptionPreferences]
);
-};
-+}; /* */
++}; /* */
export default useGetEncryptionPreferences;
+diff --git a/packages/shared/lib/interfaces/hooks/GetEncryptionPreferences.ts b/packages/shared/lib/interfaces/hooks/GetEncryptionPreferences.ts
+index d31b0bf797..407bb22503 100644
+--- a/packages/shared/lib/interfaces/hooks/GetEncryptionPreferences.ts
++++ b/packages/shared/lib/interfaces/hooks/GetEncryptionPreferences.ts
+@@ -2,6 +2,7 @@ import { EncryptionPreferences } from '../../mail/encryptionPreferences';
+ import { ContactEmail } from '../contacts';
+
+ export type GetEncryptionPreferences = ({
++ /* TODO review signatures */
+ email,
+ intendedForEmail,
+ lifetime,
+@@ -15,4 +16,4 @@ export type GetEncryptionPreferences = ({
+ intendedForEmail?: boolean;
+ lifetime?: number;
+ contactEmailsMap?: { [email: string]: ContactEmail | undefined };
+-}) => Promise;
++}) => Promise;/* */
+
diff --git a/packages/components/hooks/useApi.ts b/packages/components/hooks/useApi.ts
index e2baface5..8b4317d5a 100644
--- a/packages/components/hooks/useApi.ts
@@ -346,10 +374,10 @@ index 0d29745777..0000000000
-export default MailDefaultHandlerModal;
diff --git a/applications/mail/src/app/components/header/search/MailSearch.tsx b/applications/mail/src/app/components/header/search/MailSearch.tsx
-index 1736085ad3..5f102e159e 100644
+index 9b542628da..f26b6a9ccc 100644
--- a/applications/mail/src/app/components/header/search/MailSearch.tsx
+++ b/applications/mail/src/app/components/header/search/MailSearch.tsx
-@@ -3,7 +3,6 @@ import { useEffect, useState } from 'react';
+@@ -3,21 +3,17 @@ import { useEffect, useState } from 'react';
import { Location } from 'history';
import {
@@ -357,9 +385,8 @@ index 1736085ad3..5f102e159e 100644
TopNavbarListItemSearchButton,
generateUID,
useAddresses,
-@@ -11,14 +10,11 @@ import {
+ useFolders,
useLabels,
- useMailSettings,
usePopperAnchor,
- useProgressiveRollout,
useToggle,
@@ -372,7 +399,7 @@ index 1736085ad3..5f102e159e 100644
import { extractSearchParameters } from '../../../helpers/mailboxUrl';
import { useClickMailContent } from '../../../hooks/useClickMailContent';
import { Breakpoints } from '../../../models/utils';
-@@ -39,11 +35,9 @@ interface Props {
+@@ -37,17 +33,15 @@ interface Props {
const MailSearch = ({ breakpoints, labelID, location, columnMode }: Props) => {
const [uid] = useState(generateUID('advanced-search-overlay'));
@@ -381,13 +408,11 @@ index 1736085ad3..5f102e159e 100644
const searchParams = extractSearchParameters(location);
const [searchInputValue, setSearchInputValue] = useState(searchParams.keyword || '');
- const [user] = useUser();
- const [, loadingMailSettings] = useMailSettings();
const [, loadingLabels] = useLabels();
const [, loadingFolders] = useFolders();
-@@ -51,7 +45,7 @@ const MailSearch = ({ breakpoints, labelID, location, columnMode }: Props) => {
- const { getESDBStatus, cacheIndexedDB, closeDropdown } = useEncryptedSearchContext();
- const { dropdownOpened } = getESDBStatus();
- const esState = useEncryptedSearchToggleState(isOpen);
+ const [, loadingAddresses] = useAddresses();
+ const { esStatus, cacheIndexedDB, closeDropdown, esIndexingProgressState } = useEncryptedSearchContext();
+ const { dropdownOpened } = esStatus;
- const showEncryptedSearch = isEncryptedSearchAvailable(user, isESUserInterfaceAvailable);
+ const showEncryptedSearch = false;
diff --git a/patches/protonmail/proton-vpn-settings.patch b/patches/protonmail/app-vpn-settings.patch
similarity index 100%
rename from patches/protonmail/proton-vpn-settings.patch
rename to patches/protonmail/app-vpn-settings.patch
diff --git a/patches/protonmail/common-7.patch b/patches/protonmail/common-7.patch
index 01c32e22..6c7c958d 100644
--- a/patches/protonmail/common-7.patch
+++ b/patches/protonmail/common-7.patch
@@ -1,3 +1,23 @@
+diff --git a/packages/shared/lib/helpers/desktop.ts b/packages/shared/lib/helpers/desktop.ts
+index 4696b429a7..fe63f75e55 100644
+--- a/packages/shared/lib/helpers/desktop.ts
++++ b/packages/shared/lib/helpers/desktop.ts
+@@ -1,13 +1,6 @@
+-import UAParser from 'ua-parser-js';
+-
+ import { isMac } from './browser';
+
+-const uaParser = new UAParser();
+-const ua = uaParser.getResult();
+-
+-export const isElectronApp = () => {
+- return /electron/i.test(ua.ua);
+-};
++export const isElectronApp = () => false;
+
+ export const isElectronOnMac = () => {
+ return isElectronApp() && isMac();
+
diff --git a/packages/components/containers/unleash/UnleashFlagProvider.tsx b/packages/components/containers/unleash/UnleashFlagProvider.tsx
index 1531d1450b..a8a8d44677 100644
--- a/packages/components/containers/unleash/UnleashFlagProvider.tsx
diff --git a/patches/protonmail/common-5.patch b/patches/protonmail/common-8.patch
similarity index 87%
rename from patches/protonmail/common-5.patch
rename to patches/protonmail/common-8.patch
index 39aea789..11f731af 100644
--- a/patches/protonmail/common-5.patch
+++ b/patches/protonmail/common-8.patch
@@ -1,9 +1,29 @@
+diff --git a/packages/shared/lib/helpers/desktop.ts b/packages/shared/lib/helpers/desktop.ts
+index 4696b429a7..fe63f75e55 100644
+--- a/packages/shared/lib/helpers/desktop.ts
++++ b/packages/shared/lib/helpers/desktop.ts
+@@ -1,13 +1,6 @@
+-import UAParser from 'ua-parser-js';
+-
+ import { isMac } from './browser';
+
+-const uaParser = new UAParser();
+-const ua = uaParser.getResult();
+-
+-export const isElectronApp = () => {
+- return /electron/i.test(ua.ua);
+-};
++export const isElectronApp = () => false;
+
+ export const isElectronOnMac = () => {
+ return isElectronApp() && isMac();
+
diff --git a/packages/components/containers/unleash/UnleashFlagProvider.tsx b/packages/components/containers/unleash/UnleashFlagProvider.tsx
-index 1531d1450b..a8a8d44677 100644
+index e9adc4f7f1..2e8d0388fd 100644
--- a/packages/components/containers/unleash/UnleashFlagProvider.tsx
+++ b/packages/components/containers/unleash/UnleashFlagProvider.tsx
@@ -3,20 +3,21 @@ import { ReactNode } from 'react';
- import FlagProvider from '@unleash/proxy-client-react';
+ import FlagProvider from '@protontech/proxy-client-react';
import { IConfig } from 'unleash-proxy-client';
-import { Api } from '@proton/shared/lib/interfaces';
@@ -153,10 +173,10 @@ index 36bd0c712..c2fb3681c 100644
return;
}
-diff --git a/applications/mail/src/app/components/list/auto-delete/variations/AutoDeleteFreeBanner.tsx b/applications/mail/src/app/components/list/auto-delete/variations/AutoDeleteFreeBanner.tsx
+diff --git a/applications/mail/src/app/components/list/banners/auto-delete/variations/AutoDeleteFreeBanner.tsx b/applications/mail/src/app/components/list/banners/auto-delete/variations/AutoDeleteFreeBanner.tsx
index 24c56ef6fe..a6046b391c 100644
---- a/applications/mail/src/app/components/list/auto-delete/variations/AutoDeleteFreeBanner.tsx
-+++ b/applications/mail/src/app/components/list/auto-delete/variations/AutoDeleteFreeBanner.tsx
+--- a/applications/mail/src/app/components/list/banners/auto-delete/variations/AutoDeleteFreeBanner.tsx
++++ b/applications/mail/src/app/components/list/banners/auto-delete/variations/AutoDeleteFreeBanner.tsx
@@ -7,6 +7,10 @@ import { AutoDeleteUpsellModal, useModalState } from '@proton/components/compone
import { PromotionBanner } from '@proton/components/containers';
@@ -170,10 +190,10 @@ index 24c56ef6fe..a6046b391c 100644
return (
diff --git a/applications/mail/src/app/hooks/useShowUpsellBanner.ts b/applications/mail/src/app/hooks/useShowUpsellBanner.ts
-index d203f913fa..178153c592 100644
+index b82b7ae976..0907c85ec6 100644
--- a/applications/mail/src/app/hooks/useShowUpsellBanner.ts
+++ b/applications/mail/src/app/hooks/useShowUpsellBanner.ts
-@@ -33,6 +33,7 @@ const useShowUpsellBanner = (labelID: string, otherBannerDisplayed: boolean) =>
+@@ -33,12 +33,14 @@ const useShowUpsellBanner = (labelID: string) => {
- No other banner is shown in the message list
- If a value is found in the localStorage that should trigger a new display
*/
@@ -181,15 +201,14 @@ index d203f913fa..178153c592 100644
const canDisplayUpsellBanner =
user.isFree &&
Date.now() > threeDaysAfterCreationDate &&
-@@ -40,6 +41,7 @@ const useShowUpsellBanner = (labelID: string, otherBannerDisplayed: boolean) =>
+ isInbox &&
needToShowUpsellBanner.current &&
- !otherBannerDisplayed &&
showAgain;
+ /* */
const handleDismissBanner = () => {
// Set the ref to false so that we hide the banner and update the localStorage value
-@@ -72,6 +74,10 @@ const useShowUpsellBanner = (labelID: string, otherBannerDisplayed: boolean) =>
+@@ -71,6 +73,10 @@ const useShowUpsellBanner = (labelID: string) => {
}
}, []);
diff --git a/patches/protonmail/common-6.patch b/patches/protonmail/common-9.patch
similarity index 89%
rename from patches/protonmail/common-6.patch
rename to patches/protonmail/common-9.patch
index fb0a5fff..a4eca27c 100644
--- a/patches/protonmail/common-6.patch
+++ b/patches/protonmail/common-9.patch
@@ -1,3 +1,13 @@
+diff --git a/packages/shared/lib/helpers/desktop.ts b/packages/shared/lib/helpers/desktop.ts
+new file mode 100644
+index 0000000000..6ece6922a0
+--- /dev/null
++++ b/packages/shared/lib/helpers/desktop.ts
+@@ -0,0 +1,3 @@
++/* */
++// TODO remove when ./packages/shared/lib/helpers/desktop.ts gets added for the "drive" app
++/* */
+
diff --git a/packages/components/containers/unleash/UnleashFlagProvider.tsx b/packages/components/containers/unleash/UnleashFlagProvider.tsx
index c3e007aa4b..f51a74683e 100644
--- a/packages/components/containers/unleash/UnleashFlagProvider.tsx
@@ -120,10 +130,10 @@ index 36bd0c712..c2fb3681c 100644
return;
}
-diff --git a/applications/mail/src/app/components/list/auto-delete/variations/AutoDeleteFreeBanner.tsx b/applications/mail/src/app/components/list/auto-delete/variations/AutoDeleteFreeBanner.tsx
+diff --git a/applications/mail/src/app/components/list/banners/auto-delete/variations/AutoDeleteFreeBanner.tsx b/applications/mail/src/app/components/list/banners/auto-delete/variations/AutoDeleteFreeBanner.tsx
index 24c56ef6fe..a6046b391c 100644
---- a/applications/mail/src/app/components/list/auto-delete/variations/AutoDeleteFreeBanner.tsx
-+++ b/applications/mail/src/app/components/list/auto-delete/variations/AutoDeleteFreeBanner.tsx
+--- a/applications/mail/src/app/components/list/banners/auto-delete/variations/AutoDeleteFreeBanner.tsx
++++ b/applications/mail/src/app/components/list/banners/auto-delete/variations/AutoDeleteFreeBanner.tsx
@@ -7,6 +7,10 @@ import { AutoDeleteUpsellModal, useModalState } from '@proton/components/compone
import { PromotionBanner } from '@proton/components/containers';
@@ -137,10 +147,10 @@ index 24c56ef6fe..a6046b391c 100644
return (
diff --git a/applications/mail/src/app/hooks/useShowUpsellBanner.ts b/applications/mail/src/app/hooks/useShowUpsellBanner.ts
-index d203f913fa..178153c592 100644
+index b82b7ae976..0907c85ec6 100644
--- a/applications/mail/src/app/hooks/useShowUpsellBanner.ts
+++ b/applications/mail/src/app/hooks/useShowUpsellBanner.ts
-@@ -33,6 +33,7 @@ const useShowUpsellBanner = (labelID: string, otherBannerDisplayed: boolean) =>
+@@ -33,12 +33,14 @@ const useShowUpsellBanner = (labelID: string) => {
- No other banner is shown in the message list
- If a value is found in the localStorage that should trigger a new display
*/
@@ -148,15 +158,14 @@ index d203f913fa..178153c592 100644
const canDisplayUpsellBanner =
user.isFree &&
Date.now() > threeDaysAfterCreationDate &&
-@@ -40,6 +41,7 @@ const useShowUpsellBanner = (labelID: string, otherBannerDisplayed: boolean) =>
+ isInbox &&
needToShowUpsellBanner.current &&
- !otherBannerDisplayed &&
showAgain;
+ /* */
const handleDismissBanner = () => {
// Set the ref to false so that we hide the banner and update the localStorage value
-@@ -72,6 +74,10 @@ const useShowUpsellBanner = (labelID: string, otherBannerDisplayed: boolean) =>
+@@ -71,6 +73,10 @@ const useShowUpsellBanner = (labelID: string) => {
}
}, []);
diff --git a/patches/protonmail/constants-11.patch b/patches/protonmail/constants-11.patch
new file mode 100644
index 00000000..b6890740
--- /dev/null
+++ b/patches/protonmail/constants-11.patch
@@ -0,0 +1,24 @@
+diff --git a/packages/shared/lib/constants.ts b/packages/shared/lib/constants.ts
+index 5481e3f8e4..a5634acd3b 100644
+--- a/packages/shared/lib/constants.ts
++++ b/packages/shared/lib/constants.ts
+@@ -82,7 +82,7 @@ interface AppConfiguration {
+
+ export const APPS_CONFIGURATION: { [key in APP_NAMES]: AppConfiguration } = {
+ [APPS.PROTONACCOUNT]: {
+- publicPath: '',
++ publicPath: '/account',
+ subdomain: 'account',
+ name: 'Proton Account',
+ bareName: 'Account',
+@@ -180,8 +180,8 @@ export const APPS_CONFIGURATION: { [key in APP_NAMES]: AppConfiguration } = {
+ settingsSlug: '',
+ },
+ [APPS.PROTONVPN_SETTINGS]: {
+- publicPath: '',
+- subdomain: '',
++ publicPath: 'account/vpn',
++ subdomain: 'account',
+ name: VPN_APP_NAME,
+ bareName: VPN_SHORT_APP_NAME,
+ webClientID: 'web-vpn-settings',
diff --git a/patches/protonmail/meta.json b/patches/protonmail/meta.json
index 068a367b..7bf4177b 100644
--- a/patches/protonmail/meta.json
+++ b/patches/protonmail/meta.json
@@ -1,67 +1,67 @@
{
"proton-mail": [
- "common-5.patch",
+ "common-7.patch",
"drop-circular-dependency-2.patch",
"url-6.patch",
- "constants-10.patch",
- "sentry-16.patch",
+ "constants-11.patch",
+ "sentry-17.patch",
"pack-api-arg-5.patch",
- "pack-webpack-8.patch",
+ "pack-webpack-9.patch",
"session-storage-5.patch",
"link-handler-7.patch",
"embedded-verification-3.patch",
- "proton-mail.patch"
+ "app-mail.patch"
],
"proton-account": [
- "common-7.patch",
+ "common-8.patch",
"drop-circular-dependency-2.patch",
"url-6.patch",
- "constants-10.patch",
- "sentry-16.patch",
+ "constants-11.patch",
+ "sentry-18.patch",
"pack-api-arg-5.patch",
"pack-webpack-9.patch",
"session-storage-5.patch",
"link-handler-7.patch",
"embedded-verification-3.patch",
- "proton-account.patch"
+ "app-account.patch"
],
"proton-calendar": [
- "common-5.patch",
+ "common-7.patch",
"drop-circular-dependency-2.patch",
"url-6.patch",
- "constants-10.patch",
- "sentry-16.patch",
+ "constants-11.patch",
+ "sentry-17.patch",
"pack-api-arg-5.patch",
- "pack-webpack-8.patch",
+ "pack-webpack-9.patch",
"session-storage-5.patch",
"link-handler-7.patch",
"embedded-verification-3.patch",
- "proton-calendar.patch"
+ "app-calendar.patch"
],
"proton-drive": [
- "common-6.patch",
+ "common-9.patch",
"drop-circular-dependency-2.patch",
"url-6.patch",
"constants-10.patch",
- "sentry-15.patch",
+ "sentry-16.patch",
"pack-api-arg-5.patch",
- "pack-webpack-8.patch",
+ "pack-webpack-9.patch",
"session-storage-5.patch",
"link-handler-7.patch",
"embedded-verification-3.patch",
- "proton-drive.patch"
+ "app-drive.patch"
],
"proton-vpn-settings": [
- "common-7.patch",
+ "common-8.patch",
"drop-circular-dependency-2.patch",
"url-6.patch",
- "constants-10.patch",
- "sentry-16.patch",
+ "constants-11.patch",
+ "sentry-18.patch",
"pack-api-arg-5.patch",
"pack-webpack-9.patch",
"session-storage-5.patch",
"link-handler-7.patch",
"embedded-verification-3.patch",
- "proton-vpn-settings.patch"
+ "app-vpn-settings.patch"
]
}
diff --git a/patches/protonmail/pack-webpack-8.patch b/patches/protonmail/pack-webpack-8.patch
deleted file mode 100644
index 43603998..00000000
--- a/patches/protonmail/pack-webpack-8.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-diff --git a/packages/pack/webpack.config.ts b/packages/pack/webpack.config.ts
-index 184720c4f9..e729826f79 100644
---- a/packages/pack/webpack.config.ts
-+++ b/packages/pack/webpack.config.ts
-@@ -1,4 +1,5 @@
- import path from 'path';
-+import fs from 'fs';
- import webpack from 'webpack';
- import 'webpack-dev-server';
- // @ts-ignore
-@@ -23,7 +24,7 @@ const getConfig = (env: any): webpack.Configuration => {
- api: env.api,
- appMode: env.appMode || 'standalone',
- featureFlags: env.featureFlags || '',
-- writeSRI: env.writeSri !== 'false',
-+ writeSRI: false,
- browserslist: isProduction
- ? `> 0.5%, not IE 11, Firefox ESR, Safari 11`
- : 'last 1 chrome version, last 1 firefox version, last 1 safari version',
-@@ -44,7 +45,20 @@ const getConfig = (env: any): webpack.Configuration => {
-
- const version = options.buildData.version;
-
-- return {
-+ return (() => {
-+ const file = path.resolve("./proton.config.js");
-+ if (fs.existsSync(file)) {
-+ console.log(
-+ /*reset:*/"\x1b[0m" +
-+ /*yellow:*/"\x1b[33m" +
-+ ">>>" +
-+ /*reset:*/"\x1b[0m", +
-+ `Found ${file}, extend the config`,
-+ )
-+ return eval("require")(file);
-+ }
-+ return (value: webpack.Configuration) => value;
-+ })()({
- target: `browserslist:${options.browserslist}`,
- mode: isProduction ? 'production' : 'development',
- bail: isProduction,
-@@ -162,7 +176,7 @@ const getConfig = (env: any): webpack.Configuration => {
- ],
- }),
- },
-- };
-+ });
- };
-
- export default getConfig;
---
diff --git a/patches/protonmail/sentry-15.patch b/patches/protonmail/sentry-17.patch
similarity index 80%
rename from patches/protonmail/sentry-15.patch
rename to patches/protonmail/sentry-17.patch
index a9b59f61..24b07f74 100644
--- a/patches/protonmail/sentry-15.patch
+++ b/patches/protonmail/sentry-17.patch
@@ -1,15 +1,16 @@
diff --git a/packages/shared/lib/helpers/sentry.ts b/packages/shared/lib/helpers/sentry.ts
-index 503abd48a4..296afc18f4 100644
+index f60b06d7f8..8186ab1afc 100644
--- a/packages/shared/lib/helpers/sentry.ts
+++ b/packages/shared/lib/helpers/sentry.ts
-@@ -1,15 +1,10 @@
+@@ -1,19 +1,11 @@
import {
BrowserOptions,
+- Integrations as SentryIntegrations,
captureException,
- configureScope,
- init,
- makeFetchTransport,
- captureMessage as sentryCaptureMessage,
+- captureMessage as sentryCaptureMessage,
} from '@sentry/browser';
-import { BrowserTransportOptions } from '@sentry/browser/types/transports/types';
@@ -17,8 +18,11 @@ index 503abd48a4..296afc18f4 100644
-import { ApiError } from '../fetch/ApiError';
import { getUIDHeaders } from '../fetch/headers';
import { ProtonConfig } from '../interfaces';
+-import { isElectronApp } from './desktop';
-@@ -67,21 +62,6 @@ export const getContentTypeHeaders = (input: RequestInfo | URL): HeadersInit =>
+ type SentryContext = {
+ authHeaders: { [key: string]: string };
+@@ -69,21 +61,6 @@ export const getContentTypeHeaders = (input: RequestInfo | URL): HeadersInit =>
return {};
};
@@ -40,25 +44,26 @@ index 503abd48a4..296afc18f4 100644
const isLocalhost = (host: string) => host.startsWith('localhost');
const isProduction = (host: string) => host.endsWith('.proton.me') || host === VPN_HOSTNAME;
-@@ -170,86 +150,10 @@ function main({
+@@ -172,94 +149,10 @@ function main({
ignore = ({ host }) => isLocalhost(host),
denyUrls = getDefaultDenyUrls(),
ignoreErrors = getDefaultIgnoreErrors(),
-}: SentryOptions) {
-- const { SENTRY_DSN, APP_VERSION } = config;
+- const { SENTRY_DSN, SENTRY_DESKTOP_DSN, APP_VERSION } = config;
+- const isElectron = isElectronApp();
+- const sentryDSN = isElectron ? SENTRY_DESKTOP_DSN || SENTRY_DSN : SENTRY_DSN;
- const { host, release, environment } = sentryConfig;
-
- // No need to configure it if we don't load the DSN
-- if (!SENTRY_DSN || ignore(sentryConfig)) {
+- if (!sentryDSN || ignore(sentryConfig)) {
- return;
- }
-+}: SentryOptions) {}
-
+-
- setUID(uid);
-
-- // Assumes SENTRY_DSN is: https://111b3eeaaec34cae8e812df705690a36@sentry/11
+- // Assumes sentryDSN is: https://111b3eeaaec34cae8e812df705690a36@sentry/11
- // To get https://111b3eeaaec34cae8e812df705690a36@protonmail.com/api/core/v4/reports/sentry/11
-- const dsn = SENTRY_DSN.replace('sentry', `${host}/api/core/v4/reports/sentry`);
+- const dsn = sentryDSN.replace('sentry', `${host}/api/core/v4/reports/sentry`);
-
- init({
- dsn,
@@ -67,6 +72,12 @@ index 503abd48a4..296afc18f4 100644
- normalizeDepth: 5,
- transport: makeProtonFetchTransport,
- autoSessionTracking: sessionTracking,
+- // do not log calls to console.log, console.error, etc.
+- integrations: [
+- new SentryIntegrations.Breadcrumbs({
+- console: false,
+- }),
+- ],
- // Disable client reports. Client reports are used by sentry to retry events that failed to send on visibility change.
- // Unfortunately Sentry does not use the custom transport for those, and thus fails to add the headers the API requires.
- sendClientReports: false,
@@ -77,12 +88,14 @@ index 503abd48a4..296afc18f4 100644
- if (stack && stack.match(/ferdi|franz/i)) {
- return null;
- }
--
++}: SentryOptions) {}
+
- // Not interested in uncaught API errors, or known errors
- if (error instanceof ApiError || error?.trace === false) {
- return null;
- }
--
++export const traceError = (...args: Parameters) => console.error(...args);
+
- if (!context.enabled) {
- return null;
- }
@@ -120,14 +133,12 @@ index 503abd48a4..296afc18f4 100644
- captureException(...args);
- }
-};
-+export const traceError = (...args: Parameters) => console.error(...args);
-
+-
-export const captureMessage = (...args: Parameters) => {
- if (!isLocalhost(window.location.host)) {
- sentryCaptureMessage(...args);
- }
-};
-+export const captureMessage = (...args: Parameters) => console.log(...args);
++export const captureMessage = (...args: Parameters) => console.log(...args);
export default main;
---
diff --git a/patches/protonmail/sentry-18.patch b/patches/protonmail/sentry-18.patch
new file mode 100644
index 00000000..7d14678a
--- /dev/null
+++ b/patches/protonmail/sentry-18.patch
@@ -0,0 +1,146 @@
+diff --git a/packages/shared/lib/helpers/sentry.ts b/packages/shared/lib/helpers/sentry.ts
+index 94065dadb1..9eaaf70ca7 100644
+--- a/packages/shared/lib/helpers/sentry.ts
++++ b/packages/shared/lib/helpers/sentry.ts
+@@ -1,19 +1,11 @@
+ import {
+ BrowserOptions,
+- Integrations as SentryIntegrations,
+ captureException,
+- configureScope,
+- init,
+- makeFetchTransport,
+- captureMessage as sentryCaptureMessage,
+ } from '@sentry/browser';
+-import { BrowserTransportOptions } from '@sentry/browser/types/transports/types';
+
+ import { VPN_HOSTNAME } from '../constants';
+-import { ApiError } from '../fetch/ApiError';
+ import { getUIDHeaders } from '../fetch/headers';
+ import { ProtonConfig } from '../interfaces';
+-import { isElectronApp } from './desktop';
+
+ type SentryContext = {
+ authHeaders: { [key: string]: string };
+@@ -70,23 +62,6 @@ export const getContentTypeHeaders = (input: FirstFetchParameter): HeadersInit =
+ return {};
+ };
+
+-const sentryFetch: typeof fetch = (input, init?) => {
+- // Force the input type due to node.js fetch types not being compatible with libdom.d.ts
+- // https://github.com/nodejs/undici/issues/1943
+- return globalThis.fetch(input as FirstFetchParameter, {
+- ...init,
+- headers: {
+- ...init?.headers,
+- ...getContentTypeHeaders(input as FirstFetchParameter),
+- ...context.authHeaders,
+- },
+- });
+-};
+-
+-const makeProtonFetchTransport = (options: BrowserTransportOptions) => {
+- return makeFetchTransport(options, sentryFetch);
+-};
+-
+ const isLocalhost = (host: string) => host.startsWith('localhost');
+ const isProduction = (host: string) => host.endsWith('.proton.me') || host === VPN_HOSTNAME;
+
+@@ -175,94 +150,10 @@ function main({
+ ignore = ({ host }) => isLocalhost(host),
+ denyUrls = getDefaultDenyUrls(),
+ ignoreErrors = getDefaultIgnoreErrors(),
+-}: SentryOptions) {
+- const { SENTRY_DSN, SENTRY_DESKTOP_DSN, APP_VERSION } = config;
+- const isElectron = isElectronApp();
+- const sentryDSN = isElectron ? SENTRY_DESKTOP_DSN || SENTRY_DSN : SENTRY_DSN;
+- const { host, release, environment } = sentryConfig;
+-
+- // No need to configure it if we don't load the DSN
+- if (!sentryDSN || ignore(sentryConfig)) {
+- return;
+- }
+-
+- setUID(uid);
+-
+- // Assumes sentryDSN is: https://111b3eeaaec34cae8e812df705690a36@sentry/11
+- // To get https://111b3eeaaec34cae8e812df705690a36@protonmail.com/api/core/v4/reports/sentry/11
+- const dsn = sentryDSN.replace('sentry', `${host}/api/core/v4/reports/sentry`);
+-
+- init({
+- dsn,
+- release,
+- environment,
+- normalizeDepth: 5,
+- transport: makeProtonFetchTransport,
+- autoSessionTracking: sessionTracking,
+- // do not log calls to console.log, console.error, etc.
+- integrations: [
+- new SentryIntegrations.Breadcrumbs({
+- console: false,
+- }),
+- ],
+- // Disable client reports. Client reports are used by sentry to retry events that failed to send on visibility change.
+- // Unfortunately Sentry does not use the custom transport for those, and thus fails to add the headers the API requires.
+- sendClientReports: false,
+- beforeSend(event, hint) {
+- const error = hint?.originalException as any;
+- const stack = typeof error === 'string' ? error : error?.stack;
+- // Filter out broken ferdi errors
+- if (stack && stack.match(/ferdi|franz/i)) {
+- return null;
+- }
++}: SentryOptions) {}
+
+- // Not interested in uncaught API errors, or known errors
+- if (error instanceof ApiError || error?.trace === false) {
+- return null;
+- }
++export const traceError = (...args: Parameters) => console.error(...args);
+
+- if (!context.enabled) {
+- return null;
+- }
+-
+- // Remove the hash from the request URL and navigation breadcrumbs to avoid
+- // leaking the search parameters of encrypted searches
+- if (event.request && event.request.url) {
+- [event.request.url] = event.request.url.split('#');
+- }
+- if (event.breadcrumbs) {
+- event.breadcrumbs = event.breadcrumbs.map((breadcrumb) => {
+- if (breadcrumb.category === 'navigation' && breadcrumb.data) {
+- [breadcrumb.data.from] = breadcrumb.data.from.split('#');
+- [breadcrumb.data.to] = breadcrumb.data.to.split('#');
+- }
+- return breadcrumb;
+- });
+- }
+-
+- return event;
+- },
+- // Some ignoreErrors and denyUrls are taken from this gist: https://gist.github.com/Chocksy/e9b2cdd4afc2aadc7989762c4b8b495a
+- // This gist is suggested in the Sentry documentation: https://docs.sentry.io/clients/javascript/tips/#decluttering-sentry
+- ignoreErrors,
+- denyUrls,
+- });
+-
+- configureScope((scope) => {
+- scope.setTag('appVersion', APP_VERSION);
+- });
+-}
+-
+-export const traceError = (...args: Parameters) => {
+- if (!isLocalhost(window.location.host)) {
+- captureException(...args);
+- }
+-};
+-
+-export const captureMessage = (...args: Parameters) => {
+- if (!isLocalhost(window.location.host)) {
+- sentryCaptureMessage(...args);
+- }
+-};
++export const captureMessage = (...args: Parameters) => console.log(...args);
+
+ export default main;
diff --git a/patches/protonmail/url-5.patch b/patches/protonmail/url-5.patch
deleted file mode 100644
index 201d5185..00000000
--- a/patches/protonmail/url-5.patch
+++ /dev/null
@@ -1,75 +0,0 @@
-diff --git a/packages/shared/lib/helpers/url.ts b/packages/shared/lib/helpers/url.ts
-index 0c21c0f042..8ccd5ce82b 100644
---- a/packages/shared/lib/helpers/url.ts
-+++ b/packages/shared/lib/helpers/url.ts
-@@ -183,48 +183,16 @@ export const getSecondLevelDomain = (hostname: string) => {
- return hostname.slice(hostname.indexOf('.') + 1);
- };
-
--export const getRelativeApiHostname = (hostname: string) => {
-- const idx = hostname.indexOf('.');
-- const first = hostname.slice(0, idx);
-- const second = hostname.slice(idx + 1);
-- return `${first}-api.${second}`;
--};
--
- export const getIsDohDomain = (origin: string) => {
- return DOH_DOMAINS.some((dohDomain) => origin.endsWith(dohDomain));
- };
-
- export const getApiSubdomainUrl = (pathname: string) => {
-- const url = new URL('/', window.location.origin);
-- if (url.hostname === 'localhost' || getIsDohDomain(url.origin)) {
-- url.pathname = `/api${pathname}`;
-- return url;
-- }
-- url.hostname = getRelativeApiHostname(url.hostname);
-+ const url = new URL('/', '___ELECTRON_MAIL_PROTON_API_ENTRY_URL_PLACEHOLDER___');
- url.pathname = pathname;
- return url;
- };
-
--export const getAppUrlFromApiUrl = (apiUrl: string, appName: APP_NAMES) => {
-- const { subdomain } = APPS_CONFIGURATION[appName];
-- const url = new URL(apiUrl);
-- const { hostname } = url;
-- const index = hostname.indexOf('.');
-- const tail = hostname.slice(index + 1);
-- url.pathname = '';
-- url.hostname = `${subdomain}.${tail}`;
-- return url;
--};
--
--export const getAppUrlRelativeToOrigin = (origin: string, appName: APP_NAMES) => {
-- const { subdomain } = APPS_CONFIGURATION[appName];
-- const url = new URL(origin);
-- const segments = url.host.split('.');
-- segments[0] = subdomain;
-- url.hostname = segments.join('.');
-- return url;
--};
--
- let cache = '';
- export const getStaticURL = (path: string) => {
- if (
-
-diff --git a/packages/shared/lib/fetch/helpers.ts b/packages/shared/lib/fetch/helpers.ts
-index 666b9f56c6..246f0e03b4 100644
---- a/packages/shared/lib/fetch/helpers.ts
-+++ b/packages/shared/lib/fetch/helpers.ts
-@@ -11,6 +11,7 @@ const appendQueryParams = (url: URL, params: { [key: string]: any }) => {
- });
- };
-
-+/* */
- export const createUrl = (urlString: string, params: { [key: string]: any } = {}) => {
- let url: URL;
- if (typeof window !== 'undefined') {
-@@ -21,6 +22,7 @@ export const createUrl = (urlString: string, params: { [key: string]: any } = {}
- appendQueryParams(url, params);
- return url;
- };
-+/* */
-
- export const checkStatus = (response: Response, config: any) => {
- const { status } = response;
diff --git a/scripts/prepare-webclient/webclients.ts b/scripts/prepare-webclient/webclients.ts
index 8bc7af61..55a76e88 100644
--- a/scripts/prepare-webclient/webclients.ts
+++ b/scripts/prepare-webclient/webclients.ts
@@ -332,7 +332,7 @@ async function executeBuildFlow(
if (repoType === "proton-drive") {
// WARN if path changes, search "Service-Worker-Allowed" keyword in "src/electron-main" and make needed adjustments
- const downloadSW = path.join(repoDistDir, "assets", "downloadSW.*.chunk.js");
+ const downloadSW = path.join(repoDistDir, "downloadSW.js");
if (
fastGlob.sync(
downloadSW,
diff --git a/src/electron-main/protocol.ts b/src/electron-main/protocol.ts
index 96290b34..87fc2d67 100644
--- a/src/electron-main/protocol.ts
+++ b/src/electron-main/protocol.ts
@@ -182,7 +182,7 @@ export async function registerAccountSessionProtocols(
// TODO tweak e2e test: navigate to "/drive" (requires to be signed-in into the mail account)
// so the scope misconfiguration-related error get printed to "log.log" file and the test gets failed then
if (resourceLocation.startsWith(
- path.join(directory, PROVIDER_REPO_MAP["proton-drive"].basePath, "assets", "downloadSW."),
+ path.join(directory, PROVIDER_REPO_MAP["proton-drive"].basePath, "downloadSW."),
)) {
/* eslint-disable max-len */
// https://github.com/ProtonMail/proton-drive/blob/04d30ae6c9fbfbc33cfc91499831e2e6458a99b1/src/.htaccess#L42-L45
diff --git a/src/electron-preload/webview/primary/provider-api/index.ts b/src/electron-preload/webview/primary/provider-api/index.ts
index 7d5e483b..b6105e67 100644
--- a/src/electron-preload/webview/primary/provider-api/index.ts
+++ b/src/electron-preload/webview/primary/provider-api/index.ts
@@ -237,7 +237,7 @@ export const initProviderApi = async (): Promise => {
const [protonApi, messageKeys, encryptionPreferences] = await Promise.all([
resolveHttpApi(),
privateApi.getMessageKeys(message),
- privateApi.getEncryptionPreferences(message.Sender.Address),
+ privateApi.getEncryptionPreferences({email: message.Sender.Address}),
]);
const verification = constructMessageVerification(encryptionPreferences);
const {data} = await privateApi.getDecryptedAttachment(
@@ -258,7 +258,7 @@ export const initProviderApi = async (): Promise => {
return result;
})(),
},
- constants: internals["../../packages/shared/lib/constants.ts"].value,
+ constants: internals["../../packages/shared/lib/mail/mailSettings.ts"].value,
history: {
async push({folderId, conversationId, mailId}) {
// eslint-disable-next-line max-len
diff --git a/src/electron-preload/webview/primary/provider-api/internals.ts b/src/electron-preload/webview/primary/provider-api/internals.ts
index 5b4517b2..67c5bdd4 100644
--- a/src/electron-preload/webview/primary/provider-api/internals.ts
+++ b/src/electron-preload/webview/primary/provider-api/internals.ts
@@ -25,7 +25,7 @@ export const resolveProviderInternals = async (): Promise =>
"./src/app/helpers/message/messageDecrypt.ts": {
value: {decryptMessage: NEVER_FN},
},
- "../../packages/shared/lib/constants.ts": {
+ "../../packages/shared/lib/mail/mailSettings.ts": {
value: {VIEW_MODE: {GROUP: NaN, SINGLE: NaN}},
},
"../../packages/shared/lib/models/mailSettingsModel.js": {
@@ -140,7 +140,7 @@ export const resolveProviderInternals = async (): Promise =>
if (typeof value?.key !== "string") {
throw new Error(`Export item validation failed: ${JSON.stringify({resultKey, key})}`);
}
- } else if (resultKey === "../../packages/shared/lib/constants.ts") {
+ } else if (resultKey === "../../packages/shared/lib/mail/mailSettings.ts") {
type ValueType = (typeof result)[typeof resultKey]["value"];
const key: keyof ValueType = "VIEW_MODE";
const value = webpack_exports[key] as Partial | null;
diff --git a/src/electron-preload/webview/primary/provider-api/model.ts b/src/electron-preload/webview/primary/provider-api/model.ts
index 8645b021..12970fb6 100644
--- a/src/electron-preload/webview/primary/provider-api/model.ts
+++ b/src/electron-preload/webview/primary/provider-api/model.ts
@@ -21,8 +21,15 @@ export type ImmediateKeys = StrictExclude
export type ProviderInternals = AddInitializedProp<{
[K in StrictExtract]: DefineObservableValue<{
readonly privateScope: null | {
- // https://github.com/ProtonMail/react-components/blob/276aeddfba47dd473e96a54dbd2b12d6214a6359/hooks/useGetEncryptionPreferences.ts
- readonly getEncryptionPreferences: (senderAddress: RestModel.Message["Sender"]["Address"]) => Promise
+ // https://github.com/ProtonMail/WebClients/blob/3768deb904dd7865487fb71cb1bcee328cf32c30/packages/shared/lib/interfaces/hooks/GetEncryptionPreferences.ts
+ readonly getEncryptionPreferences: (
+ attr: {
+ email: RestModel.Message["Sender"]["Address"]
+ intendedForEmail?: boolean;
+ lifetime?: number;
+ contactEmailsMap?: { [email: string]: RestModel.ContactEmail | undefined };
+ }
+ ) => Promise
// https://github.com/ProtonMail/proton-mail/blob/77b133013cdb5695aa23c0c4c29cc6578878faa5/src/app/hooks/message/useGetMessageKeys.ts#L13
readonly getMessageKeys: (message: Pick) => Promise
// https://github.com/ProtonMail/proton-mail/blob/77b133013cdb5695aa23c0c4c29cc6578878faa5/src/app/helpers/attachment/attachmentLoader.ts#L46
@@ -54,7 +61,7 @@ export type ProviderInternals = AddInitializedProp<{
}>>
}
} & {
- [K in StrictExtract]: {
+ [K in StrictExtract]: {
readonly VIEW_MODE: { readonly GROUP: number; readonly SINGLE: number }
}
} & {
@@ -124,7 +131,7 @@ export type ProviderApi = { _throwErrorOnRateLimitedMethodCall?: boolean } & Rea
buildMessagesCountApiUrlTester: (options: { entryApiUrl: string }) => (url: string) => boolean
decryptMessage: (message: RestModel.Message) => Promise<{ decryptedSubject?: string, decryptedBody: string }>
}>
- constants: ProviderInternals["../../packages/shared/lib/constants.ts"]["value"],
+ constants: ProviderInternals["../../packages/shared/lib/mail/mailSettings.ts"]["value"],
label: Readonly<{
get: (
...args: Parameters
diff --git a/src/shared/const/proton-apps.ts b/src/shared/const/proton-apps.ts
index c6ba4fea..708cb71e 100644
--- a/src/shared/const/proton-apps.ts
+++ b/src/shared/const/proton-apps.ts
@@ -23,7 +23,7 @@ export const PROVIDER_REPO_MAP = {
basePath: "",
apiSubdomain: "mail-api",
repoRelativeDistDir: "./dist",
- tag: "proton-mail@5.0.29.7",
+ tag: "proton-mail@5.0.31.16",
protonPack: {
webpackIndexEntryItems: [
// immediate
@@ -31,7 +31,7 @@ export const PROVIDER_REPO_MAP = {
"../../packages/shared/lib/api/events.ts",
"../../packages/shared/lib/api/labels.ts",
"../../packages/shared/lib/api/messages.ts",
- "../../packages/shared/lib/constants.ts",
+ "../../packages/shared/lib/mail/mailSettings.ts",
"../../packages/shared/lib/models/mailSettingsModel.js",
"./src/app/containers/PageContainer.tsx",
"./src/app/helpers/mailboxUrl.ts",
@@ -49,14 +49,14 @@ export const PROVIDER_REPO_MAP = {
basePath: "account",
apiSubdomain: "account-api",
repoRelativeDistDir: "./dist",
- tag: "proton-account@5.0.54.0",
+ tag: "proton-account@5.0.68.1",
protonPack: {}
},
[PROVIDER_APP_NAMES[2]]: {
basePath: "calendar",
apiSubdomain: "calendar-api",
repoRelativeDistDir: "./dist",
- tag: "proton-calendar@5.0.15.5",
+ tag: "proton-calendar@5.0.16.13",
protonPack: {
webpackIndexEntryItems: [
// immediate
@@ -69,14 +69,14 @@ export const PROVIDER_REPO_MAP = {
basePath: "drive",
apiSubdomain: "drive-api",
repoRelativeDistDir: "./dist",
- tag: "proton-drive@5.0.15.4",
+ tag: "proton-drive@5.0.16.8",
protonPack: {},
},
[PROVIDER_APP_NAMES[4]]: {
basePath: "account/vpn",
apiSubdomain: "account-api",
repoRelativeDistDir: "./dist",
- tag: "proton-vpn-settings@5.0.50.0",
+ tag: "proton-vpn-settings@5.0.59.0",
protonPack: {},
},
} as const;