@oxyhq/services 22.5.0 → 22.6.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/index.js +1 -1
- package/lib/commonjs/ui/client.js +1 -1
- package/lib/commonjs/ui/components/FontLoader.js +18 -145
- package/lib/commonjs/ui/components/FontLoader.js.map +1 -1
- package/lib/commonjs/ui/components/FontLoader.native.js +88 -0
- package/lib/commonjs/ui/components/FontLoader.native.js.map +1 -0
- package/lib/commonjs/ui/components/OxyProvider.js +1 -1
- package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js +16 -27
- package/lib/commonjs/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/UploadPreview.js.map +1 -1
- package/lib/commonjs/ui/components/fileManagement/styles.js +1 -225
- package/lib/commonjs/ui/components/fileManagement/styles.js.map +1 -1
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js +5 -2
- package/lib/commonjs/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/commonjs/ui/context/useOxyAccountGraph.js +7 -0
- package/lib/commonjs/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js +10 -4
- package/lib/commonjs/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/commonjs/ui/hooks/queries/userCache.js +33 -9
- package/lib/commonjs/ui/hooks/queries/userCache.js.map +1 -1
- package/lib/commonjs/ui/hooks/useAvatarPicker.js +23 -8
- package/lib/commonjs/ui/hooks/useAvatarPicker.js.map +1 -1
- package/lib/commonjs/ui/hooks/useFileDownloadUrl.js +7 -21
- package/lib/commonjs/ui/hooks/useFileDownloadUrl.js.map +1 -1
- package/lib/commonjs/ui/hooks/useResolvedFileUrls.js +163 -0
- package/lib/commonjs/ui/hooks/useResolvedFileUrls.js.map +1 -0
- package/lib/commonjs/ui/index.js +1 -1
- package/lib/commonjs/ui/screens/FileManagementScreen.js +51 -22
- package/lib/commonjs/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js +216 -203
- package/lib/commonjs/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js +26 -9
- package/lib/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
- package/lib/commonjs/ui/screens/fileManagement/photoGridLayout.js +44 -0
- package/lib/commonjs/ui/screens/fileManagement/photoGridLayout.js.map +1 -0
- package/lib/commonjs/ui/session/tokenTransport.js +21 -10
- package/lib/commonjs/ui/session/tokenTransport.js.map +1 -1
- package/lib/commonjs/ui/utils/fileManagement.js +0 -40
- package/lib/commonjs/ui/utils/fileManagement.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/ui/client.js +1 -1
- package/lib/module/ui/client.js.map +1 -1
- package/lib/module/ui/components/FontLoader.js +18 -146
- package/lib/module/ui/components/FontLoader.js.map +1 -1
- package/lib/module/ui/components/FontLoader.native.js +83 -0
- package/lib/module/ui/components/FontLoader.native.js.map +1 -0
- package/lib/module/ui/components/OxyProvider.js +1 -1
- package/lib/module/ui/components/OxyProvider.js.map +1 -1
- package/lib/module/ui/components/fileManagement/FileDetailsModal.js +16 -27
- package/lib/module/ui/components/fileManagement/FileDetailsModal.js.map +1 -1
- package/lib/module/ui/components/fileManagement/UploadPreview.js.map +1 -1
- package/lib/module/ui/components/fileManagement/styles.js +0 -224
- package/lib/module/ui/components/fileManagement/styles.js.map +1 -1
- package/lib/module/ui/context/hooks/useAuthOperations.js +5 -2
- package/lib/module/ui/context/hooks/useAuthOperations.js.map +1 -1
- package/lib/module/ui/context/useOxyAccountGraph.js +7 -0
- package/lib/module/ui/context/useOxyAccountGraph.js.map +1 -1
- package/lib/module/ui/hooks/queries/useAccountQueries.js +10 -4
- package/lib/module/ui/hooks/queries/useAccountQueries.js.map +1 -1
- package/lib/module/ui/hooks/queries/userCache.js +33 -9
- package/lib/module/ui/hooks/queries/userCache.js.map +1 -1
- package/lib/module/ui/hooks/useAvatarPicker.js +23 -8
- package/lib/module/ui/hooks/useAvatarPicker.js.map +1 -1
- package/lib/module/ui/hooks/useFileDownloadUrl.js +7 -21
- package/lib/module/ui/hooks/useFileDownloadUrl.js.map +1 -1
- package/lib/module/ui/hooks/useResolvedFileUrls.js +157 -0
- package/lib/module/ui/hooks/useResolvedFileUrls.js.map +1 -0
- package/lib/module/ui/index.js +1 -1
- package/lib/module/ui/index.js.map +1 -1
- package/lib/module/ui/screens/FileManagementScreen.js +52 -23
- package/lib/module/ui/screens/FileManagementScreen.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js +218 -205
- package/lib/module/ui/screens/fileManagement/PhotoPickerSection.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js +26 -9
- package/lib/module/ui/screens/fileManagement/hooks/useFileUploadState.js.map +1 -1
- package/lib/module/ui/screens/fileManagement/photoGridLayout.js +39 -0
- package/lib/module/ui/screens/fileManagement/photoGridLayout.js.map +1 -0
- package/lib/module/ui/session/tokenTransport.js +21 -10
- package/lib/module/ui/session/tokenTransport.js.map +1 -1
- package/lib/module/ui/utils/fileManagement.js +0 -39
- package/lib/module/ui/utils/fileManagement.js.map +1 -1
- package/lib/typescript/commonjs/ui/components/FontLoader.d.ts +14 -5
- package/lib/typescript/commonjs/ui/components/FontLoader.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/FontLoader.native.d.ts +13 -0
- package/lib/typescript/commonjs/ui/components/FontLoader.native.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/components/fileManagement/FileDetailsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/components/fileManagement/styles.d.ts +0 -218
- package/lib/typescript/commonjs/ui/components/fileManagement/styles.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts +9 -0
- package/lib/typescript/commonjs/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/queries/userCache.d.ts +3 -0
- package/lib/typescript/commonjs/ui/hooks/queries/userCache.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useAvatarPicker.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useFileDownloadUrl.d.ts +3 -2
- package/lib/typescript/commonjs/ui/hooks/useFileDownloadUrl.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/hooks/useResolvedFileUrls.d.ts +48 -0
- package/lib/typescript/commonjs/ui/hooks/useResolvedFileUrls.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/screens/fileManagement/photoGridLayout.d.ts +37 -0
- package/lib/typescript/commonjs/ui/screens/fileManagement/photoGridLayout.d.ts.map +1 -0
- package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts +15 -8
- package/lib/typescript/commonjs/ui/session/tokenTransport.d.ts.map +1 -1
- package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts +4 -11
- package/lib/typescript/commonjs/ui/utils/fileManagement.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +1 -1
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/client.d.ts +1 -1
- package/lib/typescript/module/ui/client.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/FontLoader.d.ts +14 -5
- package/lib/typescript/module/ui/components/FontLoader.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/FontLoader.native.d.ts +13 -0
- package/lib/typescript/module/ui/components/FontLoader.native.d.ts.map +1 -0
- package/lib/typescript/module/ui/components/fileManagement/FileDetailsModal.d.ts.map +1 -1
- package/lib/typescript/module/ui/components/fileManagement/styles.d.ts +0 -218
- package/lib/typescript/module/ui/components/fileManagement/styles.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/hooks/useAuthOperations.d.ts.map +1 -1
- package/lib/typescript/module/ui/context/useOxyAccountGraph.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts +9 -0
- package/lib/typescript/module/ui/hooks/queries/useAccountQueries.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/queries/userCache.d.ts +3 -0
- package/lib/typescript/module/ui/hooks/queries/userCache.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useAvatarPicker.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useFileDownloadUrl.d.ts +3 -2
- package/lib/typescript/module/ui/hooks/useFileDownloadUrl.d.ts.map +1 -1
- package/lib/typescript/module/ui/hooks/useResolvedFileUrls.d.ts +48 -0
- package/lib/typescript/module/ui/hooks/useResolvedFileUrls.d.ts.map +1 -0
- package/lib/typescript/module/ui/index.d.ts +1 -1
- package/lib/typescript/module/ui/index.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/FileManagementScreen.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/PhotoPickerSection.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/hooks/useFileUploadState.d.ts.map +1 -1
- package/lib/typescript/module/ui/screens/fileManagement/photoGridLayout.d.ts +37 -0
- package/lib/typescript/module/ui/screens/fileManagement/photoGridLayout.d.ts.map +1 -0
- package/lib/typescript/module/ui/session/tokenTransport.d.ts +15 -8
- package/lib/typescript/module/ui/session/tokenTransport.d.ts.map +1 -1
- package/lib/typescript/module/ui/utils/fileManagement.d.ts +4 -11
- package/lib/typescript/module/ui/utils/fileManagement.d.ts.map +1 -1
- package/package.json +5 -10
- package/src/ui/components/FontLoader.native.tsx +88 -0
- package/src/ui/components/FontLoader.tsx +16 -151
- package/src/ui/components/fileManagement/FileDetailsModal.tsx +17 -18
- package/src/ui/components/fileManagement/UploadPreview.tsx +1 -1
- package/src/ui/components/fileManagement/styles.ts +0 -225
- package/src/ui/context/hooks/useAuthOperations.ts +5 -2
- package/src/ui/context/useOxyAccountGraph.ts +5 -0
- package/src/ui/hooks/queries/__tests__/userCache.test.ts +29 -0
- package/src/ui/hooks/queries/useAccountQueries.ts +10 -4
- package/src/ui/hooks/queries/userCache.ts +31 -8
- package/src/ui/hooks/useAvatarPicker.ts +27 -7
- package/src/ui/hooks/useFileDownloadUrl.ts +7 -23
- package/src/ui/hooks/useResolvedFileUrls.ts +170 -0
- package/src/ui/screens/FileManagementScreen.tsx +55 -27
- package/src/ui/screens/__tests__/photoGridLayout.test.ts +57 -0
- package/src/ui/screens/fileManagement/PhotoPickerSection.tsx +215 -213
- package/src/ui/screens/fileManagement/hooks/useFileUploadState.ts +27 -3
- package/src/ui/screens/fileManagement/photoGridLayout.ts +45 -0
- package/src/ui/session/__tests__/tokenTransport.test.ts +25 -10
- package/src/ui/session/tokenTransport.ts +21 -10
- package/src/ui/utils/fileManagement.ts +3 -46
- package/lib/typescript/types/expo-vector-icons.d.ts +0 -22
- package/src/types/expo-vector-icons.d.ts +0 -22
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Column / tile geometry for the "Choose photo" grid.
|
|
3
|
+
*
|
|
4
|
+
* CRITICAL: the grid MUST size its tiles from the width of the bottom-sheet
|
|
5
|
+
* container it actually renders in — NOT the device screen. On wide viewports
|
|
6
|
+
* the sheet is centered and narrower than the screen (Bloom `<Dialog>` centers
|
|
7
|
+
* on `md+`), so deriving columns/tiles from `Dimensions.get('window').width`
|
|
8
|
+
* (or `useWindowDimensions`) overflows / mis-sizes the tiles. The caller
|
|
9
|
+
* therefore measures the grid container (`onLayout` on a `style`-only wrapper —
|
|
10
|
+
* RN-Web does not fire `onLayout` for `className`'d nodes) and passes that
|
|
11
|
+
* measured width here.
|
|
12
|
+
*
|
|
13
|
+
* Pure and side-effect free so it is unit-testable in Jest (which cannot catch
|
|
14
|
+
* layout bugs in the rendered tree).
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Inter-tile gutter, in px. Apple Photos-style hairline gap. */
|
|
18
|
+
export const PHOTO_GRID_GUTTER = 2;
|
|
19
|
+
|
|
20
|
+
/** Container width (px) at/above which the grid switches to 4 columns. */
|
|
21
|
+
export const PHOTO_GRID_WIDE_BREAKPOINT = 600;
|
|
22
|
+
|
|
23
|
+
export interface PhotoGridLayout {
|
|
24
|
+
/** Number of columns for the current container width. */
|
|
25
|
+
columns: number;
|
|
26
|
+
/**
|
|
27
|
+
* Square tile edge in px. Floored so a full row (columns tiles + gutters)
|
|
28
|
+
* never exceeds the container width.
|
|
29
|
+
*/
|
|
30
|
+
cellSize: number;
|
|
31
|
+
/** Inter-tile gutter used to derive `cellSize`. */
|
|
32
|
+
gutter: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Derive the column count + square tile size from the measured grid-container
|
|
37
|
+
* width. Returns `cellSize: 0` for a not-yet-measured (`<= 0`) width so callers
|
|
38
|
+
* can gate rendering until a real measurement arrives.
|
|
39
|
+
*/
|
|
40
|
+
export function computePhotoGridLayout(containerWidth: number): PhotoGridLayout {
|
|
41
|
+
const columns = containerWidth >= PHOTO_GRID_WIDE_BREAKPOINT ? 4 : 3;
|
|
42
|
+
const usable = containerWidth - PHOTO_GRID_GUTTER * (columns - 1);
|
|
43
|
+
const cellSize = usable > 0 ? Math.floor(usable / columns) : 0;
|
|
44
|
+
return { columns, cellSize, gutter: PHOTO_GRID_GUTTER };
|
|
45
|
+
}
|
|
@@ -5,12 +5,14 @@ import { createTokenTransport } from '../tokenTransport';
|
|
|
5
5
|
// The device-first transport no longer owns a private mint single-flight: it
|
|
6
6
|
// routes through the ONE shared `oxyServices.httpService.refreshAccessToken(...)`
|
|
7
7
|
// the scheduler/preflight/401 use, so concurrent lanes can never double-rotate
|
|
8
|
-
// the device secret.
|
|
9
|
-
//
|
|
8
|
+
// the device secret. It short-circuits ONLY when the planted bearer already
|
|
9
|
+
// identifies the state's active account — a bearer for a DIFFERENT account (an
|
|
10
|
+
// account switch) must still mint the new account's token. These tests exercise
|
|
11
|
+
// that account-match contract and the transport's error/swallow behavior.
|
|
10
12
|
|
|
11
|
-
function fakeOxy(
|
|
13
|
+
function fakeOxy(currentUserId: string | null, refreshAccessToken = jest.fn(async () => 'minted-token')) {
|
|
12
14
|
return {
|
|
13
|
-
|
|
15
|
+
getCurrentUserId: jest.fn().mockReturnValue(currentUserId),
|
|
14
16
|
httpService: { refreshAccessToken },
|
|
15
17
|
};
|
|
16
18
|
}
|
|
@@ -24,9 +26,9 @@ const state: DeviceSessionState = {
|
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
describe('createTokenTransport', () => {
|
|
27
|
-
test('no-ops when
|
|
29
|
+
test('no-ops when the planted bearer already belongs to the active account', async () => {
|
|
28
30
|
const refreshAccessToken = jest.fn(async () => 'minted-token');
|
|
29
|
-
const oxy = fakeOxy('
|
|
31
|
+
const oxy = fakeOxy('a1', refreshAccessToken);
|
|
30
32
|
const transport = createTokenTransport(oxy as never);
|
|
31
33
|
|
|
32
34
|
await transport.ensureActiveToken(state);
|
|
@@ -34,7 +36,20 @@ describe('createTokenTransport', () => {
|
|
|
34
36
|
expect(refreshAccessToken).not.toHaveBeenCalled();
|
|
35
37
|
});
|
|
36
38
|
|
|
37
|
-
test('mints
|
|
39
|
+
test('mints when the planted bearer belongs to a DIFFERENT account (account switch)', async () => {
|
|
40
|
+
// The core account-switch 404 fix: a bearer for the PREVIOUS account must
|
|
41
|
+
// NOT short-circuit — it must mint the new active account's token.
|
|
42
|
+
const refreshAccessToken = jest.fn(async () => 'minted-token');
|
|
43
|
+
const oxy = fakeOxy('previous-account', refreshAccessToken);
|
|
44
|
+
const transport = createTokenTransport(oxy as never);
|
|
45
|
+
|
|
46
|
+
await transport.ensureActiveToken(state);
|
|
47
|
+
|
|
48
|
+
expect(refreshAccessToken).toHaveBeenCalledTimes(1);
|
|
49
|
+
expect(refreshAccessToken).toHaveBeenCalledWith('preflight');
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
test('mints via the shared httpService.refreshAccessToken single-flight when no bearer is present', async () => {
|
|
38
53
|
const refreshAccessToken = jest.fn(async () => 'minted-token');
|
|
39
54
|
const oxy = fakeOxy(null, refreshAccessToken);
|
|
40
55
|
const transport = createTokenTransport(oxy as never);
|
|
@@ -91,10 +106,10 @@ describe('createTokenTransport', () => {
|
|
|
91
106
|
await expect(Promise.all([first, second])).resolves.toEqual([undefined, undefined]);
|
|
92
107
|
});
|
|
93
108
|
|
|
94
|
-
test('treats a throwing
|
|
109
|
+
test('treats a throwing bearer-account check as a mismatch and still mints', async () => {
|
|
95
110
|
const refreshAccessToken = jest.fn(async () => 'minted-token');
|
|
96
111
|
const oxy = fakeOxy(null, refreshAccessToken);
|
|
97
|
-
oxy.
|
|
112
|
+
oxy.getCurrentUserId.mockImplementation(() => {
|
|
98
113
|
throw new Error('storage unavailable');
|
|
99
114
|
});
|
|
100
115
|
const transport = createTokenTransport(oxy as never);
|
|
@@ -103,7 +118,7 @@ describe('createTokenTransport', () => {
|
|
|
103
118
|
await expect(transport.ensureActiveToken(state)).resolves.toBeUndefined();
|
|
104
119
|
|
|
105
120
|
expect(warnSpy).toHaveBeenCalledWith(
|
|
106
|
-
'ensureActiveToken:
|
|
121
|
+
'ensureActiveToken: bearer-account check threw',
|
|
107
122
|
{ component: 'TokenTransport' },
|
|
108
123
|
expect.any(Error),
|
|
109
124
|
);
|
|
@@ -5,14 +5,21 @@ import type { DeviceSessionState } from '@oxyhq/contracts';
|
|
|
5
5
|
* Platform `TokenTransport` for `SessionClient` (device-first model).
|
|
6
6
|
*
|
|
7
7
|
* `ensureActiveToken` is the fallback the client uses when a `session_state`
|
|
8
|
-
* push arrived WITHOUT an embedded `activeToken` and the
|
|
9
|
-
*
|
|
10
|
-
* request-time preflight, and the 401
|
|
11
|
-
* `oxyServices.httpService.refreshAccessToken(...)` — which runs
|
|
12
|
-
* refresh handler (present the persisted zero-cookie `deviceId` +
|
|
13
|
-
* at `POST /session/device/token
|
|
14
|
-
*
|
|
15
|
-
*
|
|
8
|
+
* push arrived WITHOUT an embedded `activeToken` and the planted bearer does not
|
|
9
|
+
* already belong to the state's active account. It mints one through the ONE
|
|
10
|
+
* unified single-flight the scheduler, the request-time preflight, and the 401
|
|
11
|
+
* retry all use — `oxyServices.httpService.refreshAccessToken(...)` — which runs
|
|
12
|
+
* the installed refresh handler (present the persisted zero-cookie `deviceId` +
|
|
13
|
+
* `deviceSecret` at `POST /session/device/token`, which mints for the device's
|
|
14
|
+
* CURRENT active account). Routing through the SAME entry point means this lane
|
|
15
|
+
* can never double-rotate the device secret against the others: it has NO
|
|
16
|
+
* private single-flight of its own.
|
|
17
|
+
*
|
|
18
|
+
* The short-circuit compares the planted bearer's ACCOUNT against
|
|
19
|
+
* `state.activeAccountId`, not mere token presence: a bearer for the PREVIOUS
|
|
20
|
+
* account (an account switch) must still mint the new account's token — skipping
|
|
21
|
+
* on presence alone would leave a subscriber observing the new active account
|
|
22
|
+
* under the old account's bearer (the account-switch 404 race).
|
|
16
23
|
*
|
|
17
24
|
* A failure is logged and swallowed: this method must never throw out (it runs
|
|
18
25
|
* inside the socket state handler).
|
|
@@ -21,11 +28,15 @@ export function createTokenTransport(oxyServices: OxyServices): TokenTransport {
|
|
|
21
28
|
return {
|
|
22
29
|
async ensureActiveToken(state: DeviceSessionState): Promise<void> {
|
|
23
30
|
try {
|
|
24
|
-
|
|
31
|
+
// Skip the mint ONLY when the planted bearer already identifies the
|
|
32
|
+
// active account. `getCurrentUserId()` decodes the bearer's `userId`/`id`
|
|
33
|
+
// (null when absent/opaque), directly comparable to the account id.
|
|
34
|
+
const activeAccountId = state.activeAccountId;
|
|
35
|
+
if (activeAccountId !== null && oxyServices.getCurrentUserId() === activeAccountId) {
|
|
25
36
|
return;
|
|
26
37
|
}
|
|
27
38
|
} catch (error) {
|
|
28
|
-
logger.warn('ensureActiveToken:
|
|
39
|
+
logger.warn('ensureActiveToken: bearer-account check threw', { component: 'TokenTransport' }, error);
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
try {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import type { Ionicons } from '@expo/vector-icons';
|
|
1
2
|
import type { AssetUploadInput, FileMetadata, RNFileDescriptor } from '@oxyhq/core';
|
|
2
|
-
import {
|
|
3
|
+
import type { ComponentProps } from 'react';
|
|
3
4
|
import { Platform } from 'react-native';
|
|
4
5
|
import { toast } from '@oxyhq/bloom';
|
|
5
6
|
import type { RouteName } from '../navigation/routes';
|
|
@@ -54,7 +55,7 @@ export function formatFileSize(bytes: number): string {
|
|
|
54
55
|
/**
|
|
55
56
|
* Get icon name for file based on content type
|
|
56
57
|
*/
|
|
57
|
-
export function getFileIcon(contentType: string):
|
|
58
|
+
export function getFileIcon(contentType: string): ComponentProps<typeof Ionicons>['name'] {
|
|
58
59
|
if (contentType.startsWith('image/')) return 'image';
|
|
59
60
|
if (contentType.startsWith('video/')) return 'videocam';
|
|
60
61
|
if (contentType.startsWith('audio/')) return 'musical-notes';
|
|
@@ -142,50 +143,6 @@ export async function convertDocumentPickerAssetToFile(
|
|
|
142
143
|
}
|
|
143
144
|
}
|
|
144
145
|
|
|
145
|
-
/**
|
|
146
|
-
* Helper to safely request a thumbnail variant only for image mime types.
|
|
147
|
-
* Prevents backend warnings: "Variant thumb not supported for mime application/pdf".
|
|
148
|
-
*
|
|
149
|
-
* @param file - File metadata
|
|
150
|
-
* @param variant - Variant type (default: 'thumb')
|
|
151
|
-
* @param getFileDownloadUrl - Function to get download URL from oxyServices
|
|
152
|
-
*/
|
|
153
|
-
export function getSafeDownloadUrl(
|
|
154
|
-
file: FileMetadata,
|
|
155
|
-
variant: string,
|
|
156
|
-
getFileDownloadUrl: (fileId: string, variant?: string) => string
|
|
157
|
-
): string {
|
|
158
|
-
const isImage = file.contentType.startsWith('image/');
|
|
159
|
-
const isVideo = file.contentType.startsWith('video/');
|
|
160
|
-
|
|
161
|
-
// Prefer explicit variant key if variants metadata present
|
|
162
|
-
if (file.variants && file.variants.length > 0) {
|
|
163
|
-
// For videos, try 'poster' regardless of requested variant
|
|
164
|
-
if (isVideo) {
|
|
165
|
-
const poster = file.variants.find(v => v.type === 'poster');
|
|
166
|
-
if (poster) return getFileDownloadUrl(file.id, 'poster');
|
|
167
|
-
}
|
|
168
|
-
if (isImage) {
|
|
169
|
-
const desired = file.variants.find(v => v.type === variant);
|
|
170
|
-
if (desired) return getFileDownloadUrl(file.id, variant);
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
if (isImage) {
|
|
175
|
-
return getFileDownloadUrl(file.id, variant);
|
|
176
|
-
}
|
|
177
|
-
if (isVideo) {
|
|
178
|
-
// Fallback to poster if backend supports implicit generation
|
|
179
|
-
try {
|
|
180
|
-
return getFileDownloadUrl(file.id, 'poster');
|
|
181
|
-
} catch {
|
|
182
|
-
return getFileDownloadUrl(file.id);
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
// Other mime types: no variant
|
|
186
|
-
return getFileDownloadUrl(file.id);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
146
|
/**
|
|
190
147
|
* Upload file raw - helper function for file uploads
|
|
191
148
|
*/
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
declare module '@expo/vector-icons' {
|
|
2
|
-
import type React from 'react';
|
|
3
|
-
import type { StyleProp, TextStyle, ImageStyle } from 'react-native';
|
|
4
|
-
|
|
5
|
-
type IconStyleProp = StyleProp<TextStyle> | StyleProp<ImageStyle>;
|
|
6
|
-
|
|
7
|
-
export const Ionicons: React.ComponentType<{
|
|
8
|
-
name: string;
|
|
9
|
-
size?: number;
|
|
10
|
-
color?: string;
|
|
11
|
-
style?: IconStyleProp;
|
|
12
|
-
testID?: string;
|
|
13
|
-
}>;
|
|
14
|
-
|
|
15
|
-
export const MaterialCommunityIcons: React.ComponentType<{
|
|
16
|
-
name: string;
|
|
17
|
-
size?: number;
|
|
18
|
-
color?: string;
|
|
19
|
-
style?: IconStyleProp;
|
|
20
|
-
testID?: string;
|
|
21
|
-
}>;
|
|
22
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
declare module '@expo/vector-icons' {
|
|
2
|
-
import type React from 'react';
|
|
3
|
-
import type { StyleProp, TextStyle, ImageStyle } from 'react-native';
|
|
4
|
-
|
|
5
|
-
type IconStyleProp = StyleProp<TextStyle> | StyleProp<ImageStyle>;
|
|
6
|
-
|
|
7
|
-
export const Ionicons: React.ComponentType<{
|
|
8
|
-
name: string;
|
|
9
|
-
size?: number;
|
|
10
|
-
color?: string;
|
|
11
|
-
style?: IconStyleProp;
|
|
12
|
-
testID?: string;
|
|
13
|
-
}>;
|
|
14
|
-
|
|
15
|
-
export const MaterialCommunityIcons: React.ComponentType<{
|
|
16
|
-
name: string;
|
|
17
|
-
size?: number;
|
|
18
|
-
color?: string;
|
|
19
|
-
style?: IconStyleProp;
|
|
20
|
-
testID?: string;
|
|
21
|
-
}>;
|
|
22
|
-
}
|