@planningcenter/chat-react-native 3.33.1 → 3.33.2-qa-664.1
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/build/components/conversation/attachments/generic_file_attachment.d.ts +0 -1
- package/build/components/conversation/attachments/generic_file_attachment.d.ts.map +1 -1
- package/build/components/conversation/attachments/generic_file_attachment.js +1 -16
- package/build/components/conversation/attachments/generic_file_attachment.js.map +1 -1
- package/build/components/conversation/message_form/message_form_attachment_file.d.ts +11 -0
- package/build/components/conversation/message_form/message_form_attachment_file.d.ts.map +1 -0
- package/build/components/conversation/message_form/message_form_attachment_file.js +8 -0
- package/build/components/conversation/message_form/message_form_attachment_file.js.map +1 -0
- package/build/components/conversation/message_form/message_form_attachment_video.d.ts.map +1 -1
- package/build/components/conversation/message_form/message_form_attachment_video.js +1 -2
- package/build/components/conversation/message_form/message_form_attachment_video.js.map +1 -1
- package/build/components/conversation/message_form.d.ts.map +1 -1
- package/build/components/conversation/message_form.js +13 -8
- package/build/components/conversation/message_form.js.map +1 -1
- package/build/components/display/file_attachment_preview.d.ts +11 -0
- package/build/components/display/file_attachment_preview.d.ts.map +1 -0
- package/build/components/display/file_attachment_preview.js +95 -0
- package/build/components/display/file_attachment_preview.js.map +1 -0
- package/build/components/display/image.d.ts.map +1 -1
- package/build/components/display/image.js +4 -1
- package/build/components/display/image.js.map +1 -1
- package/build/components/display/index.d.ts +1 -0
- package/build/components/display/index.d.ts.map +1 -1
- package/build/components/display/index.js +1 -0
- package/build/components/display/index.js.map +1 -1
- package/build/hooks/attachments/fallback_chat_configuration.d.ts +1 -0
- package/build/hooks/attachments/fallback_chat_configuration.d.ts.map +1 -1
- package/build/hooks/attachments/fallback_chat_configuration.js +23 -0
- package/build/hooks/attachments/fallback_chat_configuration.js.map +1 -1
- package/build/hooks/paginator_meta.d.ts +4 -0
- package/build/hooks/paginator_meta.d.ts.map +1 -0
- package/build/hooks/paginator_meta.js +14 -0
- package/build/hooks/paginator_meta.js.map +1 -0
- package/build/hooks/use_api.d.ts.map +1 -1
- package/build/hooks/use_api.js +2 -9
- package/build/hooks/use_api.js.map +1 -1
- package/build/hooks/use_chat_configuration.d.ts +1 -0
- package/build/hooks/use_chat_configuration.d.ts.map +1 -1
- package/build/hooks/use_chat_configuration.js +9 -1
- package/build/hooks/use_chat_configuration.js.map +1 -1
- package/build/hooks/use_suspense_api.d.ts.map +1 -1
- package/build/hooks/use_suspense_api.js +2 -9
- package/build/hooks/use_suspense_api.js.map +1 -1
- package/build/index.d.ts +1 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/screens/avatar_picker/emoji_tab.d.ts.map +1 -1
- package/build/screens/avatar_picker/emoji_tab.js +10 -1
- package/build/screens/avatar_picker/emoji_tab.js.map +1 -1
- package/build/types/api_primitives.d.ts +8 -1
- package/build/types/api_primitives.d.ts.map +1 -1
- package/build/types/api_primitives.js.map +1 -1
- package/build/types/resources/chat_configuration_resource.d.ts +1 -0
- package/build/types/resources/chat_configuration_resource.d.ts.map +1 -1
- package/build/types/resources/chat_configuration_resource.js.map +1 -1
- package/build/utils/attachment_kind.d.ts +5 -0
- package/build/utils/attachment_kind.d.ts.map +1 -0
- package/build/utils/attachment_kind.js +46 -0
- package/build/utils/attachment_kind.js.map +1 -0
- package/build/utils/index.d.ts +1 -0
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +1 -0
- package/build/utils/index.js.map +1 -1
- package/build/utils/native_adapters/document_picker.d.ts +5 -2
- package/build/utils/native_adapters/document_picker.d.ts.map +1 -1
- package/build/utils/native_adapters/document_picker.js.map +1 -1
- package/package.json +3 -3
- package/src/__tests__/contexts/session_context.tsx +3 -8
- package/src/__tests__/hooks/paginator_meta.test.ts +15 -0
- package/src/__tests__/hooks/useTheme.tsx +3 -3
- package/src/__tests__/hooks/use_async_storage.test.tsx +3 -8
- package/src/__tests__/hooks/use_attachment_uploader.test.tsx +3 -2
- package/src/__tests__/hooks/use_chat_configuration.test.tsx +29 -4
- package/src/__utils__/query_client.ts +14 -0
- package/src/components/conversation/attachments/generic_file_attachment.tsx +1 -14
- package/src/components/conversation/message_form/message_form_attachment_file.tsx +26 -0
- package/src/components/conversation/message_form/message_form_attachment_video.tsx +1 -2
- package/src/components/conversation/message_form.tsx +23 -8
- package/src/components/display/file_attachment_preview.tsx +135 -0
- package/src/components/display/image.tsx +5 -0
- package/src/components/display/index.ts +1 -0
- package/src/hooks/attachments/fallback_chat_configuration.ts +24 -0
- package/src/hooks/paginator_meta.ts +13 -0
- package/src/hooks/use_api.ts +2 -14
- package/src/hooks/use_chat_configuration.ts +9 -0
- package/src/hooks/use_suspense_api.ts +2 -14
- package/src/index.tsx +1 -0
- package/src/screens/avatar_picker/emoji_tab.tsx +13 -1
- package/src/types/api_primitives.ts +9 -1
- package/src/types/resources/chat_configuration_resource.ts +4 -0
- package/src/utils/__tests__/attachment_kind.test.ts +37 -0
- package/src/utils/attachment_kind.ts +47 -0
- package/src/utils/index.ts +1 -0
- package/src/utils/native_adapters/document_picker.ts +9 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,mCAAmC,CAAA;AACjD,cAAc,kCAAkC,CAAA;AAChD,cAAc,2BAA2B,CAAA;AACzC,cAAc,mBAAmB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,mCAAmC,CAAA;AACjD,cAAc,kCAAkC,CAAA;AAChD,cAAc,2BAA2B,CAAA;AACzC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA"}
|
package/build/utils/index.js
CHANGED
|
@@ -10,5 +10,6 @@ export * from './reaction_constants';
|
|
|
10
10
|
export * from './destructure_chat_group_graph_id';
|
|
11
11
|
export * from './convert_attachments_for_create';
|
|
12
12
|
export * from './assert_keys_are_numbers';
|
|
13
|
+
export * from './attachment_kind';
|
|
13
14
|
export * from './system_messages';
|
|
14
15
|
//# sourceMappingURL=index.js.map
|
package/build/utils/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,mCAAmC,CAAA;AACjD,cAAc,kCAAkC,CAAA;AAChD,cAAc,2BAA2B,CAAA;AACzC,cAAc,mBAAmB,CAAA","sourcesContent":["export * from './session'\nexport * from './theme'\nexport * from './styles'\nexport * from './client'\nexport * from './uri'\nexport * from './cache'\nexport * from './native_adapters'\nexport * from './pluralize'\nexport * from './reaction_constants'\nexport * from './destructure_chat_group_graph_id'\nexport * from './convert_attachments_for_create'\nexport * from './assert_keys_are_numbers'\nexport * from './system_messages'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,SAAS,CAAA;AACvB,cAAc,UAAU,CAAA;AACxB,cAAc,UAAU,CAAA;AACxB,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,sBAAsB,CAAA;AACpC,cAAc,mCAAmC,CAAA;AACjD,cAAc,kCAAkC,CAAA;AAChD,cAAc,2BAA2B,CAAA;AACzC,cAAc,mBAAmB,CAAA;AACjC,cAAc,mBAAmB,CAAA","sourcesContent":["export * from './session'\nexport * from './theme'\nexport * from './styles'\nexport * from './client'\nexport * from './uri'\nexport * from './cache'\nexport * from './native_adapters'\nexport * from './pluralize'\nexport * from './reaction_constants'\nexport * from './destructure_chat_group_graph_id'\nexport * from './convert_attachments_for_create'\nexport * from './assert_keys_are_numbers'\nexport * from './attachment_kind'\nexport * from './system_messages'\n"]}
|
|
@@ -13,11 +13,14 @@ type DocumentPickerCanceledResult = {
|
|
|
13
13
|
assets: null;
|
|
14
14
|
};
|
|
15
15
|
export type DocumentPickerResult = DocumentPickerSuccessResult | DocumentPickerCanceledResult;
|
|
16
|
+
export interface DocumentPickerOpenOptions {
|
|
17
|
+
mimeTypes?: string[];
|
|
18
|
+
}
|
|
16
19
|
interface DocumentPicker {
|
|
17
|
-
openAsync: () => Promise<DocumentPickerResult>;
|
|
20
|
+
openAsync: (options?: DocumentPickerOpenOptions) => Promise<DocumentPickerResult>;
|
|
18
21
|
}
|
|
19
22
|
export declare class DocumentPickerAdapter {
|
|
20
|
-
openAsync: () => Promise<DocumentPickerResult>;
|
|
23
|
+
openAsync: (options?: DocumentPickerOpenOptions) => Promise<DocumentPickerResult>;
|
|
21
24
|
configured: boolean;
|
|
22
25
|
constructor(methods?: DocumentPicker);
|
|
23
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document_picker.d.ts","sourceRoot":"","sources":["../../../src/utils/native_adapters/document_picker.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,2BAA2B,GAAG;IACjC,QAAQ,EAAE,KAAK,CAAA;IACf,MAAM,EAAE,mBAAmB,EAAE,CAAA;CAC9B,CAAA;AAED,KAAK,4BAA4B,GAAG;IAClC,QAAQ,EAAE,IAAI,CAAA;IACd,MAAM,EAAE,IAAI,CAAA;CACb,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,2BAA2B,GAAG,4BAA4B,CAAA;AAE7F,UAAU,cAAc;IACtB,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"document_picker.d.ts","sourceRoot":"","sources":["../../../src/utils/native_adapters/document_picker.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,mBAAmB,GAAG;IAChC,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,CAAA;AAED,KAAK,2BAA2B,GAAG;IACjC,QAAQ,EAAE,KAAK,CAAA;IACf,MAAM,EAAE,mBAAmB,EAAE,CAAA;CAC9B,CAAA;AAED,KAAK,4BAA4B,GAAG;IAClC,QAAQ,EAAE,IAAI,CAAA;IACd,MAAM,EAAE,IAAI,CAAA;CACb,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,2BAA2B,GAAG,4BAA4B,CAAA;AAE7F,MAAM,WAAW,yBAAyB;IAIxC,SAAS,CAAC,EAAE,MAAM,EAAE,CAAA;CACrB;AAED,UAAU,cAAc;IACtB,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAA;CAClF;AAED,qBAAa,qBAAqB;IAChC,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,yBAAyB,KAAK,OAAO,CAAC,oBAAoB,CAAC,CAAA;IACjF,UAAU,EAAE,OAAO,CAAA;gBAEP,OAAO,CAAC,EAAE,cAAc;CAIrC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"document_picker.js","sourceRoot":"","sources":["../../../src/utils/native_adapters/document_picker.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"document_picker.js","sourceRoot":"","sources":["../../../src/utils/native_adapters/document_picker.ts"],"names":[],"mappings":"AA8BA,MAAM,OAAO,qBAAqB;IAChC,SAAS,CAAwE;IACjF,UAAU,CAAS;IAEnB,YAAY,OAAwB;QAClC,IAAI,CAAC,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;QACvF,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,OAAO,CAAA;IAC7B,CAAC;CACF","sourcesContent":["export type DocumentPickerAsset = {\n uri: string\n name: string\n size?: number\n mimeType?: string\n}\n\ntype DocumentPickerSuccessResult = {\n canceled: false\n assets: DocumentPickerAsset[]\n}\n\ntype DocumentPickerCanceledResult = {\n canceled: true\n assets: null\n}\n\nexport type DocumentPickerResult = DocumentPickerSuccessResult | DocumentPickerCanceledResult\n\nexport interface DocumentPickerOpenOptions {\n // MIME types the picker should restrict to. Hosts forward to the\n // underlying picker's `type` argument. Omitted/empty means no\n // restriction (the picker behaves as before).\n mimeTypes?: string[]\n}\n\ninterface DocumentPicker {\n openAsync: (options?: DocumentPickerOpenOptions) => Promise<DocumentPickerResult>\n}\n\nexport class DocumentPickerAdapter {\n openAsync: (options?: DocumentPickerOpenOptions) => Promise<DocumentPickerResult>\n configured: boolean\n\n constructor(methods?: DocumentPicker) {\n this.openAsync = methods?.openAsync ?? (async () => ({ canceled: true, assets: null }))\n this.configured = !!methods\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@planningcenter/chat-react-native",
|
|
3
|
-
"version": "3.33.1",
|
|
3
|
+
"version": "3.33.2-qa-664.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@fortawesome/react-native-fontawesome": "^0.3.2",
|
|
28
28
|
"lodash-inflection": "^1.5.0",
|
|
29
29
|
"react-compiler-runtime": "^1.0.0",
|
|
30
|
-
"rn-emoji-keyboard": "
|
|
30
|
+
"rn-emoji-keyboard": "1.7.0"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@planningcenter/datetime-fmt": ">=2.0.0",
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"react-native-url-polyfill": "^2.0.0",
|
|
66
66
|
"typescript": "~5.9.2"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "35b43ec0bbb57ea9220ce95b0f4e49acf7779f87"
|
|
69
69
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
2
|
-
import {
|
|
2
|
+
import { QueryClientProvider } from '@tanstack/react-query'
|
|
3
3
|
import { renderHook, act } from '@testing-library/react-hooks'
|
|
4
4
|
import React, { useContext, Suspense } from 'react'
|
|
5
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
5
6
|
import {
|
|
6
7
|
SessionContext,
|
|
7
8
|
SessionContextProvider,
|
|
@@ -67,13 +68,7 @@ const waitForQuery = async () => {
|
|
|
67
68
|
}
|
|
68
69
|
|
|
69
70
|
const createWrapper = (config: SessionContextConfig) => {
|
|
70
|
-
const queryClient =
|
|
71
|
-
defaultOptions: {
|
|
72
|
-
queries: {
|
|
73
|
-
retry: false,
|
|
74
|
-
},
|
|
75
|
-
},
|
|
76
|
-
})
|
|
71
|
+
const queryClient = buildTestQueryClient()
|
|
77
72
|
|
|
78
73
|
return ({ children }: { children: React.ReactNode }) => (
|
|
79
74
|
<QueryClientProvider client={queryClient}>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getNextPageParamFromMeta } from '../../hooks/paginator_meta'
|
|
2
|
+
|
|
3
|
+
describe('getNextPageParamFromMeta', () => {
|
|
4
|
+
it.each([
|
|
5
|
+
[undefined, undefined],
|
|
6
|
+
[{}, undefined],
|
|
7
|
+
[{ idLt: '01ABC' }, { where: { id_lt: '01ABC' } }],
|
|
8
|
+
[{ idLte: '01ABC' }, { where: { id_lte: '01ABC' } }],
|
|
9
|
+
[{ idGt: '01ABC' }, { where: { id_gt: '01ABC' } }],
|
|
10
|
+
[{ idGte: '01ABC' }, { where: { id_gte: '01ABC' } }],
|
|
11
|
+
[{ offset: '40' }, { offset: 40 }],
|
|
12
|
+
])('maps %p to %p', (input, expected) => {
|
|
13
|
+
expect(getNextPageParamFromMeta(input)).toEqual(expected)
|
|
14
|
+
})
|
|
15
|
+
})
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
|
|
2
2
|
import { renderHook } from '@testing-library/react-native'
|
|
3
3
|
import React from 'react'
|
|
4
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
4
5
|
import { ChatProvider, CreateChatThemeProps } from '../../contexts/chat_context'
|
|
5
6
|
import { useTheme } from '../../hooks'
|
|
6
7
|
|
|
@@ -14,11 +15,10 @@ let themeProps: CreateChatThemeProps = {
|
|
|
14
15
|
let queryClient: QueryClient
|
|
15
16
|
|
|
16
17
|
beforeEach(() => {
|
|
17
|
-
queryClient =
|
|
18
|
+
queryClient = buildTestQueryClient({
|
|
18
19
|
defaultOptions: {
|
|
19
20
|
queries: {
|
|
20
|
-
|
|
21
|
-
refetchInterval: false, // Disable refetch intervals in tests
|
|
21
|
+
refetchInterval: false,
|
|
22
22
|
refetchOnWindowFocus: false,
|
|
23
23
|
refetchOnReconnect: false,
|
|
24
24
|
},
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import AsyncStorage from '@react-native-async-storage/async-storage'
|
|
2
|
-
import {
|
|
2
|
+
import { QueryClientProvider } from '@tanstack/react-query'
|
|
3
3
|
import { renderHook, act } from '@testing-library/react-hooks'
|
|
4
4
|
import React, { Suspense } from 'react'
|
|
5
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
5
6
|
import { useAsyncStorage } from '../../hooks/use_async_storage'
|
|
6
7
|
|
|
7
8
|
jest.mock('@react-native-async-storage/async-storage')
|
|
@@ -14,13 +15,7 @@ afterAll(() => {
|
|
|
14
15
|
const mockAsyncStorage = AsyncStorage as jest.Mocked<typeof AsyncStorage>
|
|
15
16
|
|
|
16
17
|
const createWrapper = () => {
|
|
17
|
-
const queryClient =
|
|
18
|
-
defaultOptions: {
|
|
19
|
-
queries: {
|
|
20
|
-
retry: false,
|
|
21
|
-
},
|
|
22
|
-
},
|
|
23
|
-
})
|
|
18
|
+
const queryClient = buildTestQueryClient()
|
|
24
19
|
|
|
25
20
|
return ({ children }: { children: React.ReactNode }) => (
|
|
26
21
|
<QueryClientProvider client={queryClient}>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QueryClientProvider } from '@tanstack/react-query'
|
|
2
2
|
import { renderHook, act } from '@testing-library/react-hooks'
|
|
3
3
|
import React from 'react'
|
|
4
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
4
5
|
import { useApiClient } from '../../hooks/use_api_client'
|
|
5
6
|
import { useAttachmentUploader } from '../../hooks/use_attachment_uploader'
|
|
6
7
|
import { useChatConfiguration } from '../../hooks/use_chat_configuration'
|
|
@@ -18,7 +19,7 @@ const mockedUseChatConfiguration = useChatConfiguration as jest.MockedFunction<
|
|
|
18
19
|
>
|
|
19
20
|
|
|
20
21
|
const createWrapper = () => {
|
|
21
|
-
const queryClient =
|
|
22
|
+
const queryClient = buildTestQueryClient()
|
|
22
23
|
return ({ children }: { children: React.ReactNode }) => (
|
|
23
24
|
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
|
|
24
25
|
)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QueryClientProvider } from '@tanstack/react-query'
|
|
2
2
|
import { renderHook, act } from '@testing-library/react-hooks'
|
|
3
3
|
import React, { Suspense } from 'react'
|
|
4
|
+
import { buildTestQueryClient } from '../../__utils__/query_client'
|
|
4
5
|
import {
|
|
5
6
|
FALLBACK_ALLOWED_FILE_EXTENSIONS,
|
|
7
|
+
FALLBACK_ALLOWED_MIME_TYPES,
|
|
6
8
|
FALLBACK_MAX_ATTACHMENTS_PER_MESSAGE,
|
|
7
9
|
FALLBACK_MAX_FILE_SIZE_IN_BYTES,
|
|
8
10
|
} from '../../hooks/attachments/fallback_chat_configuration'
|
|
@@ -10,9 +12,7 @@ import * as useApiClientModule from '../../hooks/use_api_client'
|
|
|
10
12
|
import { useChatConfiguration } from '../../hooks/use_chat_configuration'
|
|
11
13
|
|
|
12
14
|
const createWrapper = () => {
|
|
13
|
-
const queryClient =
|
|
14
|
-
defaultOptions: { queries: { retry: false } },
|
|
15
|
-
})
|
|
15
|
+
const queryClient = buildTestQueryClient()
|
|
16
16
|
|
|
17
17
|
return ({ children }: { children: React.ReactNode }) => (
|
|
18
18
|
<QueryClientProvider client={queryClient}>
|
|
@@ -47,6 +47,7 @@ describe('useChatConfiguration', () => {
|
|
|
47
47
|
type: 'ChatConfiguration',
|
|
48
48
|
id: 'current',
|
|
49
49
|
allowedFileExtensions: ['.pdf', '.jpg'],
|
|
50
|
+
allowedMimeTypes: ['application/pdf', 'image/jpeg'],
|
|
50
51
|
maxFileSizeInBytes: 1000,
|
|
51
52
|
maxAttachmentsPerMessage: 3,
|
|
52
53
|
},
|
|
@@ -60,11 +61,34 @@ describe('useChatConfiguration', () => {
|
|
|
60
61
|
|
|
61
62
|
expect(result.current).toEqual({
|
|
62
63
|
allowedFileExtensions: ['.pdf', '.jpg'],
|
|
64
|
+
allowedMimeTypes: ['application/pdf', 'image/jpeg'],
|
|
63
65
|
maxFileSizeInBytes: 1000,
|
|
64
66
|
maxAttachmentsPerMessage: 3,
|
|
65
67
|
})
|
|
66
68
|
})
|
|
67
69
|
|
|
70
|
+
it('falls back to FALLBACK_ALLOWED_MIME_TYPES when the server omits the field', async () => {
|
|
71
|
+
// During server-side rollout the field may be absent from the response.
|
|
72
|
+
mockApiClient(() =>
|
|
73
|
+
Promise.resolve({
|
|
74
|
+
data: {
|
|
75
|
+
type: 'ChatConfiguration',
|
|
76
|
+
id: 'current',
|
|
77
|
+
allowedFileExtensions: ['.pdf'],
|
|
78
|
+
maxFileSizeInBytes: 1000,
|
|
79
|
+
maxAttachmentsPerMessage: 3,
|
|
80
|
+
},
|
|
81
|
+
links: {},
|
|
82
|
+
meta: {},
|
|
83
|
+
})
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
const { result } = renderHook(() => useChatConfiguration(), { wrapper: createWrapper() })
|
|
87
|
+
await waitForQuery()
|
|
88
|
+
|
|
89
|
+
expect(result.current.allowedMimeTypes).toEqual(FALLBACK_ALLOWED_MIME_TYPES)
|
|
90
|
+
})
|
|
91
|
+
|
|
68
92
|
it('returns fallback values when the API rejects', async () => {
|
|
69
93
|
mockApiClient(() => Promise.reject(new Error('boom')))
|
|
70
94
|
|
|
@@ -73,6 +97,7 @@ describe('useChatConfiguration', () => {
|
|
|
73
97
|
|
|
74
98
|
expect(result.current).toEqual({
|
|
75
99
|
allowedFileExtensions: FALLBACK_ALLOWED_FILE_EXTENSIONS,
|
|
100
|
+
allowedMimeTypes: FALLBACK_ALLOWED_MIME_TYPES,
|
|
76
101
|
maxFileSizeInBytes: FALLBACK_MAX_FILE_SIZE_IN_BYTES,
|
|
77
102
|
maxAttachmentsPerMessage: FALLBACK_MAX_ATTACHMENTS_PER_MESSAGE,
|
|
78
103
|
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { QueryClient, QueryClientConfig } from '@tanstack/react-query'
|
|
2
|
+
import { merge } from 'lodash'
|
|
3
|
+
|
|
4
|
+
const baseConfig: QueryClientConfig = {
|
|
5
|
+
defaultOptions: {
|
|
6
|
+
queries: {
|
|
7
|
+
retry: false,
|
|
8
|
+
gcTime: 0,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const buildTestQueryClient = (overrides: QueryClientConfig = {}) =>
|
|
14
|
+
new QueryClient(merge({}, baseConfig, overrides))
|
|
@@ -3,7 +3,7 @@ import React from 'react'
|
|
|
3
3
|
import { StyleSheet, View } from 'react-native'
|
|
4
4
|
import { useTheme } from '../../../hooks'
|
|
5
5
|
import { DenormalizedMessageAttachmentResource } from '../../../types/resources/denormalized_attachment_resource'
|
|
6
|
-
import { Linking } from '../../../utils'
|
|
6
|
+
import { Linking, getAttachmentIconName } from '../../../utils'
|
|
7
7
|
import { tokens } from '../../../vendor/tapestry/tokens'
|
|
8
8
|
import { Icon } from '../../display'
|
|
9
9
|
import { AttachmentCard, AttachmentCardTitle } from './attachment_card'
|
|
@@ -75,16 +75,3 @@ const useStyles = () => {
|
|
|
75
75
|
},
|
|
76
76
|
})
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
export function getAttachmentIconName(type: string) {
|
|
80
|
-
const isImage = type.startsWith('image/')
|
|
81
|
-
const isVideo = type.startsWith('video/')
|
|
82
|
-
const isAudio = type.startsWith('audio/')
|
|
83
|
-
const isPdf = type === 'application/pdf'
|
|
84
|
-
|
|
85
|
-
if (isImage) return 'general.outlinedImageFile'
|
|
86
|
-
if (isVideo) return 'general.outlinedVideoFile'
|
|
87
|
-
if (isAudio) return 'general.outlinedMusicFile'
|
|
88
|
-
if (isPdf) return 'general.outlinedPdfFile'
|
|
89
|
-
return 'general.outlinedGenericFile'
|
|
90
|
-
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { FileAttachment } from '../../../types/resources/denormalized_attachment_resource_for_create'
|
|
3
|
+
import { FileAttachmentPreview } from '../../display'
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
status: FileAttachment['status']
|
|
7
|
+
name: string
|
|
8
|
+
contentType?: string
|
|
9
|
+
removeAttachment: () => void
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function MessageFormAttachmentFile({ name, contentType, status, removeAttachment }: Props) {
|
|
13
|
+
const loading = status === 'uploading'
|
|
14
|
+
const error = status === 'error'
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<FileAttachmentPreview
|
|
18
|
+
name={name}
|
|
19
|
+
contentType={contentType}
|
|
20
|
+
onRemovePress={removeAttachment}
|
|
21
|
+
loading={loading}
|
|
22
|
+
error={error}
|
|
23
|
+
hideRemoveButton={loading}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
@@ -11,7 +11,6 @@ interface Props {
|
|
|
11
11
|
export function MessageFormAttachmentVideo({ name, status, removeAttachment }: Props) {
|
|
12
12
|
const loading = status === 'uploading'
|
|
13
13
|
const error = status === 'error'
|
|
14
|
-
const ready = status === 'success'
|
|
15
14
|
|
|
16
15
|
return (
|
|
17
16
|
<VideoAttachmentPreview
|
|
@@ -19,7 +18,7 @@ export function MessageFormAttachmentVideo({ name, status, removeAttachment }: P
|
|
|
19
18
|
onRemovePress={removeAttachment}
|
|
20
19
|
loading={loading}
|
|
21
20
|
error={error}
|
|
22
|
-
hideRemoveButton={
|
|
21
|
+
hideRemoveButton={loading}
|
|
23
22
|
/>
|
|
24
23
|
)
|
|
25
24
|
}
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from '../../hooks'
|
|
24
24
|
import { useAttachmentUploader } from '../../hooks/use_attachment_uploader'
|
|
25
25
|
import { useBroadcastTypingStatus } from '../../hooks/use_broadcast_typing_status'
|
|
26
|
+
import { useChatConfiguration } from '../../hooks/use_chat_configuration'
|
|
26
27
|
import { useMessageCreateOrUpdate } from '../../hooks/use_message_create_or_update'
|
|
27
28
|
import { useMessageDraft } from '../../hooks/use_message_draft'
|
|
28
29
|
import { ConversationScreenProps } from '../../screens/conversation_screen'
|
|
@@ -36,6 +37,7 @@ import {
|
|
|
36
37
|
platformFontWeightMedium,
|
|
37
38
|
platformPressedOpacityStyle,
|
|
38
39
|
} from '../../utils'
|
|
40
|
+
import { pickAttachmentPreviewKind } from '../../utils/attachment_kind'
|
|
39
41
|
import {
|
|
40
42
|
DocumentPicker,
|
|
41
43
|
DocumentPickerResult,
|
|
@@ -46,6 +48,7 @@ import {
|
|
|
46
48
|
import { tokens } from '../../vendor/tapestry/tokens'
|
|
47
49
|
import { Button } from '../display/button'
|
|
48
50
|
import BannerPrimitive from '../primitive/banner_primitive'
|
|
51
|
+
import { MessageFormAttachmentFile } from './message_form/message_form_attachment_file'
|
|
49
52
|
import { MessageFormAttachmentImage } from './message_form/message_form_attachment_image'
|
|
50
53
|
import { MessageFormAttachmentVideo } from './message_form/message_form_attachment_video'
|
|
51
54
|
|
|
@@ -286,15 +289,28 @@ function MessageFormAttachments() {
|
|
|
286
289
|
contentContainerStyle={styles.messageFormAttachments}
|
|
287
290
|
>
|
|
288
291
|
{attachments.map(attachment => {
|
|
289
|
-
|
|
292
|
+
const kind = pickAttachmentPreviewKind(attachment.file.type, attachment.file.name)
|
|
293
|
+
const remove = () => attachmentUploader?.removeAttachment(attachment)
|
|
294
|
+
|
|
295
|
+
if (kind === 'video') {
|
|
290
296
|
return (
|
|
291
297
|
<MessageFormAttachmentVideo
|
|
292
298
|
key={attachment.file.uri}
|
|
293
299
|
name={attachment.file.name}
|
|
294
300
|
status={attachment.status}
|
|
295
|
-
removeAttachment={
|
|
296
|
-
|
|
297
|
-
|
|
301
|
+
removeAttachment={remove}
|
|
302
|
+
/>
|
|
303
|
+
)
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (kind === 'file') {
|
|
307
|
+
return (
|
|
308
|
+
<MessageFormAttachmentFile
|
|
309
|
+
key={attachment.file.uri}
|
|
310
|
+
name={attachment.file.name}
|
|
311
|
+
contentType={attachment.file.type}
|
|
312
|
+
status={attachment.status}
|
|
313
|
+
removeAttachment={remove}
|
|
298
314
|
/>
|
|
299
315
|
)
|
|
300
316
|
}
|
|
@@ -307,9 +323,7 @@ function MessageFormAttachments() {
|
|
|
307
323
|
status={attachment.status}
|
|
308
324
|
width={attachment.file.width}
|
|
309
325
|
height={attachment.file.height}
|
|
310
|
-
removeAttachment={
|
|
311
|
-
attachmentUploader?.removeAttachment(attachment)
|
|
312
|
-
}}
|
|
326
|
+
removeAttachment={remove}
|
|
313
327
|
/>
|
|
314
328
|
)
|
|
315
329
|
})}
|
|
@@ -503,6 +517,7 @@ function MessageFormAttachmentPicker() {
|
|
|
503
517
|
const styles = useMessageFormStyles()
|
|
504
518
|
const { usingGiphy, attachmentUploader, currentlyEditingMessage } =
|
|
505
519
|
React.useContext(MessageFormContext)
|
|
520
|
+
const { allowedMimeTypes } = useChatConfiguration()
|
|
506
521
|
const [isOpen, setIsOpen] = useState(false)
|
|
507
522
|
|
|
508
523
|
function uploadImagePickerResult(result: ImagePickerResult) {
|
|
@@ -561,7 +576,7 @@ function MessageFormAttachmentPicker() {
|
|
|
561
576
|
|
|
562
577
|
const pickFile = async () => {
|
|
563
578
|
setIsOpen(false)
|
|
564
|
-
let result = await DocumentPicker.openAsync()
|
|
579
|
+
let result = await DocumentPicker.openAsync({ mimeTypes: allowedMimeTypes })
|
|
565
580
|
if (!result.canceled) {
|
|
566
581
|
uploadDocumentPickerResult(result)
|
|
567
582
|
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { View, StyleSheet } from 'react-native'
|
|
2
|
+
import { useTheme } from '../../hooks'
|
|
3
|
+
import { platformFontWeightMedium } from '../../utils'
|
|
4
|
+
import { getAttachmentIconName } from '../../utils/attachment_kind'
|
|
5
|
+
import { tokens } from '../../vendor/tapestry/tokens'
|
|
6
|
+
import { Icon } from './icon'
|
|
7
|
+
import { IconButton } from './icon_button'
|
|
8
|
+
import { Spinner } from './spinner'
|
|
9
|
+
import { Text } from './text'
|
|
10
|
+
|
|
11
|
+
interface FileAttachmentPreviewProps {
|
|
12
|
+
name: string
|
|
13
|
+
contentType?: string
|
|
14
|
+
onRemovePress: () => void
|
|
15
|
+
loading?: boolean
|
|
16
|
+
error?: boolean
|
|
17
|
+
hideRemoveButton?: boolean
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export const FileAttachmentPreview = ({
|
|
21
|
+
name,
|
|
22
|
+
contentType,
|
|
23
|
+
onRemovePress,
|
|
24
|
+
loading = false,
|
|
25
|
+
error = false,
|
|
26
|
+
hideRemoveButton = false,
|
|
27
|
+
}: FileAttachmentPreviewProps) => {
|
|
28
|
+
const styles = useStyles({ error })
|
|
29
|
+
|
|
30
|
+
if (loading) {
|
|
31
|
+
return (
|
|
32
|
+
<View style={styles.container}>
|
|
33
|
+
<Spinner size={20} style={styles.spinner} />
|
|
34
|
+
</View>
|
|
35
|
+
)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<View style={styles.container}>
|
|
40
|
+
<View style={styles.contentContainer}>
|
|
41
|
+
<Icon name={getAttachmentIconName(contentType)} size={18} style={styles.fileIcon} />
|
|
42
|
+
<View style={styles.textContainer}>
|
|
43
|
+
<Text
|
|
44
|
+
variant="tertiary"
|
|
45
|
+
numberOfLines={1}
|
|
46
|
+
style={styles.nameText}
|
|
47
|
+
accessibilityLabel={`File attachment: ${name}`}
|
|
48
|
+
>
|
|
49
|
+
{name}
|
|
50
|
+
</Text>
|
|
51
|
+
</View>
|
|
52
|
+
</View>
|
|
53
|
+
{!hideRemoveButton && (
|
|
54
|
+
<IconButton
|
|
55
|
+
name="general.x"
|
|
56
|
+
onPress={onRemovePress}
|
|
57
|
+
size="xxs"
|
|
58
|
+
appearance="neutral"
|
|
59
|
+
style={styles.closeButton}
|
|
60
|
+
accessibilityLabel="Remove file attachment"
|
|
61
|
+
/>
|
|
62
|
+
)}
|
|
63
|
+
{error && (
|
|
64
|
+
<View style={styles.errorBadge}>
|
|
65
|
+
<Icon name="general.exclamationTriangle" size={12} style={styles.errorIcon} />
|
|
66
|
+
</View>
|
|
67
|
+
)}
|
|
68
|
+
</View>
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const useStyles = ({ error }: Partial<FileAttachmentPreviewProps>) => {
|
|
73
|
+
const { colors } = useTheme()
|
|
74
|
+
const borderRadius = 8
|
|
75
|
+
|
|
76
|
+
return StyleSheet.create({
|
|
77
|
+
container: {
|
|
78
|
+
height: 60,
|
|
79
|
+
minWidth: 150,
|
|
80
|
+
flexDirection: 'row',
|
|
81
|
+
justifyContent: 'space-between',
|
|
82
|
+
alignItems: 'center',
|
|
83
|
+
gap: 8,
|
|
84
|
+
backgroundColor: colors.fillColorNeutral070,
|
|
85
|
+
borderColor: error ? colors.statusErrorBorder : colors.borderColorDefaultBase,
|
|
86
|
+
borderWidth: error ? 2 : 1,
|
|
87
|
+
borderRadius,
|
|
88
|
+
padding: 4,
|
|
89
|
+
},
|
|
90
|
+
contentContainer: {
|
|
91
|
+
flexDirection: 'row',
|
|
92
|
+
gap: 8,
|
|
93
|
+
alignItems: 'center',
|
|
94
|
+
flexShrink: 1,
|
|
95
|
+
paddingHorizontal: 8,
|
|
96
|
+
paddingVertical: 4,
|
|
97
|
+
},
|
|
98
|
+
textContainer: {
|
|
99
|
+
flexShrink: 1,
|
|
100
|
+
flexDirection: 'column',
|
|
101
|
+
},
|
|
102
|
+
fileIcon: {
|
|
103
|
+
color: error ? colors.iconColorDefaultDisabled : colors.iconColorDefaultPrimary,
|
|
104
|
+
},
|
|
105
|
+
nameText: {
|
|
106
|
+
color: error ? colors.textColorDefaultDisabled : colors.textColorDefaultPrimary,
|
|
107
|
+
fontWeight: platformFontWeightMedium,
|
|
108
|
+
flexShrink: 1,
|
|
109
|
+
},
|
|
110
|
+
closeButton: {
|
|
111
|
+
backgroundColor: colors.fillColorNeutral050Base,
|
|
112
|
+
borderRadius: 16,
|
|
113
|
+
height: 20,
|
|
114
|
+
width: 20,
|
|
115
|
+
alignSelf: 'flex-start',
|
|
116
|
+
},
|
|
117
|
+
errorBadge: {
|
|
118
|
+
backgroundColor: colors.statusErrorBorder,
|
|
119
|
+
position: 'absolute',
|
|
120
|
+
bottom: 0,
|
|
121
|
+
right: 0,
|
|
122
|
+
zIndex: 2,
|
|
123
|
+
borderStartStartRadius: borderRadius,
|
|
124
|
+
padding: 4,
|
|
125
|
+
},
|
|
126
|
+
errorIcon: {
|
|
127
|
+
color: tokens.colorNeutral100White,
|
|
128
|
+
transform: [{ translateX: 1 }],
|
|
129
|
+
fontSize: 10,
|
|
130
|
+
},
|
|
131
|
+
spinner: {
|
|
132
|
+
marginHorizontal: 'auto',
|
|
133
|
+
},
|
|
134
|
+
})
|
|
135
|
+
}
|
|
@@ -79,6 +79,10 @@ export function Image({
|
|
|
79
79
|
onLoad?.(event)
|
|
80
80
|
}
|
|
81
81
|
|
|
82
|
+
const handleOnError = () => {
|
|
83
|
+
setIsImageLoading(false)
|
|
84
|
+
}
|
|
85
|
+
|
|
82
86
|
const isLoading = isImageLoading || loading
|
|
83
87
|
|
|
84
88
|
const ImageComponent = animatedImageStyle ? Animated.Image : ReactNativeImage
|
|
@@ -94,6 +98,7 @@ export function Image({
|
|
|
94
98
|
<ImageComponent
|
|
95
99
|
style={[styles.image, imageStyles, animatedImageStyle]}
|
|
96
100
|
onLoad={handleOnLoad}
|
|
101
|
+
onError={handleOnError}
|
|
97
102
|
source={source}
|
|
98
103
|
alt={isLoading ? '' : alt}
|
|
99
104
|
{...props}
|
|
@@ -12,6 +12,7 @@ export * from './heading'
|
|
|
12
12
|
export * from './icon_button'
|
|
13
13
|
export * from './icon'
|
|
14
14
|
export * from './image'
|
|
15
|
+
export * from './file_attachment_preview'
|
|
15
16
|
export * from './image_attachment_preview'
|
|
16
17
|
export * from './video_attachment_preview'
|
|
17
18
|
export * from './person'
|
|
@@ -56,6 +56,30 @@ export const FALLBACK_ALLOWED_FILE_EXTENSIONS = [
|
|
|
56
56
|
'.xlsx',
|
|
57
57
|
]
|
|
58
58
|
|
|
59
|
+
// Broad MIME categories covering the extensions in
|
|
60
|
+
// FALLBACK_ALLOWED_FILE_EXTENSIONS. Used to constrain native pickers up
|
|
61
|
+
// front; final accept/reject still uses the extension list because the
|
|
62
|
+
// picker's `type` filter is advisory on iOS and Android.
|
|
63
|
+
export const FALLBACK_ALLOWED_MIME_TYPES = [
|
|
64
|
+
'image/*',
|
|
65
|
+
'video/*',
|
|
66
|
+
'audio/*',
|
|
67
|
+
'application/pdf',
|
|
68
|
+
'application/msword',
|
|
69
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
|
70
|
+
'application/vnd.ms-excel',
|
|
71
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
72
|
+
'application/vnd.ms-powerpoint',
|
|
73
|
+
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
|
74
|
+
'application/vnd.apple.pages',
|
|
75
|
+
'application/vnd.apple.numbers',
|
|
76
|
+
'application/vnd.apple.keynote',
|
|
77
|
+
'application/rtf',
|
|
78
|
+
'text/plain',
|
|
79
|
+
'text/rtf',
|
|
80
|
+
'text/vcard',
|
|
81
|
+
]
|
|
82
|
+
|
|
59
83
|
export const FALLBACK_MAX_FILE_SIZE_IN_BYTES = 50 * 1024 * 1024
|
|
60
84
|
|
|
61
85
|
export const FALLBACK_MAX_ATTACHMENTS_PER_MESSAGE = 10
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NextPageCursor } from '../types/api_primitives'
|
|
2
|
+
import { RequestData } from '../utils/client'
|
|
3
|
+
|
|
4
|
+
export const getNextPageParamFromMeta = (
|
|
5
|
+
next: NextPageCursor = {}
|
|
6
|
+
): Partial<RequestData> | undefined => {
|
|
7
|
+
if (next.idLt) return { where: { id_lt: next.idLt } }
|
|
8
|
+
if (next.idGt) return { where: { id_gt: next.idGt } }
|
|
9
|
+
if (next.idLte) return { where: { id_lte: next.idLte } }
|
|
10
|
+
if (next.idGte) return { where: { id_gte: next.idGte } }
|
|
11
|
+
if (next.offset) return { offset: Number(next.offset) }
|
|
12
|
+
return undefined
|
|
13
|
+
}
|