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;