From 5d22cba48f90a887efa8da52696d2c6583308afe Mon Sep 17 00:00:00 2001 From: David Russell Date: Fri, 28 Mar 2025 11:21:59 +0000 Subject: [PATCH 1/6] creates preview optin service to opt in users by region --- src/browser/index.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/browser/index.tsx b/src/browser/index.tsx index 89aa524422..3b87ffeafd 100644 --- a/src/browser/index.tsx +++ b/src/browser/index.tsx @@ -23,14 +23,16 @@ import ReactDOM from 'react-dom' import AppInit, { setupSentry } from './AppInit' import './init' import { navigateToPreview } from './modules/Stream/StartPreviewFrame' +import { optedInByRegion } from './services/preview-optin-service' setupSentry() + ;(async () => { - const doesPreferQuery = localStorage.getItem('prefersOldBrowser') === 'false' + const optedInToPreview = optedInByRegion() try { const response = await fetch('./preview/manifest.json') if (response.status === 200) { - if (doesPreferQuery) { + if (optedInToPreview) { navigateToPreview() } else { localStorage.setItem('previewAvailable', 'true') From 18b615e4433ab0d99bd7eea95b8a32172ef87651 Mon Sep 17 00:00:00 2001 From: David Russell Date: Fri, 28 Mar 2025 11:24:30 +0000 Subject: [PATCH 2/6] adds optin service --- src/browser/services/preview-optin-service.ts | 123 ++++++++++++++++++ 1 file changed, 123 insertions(+) create mode 100644 src/browser/services/preview-optin-service.ts diff --git a/src/browser/services/preview-optin-service.ts b/src/browser/services/preview-optin-service.ts new file mode 100644 index 0000000000..3812453757 --- /dev/null +++ b/src/browser/services/preview-optin-service.ts @@ -0,0 +1,123 @@ +const EMEA_LOCALES = [ + 'bg-bg', + 'cs-cz', + 'cy-gb', + 'da-dk', + 'de-de', + 'el-gr', + 'en-gb', + 'et-ee', + 'fi-fi', + 'fr-fr', + 'ga-ie', + 'hr-hr', + 'hu-hu', + 'is-is', + 'it-it', + 'lb-lu', + 'lt-lt', + 'lv-lv', + 'mk-mk', + 'mt-mt', + 'nl-nl', + 'no-no', + 'pl-pl', + 'pt-pt', + 'ro-ro', + 'ru-ru', + 'sk-sk', + 'sl-si', + 'sr-rs', + 'sv-se', + 'uk-ua' +] + +const APAC_LOCALES = [ + 'as-in', + 'az-az', + 'bn-bd', + 'bn-in', + 'bo-cn', + 'fil-ph', + 'gu-in', + 'hi-in', + 'hy-am', + 'id-id', + 'ja-jp', + 'ka-ge', + 'km-kh', + 'kn-in', + 'ko-kr', + 'lo-la', + 'ml-in', + 'mn-mn', + 'mr-in', + 'ms-my', + 'my-mm', + 'ne-np', + 'or-in', + 'pa-in', + 'ps-af', + 'sa-in', + 'si-lk', + 'ta-in', + 'te-in', + 'th-th', + 'tr-tr', + 'ug-cn', + 'ur-in', + 'ur-pk', + 'vi-vn', + 'zh-cn', + 'zh-hk', + 'zh-tw' +] + +const AMERICAS_LOCALES = [ + 'ay-bo', + 'en-029', + 'en-ca', + 'en-us', + 'es-419', + 'es-ar', + 'es-bo', + 'es-cl', + 'es-co', + 'es-cr', + 'es-cu', + 'es-do', + 'es-ec', + 'es-gq', + 'es-gt', + 'es-hn', + 'es-mx', + 'es-ni', + 'es-pa', + 'es-pe', + 'es-pr', + 'es-py', + 'es-sv', + 'es-uy', + 'es-ve', + 'fr-029', + 'fr-ca', + 'gn-py', + 'pt-419', + 'pt-br', + 'qu-pe' +] + +const OPTED_IN_LOCALES = [...EMEA_LOCALES] + +const userPrefersQuery = (): boolean => { + const prefersOldBrowser = localStorage.getItem('prefersOldBrowser') + const doesPreferQuery = prefersOldBrowser === 'false' + return doesPreferQuery || prefersOldBrowser === null +} + +export const optedInByRegion = (): boolean => { + return ( + OPTED_IN_LOCALES.includes(navigator.language.toLowerCase()) && + userPrefersQuery() + ) +} From b09d2070954dcd78e4613d430e0f2f510a5bb109 Mon Sep 17 00:00:00 2001 From: David Russell Date: Fri, 28 Mar 2025 11:56:33 +0000 Subject: [PATCH 3/6] simplifies eu locale list --- src/browser/services/preview-optin-service.ts | 148 +++++------------- 1 file changed, 40 insertions(+), 108 deletions(-) diff --git a/src/browser/services/preview-optin-service.ts b/src/browser/services/preview-optin-service.ts index 3812453757..2546a7c5e0 100644 --- a/src/browser/services/preview-optin-service.ts +++ b/src/browser/services/preview-optin-service.ts @@ -1,113 +1,45 @@ -const EMEA_LOCALES = [ - 'bg-bg', - 'cs-cz', - 'cy-gb', - 'da-dk', - 'de-de', - 'el-gr', - 'en-gb', - 'et-ee', - 'fi-fi', - 'fr-fr', - 'ga-ie', - 'hr-hr', - 'hu-hu', - 'is-is', - 'it-it', - 'lb-lu', - 'lt-lt', - 'lv-lv', - 'mk-mk', - 'mt-mt', - 'nl-nl', - 'no-no', - 'pl-pl', - 'pt-pt', - 'ro-ro', - 'ru-ru', - 'sk-sk', - 'sl-si', - 'sr-rs', - 'sv-se', - 'uk-ua' +const EU_LOCALES = [ + 'bg-bg', // Bulgarian (Bulgaria) + 'cs-cz', // Czech (Czech Republic) + 'cy-gb', // Welsh (United Kingdom) + 'da-dk', // Danish (Denmark) + 'de-at', // German (Austria) + 'de-ch', // German (Switzerland) + 'de-de', // German (Germany) + 'el-gr', // Greek (Greece) + 'en-gb', // English (United Kingdom) + 'en-ie', // English (Ireland) + 'et-ee', // Estonian (Estonia) + 'fi-fi', // Finnish (Finland) + 'fr-be', // French (Belgium) + 'fr-ch', // French (Switzerland) + 'fr-fr', // French (France) + 'ga-ie', // Irish (Ireland) + 'hr-hr', // Croatian (Croatia) + 'hu-hu', // Hungarian (Hungary) + 'is-is', // Icelandic (Iceland) + 'it-ch', // Italian (Switzerland) + 'it-it', // Italian (Italy) + 'lb-lu', // Luxembourgish (Luxembourg) + 'lt-lt', // Lithuanian (Lithuania) + 'lv-lv', // Latvian (Latvia) + 'mk-mk', // Macedonian (North Macedonia) + 'mt-mt', // Maltese (Malta) + 'nl-be', // Dutch (Belgium) + 'nl-nl', // Dutch (Netherlands) + 'no-no', // Norwegian (Norway) + 'pl-pl', // Polish (Poland) + 'pt-pt', // Portuguese (Portugal) + 'ro-ro', // Romanian (Romania) + 'ru-ru', // Russian (Russia) + 'sk-sk', // Slovak (Slovakia) + 'sl-si', // Slovenian (Slovenia) + 'sr-rs', // Serbian (Serbia) + 'sv-se', // Swedish (Sweden) + 'uk-ua' // Ukrainian (Ukraine) ] -const APAC_LOCALES = [ - 'as-in', - 'az-az', - 'bn-bd', - 'bn-in', - 'bo-cn', - 'fil-ph', - 'gu-in', - 'hi-in', - 'hy-am', - 'id-id', - 'ja-jp', - 'ka-ge', - 'km-kh', - 'kn-in', - 'ko-kr', - 'lo-la', - 'ml-in', - 'mn-mn', - 'mr-in', - 'ms-my', - 'my-mm', - 'ne-np', - 'or-in', - 'pa-in', - 'ps-af', - 'sa-in', - 'si-lk', - 'ta-in', - 'te-in', - 'th-th', - 'tr-tr', - 'ug-cn', - 'ur-in', - 'ur-pk', - 'vi-vn', - 'zh-cn', - 'zh-hk', - 'zh-tw' -] - -const AMERICAS_LOCALES = [ - 'ay-bo', - 'en-029', - 'en-ca', - 'en-us', - 'es-419', - 'es-ar', - 'es-bo', - 'es-cl', - 'es-co', - 'es-cr', - 'es-cu', - 'es-do', - 'es-ec', - 'es-gq', - 'es-gt', - 'es-hn', - 'es-mx', - 'es-ni', - 'es-pa', - 'es-pe', - 'es-pr', - 'es-py', - 'es-sv', - 'es-uy', - 'es-ve', - 'fr-029', - 'fr-ca', - 'gn-py', - 'pt-419', - 'pt-br', - 'qu-pe' -] - -const OPTED_IN_LOCALES = [...EMEA_LOCALES] +const OPTED_IN_LOCALES = [...EU_LOCALES] const userPrefersQuery = (): boolean => { const prefersOldBrowser = localStorage.getItem('prefersOldBrowser') From 59e59600c87ccdc67d3619935c84b6faefc8ddb2 Mon Sep 17 00:00:00 2001 From: David Russell Date: Fri, 28 Mar 2025 12:12:02 +0000 Subject: [PATCH 4/6] renames optout function --- src/browser/services/preview-optin-service.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/services/preview-optin-service.ts b/src/browser/services/preview-optin-service.ts index 2546a7c5e0..e5542aa58f 100644 --- a/src/browser/services/preview-optin-service.ts +++ b/src/browser/services/preview-optin-service.ts @@ -41,7 +41,7 @@ const EU_LOCALES = [ const OPTED_IN_LOCALES = [...EU_LOCALES] -const userPrefersQuery = (): boolean => { +const userHasNotOptedOutOfPreview = (): boolean => { const prefersOldBrowser = localStorage.getItem('prefersOldBrowser') const doesPreferQuery = prefersOldBrowser === 'false' return doesPreferQuery || prefersOldBrowser === null @@ -50,6 +50,6 @@ const userPrefersQuery = (): boolean => { export const optedInByRegion = (): boolean => { return ( OPTED_IN_LOCALES.includes(navigator.language.toLowerCase()) && - userPrefersQuery() + userHasNotOptedOutOfPreview() ) } From c610d1f0cb56bb964c25e3a657ac900bf563f518 Mon Sep 17 00:00:00 2001 From: David Russell Date: Mon, 31 Mar 2025 08:59:42 +0100 Subject: [PATCH 5/6] opt in users by utc offset --- src/browser/index.tsx | 4 +- src/browser/services/preview-optin-service.ts | 53 ++----------------- 2 files changed, 7 insertions(+), 50 deletions(-) diff --git a/src/browser/index.tsx b/src/browser/index.tsx index 3b87ffeafd..73b7c14906 100644 --- a/src/browser/index.tsx +++ b/src/browser/index.tsx @@ -23,12 +23,12 @@ import ReactDOM from 'react-dom' import AppInit, { setupSentry } from './AppInit' import './init' import { navigateToPreview } from './modules/Stream/StartPreviewFrame' -import { optedInByRegion } from './services/preview-optin-service' +import { optedInByUtcOffset } from './services/preview-optin-service' setupSentry() ;(async () => { - const optedInToPreview = optedInByRegion() + const optedInToPreview = optedInByUtcOffset() try { const response = await fetch('./preview/manifest.json') if (response.status === 200) { diff --git a/src/browser/services/preview-optin-service.ts b/src/browser/services/preview-optin-service.ts index e5542aa58f..9c7dcd6df9 100644 --- a/src/browser/services/preview-optin-service.ts +++ b/src/browser/services/preview-optin-service.ts @@ -1,55 +1,12 @@ -const EU_LOCALES = [ - 'bg-bg', // Bulgarian (Bulgaria) - 'cs-cz', // Czech (Czech Republic) - 'cy-gb', // Welsh (United Kingdom) - 'da-dk', // Danish (Denmark) - 'de-at', // German (Austria) - 'de-ch', // German (Switzerland) - 'de-de', // German (Germany) - 'el-gr', // Greek (Greece) - 'en-gb', // English (United Kingdom) - 'en-ie', // English (Ireland) - 'et-ee', // Estonian (Estonia) - 'fi-fi', // Finnish (Finland) - 'fr-be', // French (Belgium) - 'fr-ch', // French (Switzerland) - 'fr-fr', // French (France) - 'ga-ie', // Irish (Ireland) - 'hr-hr', // Croatian (Croatia) - 'hu-hu', // Hungarian (Hungary) - 'is-is', // Icelandic (Iceland) - 'it-ch', // Italian (Switzerland) - 'it-it', // Italian (Italy) - 'lb-lu', // Luxembourgish (Luxembourg) - 'lt-lt', // Lithuanian (Lithuania) - 'lv-lv', // Latvian (Latvia) - 'mk-mk', // Macedonian (North Macedonia) - 'mt-mt', // Maltese (Malta) - 'nl-be', // Dutch (Belgium) - 'nl-nl', // Dutch (Netherlands) - 'no-no', // Norwegian (Norway) - 'pl-pl', // Polish (Poland) - 'pt-pt', // Portuguese (Portugal) - 'ro-ro', // Romanian (Romania) - 'ru-ru', // Russian (Russia) - 'sk-sk', // Slovak (Slovakia) - 'sl-si', // Slovenian (Slovenia) - 'sr-rs', // Serbian (Serbia) - 'sv-se', // Swedish (Sweden) - 'uk-ua' // Ukrainian (Ukraine) -] - -const OPTED_IN_LOCALES = [...EU_LOCALES] - const userHasNotOptedOutOfPreview = (): boolean => { const prefersOldBrowser = localStorage.getItem('prefersOldBrowser') const doesPreferQuery = prefersOldBrowser === 'false' return doesPreferQuery || prefersOldBrowser === null } -export const optedInByRegion = (): boolean => { - return ( - OPTED_IN_LOCALES.includes(navigator.language.toLowerCase()) && - userHasNotOptedOutOfPreview() - ) +export const optedInByUtcOffset = (): boolean => { + const utcOffset = new Date().getTimezoneOffset() + // UTC offset of -120 minutes (2 hours) e.g. CEST to 0 minutes (0 hours) + const utcOffsetIsOptedIn = utcOffset >= -120 && utcOffset <= 0 + return utcOffsetIsOptedIn && userHasNotOptedOutOfPreview() } From 1be04d3037204fca091d5cdc4c9201971c1c8e5b Mon Sep 17 00:00:00 2001 From: David Russell Date: Mon, 31 Mar 2025 13:24:10 +0100 Subject: [PATCH 6/6] removes regional opt-in, uses simple opt in approach --- src/browser/index.tsx | 6 ++++-- src/browser/services/preview-optin-service.ts | 12 ------------ 2 files changed, 4 insertions(+), 14 deletions(-) delete mode 100644 src/browser/services/preview-optin-service.ts diff --git a/src/browser/index.tsx b/src/browser/index.tsx index 73b7c14906..41c3984829 100644 --- a/src/browser/index.tsx +++ b/src/browser/index.tsx @@ -23,12 +23,14 @@ import ReactDOM from 'react-dom' import AppInit, { setupSentry } from './AppInit' import './init' import { navigateToPreview } from './modules/Stream/StartPreviewFrame' -import { optedInByUtcOffset } from './services/preview-optin-service' setupSentry() ;(async () => { - const optedInToPreview = optedInByUtcOffset() + const prefersOldBrowser = localStorage.getItem('prefersOldBrowser') + const doesPreferQuery = prefersOldBrowser === 'false' + const optedInToPreview = doesPreferQuery || prefersOldBrowser === null + try { const response = await fetch('./preview/manifest.json') if (response.status === 200) { diff --git a/src/browser/services/preview-optin-service.ts b/src/browser/services/preview-optin-service.ts deleted file mode 100644 index 9c7dcd6df9..0000000000 --- a/src/browser/services/preview-optin-service.ts +++ /dev/null @@ -1,12 +0,0 @@ -const userHasNotOptedOutOfPreview = (): boolean => { - const prefersOldBrowser = localStorage.getItem('prefersOldBrowser') - const doesPreferQuery = prefersOldBrowser === 'false' - return doesPreferQuery || prefersOldBrowser === null -} - -export const optedInByUtcOffset = (): boolean => { - const utcOffset = new Date().getTimezoneOffset() - // UTC offset of -120 minutes (2 hours) e.g. CEST to 0 minutes (0 hours) - const utcOffsetIsOptedIn = utcOffset >= -120 && utcOffset <= 0 - return utcOffsetIsOptedIn && userHasNotOptedOutOfPreview() -}