@oxyhq/services 19.2.0 → 20.0.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/lib/commonjs/ui/components/FollowButton.js +1 -2
- package/lib/commonjs/ui/components/FollowButton.js.map +1 -1
- package/lib/commonjs/ui/components/SettingsIcon.js +1 -2
- package/lib/commonjs/ui/components/SettingsIcon.js.map +1 -1
- package/lib/commonjs/ui/components/logo/LogoIcon.js +0 -2
- package/lib/commonjs/ui/components/logo/LogoIcon.js.map +1 -1
- package/lib/commonjs/ui/components/logo/LogoText.js +0 -2
- package/lib/commonjs/ui/components/logo/LogoText.js.map +1 -1
- package/lib/commonjs/ui/context/OxyContext.js +9 -8
- package/lib/commonjs/ui/context/OxyContext.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +1 -3
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/hooks/useLanguageManagement.js +109 -28
- package/lib/commonjs/ui/hooks/useLanguageManagement.js.map +1 -1
- package/lib/commonjs/ui/hooks/useSessionManagement.js +1 -3
- package/lib/commonjs/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js +151 -88
- package/lib/commonjs/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/PreferencesScreen.js +5 -6
- package/lib/commonjs/ui/screens/PreferencesScreen.js.map +1 -1
- package/lib/module/ui/components/FollowButton.js +1 -1
- package/lib/module/ui/components/FollowButton.js.map +1 -1
- package/lib/module/ui/components/SettingsIcon.js +1 -1
- package/lib/module/ui/components/SettingsIcon.js.map +1 -1
- package/lib/module/ui/components/logo/LogoIcon.js +0 -1
- package/lib/module/ui/components/logo/LogoIcon.js.map +1 -1
- package/lib/module/ui/components/logo/LogoText.js +0 -1
- package/lib/module/ui/components/logo/LogoText.js.map +1 -1
- package/lib/module/ui/context/OxyContext.js +9 -8
- package/lib/module/ui/context/OxyContext.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +1 -3
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/hooks/useLanguageManagement.js +107 -29
- package/lib/module/ui/hooks/useLanguageManagement.js.map +1 -1
- package/lib/module/ui/hooks/useSessionManagement.js +1 -3
- package/lib/module/ui/hooks/useSessionManagement.js.map +1 -1
- package/lib/module/ui/screens/FeedbackScreen.js.map +1 -1
- package/lib/module/ui/screens/LanguageSelectorScreen.js +153 -91
- package/lib/module/ui/screens/LanguageSelectorScreen.js.map +1 -1
- package/lib/module/ui/screens/PreferencesScreen.js +5 -6
- package/lib/module/ui/screens/PreferencesScreen.js.map +1 -1
- package/lib/typescript/commonjs/ui/components/FollowButton.d.ts +2 -2
- package/lib/typescript/commonjs/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/OxyPayButton.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/OxyPayButton.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/SettingsIcon.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/SettingsIcon.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/logo/LogoIcon.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/logo/LogoIcon.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/logo/LogoText.d.ts +1 -1
- package/lib/typescript/commonjs/ui/components/logo/LogoText.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts +1 -1
- package/lib/typescript/commonjs/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts +1 -2
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts +3 -0
- package/lib/typescript/commonjs/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts +2 -1
- package/lib/typescript/commonjs/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useFollow.d.ts +1 -1
- package/lib/typescript/commonjs/ui/hooks/useFollow.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useLanguageManagement.d.ts +52 -8
- package/lib/typescript/commonjs/ui/hooks/useLanguageManagement.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts +1 -2
- package/lib/typescript/commonjs/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/PreferencesScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/FileListSection.d.ts +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/FileListSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/FollowButton.d.ts +2 -2
- package/lib/typescript/module/ui/components/FollowButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/OxyPayButton.d.ts +1 -1
- package/lib/typescript/module/ui/components/OxyPayButton.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/SettingsIcon.d.ts +1 -1
- package/lib/typescript/module/ui/components/SettingsIcon.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/logo/LogoIcon.d.ts +1 -1
- package/lib/typescript/module/ui/components/logo/LogoIcon.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/logo/LogoText.d.ts +1 -1
- package/lib/typescript/module/ui/components/logo/LogoText.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts +1 -1
- package/lib/typescript/module/ui/context/OxyContext.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts +1 -2
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts +3 -0
- package/lib/typescript/module/ui/context/oxyContextTypes.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts +2 -1
- package/lib/typescript/module/ui/hooks/mutations/useAccountMutations.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useFollow.d.ts +1 -1
- package/lib/typescript/module/ui/hooks/useFollow.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useLanguageManagement.d.ts +52 -8
- package/lib/typescript/module/ui/hooks/useLanguageManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts +1 -2
- package/lib/typescript/module/ui/hooks/useSessionManagement.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/LanguageSelectorScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/PreferencesScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/FileListSection.d.ts +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/FileListSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/package.json +18 -17
- package/src/ui/components/FollowButton.tsx +6 -5
- package/src/ui/components/OxyPayButton.tsx +1 -1
- package/src/ui/components/SettingsIcon.tsx +2 -1
- package/src/ui/components/logo/LogoIcon.tsx +2 -1
- package/src/ui/components/logo/LogoText.tsx +2 -1
- package/src/ui/context/OxyContext.tsx +13 -11
- package/src/ui/context/hooks/useAuthOperations.ts +1 -5
- package/src/ui/context/oxyContextTypes.ts +3 -0
- package/src/ui/hooks/useFollow.ts +1 -1
- package/src/ui/hooks/useLanguageManagement.ts +144 -42
- package/src/ui/hooks/useSessionManagement.ts +1 -4
- package/src/ui/screens/FeedbackScreen.tsx +1 -1
- package/src/ui/screens/LanguageSelectorScreen.tsx +195 -104
- package/src/ui/screens/PreferencesScreen.tsx +4 -6
- package/src/ui/screens/fileManagement/FileListSection.tsx +1 -1
- package/src/ui/screens/fileManagement/hooks/useFileUploadState.ts +1 -1
|
@@ -3,33 +3,119 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
exports.addLocale = addLocale;
|
|
7
|
+
exports.removeLocale = removeLocale;
|
|
8
|
+
exports.setPrimaryLocale = setPrimaryLocale;
|
|
6
9
|
exports.useLanguageManagement = void 0;
|
|
7
10
|
var _react = require("react");
|
|
8
11
|
var _core = require("@oxyhq/core");
|
|
9
12
|
var _errorHandlers = require("../utils/errorHandlers.js");
|
|
10
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Append `locale` to an ordered locale list if not already present. Canonical
|
|
15
|
+
* order is preserved; the new locale lands last (non-primary).
|
|
16
|
+
*/
|
|
17
|
+
function addLocale(languages, locale) {
|
|
18
|
+
const canonical = (0, _core.normalizeLocale)(locale);
|
|
19
|
+
if (!canonical) return [...languages];
|
|
20
|
+
if (languages.includes(canonical)) return [...languages];
|
|
21
|
+
return [...languages, canonical];
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Remove `locale` from an ordered locale list. The list's new first element
|
|
26
|
+
* becomes the primary locale.
|
|
27
|
+
*/
|
|
28
|
+
function removeLocale(languages, locale) {
|
|
29
|
+
const canonical = (0, _core.normalizeLocale)(locale);
|
|
30
|
+
if (!canonical) return [...languages];
|
|
31
|
+
return languages.filter(entry => entry !== canonical);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Move `locale` to the front of an ordered locale list, making it primary.
|
|
36
|
+
* Adds it if it was not already present.
|
|
37
|
+
*/
|
|
38
|
+
function setPrimaryLocale(languages, locale) {
|
|
39
|
+
const canonical = (0, _core.normalizeLocale)(locale);
|
|
40
|
+
if (!canonical) return [...languages];
|
|
41
|
+
return [canonical, ...languages.filter(entry => entry !== canonical)];
|
|
42
|
+
}
|
|
11
43
|
|
|
12
44
|
/**
|
|
13
|
-
*
|
|
45
|
+
* Resolve the device/browser locale, mapped to a supported catalog locale.
|
|
14
46
|
*
|
|
15
|
-
*
|
|
47
|
+
* Reads the platform's ordered locale preferences (`navigator.languages` /
|
|
48
|
+
* `navigator.language` on web, `Intl.DateTimeFormat().resolvedOptions().locale`
|
|
49
|
+
* on Hermes) and returns the first that resolves to a supported locale —
|
|
50
|
+
* either exactly or by base-language match (`fr-BE` → `fr-FR`). Falls back to
|
|
51
|
+
* {@link FALLBACK_LOCALE} when nothing resolves. Pure and side-effect free.
|
|
52
|
+
*/
|
|
53
|
+
function resolveDeviceLocale() {
|
|
54
|
+
const candidates = [];
|
|
55
|
+
if (typeof navigator !== 'undefined') {
|
|
56
|
+
const nav = navigator;
|
|
57
|
+
if (Array.isArray(nav.languages)) {
|
|
58
|
+
candidates.push(...nav.languages);
|
|
59
|
+
}
|
|
60
|
+
if (typeof nav.language === 'string') {
|
|
61
|
+
candidates.push(nav.language);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const intlLocale = Intl.DateTimeFormat().resolvedOptions().locale;
|
|
66
|
+
if (intlLocale) {
|
|
67
|
+
candidates.push(intlLocale);
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
// Intl is unavailable or incomplete on this runtime — fall through to the
|
|
71
|
+
// navigator-provided candidates (or the fallback locale below).
|
|
72
|
+
}
|
|
73
|
+
for (const candidate of candidates) {
|
|
74
|
+
const exact = (0, _core.normalizeLocale)(candidate);
|
|
75
|
+
if (exact) return exact;
|
|
76
|
+
const base = (0, _core.getBaseLanguage)(candidate);
|
|
77
|
+
const byBase = _core.SUPPORTED_LANGUAGES.find(entry => entry.language === base);
|
|
78
|
+
if (byBase) return byBase.code;
|
|
79
|
+
}
|
|
80
|
+
return _core.FALLBACK_LOCALE;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Resolve and manage the app's active UI locale.
|
|
85
|
+
*
|
|
86
|
+
* The active locale is DERIVED, not stored:
|
|
87
|
+
* - Signed in → the account's primary locale (`getPrimaryLanguage(user)`),
|
|
88
|
+
* falling back to {@link FALLBACK_LOCALE}. This is what makes every Oxy app
|
|
89
|
+
* follow the account's language automatically.
|
|
90
|
+
* - Signed out → a locally-chosen guest override if one exists, otherwise the
|
|
91
|
+
* device locale.
|
|
92
|
+
*
|
|
93
|
+
* The only external system this hook synchronizes with is local storage (the
|
|
94
|
+
* guest override), which is loaded once on mount.
|
|
16
95
|
*/
|
|
17
96
|
const useLanguageManagement = ({
|
|
18
97
|
storage,
|
|
19
98
|
languageKey,
|
|
99
|
+
user,
|
|
20
100
|
onError,
|
|
21
101
|
logger
|
|
22
102
|
}) => {
|
|
23
|
-
|
|
103
|
+
// The device locale is fixed for the lifetime of the runtime.
|
|
104
|
+
const deviceLanguage = (0, _react.useMemo)(resolveDeviceLocale, []);
|
|
105
|
+
|
|
106
|
+
// The locally-owned guest override (a single locale). `null` until loaded
|
|
107
|
+
// from storage or explicitly set; the derived locale falls back to the device
|
|
108
|
+
// locale while it is `null`.
|
|
109
|
+
const [guestLanguage, setGuestLanguage] = (0, _react.useState)(null);
|
|
24
110
|
const loadLanguageFromStorage = (0, _react.useCallback)(async () => {
|
|
25
111
|
if (!storage) {
|
|
26
112
|
return;
|
|
27
113
|
}
|
|
28
114
|
try {
|
|
29
115
|
const savedLanguageRaw = await storage.getItem(languageKey);
|
|
30
|
-
const normalized = (0, _core.
|
|
116
|
+
const normalized = savedLanguageRaw ? (0, _core.normalizeLocale)(savedLanguageRaw) : undefined;
|
|
31
117
|
if (normalized) {
|
|
32
|
-
|
|
118
|
+
setGuestLanguage(normalized);
|
|
33
119
|
}
|
|
34
120
|
} catch (error) {
|
|
35
121
|
const message = (0, _errorHandlers.extractErrorMessage)(error, 'Failed to load language preference');
|
|
@@ -52,14 +138,17 @@ const useLanguageManagement = ({
|
|
|
52
138
|
}
|
|
53
139
|
});
|
|
54
140
|
}, [loadLanguageFromStorage, logger]);
|
|
55
|
-
const setLanguage = (0, _react.useCallback)(async
|
|
141
|
+
const setLanguage = (0, _react.useCallback)(async locale => {
|
|
56
142
|
if (!storage) {
|
|
57
143
|
throw new Error('Storage not initialized');
|
|
58
144
|
}
|
|
59
|
-
const normalized = (0, _core.
|
|
145
|
+
const normalized = (0, _core.normalizeLocale)(locale);
|
|
146
|
+
if (!normalized) {
|
|
147
|
+
throw new Error(`Unsupported locale: ${locale}`);
|
|
148
|
+
}
|
|
60
149
|
try {
|
|
61
150
|
await storage.setItem(languageKey, normalized);
|
|
62
|
-
|
|
151
|
+
setGuestLanguage(normalized);
|
|
63
152
|
} catch (error) {
|
|
64
153
|
const message = (0, _errorHandlers.extractErrorMessage)(error, 'Failed to save language preference');
|
|
65
154
|
onError?.({
|
|
@@ -75,36 +164,28 @@ const useLanguageManagement = ({
|
|
|
75
164
|
throw error instanceof Error ? error : new Error(message);
|
|
76
165
|
}
|
|
77
166
|
}, [languageKey, logger, onError, storage]);
|
|
78
|
-
const
|
|
79
|
-
if (
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
const userLanguage = user?.language;
|
|
83
|
-
if (!userLanguage) {
|
|
84
|
-
return;
|
|
167
|
+
const languages = (0, _react.useMemo)(() => {
|
|
168
|
+
if (user) {
|
|
169
|
+
return (0, _core.getUserLanguages)(user);
|
|
85
170
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
if (logger) {
|
|
92
|
-
logger('Failed to apply server language preference', error);
|
|
93
|
-
} else if (__DEV__) {
|
|
94
|
-
console.warn('Failed to apply server language preference', error);
|
|
95
|
-
}
|
|
171
|
+
return guestLanguage ? [guestLanguage] : [];
|
|
172
|
+
}, [user, guestLanguage]);
|
|
173
|
+
const currentLanguage = (0, _react.useMemo)(() => {
|
|
174
|
+
if (user) {
|
|
175
|
+
return (0, _core.getPrimaryLanguage)(user) ?? _core.FALLBACK_LOCALE;
|
|
96
176
|
}
|
|
97
|
-
|
|
177
|
+
return guestLanguage ?? deviceLanguage;
|
|
178
|
+
}, [user, guestLanguage, deviceLanguage]);
|
|
98
179
|
const metadata = (0, _react.useMemo)(() => (0, _core.getLanguageMetadata)(currentLanguage), [currentLanguage]);
|
|
99
180
|
const languageName = (0, _react.useMemo)(() => (0, _core.getLanguageName)(currentLanguage), [currentLanguage]);
|
|
100
181
|
const nativeLanguageName = (0, _react.useMemo)(() => (0, _core.getNativeLanguageName)(currentLanguage), [currentLanguage]);
|
|
101
182
|
return {
|
|
102
183
|
currentLanguage,
|
|
184
|
+
languages,
|
|
103
185
|
metadata,
|
|
104
186
|
languageName,
|
|
105
187
|
nativeLanguageName,
|
|
106
188
|
setLanguage,
|
|
107
|
-
applyLanguagePreference,
|
|
108
189
|
hydrateLanguage: loadLanguageFromStorage
|
|
109
190
|
};
|
|
110
191
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_core","_errorHandlers","
|
|
1
|
+
{"version":3,"names":["_react","require","_core","_errorHandlers","addLocale","languages","locale","canonical","normalizeLocale","includes","removeLocale","filter","entry","setPrimaryLocale","resolveDeviceLocale","candidates","navigator","nav","Array","isArray","push","language","intlLocale","Intl","DateTimeFormat","resolvedOptions","candidate","exact","base","getBaseLanguage","byBase","SUPPORTED_LANGUAGES","find","code","FALLBACK_LOCALE","useLanguageManagement","storage","languageKey","user","onError","logger","deviceLanguage","useMemo","guestLanguage","setGuestLanguage","useState","loadLanguageFromStorage","useCallback","savedLanguageRaw","getItem","normalized","undefined","error","message","extractErrorMessage","status","__DEV__","console","warn","useEffect","catch","setLanguage","Error","setItem","getUserLanguages","currentLanguage","getPrimaryLanguage","metadata","getLanguageMetadata","languageName","getLanguageName","nativeLanguageName","getNativeLanguageName","hydrateLanguage","exports"],"sourceRoot":"../../../../src","sources":["ui/hooks/useLanguageManagement.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -26,7 +26,6 @@ const useSessionManagement = ({
|
|
|
26
26
|
storageKeyPrefix,
|
|
27
27
|
loginSuccess,
|
|
28
28
|
logoutStore,
|
|
29
|
-
applyLanguagePreference,
|
|
30
29
|
onAuthStateChange,
|
|
31
30
|
onError,
|
|
32
31
|
setAuthError,
|
|
@@ -152,9 +151,8 @@ const useSessionManagement = ({
|
|
|
152
151
|
setActiveSessionId(sessionId);
|
|
153
152
|
loginSuccess(user);
|
|
154
153
|
await saveActiveSessionId(sessionId);
|
|
155
|
-
await applyLanguagePreference(user);
|
|
156
154
|
onAuthStateChange?.(user);
|
|
157
|
-
}, [
|
|
155
|
+
}, [loginSuccess, onAuthStateChange, saveActiveSessionId, setTokenReady]);
|
|
158
156
|
const removalTimerIdsRef = (0, _react.useRef)(new Set());
|
|
159
157
|
const trackRemovedSession = (0, _react.useCallback)(sessionId => {
|
|
160
158
|
removedSessionsRef.current.add(sessionId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_core","_sessionHelpers","_storageHelpers","_errorHandlers","_queryClient","_isWebBrowser","_crossOriginRestore","DEFAULT_SAVE_ERROR_MESSAGE","CLEAR_STORAGE_ERROR","useSessionManagement","oxyServices","storage","storageKeyPrefix","loginSuccess","logoutStore","
|
|
1
|
+
{"version":3,"names":["_react","require","_core","_sessionHelpers","_storageHelpers","_errorHandlers","_queryClient","_isWebBrowser","_crossOriginRestore","DEFAULT_SAVE_ERROR_MESSAGE","CLEAR_STORAGE_ERROR","useSessionManagement","oxyServices","storage","storageKeyPrefix","loginSuccess","logoutStore","onAuthStateChange","onError","setAuthError","logger","setTokenReady","queryClient","sessions","setSessions","useState","activeSessionId","setActiveSessionId","sessionsRef","useRef","current","activeSessionIdRef","refreshInFlightRef","removedSessionsRef","Set","lastRefreshRef","storageKeys","useMemo","getStorageKeys","saveSessionIds","useCallback","sessionIds","uniqueIds","Array","from","setItem","JSON","stringify","error","isDev","console","warn","updateSessions","incoming","options","prevSessions","processed","merge","mergeSessions","normalizeAndSortSessions","map","session","sessionId","preserveSessionIds","sessionsArraysEqual","saveActiveSessionId","handleAuthError","defaultMessage","code","removeActiveSessionId","removeItem","clearSessionStorage","clearSessionState","clearTokens","clear","clearQueryCache","clearCrossOriginRestoreGuards","activateSession","user","removalTimerIdsRef","trackRemovedSession","add","timerId","setTimeout","delete","useEffect","forEach","clearTimeout","switchSession","isWebBrowser","getAccessToken","Error","validation","validateSession","useHeaderValidation","valid","deviceSessions","fetchSessionsWithFallback","fallbackUserId","id","invalidSession","isInvalidSessionError","filter","refreshSessions","activeUserId","now","Date","refreshPromise","isRefreshInFlight","Boolean","exports"],"sourceRoot":"../../../../src","sources":["ui/hooks/useSessionManagement.ts"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA;AAGA,IAAAE,eAAA,GAAAF,OAAA;AACA,IAAAG,eAAA,GAAAH,OAAA;AACA,IAAAI,cAAA,GAAAJ,OAAA;AAGA,IAAAK,YAAA,GAAAL,OAAA;AACA,IAAAM,aAAA,GAAAN,OAAA;AACA,IAAAO,mBAAA,GAAAP,OAAA;AA8BA,MAAMQ,0BAA0B,GAAG,6BAA6B;AAChE,MAAMC,mBAAmB,GAAG,yBAAyB;;AAErD;AACA;AACA;AACA;AACA;AACO,MAAMC,oBAAoB,GAAGA,CAAC;EACnCC,WAAW;EACXC,OAAO;EACPC,gBAAgB;EAChBC,YAAY;EACZC,WAAW;EACXC,iBAAiB;EACjBC,OAAO;EACPC,YAAY;EACZC,MAAM;EACNC,aAAa;EACbC;AAC2B,CAAC,KAAiC;EAC7D,MAAM,CAACC,QAAQ,EAAEC,WAAW,CAAC,GAAG,IAAAC,eAAQ,EAAkB,EAAE,CAAC;EAC7D,MAAM,CAACC,eAAe,EAAEC,kBAAkB,CAAC,GAAG,IAAAF,eAAQ,EAAgB,IAAI,CAAC;;EAE3E;EACA,MAAMG,WAAW,GAAG,IAAAC,aAAM,EAACN,QAAQ,CAAC;EACpCK,WAAW,CAACE,OAAO,GAAGP,QAAQ;EAC9B,MAAMQ,kBAAkB,GAAG,IAAAF,aAAM,EAACH,eAAe,CAAC;EAClDK,kBAAkB,CAACD,OAAO,GAAGJ,eAAe;EAE5C,MAAMM,kBAAkB,GAAG,IAAAH,aAAM,EAAuB,IAAI,CAAC;EAC7D,MAAMI,kBAAkB,GAAG,IAAAJ,aAAM,EAAc,IAAIK,GAAG,CAAC,CAAC,CAAC;EACzD,MAAMC,cAAc,GAAG,IAAAN,aAAM,EAAS,CAAC,CAAC;EAExC,MAAMO,WAAW,GAAG,IAAAC,cAAO,EAAC,MAAM,IAAAC,8BAAc,EAACxB,gBAAgB,CAAC,EAAE,CAACA,gBAAgB,CAAC,CAAC;EAEvF,MAAMyB,cAAc,GAAG,IAAAC,kBAAW,EAChC,MAAOC,UAAoB,IAAoB;IAC7C,IAAI,CAAC5B,OAAO,EAAE;IACd,IAAI;MACF,MAAM6B,SAAS,GAAGC,KAAK,CAACC,IAAI,CAAC,IAAIV,GAAG,CAACO,UAAU,CAAC,CAAC;MACjD,MAAM5B,OAAO,CAACgC,OAAO,CAACT,WAAW,CAACK,UAAU,EAAEK,IAAI,CAACC,SAAS,CAACL,SAAS,CAAC,CAAC;IAC1E,CAAC,CAAC,OAAOM,KAAK,EAAE;MACd,IAAI5B,MAAM,EAAE;QACVA,MAAM,CAACX,0BAA0B,EAAEuC,KAAK,CAAC;MAC3C,CAAC,MAAM,IAAI,IAAAC,WAAK,EAAC,CAAC,EAAE;QAClBC,OAAO,CAACC,IAAI,CAAC,6BAA6B,EAAEH,KAAK,CAAC;MACpD;IACF;EACF,CAAC,EACD,CAAC5B,MAAM,EAAEP,OAAO,EAAEuB,WAAW,CAACK,UAAU,CAC1C,CAAC;EAED,MAAMW,cAAc,GAAG,IAAAZ,kBAAW,EAChC,CAACa,QAAyB,EAAEC,OAA2D,GAAG,CAAC,CAAC,KAAW;IACrG9B,WAAW,CAAE+B,YAAY,IAAK;MAC5B,MAAMC,SAAS,GAAGF,OAAO,CAACG,KAAK,GAC3B,IAAAC,mBAAa,EAACH,YAAY,EAAEF,QAAQ,EAAEtB,kBAAkB,CAACD,OAAO,EAAE,KAAK,CAAC,GACxE,IAAA6B,8BAAwB,EAACN,QAAQ,EAAEtB,kBAAkB,CAACD,OAAO,EAAE,KAAK,CAAC;MAEzE,IAAIjB,OAAO,EAAE;QACX,KAAK0B,cAAc,CAAC,CAClB,GAAGiB,SAAS,CAACI,GAAG,CAAEC,OAAO,IAAKA,OAAO,CAACC,SAAS,CAAC,EAChD,IAAIR,OAAO,CAACS,kBAAkB,IAAI,EAAE,CAAC,CACtC,CAAC;MACJ;MAEA,IAAI,IAAAC,yBAAmB,EAACT,YAAY,EAAEC,SAAS,CAAC,EAAE;QAChD,OAAOD,YAAY;MACrB;MACA,OAAOC,SAAS;IAClB,CAAC,CAAC;EACJ,CAAC,EACD,CAACjB,cAAc,EAAE1B,OAAO,CAC1B,CAAC;EAED,MAAMoD,mBAAmB,GAAG,IAAAzB,kBAAW,EACrC,MAAOsB,SAAiB,IAAoB;IAC1C,IAAI,CAACjD,OAAO,EAAE;IACd,IAAI;MACF,MAAMA,OAAO,CAACgC,OAAO,CAACT,WAAW,CAACV,eAAe,EAAEoC,SAAS,CAAC;IAC/D,CAAC,CAAC,OAAOd,KAAK,EAAE;MACd,IAAAkB,8BAAe,EAAClB,KAAK,EAAE;QACrBmB,cAAc,EAAE1D,0BAA0B;QAC1C2D,IAAI,EAAE,2BAA2B;QACjClD,OAAO;QACPC,YAAY;QACZC;MACF,CAAC,CAAC;IACJ;EACF,CAAC,EACD,CAACA,MAAM,EAAEF,OAAO,EAAEC,YAAY,EAAEN,OAAO,EAAEuB,WAAW,CAACV,eAAe,CACtE,CAAC;EAED,MAAM2C,qBAAqB,GAAG,IAAA7B,kBAAW,EAAC,YAA2B;IACnE,IAAI,CAAC3B,OAAO,EAAE;IACd,IAAI;MACF,MAAMA,OAAO,CAACyD,UAAU,CAAClC,WAAW,CAACV,eAAe,CAAC;IACvD,CAAC,CAAC,OAAOsB,KAAK,EAAE;MACd,IAAAkB,8BAAe,EAAClB,KAAK,EAAE;QACrBmB,cAAc,EAAE1D,0BAA0B;QAC1C2D,IAAI,EAAE,2BAA2B;QACjClD,OAAO;QACPC,YAAY;QACZC;MACF,CAAC,CAAC;IACJ;EACF,CAAC,EAAE,CAACA,MAAM,EAAEF,OAAO,EAAEC,YAAY,EAAEN,OAAO,EAAEuB,WAAW,CAACV,eAAe,CAAC,CAAC;EAEzE,MAAM6C,mBAAmB,GAAG,IAAA/B,kBAAW,EAAC,YAA2B;IACjE,IAAI,CAAC3B,OAAO,EAAE;IACd,IAAI;MACF,MAAMA,OAAO,CAACyD,UAAU,CAAClC,WAAW,CAACV,eAAe,CAAC;MACrD,MAAMb,OAAO,CAACyD,UAAU,CAAClC,WAAW,CAACK,UAAU,CAAC;MAChD;IACF,CAAC,CAAC,OAAOO,KAAK,EAAE;MACd,IAAAkB,8BAAe,EAAClB,KAAK,EAAE;QACrBmB,cAAc,EAAEzD,mBAAmB;QACnC0D,IAAI,EAAE,eAAe;QACrBlD,OAAO;QACPC,YAAY;QACZC;MACF,CAAC,CAAC;IACJ;EACF,CAAC,EAAE,CAACA,MAAM,EAAEF,OAAO,EAAEC,YAAY,EAAEN,OAAO,EAAEuB,WAAW,CAACV,eAAe,EAAEU,WAAW,CAACK,UAAU,CAAC,CAAC;EAEjG,MAAM+B,iBAAiB,GAAG,IAAAhC,kBAAW,EAAC,YAA2B;IAC/DhB,WAAW,CAAC,EAAE,CAAC;IACfG,kBAAkB,CAAC,IAAI,CAAC;IACxBX,WAAW,CAAC,CAAC;;IAEb;IACA;IACA;IACA;IACA;IACA;IACAJ,WAAW,CAAC6D,WAAW,CAAC,CAAC;;IAEzB;IACA,IAAInD,WAAW,EAAE;MACfA,WAAW,CAACoD,KAAK,CAAC,CAAC;IACrB;;IAEA;IACA,IAAI7D,OAAO,EAAE;MACX,IAAI;QACF,MAAM,IAAA8D,4BAAe,EAAC9D,OAAO,CAAC;MAChC,CAAC,CAAC,OAAOmC,KAAK,EAAE;QACd,IAAI5B,MAAM,EAAE;UACVA,MAAM,CAAC,uCAAuC,EAAE4B,KAAK,CAAC;QACxD;MACF;IACF;IAEA,MAAMuB,mBAAmB,CAAC,CAAC;IAC3B,IAAAK,iDAA6B,EAAC,CAAC;IAC/B3D,iBAAiB,GAAG,IAAI,CAAC;EAC3B,CAAC,EAAE,CAACsD,mBAAmB,EAAEvD,WAAW,EAAEC,iBAAiB,EAAEL,WAAW,EAAEU,WAAW,EAAET,OAAO,EAAEO,MAAM,CAAC,CAAC;EAEpG,MAAMyD,eAAe,GAAG,IAAArC,kBAAW,EACjC,OAAOsB,SAAiB,EAAEgB,IAAU,KAAoB;IACtDzD,aAAa,GAAG,IAAI,CAAC;IACrBM,kBAAkB,CAACmC,SAAS,CAAC;IAC7B/C,YAAY,CAAC+D,IAAI,CAAC;IAClB,MAAMb,mBAAmB,CAACH,SAAS,CAAC;IACpC7C,iBAAiB,GAAG6D,IAAI,CAAC;EAC3B,CAAC,EACD,CAAC/D,YAAY,EAAEE,iBAAiB,EAAEgD,mBAAmB,EAAE5C,aAAa,CACtE,CAAC;EAED,MAAM0D,kBAAkB,GAAG,IAAAlD,aAAM,EAAqC,IAAIK,GAAG,CAAC,CAAC,CAAC;EAEhF,MAAM8C,mBAAmB,GAAG,IAAAxC,kBAAW,EAAEsB,SAAiB,IAAK;IAC7D7B,kBAAkB,CAACH,OAAO,CAACmD,GAAG,CAACnB,SAAS,CAAC;IACzC,MAAMoB,OAAO,GAAGC,UAAU,CAAC,MAAM;MAC/BlD,kBAAkB,CAACH,OAAO,CAACsD,MAAM,CAACtB,SAAS,CAAC;MAC5CiB,kBAAkB,CAACjD,OAAO,CAACsD,MAAM,CAACF,OAAO,CAAC;IAC5C,CAAC,EAAE,IAAI,CAAC;IACRH,kBAAkB,CAACjD,OAAO,CAACmD,GAAG,CAACC,OAAO,CAAC;EACzC,CAAC,EAAE,EAAE,CAAC;EAEN,IAAAG,gBAAS,EAAC,MAAM;IACd,OAAO,MAAM;MACXN,kBAAkB,CAACjD,OAAO,CAACwD,OAAO,CAACC,YAAY,CAAC;IAClD,CAAC;EACH,CAAC,EAAE,EAAE,CAAC;EAEN,MAAMC,aAAa,GAAG,IAAAhD,kBAAW,EAC/B,MAAOsB,SAAiB,IAAoB;IAC1C,IAAI;MACF;MACA;MACA;MACA;MACA;MACA;MACA;MACA,IAAI,IAAA2B,0BAAY,EAAC,CAAC,IAAI,CAAC7E,WAAW,CAAC8E,cAAc,CAAC,CAAC,EAAE;QACnD,MAAM,IAAIC,KAAK,CAAC,+BAA+B,CAAC;MAClD;MAEA,MAAMC,UAAU,GAAG,MAAMhF,WAAW,CAACiF,eAAe,CAAC/B,SAAS,EAAE;QAAEgC,mBAAmB,EAAE;MAAK,CAAC,CAAC;MAC9F,IAAI,CAACF,UAAU,EAAEG,KAAK,EAAE;QACtB,MAAM,IAAIJ,KAAK,CAAC,+BAA+B,CAAC;MAClD;MAEA,IAAI,CAACC,UAAU,CAACd,IAAI,EAAE;QACpB,MAAM,IAAIa,KAAK,CAAC,iDAAiD,CAAC;MACpE;MAEA,MAAMb,IAAI,GAAGc,UAAU,CAACd,IAAY;MACpC,MAAMD,eAAe,CAACf,SAAS,EAAEgB,IAAI,CAAC;MAEtC,IAAI;QACF,MAAMkB,cAAc,GAAG,MAAM,IAAAC,yCAAyB,EAACrF,WAAW,EAAEkD,SAAS,EAAE;UAC7EoC,cAAc,EAAEpB,IAAI,CAACqB,EAAE;UACvB/E;QACF,CAAC,CAAC;QACFgC,cAAc,CAAC4C,cAAc,EAAE;UAAEvC,KAAK,EAAE;QAAK,CAAC,CAAC;MACjD,CAAC,CAAC,OAAOT,KAAK,EAAE;QACd,IAAI,IAAAC,WAAK,EAAC,CAAC,EAAE;UACXC,OAAO,CAACC,IAAI,CAAC,8CAA8C,EAAEH,KAAK,CAAC;QACrE;MACF;MAEA,OAAO8B,IAAI;IACb,CAAC,CAAC,OAAO9B,KAAK,EAAE;MACd,MAAMoD,cAAc,GAAG,IAAAC,oCAAqB,EAACrD,KAAK,CAAC;MAEnD,IAAIoD,cAAc,EAAE;QAClB;QACA;QACA;QACAhD,cAAc,CAACxB,WAAW,CAACE,OAAO,CAACwE,MAAM,CAAEzC,OAAO,IAAKA,OAAO,CAACC,SAAS,KAAKA,SAAS,CAAC,EAAE;UACvFL,KAAK,EAAE;QACT,CAAC,CAAC;MACJ;MAEA,IAAAS,8BAAe,EAAClB,KAAK,EAAE;QACrBmB,cAAc,EAAE,0BAA0B;QAC1CC,IAAI,EAAEgC,cAAc,GAAG,iBAAiB,GAAG,sBAAsB;QACjElF,OAAO;QACPC,YAAY;QACZC;MACF,CAAC,CAAC;MACF,MAAM4B,KAAK,YAAY2C,KAAK,GAAG3C,KAAK,GAAG,IAAI2C,KAAK,CAAC,0BAA0B,CAAC;IAC9E;EACF,CAAC,EACD,CACEd,eAAe,EACfzD,MAAM,EACNF,OAAO,EACPN,WAAW,EACXO,YAAY,EACZiC,cAAc,CAElB,CAAC;EAED,MAAMmD,eAAe,GAAG,IAAA/D,kBAAW,EACjC,MAAOgE,YAAqB,IAAoB;IAC9C;IACA;IACA;IACA,MAAM9E,eAAe,GAAGK,kBAAkB,CAACD,OAAO;IAClD,IAAI,CAACJ,eAAe,EAAE;IAEtB,IAAIM,kBAAkB,CAACF,OAAO,EAAE;MAC9B,MAAME,kBAAkB,CAACF,OAAO;MAChC;IACF;IAEA,MAAM2E,GAAG,GAAGC,IAAI,CAACD,GAAG,CAAC,CAAC;IACtB,IAAIA,GAAG,GAAGtE,cAAc,CAACL,OAAO,GAAG,GAAG,EAAE;MACtC;IACF;IACAK,cAAc,CAACL,OAAO,GAAG2E,GAAG;IAE5B,MAAME,cAAc,GAAG,CAAC,YAAY;MAClC,IAAI;QACF,MAAMX,cAAc,GAAG,MAAM,IAAAC,yCAAyB,EAACrF,WAAW,EAAEc,eAAe,EAAE;UACnFwE,cAAc,EAAEM,YAAY;UAC5BpF;QACF,CAAC,CAAC;QACFgC,cAAc,CAAC4C,cAAc,EAAE;UAAEvC,KAAK,EAAE;QAAK,CAAC,CAAC;MACjD,CAAC,CAAC,OAAOT,KAAK,EAAE;QACd,IAAI,IAAAqD,oCAAqB,EAACrD,KAAK,CAAC,EAAE;UAChC;UACA;UACA;UACA,MAAMwB,iBAAiB,CAAC,CAAC;UACzB;QACF;QAEA,IAAAN,8BAAe,EAAClB,KAAK,EAAE;UACrBmB,cAAc,EAAE,4BAA4B;UAC5CC,IAAI,EAAE,uBAAuB;UAC7BlD,OAAO;UACPC,YAAY;UACZC;QACF,CAAC,CAAC;MACJ,CAAC,SAAS;QACRY,kBAAkB,CAACF,OAAO,GAAG,IAAI;QACjCK,cAAc,CAACL,OAAO,GAAG4E,IAAI,CAACD,GAAG,CAAC,CAAC;MACrC;IACF,CAAC,EAAE,CAAC;IAEJzE,kBAAkB,CAACF,OAAO,GAAG6E,cAAc;IAC3C,MAAMA,cAAc;EACtB,CAAC,EACD,CACEnC,iBAAiB,EACjBpD,MAAM,EACNF,OAAO,EACPN,WAAW,EACXO,YAAY,EACZiC,cAAc,CAElB,CAAC;EAED,MAAMwD,iBAAiB,GAAGC,OAAO,CAAC7E,kBAAkB,CAACF,OAAO,CAAC;EAE7D,OAAO;IACLP,QAAQ;IACRG,eAAe;IACfC,kBAAkB;IAClByB,cAAc;IACdoC,aAAa;IACbe,eAAe;IACf/B,iBAAiB;IACjBP,mBAAmB;IACnBe,mBAAmB;IACnB5C,WAAW;IACXwE;EACF,CAAC;AACH,CAAC;AAACE,OAAA,CAAAnG,oBAAA,GAAAA,oBAAA","ignoreList":[]}
|
|
@@ -7,112 +7,139 @@ exports.default = void 0;
|
|
|
7
7
|
var _react = _interopRequireWildcard(require("react"));
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _theme = require("@oxyhq/bloom/theme");
|
|
10
|
-
var _core = require("@oxyhq/core");
|
|
11
10
|
var _vectorIcons = require("@expo/vector-icons");
|
|
12
11
|
var _bloom = require("@oxyhq/bloom");
|
|
13
12
|
var _typography = require("@oxyhq/bloom/typography");
|
|
14
13
|
var _searchInput = require("@oxyhq/bloom/search-input");
|
|
15
14
|
var _settingsList = require("@oxyhq/bloom/settings-list");
|
|
15
|
+
var _core = require("@oxyhq/core");
|
|
16
16
|
var _Header = _interopRequireDefault(require("../components/Header.js"));
|
|
17
17
|
var _useI18n = require("../hooks/useI18n.js");
|
|
18
18
|
var _OxyContext = require("../context/OxyContext.js");
|
|
19
|
+
var _useLanguageManagement = require("../hooks/useLanguageManagement.js");
|
|
20
|
+
var _useAccountMutations = require("../hooks/mutations/useAccountMutations.js");
|
|
19
21
|
var _jsxRuntime = require("react/jsx-runtime");
|
|
20
22
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
21
23
|
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
|
|
22
|
-
// Size (in dp) of the circular
|
|
23
|
-
const
|
|
24
|
-
//
|
|
25
|
-
const
|
|
24
|
+
// Size (in dp) of the circular chip rendered as each row's leading icon.
|
|
25
|
+
const CHIP_SIZE = 40;
|
|
26
|
+
// Trailing remove-affordance icon size (dp).
|
|
27
|
+
const REMOVE_ICON_SIZE = 24;
|
|
28
|
+
|
|
29
|
+
/** O(1) catalog lookup by canonical locale code. */
|
|
30
|
+
const CATALOG_BY_CODE = new Map(_core.SUPPORTED_LANGUAGES.map(entry => [entry.code, entry]));
|
|
26
31
|
|
|
27
32
|
/**
|
|
28
|
-
* LanguageSelectorScreen -
|
|
33
|
+
* LanguageSelectorScreen — multi-select over the supported BCP-47 locales.
|
|
29
34
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
35
|
+
* The user picks one or more locales; the FIRST (primary) drives the app's UI
|
|
36
|
+
* language. When signed in the ordered selection is persisted to the account
|
|
37
|
+
* (`updateProfile({ languages })`, primary first) and every Oxy app follows it;
|
|
38
|
+
* when signed out a single local override is stored on-device.
|
|
34
39
|
*/
|
|
35
40
|
const LanguageSelectorScreen = ({
|
|
36
41
|
goBack,
|
|
37
|
-
onClose
|
|
38
|
-
theme
|
|
42
|
+
onClose
|
|
39
43
|
}) => {
|
|
40
|
-
// Use useOxy() hook for OxyContext values. The language preference persists
|
|
41
|
-
// on the ACTIVE account's profile — the active session IS that account — so
|
|
42
|
-
// gate the server sync on the active account.
|
|
43
44
|
const {
|
|
44
45
|
user,
|
|
46
|
+
isAuthenticated,
|
|
45
47
|
currentLanguage,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
isAuthenticated
|
|
48
|
+
currentLanguages,
|
|
49
|
+
setLanguage
|
|
49
50
|
} = (0, _OxyContext.useOxy)();
|
|
50
51
|
const {
|
|
51
52
|
t
|
|
52
53
|
} = (0, _useI18n.useI18n)();
|
|
53
54
|
const bloomTheme = (0, _theme.useTheme)();
|
|
54
|
-
const
|
|
55
|
-
const [isLoading, setIsLoading] = (0, _react.useState)(false);
|
|
55
|
+
const updateProfile = (0, _useAccountMutations.useUpdateProfile)();
|
|
56
56
|
const [query, setQuery] = (0, _react.useState)('');
|
|
57
|
+
const [isSubmitting, setIsSubmitting] = (0, _react.useState)(false);
|
|
57
58
|
|
|
58
|
-
//
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
// The current ordered selection: the account locales when signed in, else
|
|
60
|
+
// the single guest/device locale. Always non-empty (`currentLanguage`
|
|
61
|
+
// resolves to the device or fallback locale).
|
|
62
|
+
const selected = (0, _react.useMemo)(() => currentLanguages.length > 0 ? currentLanguages : [currentLanguage], [currentLanguages, currentLanguage]);
|
|
63
|
+
const selectedSet = (0, _react.useMemo)(() => new Set(selected), [selected]);
|
|
64
|
+
const selectedEntries = (0, _react.useMemo)(() => selected.map(code => CATALOG_BY_CODE.get(code)).filter(entry => entry !== undefined), [selected]);
|
|
65
|
+
|
|
66
|
+
// Available = supported locales not already selected, filtered by the query
|
|
67
|
+
// (matches English name + native name).
|
|
68
|
+
const availableEntries = (0, _react.useMemo)(() => {
|
|
69
|
+
const normalizedQuery = query.trim().toLowerCase();
|
|
70
|
+
return _core.SUPPORTED_LANGUAGES.filter(entry => {
|
|
71
|
+
if (selectedSet.has(entry.code)) {
|
|
72
|
+
return false;
|
|
73
|
+
}
|
|
74
|
+
if (!normalizedQuery) {
|
|
75
|
+
return true;
|
|
76
|
+
}
|
|
77
|
+
return entry.name.toLowerCase().includes(normalizedQuery) || entry.nativeName.toLowerCase().includes(normalizedQuery);
|
|
78
|
+
});
|
|
79
|
+
}, [query, selectedSet]);
|
|
80
|
+
const isBusy = isSubmitting || updateProfile.isPending;
|
|
81
|
+
|
|
82
|
+
// Persist the next ordered selection. Signed-in accounts write the full
|
|
83
|
+
// ordered array; guests store only the primary locally.
|
|
84
|
+
const commitSelection = (0, _react.useCallback)(async (next, announceCode) => {
|
|
85
|
+
if (isBusy || next.length === 0) {
|
|
86
|
+
return;
|
|
62
87
|
}
|
|
63
|
-
|
|
88
|
+
setIsSubmitting(true);
|
|
64
89
|
try {
|
|
65
|
-
let serverSyncFailed = false;
|
|
66
|
-
|
|
67
|
-
// If signed in, persist preference to backend user settings
|
|
68
90
|
if (isAuthenticated && user?.id) {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
// Server sync failed, but we'll save locally anyway
|
|
75
|
-
serverSyncFailed = true;
|
|
76
|
-
if (__DEV__) {
|
|
77
|
-
console.warn('Failed to sync language to server (will save locally only):', e instanceof Error ? e.message : e);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
91
|
+
await updateProfile.mutateAsync({
|
|
92
|
+
languages: next
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
await setLanguage(next[0]);
|
|
80
96
|
}
|
|
81
|
-
|
|
82
|
-
// Always persist locally for immediate UX and for guests
|
|
83
|
-
await setLanguage(languageId);
|
|
84
|
-
const selectedLang = _core.SUPPORTED_LANGUAGES.find(lang => lang.id === languageId);
|
|
85
|
-
|
|
86
|
-
// Show success message (language is saved locally regardless of server sync)
|
|
87
97
|
_bloom.toast.success(t('language.changed', {
|
|
88
|
-
lang:
|
|
98
|
+
lang: (0, _core.getNativeLanguageName)(announceCode)
|
|
89
99
|
}));
|
|
90
|
-
|
|
91
|
-
// Log server sync failure only in dev mode (user experience is still good - saved locally)
|
|
92
|
-
if (serverSyncFailed && __DEV__) {
|
|
93
|
-
console.warn('Language saved locally but server sync failed');
|
|
94
|
-
}
|
|
95
|
-
setIsLoading(false);
|
|
96
|
-
// Close the bottom sheet if possible; otherwise, go back
|
|
97
|
-
if (onClose) onClose();else goBack?.();
|
|
98
100
|
} catch (error) {
|
|
99
|
-
//
|
|
101
|
+
// `useUpdateProfile` already surfaces a toast on failure; only the
|
|
102
|
+
// local (guest) path needs its own error toast.
|
|
103
|
+
if (!(isAuthenticated && user?.id)) {
|
|
104
|
+
_bloom.toast.error(t('language.saveFailed'));
|
|
105
|
+
}
|
|
100
106
|
if (__DEV__) {
|
|
101
107
|
console.error('Error saving language preference:', error);
|
|
102
108
|
}
|
|
103
|
-
|
|
104
|
-
|
|
109
|
+
} finally {
|
|
110
|
+
setIsSubmitting(false);
|
|
105
111
|
}
|
|
106
|
-
}, [
|
|
112
|
+
}, [isAuthenticated, user?.id, updateProfile, setLanguage, t, isBusy]);
|
|
107
113
|
|
|
108
|
-
//
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
114
|
+
// Adding a locale: signed-in appends (non-primary); a guest can only hold a
|
|
115
|
+
// single locale, so the tapped locale becomes their primary.
|
|
116
|
+
const handleAdd = (0, _react.useCallback)(code => {
|
|
117
|
+
const next = isAuthenticated && user?.id ? (0, _useLanguageManagement.addLocale)(selected, code) : [code];
|
|
118
|
+
void commitSelection(next, code);
|
|
119
|
+
}, [isAuthenticated, user?.id, selected, commitSelection]);
|
|
120
|
+
const handleSetPrimary = (0, _react.useCallback)(code => {
|
|
121
|
+
if (selected[0] === code) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
void commitSelection((0, _useLanguageManagement.setPrimaryLocale)(selected, code), code);
|
|
125
|
+
}, [selected, commitSelection]);
|
|
126
|
+
const handleRemove = (0, _react.useCallback)(code => {
|
|
127
|
+
if (selected.length <= 1) {
|
|
128
|
+
return;
|
|
113
129
|
}
|
|
114
|
-
|
|
115
|
-
|
|
130
|
+
const next = (0, _useLanguageManagement.removeLocale)(selected, code);
|
|
131
|
+
const announceCode = next[0] ?? code;
|
|
132
|
+
void commitSelection(next, announceCode);
|
|
133
|
+
}, [selected, commitSelection]);
|
|
134
|
+
const renderChip = entry => /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
135
|
+
className: "bg-fill-secondary items-center justify-center",
|
|
136
|
+
style: styles.chip,
|
|
137
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
138
|
+
className: "text-text-secondary",
|
|
139
|
+
style: styles.chipLabel,
|
|
140
|
+
children: entry.language.toUpperCase()
|
|
141
|
+
})
|
|
142
|
+
});
|
|
116
143
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
117
144
|
className: "flex-1 bg-bg",
|
|
118
145
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_Header.default, {
|
|
@@ -125,7 +152,6 @@ const LanguageSelectorScreen = ({
|
|
|
125
152
|
className: "flex-1",
|
|
126
153
|
contentContainerClassName: "px-screen-margin pt-space-24 pb-space-24",
|
|
127
154
|
showsVerticalScrollIndicator: false,
|
|
128
|
-
removeClippedSubviews: true,
|
|
129
155
|
keyboardShouldPersistTaps: "handled",
|
|
130
156
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
131
157
|
className: "mb-space-16",
|
|
@@ -147,28 +173,60 @@ const LanguageSelectorScreen = ({
|
|
|
147
173
|
label: t('language.search') || 'Search languages'
|
|
148
174
|
})
|
|
149
175
|
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_settingsList.SettingsListGroup, {
|
|
150
|
-
|
|
151
|
-
|
|
176
|
+
title: t('language.selected'),
|
|
177
|
+
children: selectedEntries.map((entry, index) => {
|
|
178
|
+
const isPrimary = index === 0;
|
|
179
|
+
const canRemove = selected.length > 1;
|
|
152
180
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_settingsList.SettingsListItem, {
|
|
153
|
-
icon:
|
|
154
|
-
|
|
155
|
-
|
|
181
|
+
icon: renderChip(entry),
|
|
182
|
+
title: entry.nativeName,
|
|
183
|
+
description: entry.name,
|
|
184
|
+
onPress: isPrimary ? undefined : () => handleSetPrimary(entry.code),
|
|
185
|
+
disabled: isBusy,
|
|
186
|
+
accessibilityLabel: isPrimary ? `${entry.name} — ${t('language.primary')}` : entry.name,
|
|
187
|
+
rightElement: isPrimary ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
188
|
+
className: "bg-fill-secondary rounded-full px-space-8 py-space-2",
|
|
156
189
|
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_typography.Text, {
|
|
157
|
-
|
|
158
|
-
|
|
190
|
+
className: "text-primary",
|
|
191
|
+
style: styles.primaryBadge,
|
|
192
|
+
children: t('language.primary')
|
|
193
|
+
})
|
|
194
|
+
}) : canRemove ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.TouchableOpacity, {
|
|
195
|
+
onPress: () => handleRemove(entry.code),
|
|
196
|
+
disabled: isBusy,
|
|
197
|
+
hitSlop: {
|
|
198
|
+
top: 8,
|
|
199
|
+
bottom: 8,
|
|
200
|
+
left: 8,
|
|
201
|
+
right: 8
|
|
202
|
+
},
|
|
203
|
+
accessibilityRole: "button",
|
|
204
|
+
accessibilityLabel: `${t('language.remove')} ${entry.name}`,
|
|
205
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
|
|
206
|
+
name: "close-circle",
|
|
207
|
+
size: REMOVE_ICON_SIZE,
|
|
208
|
+
color: bloomTheme.colors.textSecondary
|
|
159
209
|
})
|
|
160
|
-
}),
|
|
161
|
-
title: language.name,
|
|
162
|
-
description: language.nativeName,
|
|
163
|
-
onPress: () => handleLanguageSelect(language.id),
|
|
164
|
-
rightElement: isSelected ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
|
|
165
|
-
name: "checkmark-circle",
|
|
166
|
-
size: CHECK_ICON_SIZE,
|
|
167
|
-
color: bloomTheme.colors.primary
|
|
168
210
|
}) : undefined,
|
|
169
211
|
showChevron: false
|
|
170
|
-
},
|
|
212
|
+
}, entry.code);
|
|
171
213
|
})
|
|
214
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_settingsList.SettingsListGroup, {
|
|
215
|
+
title: t('language.available'),
|
|
216
|
+
children: availableEntries.map(entry => /*#__PURE__*/(0, _jsxRuntime.jsx)(_settingsList.SettingsListItem, {
|
|
217
|
+
icon: renderChip(entry),
|
|
218
|
+
title: entry.nativeName,
|
|
219
|
+
description: entry.name,
|
|
220
|
+
onPress: () => handleAdd(entry.code),
|
|
221
|
+
disabled: isBusy,
|
|
222
|
+
accessibilityLabel: entry.name,
|
|
223
|
+
rightElement: /*#__PURE__*/(0, _jsxRuntime.jsx)(_vectorIcons.Ionicons, {
|
|
224
|
+
name: "add-circle-outline",
|
|
225
|
+
size: REMOVE_ICON_SIZE,
|
|
226
|
+
color: bloomTheme.colors.textSecondary
|
|
227
|
+
}),
|
|
228
|
+
showChevron: false
|
|
229
|
+
}, entry.code))
|
|
172
230
|
})]
|
|
173
231
|
})]
|
|
174
232
|
});
|
|
@@ -185,13 +243,18 @@ const styles = _reactNative.StyleSheet.create({
|
|
|
185
243
|
fontSize: 16,
|
|
186
244
|
lineHeight: 22
|
|
187
245
|
},
|
|
188
|
-
|
|
189
|
-
width:
|
|
190
|
-
height:
|
|
191
|
-
borderRadius:
|
|
246
|
+
chip: {
|
|
247
|
+
width: CHIP_SIZE,
|
|
248
|
+
height: CHIP_SIZE,
|
|
249
|
+
borderRadius: CHIP_SIZE / 2
|
|
250
|
+
},
|
|
251
|
+
chipLabel: {
|
|
252
|
+
fontSize: 13,
|
|
253
|
+
fontWeight: '600'
|
|
192
254
|
},
|
|
193
|
-
|
|
194
|
-
fontSize:
|
|
255
|
+
primaryBadge: {
|
|
256
|
+
fontSize: 12,
|
|
257
|
+
fontWeight: '600'
|
|
195
258
|
}
|
|
196
259
|
});
|
|
197
260
|
|