stream-chat 9.50.3 → 10.0.0-rc.2

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.
Files changed (242) hide show
  1. package/dist/cjs/index.browser.js +19798 -14472
  2. package/dist/cjs/index.browser.js.map +4 -4
  3. package/dist/cjs/index.node.js +19817 -14482
  4. package/dist/cjs/index.node.js.map +4 -4
  5. package/dist/esm/index.mjs +19795 -14469
  6. package/dist/esm/index.mjs.map +4 -4
  7. package/dist/types/ChannelManager.d.ts +221 -0
  8. package/dist/types/EventHandlerPipeline.d.ts +104 -0
  9. package/dist/types/api-client.d.ts +26 -0
  10. package/dist/types/campaign.d.ts +0 -44
  11. package/dist/types/channel.d.ts +454 -479
  12. package/dist/types/channel_batch_updater.d.ts +0 -93
  13. package/dist/types/channel_state.d.ts +53 -201
  14. package/dist/types/client.d.ts +451 -1920
  15. package/dist/types/client_state.d.ts +4 -4
  16. package/dist/types/configuration/InstanceConfigurationService.d.ts +26 -0
  17. package/dist/types/configuration/index.d.ts +1 -0
  18. package/dist/types/configuration/types.d.ts +53 -0
  19. package/dist/types/connection.d.ts +49 -41
  20. package/dist/types/connection_fallback.d.ts +6 -4
  21. package/dist/types/constants.d.ts +0 -4
  22. package/dist/types/custom_types.d.ts +2 -0
  23. package/dist/types/entityStore/EntityStore.d.ts +111 -0
  24. package/dist/types/entityStore/StoreBackedItemIndex.d.ts +60 -0
  25. package/dist/types/entityStore/applyReactionLocally.d.ts +26 -0
  26. package/dist/types/entityStore/index.d.ts +2 -0
  27. package/dist/types/errors.d.ts +10 -2
  28. package/dist/types/gen/chat/ChannelApi.d.ts +45 -0
  29. package/dist/types/gen/chat/ChatApi.d.ts +334 -0
  30. package/dist/types/gen/model-decoders/decoders.d.ts +3 -0
  31. package/dist/types/gen/model-decoders/event-decoder-mapping.d.ts +6 -0
  32. package/dist/types/gen/models/index.d.ts +8836 -0
  33. package/dist/types/gen/moderation/ModerationApi.d.ts +50 -0
  34. package/dist/types/gen-imports.d.ts +3 -0
  35. package/dist/types/index.d.ts +8 -7
  36. package/dist/types/insights.d.ts +9 -8
  37. package/dist/types/logger.d.ts +9 -0
  38. package/dist/types/messageComposer/LocationComposer.d.ts +7 -4
  39. package/dist/types/messageComposer/attachmentIdentity.d.ts +2 -2
  40. package/dist/types/messageComposer/attachmentManager.d.ts +8 -4
  41. package/dist/types/messageComposer/configuration/types.d.ts +11 -11
  42. package/dist/types/messageComposer/linkPreviewsManager.d.ts +25 -13
  43. package/dist/types/messageComposer/messageComposer.d.ts +10 -10
  44. package/dist/types/messageComposer/middleware/messageComposer/types.d.ts +3 -3
  45. package/dist/types/messageComposer/middleware/pollComposer/types.d.ts +4 -7
  46. package/dist/types/messageComposer/middleware/textComposer/commandUtils.d.ts +3 -3
  47. package/dist/types/messageComposer/middleware/textComposer/commands.d.ts +7 -7
  48. package/dist/types/messageComposer/middleware/textComposer/mentions.d.ts +218 -4
  49. package/dist/types/messageComposer/middleware/textComposer/types.d.ts +9 -4
  50. package/dist/types/messageComposer/pollComposer.d.ts +5 -4
  51. package/dist/types/messageComposer/textComposer.d.ts +8 -3
  52. package/dist/types/messageComposer/types.d.ts +6 -28
  53. package/dist/types/messageDelivery/MessageDeliveryReporter.d.ts +40 -25
  54. package/dist/types/messageDelivery/MessageReceiptsTracker.d.ts +53 -12
  55. package/dist/types/messageOperations/MessageOperationStatePolicy.d.ts +19 -0
  56. package/dist/types/messageOperations/MessageOperations.d.ts +17 -0
  57. package/dist/types/messageOperations/index.d.ts +3 -0
  58. package/dist/types/messageOperations/types.d.ts +49 -0
  59. package/dist/types/moderation.d.ts +21 -203
  60. package/dist/types/notifications/types.d.ts +8 -7
  61. package/dist/types/offline-support/offline_support_api.d.ts +111 -87
  62. package/dist/types/offline-support/offline_sync_manager.d.ts +0 -7
  63. package/dist/types/offline-support/types.d.ts +19 -23
  64. package/dist/types/offline-support/util.d.ts +4 -2
  65. package/dist/types/pagination/FilterBuilder.d.ts +1 -1
  66. package/dist/types/pagination/ItemIndex.d.ts +25 -0
  67. package/dist/types/pagination/cursorDerivation/createdAtAroundPaginationFlags.d.ts +9 -0
  68. package/dist/types/pagination/cursorDerivation/idAroundPaginationFlags.d.ts +6 -0
  69. package/dist/types/pagination/cursorDerivation/index.d.ts +1 -0
  70. package/dist/types/pagination/cursorDerivation/linearPaginationFlags.d.ts +6 -0
  71. package/dist/types/pagination/filterCompiler.d.ts +7 -0
  72. package/dist/types/pagination/index.d.ts +1 -3
  73. package/dist/types/pagination/paginators/BasePaginator.d.ts +848 -0
  74. package/dist/types/pagination/paginators/ChannelPaginator.d.ts +212 -0
  75. package/dist/types/pagination/paginators/MessageIntervalPaginator.d.ts +282 -0
  76. package/dist/types/pagination/paginators/MessagePaginator.d.ts +208 -0
  77. package/dist/types/pagination/paginators/PinnedMessagePaginator.d.ts +39 -0
  78. package/dist/types/pagination/paginators/ReminderPaginator.d.ts +19 -0
  79. package/dist/types/pagination/paginators/UserGroupPaginator.d.ts +24 -0
  80. package/dist/types/pagination/paginators/index.d.ts +7 -0
  81. package/dist/types/pagination/paginators/stateThrottling.d.ts +2 -0
  82. package/dist/types/pagination/sortCompiler.d.ts +49 -0
  83. package/dist/types/pagination/types.normalization.d.ts +11 -0
  84. package/dist/types/pagination/utility.normalization.d.ts +18 -0
  85. package/dist/types/pagination/utility.queryChannel.d.ts +26 -0
  86. package/dist/types/pagination/utility.search.d.ts +13 -0
  87. package/dist/types/permissions.d.ts +1 -1
  88. package/dist/types/poll.d.ts +29 -32
  89. package/dist/types/poll_manager.d.ts +2 -2
  90. package/dist/types/reminders/Reminder.d.ts +2 -5
  91. package/dist/types/reminders/ReminderManager.d.ts +2 -9
  92. package/dist/types/search/MessageSearchSource.d.ts +4 -4
  93. package/dist/types/search/UserSearchSource.d.ts +1 -1
  94. package/dist/types/search/types.d.ts +3 -3
  95. package/dist/types/segment.d.ts +0 -34
  96. package/dist/types/signing.d.ts +105 -65
  97. package/dist/types/store.d.ts +1 -0
  98. package/dist/types/thread.d.ts +70 -34
  99. package/dist/types/thread_manager.d.ts +3 -3
  100. package/dist/types/token_manager.d.ts +15 -10
  101. package/dist/types/types.d.ts +197 -3404
  102. package/dist/types/utils/FixedSizeQueueCache.d.ts +12 -6
  103. package/dist/types/utils/WithSubscriptions.d.ts +2 -1
  104. package/dist/types/utils/concurrency.d.ts +4 -4
  105. package/dist/types/utils/mergeWith/mergeWith.d.ts +3 -3
  106. package/dist/types/utils/mergeWith/mergeWithCore.d.ts +8 -3
  107. package/dist/types/utils/retryable.d.ts +34 -0
  108. package/dist/types/utils/throttling/throttle.d.ts +36 -0
  109. package/dist/types/utils.d.ts +100 -194
  110. package/package.json +7 -3
  111. package/src/ChannelManager.ts +724 -0
  112. package/src/CooldownTimer.ts +2 -2
  113. package/src/EventHandlerPipeline.ts +228 -0
  114. package/src/LiveLocationManager.ts +12 -11
  115. package/src/api-client.ts +275 -0
  116. package/src/campaign.ts +1 -77
  117. package/src/channel.ts +1344 -1282
  118. package/src/channel_batch_updater.ts +1 -211
  119. package/src/channel_state.ts +144 -1013
  120. package/src/client.ts +936 -3995
  121. package/src/client_state.ts +4 -4
  122. package/src/configuration/InstanceConfigurationService.ts +73 -0
  123. package/src/configuration/index.ts +1 -0
  124. package/src/configuration/types.ts +81 -0
  125. package/src/connection.ts +145 -94
  126. package/src/connection_fallback.ts +29 -27
  127. package/src/constants.ts +1 -5
  128. package/src/custom_types.ts +4 -1
  129. package/src/entityStore/EntityStore.ts +208 -0
  130. package/src/entityStore/StoreBackedItemIndex.ts +115 -0
  131. package/src/entityStore/applyReactionLocally.ts +113 -0
  132. package/src/entityStore/index.ts +2 -0
  133. package/src/errors.ts +14 -2
  134. package/src/gen/chat/ChannelApi.ts +275 -0
  135. package/src/gen/chat/ChatApi.ts +2554 -0
  136. package/src/gen/model-decoders/decoders.ts +2680 -0
  137. package/src/gen/model-decoders/event-decoder-mapping.ts +198 -0
  138. package/src/gen/models/index.ts +12673 -0
  139. package/src/gen/moderation/ModerationApi.ts +607 -0
  140. package/src/gen-imports.ts +3 -0
  141. package/src/index.ts +11 -12
  142. package/src/insights.ts +6 -5
  143. package/src/logger.ts +28 -0
  144. package/src/messageComposer/LocationComposer.ts +9 -5
  145. package/src/messageComposer/MessageComposerEffectHandlers.ts +1 -0
  146. package/src/messageComposer/attachmentIdentity.ts +16 -9
  147. package/src/messageComposer/attachmentManager.ts +13 -8
  148. package/src/messageComposer/configuration/types.ts +11 -11
  149. package/src/messageComposer/linkPreviewsManager.ts +9 -10
  150. package/src/messageComposer/messageComposer.ts +57 -53
  151. package/src/messageComposer/middleware/messageComposer/attachments.ts +1 -2
  152. package/src/messageComposer/middleware/messageComposer/cleanData.ts +1 -1
  153. package/src/messageComposer/middleware/messageComposer/compositionValidation.ts +2 -2
  154. package/src/messageComposer/middleware/messageComposer/messageComposerState.ts +2 -2
  155. package/src/messageComposer/middleware/messageComposer/sharedLocation.ts +4 -3
  156. package/src/messageComposer/middleware/messageComposer/textComposer.ts +2 -2
  157. package/src/messageComposer/middleware/messageComposer/types.ts +3 -4
  158. package/src/messageComposer/middleware/messageComposer/userDataInjection.ts +9 -5
  159. package/src/messageComposer/middleware/pollComposer/state.ts +0 -2
  160. package/src/messageComposer/middleware/pollComposer/types.ts +4 -7
  161. package/src/messageComposer/middleware/textComposer/TextComposerMiddlewareExecutor.ts +10 -1
  162. package/src/messageComposer/middleware/textComposer/commandEffects.ts +4 -4
  163. package/src/messageComposer/middleware/textComposer/commandUtils.ts +3 -6
  164. package/src/messageComposer/middleware/textComposer/commands.ts +3 -3
  165. package/src/messageComposer/middleware/textComposer/mentionUtils.ts +1 -1
  166. package/src/messageComposer/middleware/textComposer/mentions.ts +31 -15
  167. package/src/messageComposer/middleware/textComposer/types.ts +9 -4
  168. package/src/messageComposer/pollComposer.ts +6 -8
  169. package/src/messageComposer/textComposer.ts +27 -2
  170. package/src/messageComposer/types.ts +6 -28
  171. package/src/messageDelivery/MessageDeliveryReporter.ts +101 -45
  172. package/src/messageDelivery/MessageReceiptsTracker.ts +294 -21
  173. package/src/messageOperations/MessageOperationStatePolicy.ts +77 -0
  174. package/src/messageOperations/MessageOperations.ts +212 -0
  175. package/src/messageOperations/index.ts +10 -0
  176. package/src/messageOperations/types.ts +64 -0
  177. package/src/moderation.ts +38 -431
  178. package/src/notifications/types.ts +8 -7
  179. package/src/offline-support/offline_support_api.ts +200 -133
  180. package/src/offline-support/offline_sync_manager.ts +23 -44
  181. package/src/offline-support/types.ts +23 -26
  182. package/src/offline-support/util.ts +5 -4
  183. package/src/pagination/FilterBuilder.ts +4 -1
  184. package/src/pagination/ItemIndex.ts +25 -0
  185. package/src/pagination/cursorDerivation/createdAtAroundPaginationFlags.ts +73 -0
  186. package/src/pagination/cursorDerivation/idAroundPaginationFlags.ts +53 -0
  187. package/src/pagination/cursorDerivation/index.ts +1 -0
  188. package/src/pagination/cursorDerivation/linearPaginationFlags.ts +86 -0
  189. package/src/pagination/filterCompiler.ts +196 -0
  190. package/src/pagination/index.ts +1 -3
  191. package/src/pagination/paginators/BasePaginator.ts +2859 -0
  192. package/src/pagination/paginators/ChannelPaginator.ts +729 -0
  193. package/src/pagination/paginators/MessageIntervalPaginator.ts +1116 -0
  194. package/src/pagination/paginators/MessagePaginator.ts +508 -0
  195. package/src/pagination/paginators/PinnedMessagePaginator.ts +108 -0
  196. package/src/pagination/paginators/ReminderPaginator.ts +107 -0
  197. package/src/pagination/paginators/UserGroupPaginator.ts +127 -0
  198. package/src/pagination/paginators/index.ts +7 -0
  199. package/src/pagination/paginators/stateThrottling.ts +31 -0
  200. package/src/pagination/sortCompiler.ts +193 -0
  201. package/src/pagination/types.normalization.ts +14 -0
  202. package/src/pagination/utility.normalization.ts +106 -0
  203. package/src/pagination/utility.queryChannel.ts +84 -0
  204. package/src/pagination/utility.search.ts +80 -0
  205. package/src/permissions.ts +7 -8
  206. package/src/poll.ts +101 -110
  207. package/src/poll_manager.ts +14 -8
  208. package/src/reminders/Reminder.ts +2 -5
  209. package/src/reminders/ReminderManager.ts +19 -21
  210. package/src/search/BaseSearchSource.ts +0 -3
  211. package/src/search/ChannelMemberSearchSource.ts +7 -1
  212. package/src/search/ChannelSearchSource.ts +10 -3
  213. package/src/search/MessageSearchSource.ts +29 -30
  214. package/src/search/UserSearchSource.ts +12 -8
  215. package/src/search/types.ts +3 -4
  216. package/src/segment.ts +1 -95
  217. package/src/signing.ts +107 -67
  218. package/src/store.ts +2 -1
  219. package/src/thread.ts +562 -238
  220. package/src/thread_manager.ts +37 -16
  221. package/src/token_manager.ts +21 -10
  222. package/src/types.ts +364 -4533
  223. package/src/uploadManager.ts +8 -0
  224. package/src/utils/FixedSizeQueueCache.ts +12 -6
  225. package/src/utils/WithSubscriptions.ts +2 -1
  226. package/src/utils/concurrency.ts +4 -4
  227. package/src/utils/mergeWith/mergeWith.ts +3 -3
  228. package/src/utils/mergeWith/mergeWithCore.ts +140 -164
  229. package/src/utils/mergeWith/mergeWithDiff.ts +3 -3
  230. package/src/utils/retryable.ts +117 -0
  231. package/src/utils/throttling/throttle.ts +130 -0
  232. package/src/utils.ts +208 -754
  233. package/dist/types/channel_manager.d.ts +0 -122
  234. package/dist/types/events.d.ts +0 -72
  235. package/dist/types/pagination/BasePaginator.d.ts +0 -69
  236. package/dist/types/pagination/ReminderPaginator.d.ts +0 -16
  237. package/dist/types/pagination/UserGroupPaginator.d.ts +0 -21
  238. package/src/channel_manager.ts +0 -830
  239. package/src/events.ts +0 -75
  240. package/src/pagination/BasePaginator.ts +0 -184
  241. package/src/pagination/ReminderPaginator.ts +0 -56
  242. package/src/pagination/UserGroupPaginator.ts +0 -93
@@ -0,0 +1,212 @@
1
+ import type { ItemCoordinates, PaginationQueryParams, PaginationQueryReturnValue, PaginatorOptions, PaginatorState, PostQueryReconcileParams, SetPaginatorItemsParams } from './BasePaginator';
2
+ import { BasePaginator } from './BasePaginator';
3
+ import type { FilterBuilderOptions } from '../FilterBuilder';
4
+ import { FilterBuilder } from '../FilterBuilder';
5
+ import type { StreamChat } from '../../client';
6
+ import type { Channel } from '../../channel';
7
+ import type { ChannelFilters, ChannelOptions, ChannelSort, ChannelStateOptions, ParsedPredefinedFilterResponse, QueryChannelsRequest } from '../../types';
8
+ /**
9
+ * The `queryChannels` request this paginator will send, plus the client-only `stateOptions`.
10
+ *
11
+ * Deliberately the request's own shape (`filter_conditions`, `sort`, `limit`, `predefined_filter`, …)
12
+ * rather than a `{ filters, sort, options }` wrapper: the same object goes on the wire, keys the
13
+ * offline-db cache and is compared for query-shape changes, so any field mapping in between would be a
14
+ * place for those three to drift apart. `MessageQueryShape` is likewise the request params themselves.
15
+ */
16
+ export type ChannelQueryShape = QueryChannelsRequest & {
17
+ /** Not part of the request — controls how the response is applied to client state. */
18
+ stateOptions?: ChannelStateOptions;
19
+ };
20
+ export type ChannelPaginatorState = PaginatorState<Channel>;
21
+ export type ChannelPaginatorRequestOptions = Partial<Omit<ChannelOptions, 'offset' | 'limit'>>;
22
+ export type ChannelSortComparatorFactoryParams = {
23
+ /** Sort the comparator is being built for — the effective sort, so a backend-resolved sort template. */
24
+ sort: ChannelSort;
25
+ /**
26
+ * The comparator `ChannelPaginator` would use for this sort. Delegate to it for the fields you do not
27
+ * want to handle yourself instead of reimplementing channel field resolution and the cid tiebreaker.
28
+ */
29
+ defaultComparator: (a: Channel, b: Channel) => number;
30
+ };
31
+ /**
32
+ * Produces the comparator that orders this paginator's channels. Consulted on **every** comparator
33
+ * rebuild (construction, `sort` change, backend-resolved predefined sort), so unlike assigning
34
+ * `sortComparator` directly, a factory is not overwritten by later sort changes.
35
+ */
36
+ export type ChannelSortComparatorFactory = (params: ChannelSortComparatorFactoryParams) => (a: Channel, b: Channel) => number;
37
+ export type ChannelPaginatorOptions = {
38
+ client: StreamChat;
39
+ channelStateOptions?: ChannelStateOptions;
40
+ filterBuilderOptions?: FilterBuilderOptions<ChannelFilters>;
41
+ filters?: ChannelFilters;
42
+ id?: string;
43
+ paginatorOptions?: PaginatorOptions<Channel, ChannelQueryShape>;
44
+ requestOptions?: ChannelPaginatorRequestOptions;
45
+ sort?: ChannelSort;
46
+ sortComparatorFactory?: ChannelSortComparatorFactory;
47
+ };
48
+ /**
49
+ * A paginated channel list. Filters are described along three independent axes — the names follow them:
50
+ *
51
+ * - origin: `staticFilters` are supplied at construction and fixed; `filterBuilder` generates the
52
+ * dynamic ones from its reactive context on every build. Every build merges dynamic over static.
53
+ * - authority: `staticFilters` are what this client asked for; `predefinedFilter` is what the backend
54
+ * reports it actually applied for a `predefined_filter` query. `effectiveFilters` is the winner of the
55
+ * two (and `effectiveSort` likewise for ordering).
56
+ * - purpose: `buildQueryFilters()` produces the filters sent to the server (and the offline-db query
57
+ * key), built from the local filters only; `buildMatchFilters()` produces the filters items are
58
+ * matched against locally, built from `effectiveFilters`. They are not interchangeable: sending the
59
+ * resolved filter back changes the query shape mid-pagination, and matching against the local filter
60
+ * admits channels the queried list excludes.
61
+ *
62
+ * Ordering follows the same authority rule: `sortComparator` is derived from `effectiveSort` and is
63
+ * rebuilt whenever that changes, so it must not be assigned to. Customize it through
64
+ * `sortComparatorFactory` (constructor option or setter, consulted on every rebuild) or by overriding
65
+ * `buildSortComparator` in a subclass.
66
+ */
67
+ export declare class ChannelPaginator extends BasePaginator<Channel, ChannelQueryShape> {
68
+ private readonly _id;
69
+ private client;
70
+ protected _staticFilters: ChannelFilters | undefined;
71
+ protected _sort: ChannelSort | undefined;
72
+ protected _options: ChannelPaginatorRequestOptions | undefined;
73
+ protected _channelStateOptions: ChannelStateOptions | undefined;
74
+ protected _nextQueryShape: ChannelQueryShape | undefined;
75
+ /** Backend-reported metadata of the last `predefined_filter` query (see `predefinedFilter`). */
76
+ protected _predefinedFilter: ParsedPredefinedFilterResponse | undefined;
77
+ /**
78
+ * Predefined-filter metadata from the response of the query currently in flight. Held until
79
+ * `postQueryReconcile` decides whether it should be committed (first page only).
80
+ */
81
+ private _pendingPredefinedFilter;
82
+ protected _sortComparatorFactory: ChannelSortComparatorFactory | undefined;
83
+ sortComparator: (a: Channel, b: Channel) => number;
84
+ filterBuilder: FilterBuilder<ChannelFilters>;
85
+ constructor({ channelStateOptions, client, id, filterBuilderOptions, filters, paginatorOptions, requestOptions, sort, sortComparatorFactory, }: ChannelPaginatorOptions);
86
+ /**
87
+ * Builds the comparator for the given sort — the single construction point, so every rebuild (the
88
+ * `sort` setter, a backend-resolved predefined sort) keeps the channel-specific path resolver and the
89
+ * cid tiebreaker; omitting either makes ordering fall back to raw `channel.data` lookups and become
90
+ * non-deterministic for equal sort values.
91
+ *
92
+ * `sortComparator` is derived state and is therefore reassigned on every rebuild — assigning to it
93
+ * directly does not survive a sort change or a predefined-filter response. To customize ordering,
94
+ * supply `sortComparatorFactory` (it is consulted on every rebuild and may delegate to
95
+ * `defaultComparator`), or override this method in a subclass.
96
+ */
97
+ protected buildSortComparator(sort: ChannelSort): (a: Channel, b: Channel) => number;
98
+ get id(): string;
99
+ get isOfflineSupportEnabled(): boolean;
100
+ get staticFilters(): ChannelFilters | undefined;
101
+ get sort(): ChannelSort;
102
+ /**
103
+ * What the backend reported it actually filtered and sorted by for the last first-page query —
104
+ * `QueryChannelsResponse.predefined_filter` (`name`, `filter`, and `sort` when the stored filter
105
+ * carries its own sort template). Set only for `predefined_filter` queries: the raw `filter_conditions`
106
+ * of a normal query are not echoed back.
107
+ */
108
+ get predefinedFilter(): ParsedPredefinedFilterResponse | undefined;
109
+ /**
110
+ * Filters this paginator matches items against client-side. A predefined filter resolved by the backend
111
+ * wins over the locally configured one: for such a query the local `filters` are not what the server
112
+ * applied, so matching against them would admit items the queried list excludes.
113
+ */
114
+ get effectiveFilters(): ChannelFilters | undefined;
115
+ /**
116
+ * Sort this paginator orders items by. Mirrors `effectiveFilters`: a sort template carried by a
117
+ * backend-resolved predefined filter takes precedence over the requested sort, matching backend
118
+ * precedence rules.
119
+ */
120
+ get effectiveSort(): ChannelSort;
121
+ get options(): ChannelOptions | undefined;
122
+ get channelStateOptions(): ChannelStateOptions | undefined;
123
+ set staticFilters(filters: ChannelFilters | undefined);
124
+ set sort(sort: ChannelSort | undefined);
125
+ set options(options: ChannelPaginatorRequestOptions | undefined);
126
+ set channelStateOptions(options: ChannelStateOptions | undefined);
127
+ get sortComparatorFactory(): ChannelSortComparatorFactory | undefined;
128
+ /**
129
+ * Take over channel ordering at any point in the paginator's life. The comparator is rebuilt
130
+ * immediately and the factory is consulted again on every later rebuild, so — unlike assigning
131
+ * `sortComparator` — a sort change or a backend-resolved predefined sort will not discard it. Set to
132
+ * `undefined` to go back to the built-in ordering.
133
+ */
134
+ set sortComparatorFactory(factory: ChannelSortComparatorFactory | undefined);
135
+ getItemId(item: Channel): string;
136
+ /**
137
+ * Filters sent to the server with the next query (and used as the offline-db query key). Deliberately
138
+ * built from the locally configured filters only — feeding the backend-resolved filter back in would
139
+ * change the query shape after the first response and make the following page look like a new first
140
+ * page to `hasPaginationQueryShapeChanged`.
141
+ */
142
+ buildQueryFilters: () => ChannelFilters;
143
+ /**
144
+ * Filters items are matched against locally — the `BasePaginator.buildMatchFilters` hook consumed by
145
+ * `matchesFilter`. Built from `effectiveFilters`, so a `predefined_filter` list matches what the
146
+ * backend applied rather than the local filters, which are not what produced the list.
147
+ */
148
+ buildMatchFilters: () => ChannelFilters;
149
+ matchesFilter(channel: Channel): boolean;
150
+ /**
151
+ * Commits the `predefined_filter` metadata of the response, or clears it when the response carried
152
+ * none (a plain `filter_conditions` query), so a switch away from a predefined filter cannot leave
153
+ * stale matching/ordering semantics behind.
154
+ */
155
+ protected applyPredefinedFilterResponse(predefinedFilter: ParsedPredefinedFilterResponse | undefined): void;
156
+ /**
157
+ * The response metadata describes the query as a whole, so it is (re)committed only when a first page
158
+ * lands — matching the legacy `ChannelManager`, which kept it untouched while paginating. A failed
159
+ * query (`results === null`) must not drop the metadata of the already loaded list either.
160
+ *
161
+ * Committing before `super` matters: the base implementation filters and ingests the page using
162
+ * `matchesFilter` and the comparators this metadata feeds.
163
+ */
164
+ postQueryReconcile(params: PostQueryReconcileParams<Channel, ChannelQueryShape>): import("./BasePaginator").ExecuteQueryReturnValue<Channel>;
165
+ protected getNextQueryShape(): ChannelQueryShape;
166
+ /** The query that produced the currently loaded list, i.e. the cache key its cids belong under. */
167
+ protected get loadedQueryRequest(): QueryChannelsRequest;
168
+ /**
169
+ * Writes a cid order into the offline cache under the query that produced it.
170
+ *
171
+ * `filters` and `sort` are passed separately even though `options` already contains them: the concrete
172
+ * (RN) DB implementation derives the cache row key from those two top-level arguments in
173
+ * `convertFilterSortToQuery`, while `options` carries the full request — the only place
174
+ * `predefined_filter` / `filter_values` / `sort_values` appear, without which two predefined-filter
175
+ * lists cannot be told apart. The duplication goes away once `convertFilterSortToQuery` derives the
176
+ * key from `options` (a change in that implementation plus a schema-version bump to flush stale rows).
177
+ */
178
+ protected cacheCidsForQuery({ cids, request, }: {
179
+ cids: string[];
180
+ request: QueryChannelsRequest;
181
+ }): void;
182
+ /**
183
+ * Persists the current cid order under the query that produced it. Called after every mutation of the
184
+ * loaded list — including live WS-driven inserts/removals, which reorder the list without any query
185
+ * running; skipping those would leave the cached order stale until the next full re-query.
186
+ */
187
+ protected persistLoadedCids(): void;
188
+ preloadFirstPageFromOfflineDb: ({ queryShape, }: PaginationQueryParams<ChannelQueryShape>) => Promise<Channel[] | undefined>;
189
+ populateOfflineDbAfterQuery: ({ items, queryShape, }: {
190
+ items?: Channel[];
191
+ queryShape?: ChannelQueryShape;
192
+ }) => undefined;
193
+ /**
194
+ * Postpones a first-page query while the offline sync is still in progress: the cached page is
195
+ * surfaced right away and the network query is handed to the sync manager, which re-runs it once
196
+ * reconciliation finished — querying (and persisting cids) against unsynced local state would race
197
+ * with the replay of pending local mutations. Mirrors `ChannelManager.queryChannels`, which deferred
198
+ * on every unsynced call and read the cache only when it had nothing loaded yet.
199
+ *
200
+ * Only first-page queries defer; paginating an already loaded list is unaffected (as was the legacy
201
+ * `loadNext`).
202
+ */
203
+ executeQuery(params?: PaginationQueryParams<ChannelQueryShape>): Promise<void | import("./BasePaginator").ExecuteQueryReturnValue<Channel>>;
204
+ query: () => Promise<PaginationQueryReturnValue<Channel>>;
205
+ filterQueryResults: (items: Channel[]) => Channel[];
206
+ setItems(params: SetPaginatorItemsParams<Channel>): void;
207
+ ingestItem(channel: Channel): boolean;
208
+ removeItem(params: {
209
+ id?: string;
210
+ item?: Channel;
211
+ }): ItemCoordinates;
212
+ }
@@ -0,0 +1,282 @@
1
+ import type { PaginationDirection, PaginationQueryParams, PaginatorState } from './BasePaginator';
2
+ import { BasePaginator, type PaginationQueryReturnValue, type PaginatorOptions } from './BasePaginator';
3
+ import type { LocalMessage, MessagePaginationOptions, MessageResponse, PinnedMessagePaginationOptions, ReactionResponse, SortParamRequest, UserResponse } from '../../types';
4
+ import type { Channel } from '../../channel';
5
+ import { StateStore } from '../../store';
6
+ import type { ItemIndexApi } from '../ItemIndex';
7
+ import type { EntityStoreChangeBatch } from '../../entityStore/EntityStore';
8
+ export type MessageFocusReason = 'jump-to-message' | 'jump-to-first-unread' | 'jump-to-latest';
9
+ export type MessageFocusSignal = {
10
+ messageId: string;
11
+ reason: MessageFocusReason;
12
+ token: number;
13
+ createdAt: number;
14
+ ttlMs: number;
15
+ };
16
+ export type MessageFocusSignalState = {
17
+ signal: MessageFocusSignal | null;
18
+ };
19
+ export type JumpToMessageOptions = {
20
+ pageSize?: number;
21
+ /**
22
+ * Optional reason attached to emitted focus signal.
23
+ * Defaults to `jump-to-message`.
24
+ */
25
+ focusReason?: MessageFocusReason;
26
+ /**
27
+ * TTL for the emitted focus signal in milliseconds.
28
+ * Defaults to `3000`.
29
+ */
30
+ focusSignalTtlMs?: number;
31
+ /**
32
+ * If true, suppresses focus signal emission after a successful jump.
33
+ */
34
+ suppressFocusSignal?: boolean;
35
+ };
36
+ export type MessagePaginatorSort = SortParamRequest[];
37
+ export type MessagePaginatorFilter = {
38
+ cid: string;
39
+ parent_id?: string;
40
+ };
41
+ export type MessagePaginatorState = PaginatorState<LocalMessage>;
42
+ export type MessageQueryShape = MessagePaginationOptions | PinnedMessagePaginationOptions;
43
+ export declare const getMessageCreatedAtTimestamp: (message: LocalMessage) => number | null;
44
+ export type MessagePaginatorOptions = {
45
+ channel: Channel;
46
+ id?: string;
47
+ itemIndex?: ItemIndexApi<LocalMessage>;
48
+ parentMessageId?: string;
49
+ /**
50
+ * Sort passed to backend message/replies query.
51
+ * Does not affect in-memory item ordering.
52
+ */
53
+ requestSort?: MessagePaginatorSort;
54
+ /**
55
+ * @deprecated Use `requestSort` instead.
56
+ */
57
+ sort?: MessagePaginatorSort;
58
+ /**
59
+ * In-memory ordering for items exposed by paginator state.
60
+ */
61
+ itemOrder?: MessagePaginatorSort;
62
+ paginatorOptions?: PaginatorOptions<LocalMessage, MessageQueryShape>;
63
+ };
64
+ /**
65
+ * MessageIntervalPaginator allows configuring backend request sort, while keeping internal item ordering stable.
66
+ * Filtering of ingested items is still limited to local predicates (`filterQueryResults`).
67
+ */
68
+ export declare class MessageIntervalPaginator extends BasePaginator<LocalMessage, MessageQueryShape> {
69
+ state: StateStore<MessagePaginatorState>;
70
+ private readonly _id;
71
+ protected channel: Channel;
72
+ protected parentMessageId?: string;
73
+ readonly messageFocusSignal: StateStore<MessageFocusSignalState>;
74
+ private clearMessageFocusSignalTimeoutId;
75
+ private messageFocusSignalToken;
76
+ protected _requestSort: MessagePaginatorSort;
77
+ protected _itemOrder: MessagePaginatorSort;
78
+ protected _nextQueryShape: MessageQueryShape | undefined;
79
+ sortComparator: (a: LocalMessage, b: LocalMessage) => number;
80
+ /**
81
+ * Single source of truth for whether a message should be included in paginator intervals/state.
82
+ * Keep this consistent with `filterQueryResults` AND cursor flag derivation.
83
+ */
84
+ shouldIncludeMessageInInterval(message: LocalMessage): boolean;
85
+ /**
86
+ * Entity-store adapter (this paginator is an `EntityStoreSubscriber`): the `EntityStore` calls this
87
+ * on each holder with the subset of its watched ids that changed. Unwraps the batch and delegates to
88
+ * the base's store-agnostic {@link BasePaginator.reconcileChangedIds}. Lives here, not on the generic
89
+ * `BasePaginator`, so the base stays free of `EntityStore` types — only message paginators are
90
+ * store-backed.
91
+ */
92
+ onEntitiesChanged({ changedIds }: EntityStoreChangeBatch): void;
93
+ /**
94
+ * Entity-store subscriber flush (the optional `EntityStoreSubscriber.flushState`): the `EntityStore`
95
+ * calls this after an optimistic (local-user) write so the change renders without throttle delay.
96
+ * Delegates to the base's generic {@link BasePaginator.flushPendingPublishes}.
97
+ */
98
+ flushState(): void;
99
+ protected get intervalItemIdsAreHeadFirst(): boolean;
100
+ protected get intervalSortDirection(): 'asc' | 'desc';
101
+ constructor({ channel, id, itemIndex, parentMessageId, requestSort, sort, itemOrder, paginatorOptions, }: MessagePaginatorOptions);
102
+ get id(): string;
103
+ get sort(): MessagePaginatorSort;
104
+ get requestSort(): MessagePaginatorSort;
105
+ get itemOrder(): MessagePaginatorSort;
106
+ /**
107
+ * Even though we do not send filters object to the server, we need to have filters for client-side item ingestion logic.
108
+ */
109
+ buildMatchFilters: () => MessagePaginatorFilter;
110
+ protected getNextQueryShape({ direction, }: Omit<PaginationQueryParams<MessageQueryShape>, 'isFirstPageQuery'>): MessageQueryShape;
111
+ getCursorFromQueryResults: ({ direction, items, }: {
112
+ direction?: PaginationDirection;
113
+ items: LocalMessage[];
114
+ }) => {
115
+ tailward: string | undefined;
116
+ headward: string | undefined;
117
+ };
118
+ query: ({ direction, }: PaginationQueryParams<MessageQueryShape>) => Promise<PaginationQueryReturnValue<LocalMessage>>;
119
+ /**
120
+ * Seed the paginator with the page a channel-open query just fetched (`Channel.query` for
121
+ * `watch`/`create`, and `client.hydrateActiveChannels`).
122
+ *
123
+ * These paths hydrate the channel read state in the SAME synchronous tick they add messages
124
+ * (`Channel._initializeState`), and the read patch drives `MessageReceiptsTracker`, which resolves
125
+ * read/delivered cursors against this paginator (`findItemByTimestamp`) whenever the server omits
126
+ * the `last_read_message_id` / `last_delivered_message_id`. `postQueryReconcile` is fully
127
+ * synchronous (filtering is a local predicate), so seeding here guarantees the paginator is
128
+ * populated before the reconcile runs. First-page reconciliation also takes the unread snapshot.
129
+ *
130
+ * The fetched page is NOT always the latest window: a channel can be opened AROUND a message
131
+ * (`messages: { id_around }` / `{ created_at_around }`), so the original pagination options are
132
+ * threaded through as the query shape. For an around/jump open this lets `postQueryReconcile`
133
+ * apply jump semantics (no forced head/tail; cursor flags derived from the around position)
134
+ * instead of wrongly flagging the window as the head (newest) page.
135
+ */
136
+ seedFirstPageSync(messages: LocalMessage[], requestedPageSize: number, messagePaginationOptions?: MessagePaginationOptions): void;
137
+ isJumpQueryShape(queryShape: MessageQueryShape): boolean;
138
+ jumpToMessage: (messageId: string, { focusReason, focusSignalTtlMs, pageSize, suppressFocusSignal, }?: JumpToMessageOptions) => Promise<boolean>;
139
+ jumpToTheLatestMessage: (options?: JumpToMessageOptions) => Promise<boolean>;
140
+ /**
141
+ * Fold an already fetched newest (head) page into the currently loaded items without issuing a
142
+ * query. The caller supplies a page it obtained on its own and this reconciles it against what is
143
+ * loaded, instead of rerunning the first page query, so the loaded set is updated in place rather
144
+ * than blanked and reloaded. Two cases, decided by whether the incoming page overlaps the loaded
145
+ * head:
146
+ *
147
+ * 1. OVERLAP - the incoming page shares at least one id with the loaded head (fewer than a full
148
+ * page is new). Merge in place: existing items are reconciled by id (edits, soft deletes), new
149
+ * items are appended and every already loaded item (including older pages already paged in) is
150
+ * kept. `hasMoreTail`/`cursor.tailward` are left as-is so the page can be any size, so deriving
151
+ * "has older items" from its length would wrongly clear it while older items remain.
152
+ *
153
+ * 2. DISJOINT - the incoming page shares no id with the loaded head (at least a full page is new).
154
+ * Merging would weld the two across the gap (the interval merge treats two head intervals as
155
+ * overlapping when one reaches further headward), hiding the items in between with no way to
156
+ * reach them. Instead the loaded set is discarded and rebuilt from the incoming page as a fresh
157
+ * contiguous head (`hasMoreTail: true`, cursor reanchored to the page's oldest item) so the
158
+ * gap and older history load again when paginating older.
159
+ *
160
+ * Both paths emit exactly once and never blank the loaded set. Noop unless the page is non empty
161
+ * and the newest slice is both loaded AND the interval currently in view (the head interval is
162
+ * anchored at the head and active); when the caller has jumped to a separate older window the
163
+ * merge is skipped so their position is preserved, and the incoming page is picked up on a later
164
+ * load.
165
+ */
166
+ mergeNewestPage: (page: LocalMessage[]) => void;
167
+ protected resolveUnreadBoundaryIdsByTimestamp: ({ lastReadAt, messages, }: {
168
+ lastReadAt: Date;
169
+ messages: LocalMessage[];
170
+ }) => {
171
+ firstUnreadMessageId: string | null;
172
+ lastReadMessageId: string | null;
173
+ };
174
+ emitMessageFocusSignal: ({ messageId, reason, ttlMs, }: {
175
+ messageId: string;
176
+ reason: MessageFocusReason;
177
+ ttlMs?: number;
178
+ }) => MessageFocusSignal;
179
+ /**
180
+ * Starts the auto-dismissal countdown for the currently active focus signal. Call this once the
181
+ * focused message has been viewed (rendered and visible), so the highlight's lifetime is measured
182
+ * from when the user could actually see it rather than from when the jump resolved. No-op if the
183
+ * signal has already been cleared or superseded (guarded by `token`).
184
+ */
185
+ scheduleMessageFocusSignalClear: ({ token, ttlMs, }?: {
186
+ token?: number;
187
+ ttlMs?: number;
188
+ }) => void;
189
+ clearMessageFocusSignal: ({ token }?: {
190
+ token?: number;
191
+ }) => void;
192
+ clearStateAndCache(): void;
193
+ /**
194
+ * Partial truncation for `channel.truncated` carrying a `truncated_at`: drop every loaded
195
+ * message strictly older than the cutoff (keeping newer ones) across all loaded windows,
196
+ * mirroring the legacy per-message-set pruning. For a full truncation (no `truncated_at`) use
197
+ * {@link MessageIntervalPaginator.clearStateAndCache} instead.
198
+ *
199
+ * Batched and edge-classified: because messages are chronological, each interval is classified by
200
+ * its `tail` (oldest) and `head` (newest) edges, so only the single interval that *straddles* the
201
+ * cutoff is scanned member-by-member — the rest are kept or dropped wholesale. The straddling
202
+ * interval becomes the new global tail (nothing older than the cutoff exists anymore), so its
203
+ * `isTail`/`hasMoreTail` are set; intervals entirely newer keep their flags (unloaded older
204
+ * messages may still sit between them and the cutoff). The active window is re-emitted once.
205
+ */
206
+ truncate: ({ truncatedAt }: {
207
+ truncatedAt: Date;
208
+ }) => void;
209
+ applyMessageDeletionForUser: ({ userId, hardDelete, deletedAt, }: {
210
+ userId: string;
211
+ hardDelete?: boolean;
212
+ deletedAt: Date;
213
+ }) => void;
214
+ /**
215
+ * Ensures quoted-message snapshots across loaded paginator cache are in sync
216
+ * with the provided message.
217
+ *
218
+ * Scans cached messages and updates any item where `quoted_message_id`
219
+ * matches `message.id`.
220
+ */
221
+ reflectQuotedMessageUpdate: (message: LocalMessage) => void;
222
+ /**
223
+ * Reflect an updated `user` object onto every cached message authored by that user, mirroring
224
+ * the legacy `ChannelState.updateUserMessages` for the main message list (does not touch
225
+ * `quoted_message.user` — that is not part of the legacy behavior).
226
+ *
227
+ * Batched: a user rename can affect many messages, so this patches the shared item index and
228
+ * re-emits the active window a single time (if it held an affected message) rather than one
229
+ * `ingestItem` re-emit per message.
230
+ */
231
+ reflectUserUpdate: (user: UserResponse) => void;
232
+ /**
233
+ * Apply a reaction WS event (`reaction.new` / `reaction.updated` / `reaction.deleted`) to the
234
+ * cached message. The event's `message` already carries the server-updated
235
+ * `reaction_groups` / `latest_reactions`; only `own_reactions` needs local preservation so a
236
+ * cross-user reaction does not wipe the current user's reactions. This re-homes what
237
+ * `ChannelState.addReaction` / `removeReaction` used to do off the now-removed
238
+ * `channel.state.messages` / `channel.state.threads` caches (the same logic backs the thread
239
+ * paginator via `Thread.messagePaginator`).
240
+ *
241
+ * `own_reactions` is seeded from the currently cached item (so another user's reaction keeps ours),
242
+ * falling back to the event's own_reactions when the message is not loaded — matching the legacy
243
+ * behavior where `_updateMessage` only mutated a message that existed locally.
244
+ *
245
+ * @param params - The reaction event payload.
246
+ * @param params.message - The reaction event's message, carrying the
247
+ * server-computed `reaction_groups` / `latest_reactions`. Ingested as-is except for `own_reactions`.
248
+ * @param params.reaction - The reaction from the event. Only added to/removed from
249
+ * `own_reactions` when its `user_id` is the current user; otherwise the current user's
250
+ * `own_reactions` are left untouched.
251
+ * @param [params.removed=false] - `true` for `reaction.deleted` (remove the reaction from
252
+ * `own_reactions`); `false` for `reaction.new` / `reaction.updated` (add it).
253
+ * @param [params.enforceUnique=false] - When adding, first clear the current user's existing
254
+ * `own_reactions` so only the incoming one remains (used by `reaction.updated`, where a user's
255
+ * reaction replaces their previous one).
256
+ *
257
+ * TODO(reactive-store): reflect reactions ONCE at the store level, not per-paginator. Both the
258
+ * channel handler (channel.ts) and the thread handler (thread.ts) call this on every reaction.*
259
+ * event, so a message held in more than one collection (a show_in_channel reply, or the thread
260
+ * parent) is reflected TWICE: two writes to the same canonical slot, each fanning out to the
261
+ * other holder (double re-projection) and minting a fresh ref that defeats the reconcile
262
+ * ref-equality bail. Idempotent (counts come wholesale from the event) so the result is correct,
263
+ * just wasteful. The store already fans out to every holder, so reflect once (by id, if held) and
264
+ * retire the per-collection reflect calls + parent path + enforce_unique branch.
265
+ */
266
+ reflectReaction: ({ enforceUnique, message, reaction, removed, }: {
267
+ message: MessageResponse | LocalMessage;
268
+ reaction: ReactionResponse;
269
+ enforceUnique?: boolean;
270
+ removed?: boolean;
271
+ }) => void;
272
+ /**
273
+ * Map a timestamp to a loaded message — the first message in the latest (head) window whose
274
+ * `created_at` is >= `timestampMs` (mirrors the legacy `ChannelState.findMessageByTimestamp`
275
+ * lower-bound search), or the newest loaded message when the timestamp is beyond it. Used by the
276
+ * receipts tracker to resolve read/delivered cursors. Searches the newest loaded window — where
277
+ * read cursors live — which is already sorted, so this is O(log n) with no re-sort.
278
+ */
279
+ findItemByTimestamp: (timestampMs: number, exactTsMatch?: boolean) => LocalMessage | null;
280
+ filterQueryResults: (items: LocalMessage[]) => LocalMessage[];
281
+ private getCanonicalQueryItems;
282
+ }