@oxyhq/core 9.2.4 → 10.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/.tsbuildinfo +1 -1
- package/dist/cjs/i18n/index.js +22 -2
- package/dist/cjs/i18n/locales/en-US.json +4 -1
- package/dist/cjs/i18n/locales/es-ES.json +4 -1
- package/dist/cjs/i18n/locales/locales/en-US.json +4 -1
- package/dist/cjs/i18n/locales/locales/es-ES.json +4 -1
- package/dist/cjs/index.js +16 -5
- package/dist/cjs/mixins/OxyServices.assets.js +10 -6
- package/dist/cjs/mixins/OxyServices.language.js +11 -10
- package/dist/cjs/mixins/OxyServices.privacy.js +6 -0
- package/dist/cjs/mixins/OxyServices.user.js +40 -0
- package/dist/cjs/server/safeFetch.js +3 -3
- package/dist/cjs/session/SessionClient.js +1 -1
- package/dist/cjs/shared/utils/colorUtils.js +9 -9
- package/dist/cjs/utils/languageUtils.js +195 -158
- package/dist/cjs/utils/platform.js +9 -2
- package/dist/cjs/utils/textNormalization.js +168 -0
- package/dist/esm/.tsbuildinfo +1 -1
- package/dist/esm/i18n/index.js +22 -2
- package/dist/esm/i18n/locales/en-US.json +4 -1
- package/dist/esm/i18n/locales/es-ES.json +4 -1
- package/dist/esm/i18n/locales/locales/en-US.json +4 -1
- package/dist/esm/i18n/locales/locales/es-ES.json +4 -1
- package/dist/esm/index.js +5 -1
- package/dist/esm/mixins/OxyServices.assets.js +10 -6
- package/dist/esm/mixins/OxyServices.language.js +12 -11
- package/dist/esm/mixins/OxyServices.privacy.js +6 -0
- package/dist/esm/mixins/OxyServices.user.js +40 -0
- package/dist/esm/server/safeFetch.js +3 -3
- package/dist/esm/session/SessionClient.js +1 -1
- package/dist/esm/shared/utils/colorUtils.js +9 -9
- package/dist/esm/utils/languageUtils.js +189 -156
- package/dist/esm/utils/platform.js +9 -2
- package/dist/esm/utils/textNormalization.js +164 -0
- package/dist/types/.tsbuildinfo +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/mixins/OxyServices.language.d.ts +4 -4
- package/dist/types/mixins/OxyServices.user.d.ts +30 -0
- package/dist/types/models/interfaces.d.ts +14 -0
- package/dist/types/session/accountDialogController.d.ts +1 -1
- package/dist/types/utils/languageUtils.d.ts +86 -24
- package/dist/types/utils/textNormalization.d.ts +100 -0
- package/package.json +3 -3
- package/src/HttpService.ts +2 -2
- package/src/crypto/keyManager.ts +3 -3
- package/src/crypto/recoveryPhrase.ts +1 -1
- package/src/i18n/index.ts +21 -2
- package/src/i18n/locales/en-US.json +4 -1
- package/src/i18n/locales/es-ES.json +4 -1
- package/src/index.ts +16 -2
- package/src/mixins/OxyServices.assets.ts +15 -11
- package/src/mixins/OxyServices.language.ts +31 -17
- package/src/mixins/OxyServices.privacy.ts +6 -0
- package/src/mixins/OxyServices.security.ts +1 -1
- package/src/mixins/OxyServices.user.ts +57 -0
- package/src/models/interfaces.ts +14 -0
- package/src/server/safeFetch.ts +3 -3
- package/src/session/SessionClient.ts +1 -1
- package/src/session/accountDialogController.ts +1 -1
- package/src/shared/utils/colorUtils.ts +11 -11
- package/src/shared/utils/errorUtils.ts +1 -1
- package/src/utils/__tests__/languageUtils.test.ts +219 -0
- package/src/utils/__tests__/textNormalization.test.ts +196 -0
- package/src/utils/avatarUtils.ts +1 -1
- package/src/utils/languageUtils.ts +223 -162
- package/src/utils/platform.ts +21 -3
- package/src/utils/requestUtils.ts +3 -3
- package/src/utils/sessionUtils.ts +2 -2
- package/src/utils/textNormalization.ts +173 -0
package/dist/cjs/i18n/index.js
CHANGED
|
@@ -16,6 +16,7 @@ const ja_JP_json_1 = __importDefault(require("./locales/ja-JP.json"));
|
|
|
16
16
|
const ko_KR_json_1 = __importDefault(require("./locales/ko-KR.json"));
|
|
17
17
|
const zh_CN_json_1 = __importDefault(require("./locales/zh-CN.json"));
|
|
18
18
|
const ar_SA_json_1 = __importDefault(require("./locales/ar-SA.json"));
|
|
19
|
+
const languageUtils_1 = require("../utils/languageUtils");
|
|
19
20
|
const DICTS = {
|
|
20
21
|
'en': en_US_json_1.default,
|
|
21
22
|
'en-US': en_US_json_1.default,
|
|
@@ -41,11 +42,30 @@ const DICTS = {
|
|
|
41
42
|
'ar-SA': ar_SA_json_1.default,
|
|
42
43
|
};
|
|
43
44
|
const FALLBACK = 'en-US';
|
|
45
|
+
/**
|
|
46
|
+
* Resolve a locale tag to the key of the dictionary that should serve it.
|
|
47
|
+
*
|
|
48
|
+
* Account locales are full BCP-47 tags (e.g. `es-MX`, `pt-BR`, `fr-CA`), but a
|
|
49
|
+
* translation dictionary is shipped per base language. Resolution order:
|
|
50
|
+
* 1. Exact dictionary for the tag (e.g. `es-ES`).
|
|
51
|
+
* 2. Dictionary for the base subtag (e.g. `es-MX` → `es`).
|
|
52
|
+
* 3. The English fallback.
|
|
53
|
+
*/
|
|
54
|
+
function resolveLang(locale) {
|
|
55
|
+
if (locale) {
|
|
56
|
+
if (DICTS[locale])
|
|
57
|
+
return locale;
|
|
58
|
+
const base = (0, languageUtils_1.getBaseLanguage)(locale);
|
|
59
|
+
if (DICTS[base])
|
|
60
|
+
return base;
|
|
61
|
+
}
|
|
62
|
+
return FALLBACK;
|
|
63
|
+
}
|
|
44
64
|
function getNested(obj, path) {
|
|
45
65
|
return path.split('.').reduce((acc, key) => (acc && acc[key] != null ? acc[key] : undefined), obj);
|
|
46
66
|
}
|
|
47
67
|
function translate(locale, key, vars) {
|
|
48
|
-
const lang = locale
|
|
68
|
+
const lang = resolveLang(locale);
|
|
49
69
|
const dict = DICTS[lang] || DICTS[FALLBACK];
|
|
50
70
|
let val = getNested(dict, key);
|
|
51
71
|
// Per-key fallback to the English dictionary when a key is missing from the
|
|
@@ -65,6 +85,6 @@ function translate(locale, key, vars) {
|
|
|
65
85
|
return val;
|
|
66
86
|
}
|
|
67
87
|
function hasKey(locale, key) {
|
|
68
|
-
const lang = locale
|
|
88
|
+
const lang = resolveLang(locale);
|
|
69
89
|
return getNested(DICTS[lang], key) != null || getNested(DICTS[FALLBACK], key) != null;
|
|
70
90
|
}
|
|
@@ -169,9 +169,12 @@
|
|
|
169
169
|
},
|
|
170
170
|
"language": {
|
|
171
171
|
"title": "Language",
|
|
172
|
-
"subtitle": "Choose your
|
|
172
|
+
"subtitle": "Choose the languages you use. The first is your primary interface language.",
|
|
173
173
|
"current": "Current Language",
|
|
174
|
+
"selected": "Your languages",
|
|
174
175
|
"available": "Available Languages",
|
|
176
|
+
"primary": "Primary",
|
|
177
|
+
"remove": "Remove",
|
|
175
178
|
"changed": "Language changed to {{lang}}",
|
|
176
179
|
"saveFailed": "Failed to save language preference",
|
|
177
180
|
"search": "Search languages"
|
|
@@ -123,9 +123,12 @@
|
|
|
123
123
|
},
|
|
124
124
|
"language": {
|
|
125
125
|
"title": "Idioma",
|
|
126
|
-
"subtitle": "Elige tu idioma
|
|
126
|
+
"subtitle": "Elige los idiomas que usas. El primero es tu idioma de interfaz principal.",
|
|
127
127
|
"current": "Idioma actual",
|
|
128
|
+
"selected": "Tus idiomas",
|
|
128
129
|
"available": "Idiomas disponibles",
|
|
130
|
+
"primary": "Principal",
|
|
131
|
+
"remove": "Quitar",
|
|
129
132
|
"changed": "Idioma cambiado a {{lang}}",
|
|
130
133
|
"saveFailed": "Error al guardar la preferencia de idioma",
|
|
131
134
|
"search": "Buscar idiomas"
|
|
@@ -169,9 +169,12 @@
|
|
|
169
169
|
},
|
|
170
170
|
"language": {
|
|
171
171
|
"title": "Language",
|
|
172
|
-
"subtitle": "Choose your
|
|
172
|
+
"subtitle": "Choose the languages you use. The first is your primary interface language.",
|
|
173
173
|
"current": "Current Language",
|
|
174
|
+
"selected": "Your languages",
|
|
174
175
|
"available": "Available Languages",
|
|
176
|
+
"primary": "Primary",
|
|
177
|
+
"remove": "Remove",
|
|
175
178
|
"changed": "Language changed to {{lang}}",
|
|
176
179
|
"saveFailed": "Failed to save language preference",
|
|
177
180
|
"search": "Search languages"
|
|
@@ -123,9 +123,12 @@
|
|
|
123
123
|
},
|
|
124
124
|
"language": {
|
|
125
125
|
"title": "Idioma",
|
|
126
|
-
"subtitle": "Elige tu idioma
|
|
126
|
+
"subtitle": "Elige los idiomas que usas. El primero es tu idioma de interfaz principal.",
|
|
127
127
|
"current": "Idioma actual",
|
|
128
|
+
"selected": "Tus idiomas",
|
|
128
129
|
"available": "Idiomas disponibles",
|
|
130
|
+
"primary": "Principal",
|
|
131
|
+
"remove": "Quitar",
|
|
129
132
|
"changed": "Idioma cambiado a {{lang}}",
|
|
130
133
|
"saveFailed": "Error al guardar la preferencia de idioma",
|
|
131
134
|
"search": "Buscar idiomas"
|
package/dist/cjs/index.js
CHANGED
|
@@ -18,10 +18,10 @@
|
|
|
18
18
|
* If a symbol does not appear here, it is NOT part of the public API.
|
|
19
19
|
*/
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.
|
|
22
|
-
exports.
|
|
23
|
-
exports.
|
|
24
|
-
exports.packageInfo = exports.runSessionColdBoot = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.switchableAccountIds = exports.projectSwitchableAccounts = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.redeemHubTicketOnHub = exports.syncHubAfterSignIn = exports.parseHubSyncReturnUrl = exports.normalizeOfficialReturnOrigin = exports.isAllowedDeviceJoinOrigin = exports.isOfficialWebOrigin = exports.isIdpHubOrigin = exports.buildHubSyncUrl = void 0;
|
|
21
|
+
exports.isWeb = exports.setPlatformOS = exports.getPlatformOS = exports.getPrimaryLanguage = exports.getUserLanguages = exports.isRTLLocale = exports.getNativeLanguageName = exports.getLanguageName = exports.getLanguageMetadata = exports.isSupportedLocale = exports.normalizeLocale = exports.getBaseLanguage = exports.FALLBACK_LOCALE = exports.SUPPORTED_LANGUAGES = exports.TopicSource = exports.TopicType = exports.SECURITY_EVENT_SEVERITY_MAP = exports.DeviceManager = exports.RecoveryPhraseService = exports.SignatureService = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = exports.sessionsArraysEqual = exports.normalizeAndSortSessions = exports.mergeSessions = exports.authenticatedApiCall = exports.withAuthErrorHandling = exports.isAuthenticationError = exports.ensureValidToken = exports.AuthenticationFailedError = exports.SessionSyncRequiredError = exports.verifyPublicCardAttestation = exports.parseAttestPayload = exports.parseIdPayload = exports.buildUserDid = exports.ORGANIZATION_CATEGORIES = exports.normalizeProfileLinks = exports.getNormalizedUserHandle = exports.getCanonicalUserHandle = exports.normalizeUserIdentityOrNull = exports.normalizeUserIdentity = exports.getNormalizedUserId = exports.OxyAppDataIdentifierError = exports.ServiceCredentialMismatchError = exports.oxyClient = exports.OXY_CLOUD_URL = exports.OxyAuthenticationTimeoutError = exports.OxyAuthenticationError = exports.OxyServices = void 0;
|
|
22
|
+
exports.retryAsync = exports.validateRequiredFields = exports.handleHttpError = exports.createApiError = exports.ErrorCodes = exports.safeJsonParse = exports.buildPaginationParams = exports.buildUrl = exports.buildSearchParams = exports.translate = exports.createDebugLogger = exports.debugError = exports.debugWarn = exports.debugLog = exports.isDev = exports.withRetry = exports.delay = exports.shouldAllowRequest = exports.recordSuccess = exports.recordFailure = exports.calculateBackoffInterval = exports.createCircuitBreakerState = exports.DEFAULT_CIRCUIT_BREAKER_CONFIG = exports.isRetryableError = exports.isNetworkError = exports.isServerError = exports.isRateLimitError = exports.isNotFoundError = exports.isForbiddenError = exports.isUnauthorizedError = exports.isAlreadyRegisteredError = exports.getErrorMessage = exports.getErrorStatus = exports.HttpStatus = exports.getSystemColorScheme = exports.systemPrefersDarkMode = exports.getOppositeTheme = exports.normalizeColorScheme = exports.normalizeTheme = exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = exports.rgbToHex = exports.hexToRgb = exports.lightenColor = exports.darkenColor = exports.isWebBrowser = exports.isAndroid = exports.isIOS = exports.isNative = void 0;
|
|
23
|
+
exports.OXY_OAUTH_CODE_VERIFIER_STORAGE_KEY = exports.OXY_OAUTH_STATE_STORAGE_KEY = exports.OXY_AUTHORIZE_URL = exports.DEFAULT_OAUTH_SCOPE = exports.generatePkcePair = exports.generateOAuthState = exports.computeCodeChallenge = exports.buildOAuthAuthorizeUrl = exports.runColdBoot = exports.CENTRAL_IDP_APEX = exports.registrableApex = exports.getAccountColor = exports.formatPublicKeyHandle = exports.getAccountFallbackHandle = exports.getAccountDisplayName = exports.createQuickAccount = exports.buildAccountsArray = exports.updateAvatarVisibility = exports.logPerformance = exports.logPayment = exports.logDevice = exports.logUser = exports.logSession = exports.logApi = exports.logAuth = exports.LogLevel = exports.logger = exports.normalizeMultilineText = exports.normalizeInlineText = exports.validateAndSanitizeUserInput = exports.isValidObjectId = exports.sanitizeHTML = exports.sanitizeString = exports.isValidFileType = exports.isValidFileSize = exports.isValidDate = exports.isValidURL = exports.isValidUUID = exports.isValidObject = exports.isValidArray = exports.isRequiredBoolean = exports.isRequiredNumber = exports.isRequiredString = exports.isValidDisplayName = exports.isValidPassword = exports.isValidUsername = exports.isValidEmail = exports.PASSWORD_REGEX = exports.USERNAME_REGEX = exports.EMAIL_REGEX = void 0;
|
|
24
|
+
exports.packageInfo = exports.runSessionColdBoot = exports.TOKEN_REFRESH_LEAD_MS = exports.startTokenRefreshScheduler = exports.installAuthRefreshHandler = exports.createAuthRefreshHandler = exports.refreshDeviceSecretArm = exports.refreshPersistedSession = exports.AUTH_STATE_STORAGE_KEY = exports.createMemoryAuthStateStore = exports.createNativeAuthStateStore = exports.createWebAuthStateStore = exports.createAccountDialogController = exports.AccountDialogController = exports.switchableAccountIds = exports.projectSwitchableAccounts = exports.accountIdsOf = exports.activeUserOf = exports.activeSessionIdOf = exports.deviceStateToClientSessions = exports.createSessionClient = exports.createSessionClientHost = exports.SessionClient = exports.redeemHubTicketOnHub = exports.syncHubAfterSignIn = exports.parseHubSyncReturnUrl = exports.normalizeOfficialReturnOrigin = exports.isAllowedDeviceJoinOrigin = exports.isOfficialWebOrigin = exports.isIdpHubOrigin = exports.buildHubSyncUrl = exports.buildIdpHubOrigin = exports.clearOAuthHandshake = exports.readOAuthHandshake = exports.persistOAuthHandshake = exports.normalizeOAuthRedirectUri = exports.OXY_CROSS_ORIGIN_RESTORE_ATTEMPTED_KEY = exports.OXY_SILENT_OAUTH_ATTEMPTED_KEY = void 0;
|
|
25
25
|
// Ensure crypto polyfills are loaded before anything else
|
|
26
26
|
require("./crypto/polyfill");
|
|
27
27
|
// ---------------------------------------------------------------------------
|
|
@@ -119,11 +119,16 @@ Object.defineProperty(exports, "TopicSource", { enumerable: true, get: function
|
|
|
119
119
|
// ---------------------------------------------------------------------------
|
|
120
120
|
var languageUtils_1 = require("./utils/languageUtils");
|
|
121
121
|
Object.defineProperty(exports, "SUPPORTED_LANGUAGES", { enumerable: true, get: function () { return languageUtils_1.SUPPORTED_LANGUAGES; } });
|
|
122
|
+
Object.defineProperty(exports, "FALLBACK_LOCALE", { enumerable: true, get: function () { return languageUtils_1.FALLBACK_LOCALE; } });
|
|
123
|
+
Object.defineProperty(exports, "getBaseLanguage", { enumerable: true, get: function () { return languageUtils_1.getBaseLanguage; } });
|
|
124
|
+
Object.defineProperty(exports, "normalizeLocale", { enumerable: true, get: function () { return languageUtils_1.normalizeLocale; } });
|
|
125
|
+
Object.defineProperty(exports, "isSupportedLocale", { enumerable: true, get: function () { return languageUtils_1.isSupportedLocale; } });
|
|
122
126
|
Object.defineProperty(exports, "getLanguageMetadata", { enumerable: true, get: function () { return languageUtils_1.getLanguageMetadata; } });
|
|
123
127
|
Object.defineProperty(exports, "getLanguageName", { enumerable: true, get: function () { return languageUtils_1.getLanguageName; } });
|
|
124
128
|
Object.defineProperty(exports, "getNativeLanguageName", { enumerable: true, get: function () { return languageUtils_1.getNativeLanguageName; } });
|
|
125
|
-
Object.defineProperty(exports, "normalizeLanguageCode", { enumerable: true, get: function () { return languageUtils_1.normalizeLanguageCode; } });
|
|
126
129
|
Object.defineProperty(exports, "isRTLLocale", { enumerable: true, get: function () { return languageUtils_1.isRTLLocale; } });
|
|
130
|
+
Object.defineProperty(exports, "getUserLanguages", { enumerable: true, get: function () { return languageUtils_1.getUserLanguages; } });
|
|
131
|
+
Object.defineProperty(exports, "getPrimaryLanguage", { enumerable: true, get: function () { return languageUtils_1.getPrimaryLanguage; } });
|
|
127
132
|
// ---------------------------------------------------------------------------
|
|
128
133
|
// Platform detection
|
|
129
134
|
// ---------------------------------------------------------------------------
|
|
@@ -228,6 +233,12 @@ Object.defineProperty(exports, "sanitizeHTML", { enumerable: true, get: function
|
|
|
228
233
|
Object.defineProperty(exports, "isValidObjectId", { enumerable: true, get: function () { return validationUtils_1.isValidObjectId; } });
|
|
229
234
|
Object.defineProperty(exports, "validateAndSanitizeUserInput", { enumerable: true, get: function () { return validationUtils_1.validateAndSanitizeUserInput; } });
|
|
230
235
|
// ---------------------------------------------------------------------------
|
|
236
|
+
// Text normalization
|
|
237
|
+
// ---------------------------------------------------------------------------
|
|
238
|
+
var textNormalization_1 = require("./utils/textNormalization");
|
|
239
|
+
Object.defineProperty(exports, "normalizeInlineText", { enumerable: true, get: function () { return textNormalization_1.normalizeInlineText; } });
|
|
240
|
+
Object.defineProperty(exports, "normalizeMultilineText", { enumerable: true, get: function () { return textNormalization_1.normalizeMultilineText; } });
|
|
241
|
+
// ---------------------------------------------------------------------------
|
|
231
242
|
// Logging
|
|
232
243
|
// ---------------------------------------------------------------------------
|
|
233
244
|
var loggerUtils_1 = require("./utils/loggerUtils");
|
|
@@ -368,14 +368,18 @@ function OxyServicesAssetsMixin(Base) {
|
|
|
368
368
|
errorMessage = error.message || errorMessage;
|
|
369
369
|
}
|
|
370
370
|
else if (error && typeof error === 'object') {
|
|
371
|
-
|
|
372
|
-
|
|
371
|
+
const errObj = error;
|
|
372
|
+
if ('message' in errObj) {
|
|
373
|
+
errorMessage = String(errObj.message) || errorMessage;
|
|
373
374
|
}
|
|
374
|
-
else if (
|
|
375
|
-
errorMessage =
|
|
375
|
+
else if (typeof errObj.error === 'string') {
|
|
376
|
+
errorMessage = errObj.error;
|
|
376
377
|
}
|
|
377
|
-
else if (
|
|
378
|
-
|
|
378
|
+
else if (errObj.data && typeof errObj.data === 'object') {
|
|
379
|
+
const dataObj = errObj.data;
|
|
380
|
+
if (dataObj.message) {
|
|
381
|
+
errorMessage = String(dataObj.message);
|
|
382
|
+
}
|
|
379
383
|
}
|
|
380
384
|
}
|
|
381
385
|
else if (error) {
|
|
@@ -58,29 +58,30 @@ function OxyServicesLanguageMixin(Base) {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
/**
|
|
61
|
-
* Get the current
|
|
61
|
+
* Get the current locale from the user profile or local storage.
|
|
62
62
|
* @param storageKeyPrefix - Optional prefix for storage key (default: 'oxy_session')
|
|
63
|
-
* @returns The current
|
|
63
|
+
* @returns The current BCP-47 locale (e.g., 'en-US') or null if not set
|
|
64
64
|
*/
|
|
65
65
|
async getCurrentLanguage(storageKeyPrefix = 'oxy_session') {
|
|
66
66
|
try {
|
|
67
|
-
// First try
|
|
67
|
+
// First try the authenticated user's primary account locale.
|
|
68
68
|
try {
|
|
69
69
|
const user = await this.getCurrentUser();
|
|
70
|
-
const
|
|
71
|
-
if (
|
|
72
|
-
return
|
|
70
|
+
const primary = (0, languageUtils_1.getPrimaryLanguage)(user);
|
|
71
|
+
if (primary) {
|
|
72
|
+
return primary;
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
|
-
catch
|
|
76
|
-
//
|
|
75
|
+
catch {
|
|
76
|
+
// Not authenticated or the profile fetch failed — fall through to the
|
|
77
|
+
// locally stored preference below.
|
|
77
78
|
}
|
|
78
|
-
// Fall back to
|
|
79
|
+
// Fall back to the locally stored locale preference.
|
|
79
80
|
const storage = await this.getStorage();
|
|
80
81
|
const storageKey = `${storageKeyPrefix}_language`;
|
|
81
82
|
const storedLanguage = await storage.getItem(storageKey);
|
|
82
83
|
if (storedLanguage) {
|
|
83
|
-
return (0, languageUtils_1.
|
|
84
|
+
return (0, languageUtils_1.normalizeLocale)(storedLanguage) ?? storedLanguage;
|
|
84
85
|
}
|
|
85
86
|
return null;
|
|
86
87
|
}
|
|
@@ -73,6 +73,9 @@ function OxyServicesPrivacyMixin(Base) {
|
|
|
73
73
|
cache: false,
|
|
74
74
|
});
|
|
75
75
|
this.clearCacheEntry('GET:/privacy/blocked');
|
|
76
|
+
// The block changed the viewer's graph (`blockedIds`) — bust the cached
|
|
77
|
+
// consolidated `GET /users/me/graph` so the next read reflects it.
|
|
78
|
+
this.clearCacheEntry('GET:/users/me/graph');
|
|
76
79
|
return result;
|
|
77
80
|
}
|
|
78
81
|
catch (error) {
|
|
@@ -96,6 +99,9 @@ function OxyServicesPrivacyMixin(Base) {
|
|
|
96
99
|
cache: false,
|
|
97
100
|
});
|
|
98
101
|
this.clearCacheEntry('GET:/privacy/blocked');
|
|
102
|
+
// Symmetric to blockUser: the unblock changed the viewer's `blockedIds`,
|
|
103
|
+
// so bust the consolidated `GET /users/me/graph` cache.
|
|
104
|
+
this.clearCacheEntry('GET:/users/me/graph');
|
|
99
105
|
return result;
|
|
100
106
|
}
|
|
101
107
|
catch (error) {
|
|
@@ -512,6 +512,10 @@ function OxyServicesUserMixin(Base) {
|
|
|
512
512
|
try {
|
|
513
513
|
const result = await this.makeRequest('POST', `/users/${userId}/follow`, undefined, { cache: false });
|
|
514
514
|
this.clearCacheEntry(`GET:/users/${userId}/follow-status`);
|
|
515
|
+
// The follow changed the viewer's graph — bust the cached consolidated
|
|
516
|
+
// `GET /users/me/graph` so the next read reflects the new following/
|
|
517
|
+
// mutual set instead of the stale pre-write snapshot.
|
|
518
|
+
this.clearCacheEntry('GET:/users/me/graph');
|
|
515
519
|
return result;
|
|
516
520
|
}
|
|
517
521
|
catch (error) {
|
|
@@ -536,6 +540,8 @@ function OxyServicesUserMixin(Base) {
|
|
|
536
540
|
for (const id of userIds) {
|
|
537
541
|
this.clearCacheEntry(`GET:/users/${id}/follow-status`);
|
|
538
542
|
}
|
|
543
|
+
// The batch changed the viewer's graph — bust the consolidated cache.
|
|
544
|
+
this.clearCacheEntry('GET:/users/me/graph');
|
|
539
545
|
return result;
|
|
540
546
|
}
|
|
541
547
|
catch (error) {
|
|
@@ -560,6 +566,8 @@ function OxyServicesUserMixin(Base) {
|
|
|
560
566
|
for (const id of userIds) {
|
|
561
567
|
this.clearCacheEntry(`GET:/users/${id}/follow-status`);
|
|
562
568
|
}
|
|
569
|
+
// The batch changed the viewer's graph — bust the consolidated cache.
|
|
570
|
+
this.clearCacheEntry('GET:/users/me/graph');
|
|
563
571
|
return result;
|
|
564
572
|
}
|
|
565
573
|
catch (error) {
|
|
@@ -574,6 +582,8 @@ function OxyServicesUserMixin(Base) {
|
|
|
574
582
|
const result = await this.makeRequest('DELETE', `/users/${userId}/follow`, undefined, { cache: false });
|
|
575
583
|
// Bust the cached follow-status so a remount reads fresh truth (see `followUser`).
|
|
576
584
|
this.clearCacheEntry(`GET:/users/${userId}/follow-status`);
|
|
585
|
+
// The unfollow changed the viewer's graph — bust the consolidated cache.
|
|
586
|
+
this.clearCacheEntry('GET:/users/me/graph');
|
|
577
587
|
return result;
|
|
578
588
|
}
|
|
579
589
|
catch (error) {
|
|
@@ -705,6 +715,36 @@ function OxyServicesUserMixin(Base) {
|
|
|
705
715
|
throw this.handleError(error);
|
|
706
716
|
}
|
|
707
717
|
}
|
|
718
|
+
/**
|
|
719
|
+
* Get the authenticated VIEWER's OWN social graph — the accounts they follow,
|
|
720
|
+
* the subset who follow back (mutuals), and the accounts they have blocked —
|
|
721
|
+
* as ONE ids-only payload. The viewer is derived server-side from the SDK's
|
|
722
|
+
* auth token (never a param).
|
|
723
|
+
*
|
|
724
|
+
* Consolidates what were three separate round trips (`getUserFollowing` /
|
|
725
|
+
* `getMutualUserIds` / `getBlockedUsers`) into a single request so a consumer
|
|
726
|
+
* can prime its whole viewer graph at once. Mirrors {@link getMutualUserIds}'s
|
|
727
|
+
* caching posture (2-minute identity-scoped cache); the follow/unfollow/block/
|
|
728
|
+
* unblock write methods bust this entry so a local mutation is reflected
|
|
729
|
+
* immediately. An anonymous caller resolves to empty lists.
|
|
730
|
+
*/
|
|
731
|
+
async getViewerGraph() {
|
|
732
|
+
try {
|
|
733
|
+
const response = await this.makeRequest('GET', '/users/me/graph', undefined, {
|
|
734
|
+
cache: true,
|
|
735
|
+
cacheTTL: 2 * 60 * 1000, // 2 minutes cache
|
|
736
|
+
});
|
|
737
|
+
const graph = response.data;
|
|
738
|
+
return {
|
|
739
|
+
followingIds: graph?.followingIds || [],
|
|
740
|
+
mutualIds: graph?.mutualIds || [],
|
|
741
|
+
blockedIds: graph?.blockedIds || [],
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
catch (error) {
|
|
745
|
+
throw this.handleError(error);
|
|
746
|
+
}
|
|
747
|
+
}
|
|
708
748
|
/**
|
|
709
749
|
* Get notifications
|
|
710
750
|
*/
|
|
@@ -164,7 +164,7 @@ function ipv6ToGroups(ip) {
|
|
|
164
164
|
for (const part of segment.split(':')) {
|
|
165
165
|
if (!/^[0-9a-fA-F]{1,4}$/.test(part))
|
|
166
166
|
return null;
|
|
167
|
-
groups.push(parseInt(part, 16));
|
|
167
|
+
groups.push(Number.parseInt(part, 16));
|
|
168
168
|
}
|
|
169
169
|
return groups;
|
|
170
170
|
};
|
|
@@ -214,8 +214,8 @@ function extractEmbeddedIpv4(ip) {
|
|
|
214
214
|
// Hex form "::ffff:0102:0304" → 1.2.3.4
|
|
215
215
|
const hexMapped = lower.match(/^::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/);
|
|
216
216
|
if (hexMapped) {
|
|
217
|
-
const hi = parseInt(hexMapped[1], 16);
|
|
218
|
-
const lo = parseInt(hexMapped[2], 16);
|
|
217
|
+
const hi = Number.parseInt(hexMapped[1], 16);
|
|
218
|
+
const lo = Number.parseInt(hexMapped[2], 16);
|
|
219
219
|
return `${(hi >> 8) & 0xff}.${hi & 0xff}.${(lo >> 8) & 0xff}.${lo & 0xff}`;
|
|
220
220
|
}
|
|
221
221
|
return null;
|
|
@@ -277,7 +277,7 @@ class SessionClient {
|
|
|
277
277
|
transports: ['websocket'],
|
|
278
278
|
autoConnect: true,
|
|
279
279
|
reconnection: true,
|
|
280
|
-
reconnectionAttempts:
|
|
280
|
+
reconnectionAttempts: Number.POSITIVE_INFINITY,
|
|
281
281
|
reconnectionDelay: 1000,
|
|
282
282
|
reconnectionDelayMax: 10000,
|
|
283
283
|
auth: (cb) => {
|
|
@@ -24,9 +24,9 @@ exports.getContrastTextColor = exports.isLightColor = exports.withOpacity = expo
|
|
|
24
24
|
*/
|
|
25
25
|
const darkenColor = (color, factor = 0.6) => {
|
|
26
26
|
const hex = color.replace('#', '');
|
|
27
|
-
const r = parseInt(hex.substring(0, 2), 16);
|
|
28
|
-
const g = parseInt(hex.substring(2, 4), 16);
|
|
29
|
-
const b = parseInt(hex.substring(4, 6), 16);
|
|
27
|
+
const r = Number.parseInt(hex.substring(0, 2), 16);
|
|
28
|
+
const g = Number.parseInt(hex.substring(2, 4), 16);
|
|
29
|
+
const b = Number.parseInt(hex.substring(4, 6), 16);
|
|
30
30
|
const newR = Math.max(0, Math.round(r * (1 - factor)));
|
|
31
31
|
const newG = Math.max(0, Math.round(g * (1 - factor)));
|
|
32
32
|
const newB = Math.max(0, Math.round(b * (1 - factor)));
|
|
@@ -47,9 +47,9 @@ exports.darkenColor = darkenColor;
|
|
|
47
47
|
*/
|
|
48
48
|
const lightenColor = (color, factor = 0.3) => {
|
|
49
49
|
const hex = color.replace('#', '');
|
|
50
|
-
const r = parseInt(hex.substring(0, 2), 16);
|
|
51
|
-
const g = parseInt(hex.substring(2, 4), 16);
|
|
52
|
-
const b = parseInt(hex.substring(4, 6), 16);
|
|
50
|
+
const r = Number.parseInt(hex.substring(0, 2), 16);
|
|
51
|
+
const g = Number.parseInt(hex.substring(2, 4), 16);
|
|
52
|
+
const b = Number.parseInt(hex.substring(4, 6), 16);
|
|
53
53
|
const newR = Math.min(255, Math.round(r + (255 - r) * factor));
|
|
54
54
|
const newG = Math.min(255, Math.round(g + (255 - g) * factor));
|
|
55
55
|
const newB = Math.min(255, Math.round(b + (255 - b) * factor));
|
|
@@ -71,9 +71,9 @@ const hexToRgb = (hex) => {
|
|
|
71
71
|
const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
|
72
72
|
return result
|
|
73
73
|
? {
|
|
74
|
-
r: parseInt(result[1], 16),
|
|
75
|
-
g: parseInt(result[2], 16),
|
|
76
|
-
b: parseInt(result[3], 16),
|
|
74
|
+
r: Number.parseInt(result[1], 16),
|
|
75
|
+
g: Number.parseInt(result[2], 16),
|
|
76
|
+
b: Number.parseInt(result[3], 16),
|
|
77
77
|
}
|
|
78
78
|
: null;
|
|
79
79
|
};
|