From 806f3bb257e07e81f1953369aeca562b6ca4d380 Mon Sep 17 00:00:00 2001 From: Eric Bailey Date: Tue, 17 Sep 2024 09:23:47 -0500 Subject: [PATCH] Cleanup, port to web --- package.json | 1 + src/state/persisted/index.ts | 46 +++++--------------------------- src/state/persisted/index.web.ts | 13 +++++---- src/state/persisted/util.ts | 45 +++++++++++++++++++++++++++++++ yarn.lock | 27 +++++++++++++++++++ 5 files changed, 87 insertions(+), 45 deletions(-) create mode 100644 src/state/persisted/util.ts diff --git a/package.json b/package.json index fc93584085..ce1e4c7fcf 100644 --- a/package.json +++ b/package.json @@ -110,6 +110,7 @@ "await-lock": "^2.2.2", "babel-plugin-transform-remove-console": "^6.9.4", "base64-js": "^1.5.1", + "bcp-47": "^2.1.0", "bcp-47-match": "^2.0.3", "date-fns": "^2.30.0", "deprecated-react-native-prop-types": "^5.0.0", diff --git a/src/state/persisted/index.ts b/src/state/persisted/index.ts index 834871ba09..51d757ad8b 100644 --- a/src/state/persisted/index.ts +++ b/src/state/persisted/index.ts @@ -8,6 +8,7 @@ import { tryStringify, } from '#/state/persisted/schema' import {PersistedApi} from './types' +import {normalizeData} from './util' export type {PersistedAccount, Schema} from '#/state/persisted/schema' export {defaults} from '#/state/persisted/schema' @@ -19,7 +20,7 @@ let _state: Schema = defaults export async function init() { const stored = await readFromStorage() if (stored) { - _state = normalizeData(stored) + _state = stored } } init satisfies PersistedApi['init'] @@ -81,44 +82,9 @@ async function readFromStorage(): Promise { }) } if (rawData) { - return tryParse(rawData) + const parsed = tryParse(rawData) + if (parsed) { + return normalizeData(parsed) + } } } - -function normalizeData(data: Schema) { - /** - * Normalize language prefs to ensure that these values only contain 2-letter - * country codes without region. - */ - try { - const next = {...data.languagePrefs} - next.primaryLanguage = next.primaryLanguage.split('-')[0] - next.contentLanguages = next.contentLanguages.map(lang => - normalizeLocaleToTwoLetterCode(lang), - ) - next.postLanguage = next.postLanguage - .split(',') - .map(lang => normalizeLocaleToTwoLetterCode(lang)) - .filter(Boolean) - .join(',') - next.postLanguageHistory = next.postLanguageHistory.map(postLanguage => { - return postLanguage - .split(',') - .map(lang => normalizeLocaleToTwoLetterCode(lang)) - .filter(Boolean) - .join(',') - }) - // mutate last in case anything above fails - data.languagePrefs = next - } catch (e: any) { - logger.error(`persisted state: failed to normalize language prefs`, { - safeMessage: e.message, - }) - } - - return data -} - -function normalizeLocaleToTwoLetterCode(lang: string) { - return lang.split('-')[0] -} diff --git a/src/state/persisted/index.web.ts b/src/state/persisted/index.web.ts index 7521776bc0..4cfc87cdb1 100644 --- a/src/state/persisted/index.web.ts +++ b/src/state/persisted/index.web.ts @@ -9,6 +9,7 @@ import { tryStringify, } from '#/state/persisted/schema' import {PersistedApi} from './types' +import {normalizeData} from './util' export type {PersistedAccount, Schema} from '#/state/persisted/schema' export {defaults} from '#/state/persisted/schema' @@ -56,10 +57,10 @@ export async function write( } catch (e) { // Ignore and go through the normal path. } - _state = { + _state = normalizeData({ ..._state, [key]: value, - } + }) writeToStorage(_state) broadcast.postMessage({event: {type: UPDATE_EVENT, key}}) broadcast.postMessage({event: UPDATE_EVENT}) // Backcompat while upgrading @@ -140,9 +141,11 @@ function readFromStorage(): Schema | undefined { return lastResult } else { const result = tryParse(rawData) - lastRawData = rawData - lastResult = result - return result + if (result) { + lastRawData = rawData + lastResult = normalizeData(result) + return lastResult + } } } } diff --git a/src/state/persisted/util.ts b/src/state/persisted/util.ts new file mode 100644 index 0000000000..ea539cd7ea --- /dev/null +++ b/src/state/persisted/util.ts @@ -0,0 +1,45 @@ +import {parse} from 'bcp-47' + +import {logger} from '#/logger' +import {Schema} from '#/state/persisted/schema' + +export function normalizeData(data: Schema) { + /** + * Normalize language prefs to ensure that these values only contain 2-letter + * country codes without region. + */ + try { + const next = {...data.languagePrefs} + next.primaryLanguage = normalizeLanguageTagToTwoLetterCode( + next.primaryLanguage, + ) + next.contentLanguages = next.contentLanguages.map(lang => + normalizeLanguageTagToTwoLetterCode(lang), + ) + next.postLanguage = next.postLanguage + .split(',') + .map(lang => normalizeLanguageTagToTwoLetterCode(lang)) + .filter(Boolean) + .join(',') + next.postLanguageHistory = next.postLanguageHistory.map(postLanguage => { + return postLanguage + .split(',') + .map(lang => normalizeLanguageTagToTwoLetterCode(lang)) + .filter(Boolean) + .join(',') + }) + // mutate last in case anything above fails + data.languagePrefs = next + } catch (e: any) { + logger.error(`persisted state: failed to normalize language prefs`, { + safeMessage: e.message, + }) + } + + return data +} + +export function normalizeLanguageTagToTwoLetterCode(lang: string) { + const result = parse(lang).language + return result ?? lang +} diff --git a/yarn.lock b/yarn.lock index 8963f0920e..04457b2717 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9579,6 +9579,15 @@ bcp-47-match@^2.0.3: resolved "https://registry.yarnpkg.com/bcp-47-match/-/bcp-47-match-2.0.3.tgz#603226f6e5d3914a581408be33b28a53144b09d0" integrity sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ== +bcp-47@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/bcp-47/-/bcp-47-2.1.0.tgz#7e80734c3338fe8320894981dccf4968c3092df6" + integrity sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w== + dependencies: + is-alphabetical "^2.0.0" + is-alphanumerical "^2.0.0" + is-decimal "^2.0.0" + better-opn@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817" @@ -13893,6 +13902,19 @@ ipaddr.js@^2.1.0: resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-2.2.0.tgz#d33fa7bac284f4de7af949638c9d68157c6b92e8" integrity sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA== +is-alphabetical@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-2.0.1.tgz#01072053ea7c1036df3c7d19a6daaec7f19e789b" + integrity sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ== + +is-alphanumerical@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz#7c03fbe96e3e931113e57f964b0a368cc2dfd875" + integrity sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw== + dependencies: + is-alphabetical "^2.0.0" + is-decimal "^2.0.0" + is-arguments@^1.0.4: version "1.1.1" resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.1.1.tgz#15b3f88fda01f2a97fec84ca761a560f123efa9b" @@ -13987,6 +14009,11 @@ is-date-object@^1.0.1, is-date-object@^1.0.5: dependencies: has-tostringtag "^1.0.0" +is-decimal@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-2.0.1.tgz#9469d2dc190d0214fd87d78b78caecc0cc14eef7" + integrity sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A== + is-directory@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1"