@ethora/chat-component-rn 26.5.16 → 26.5.17
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/components/MainComponents/ReduxWrapper.js +4 -0
- package/lib/commonjs/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/commonjs/context/xmppProvider.js +4 -0
- package/lib/commonjs/context/xmppProvider.js.map +1 -1
- package/lib/commonjs/helpers/historyPreloadScheduler.js +118 -113
- package/lib/commonjs/helpers/historyPreloadScheduler.js.map +1 -1
- package/lib/commonjs/hooks/useChatFonts.js +137 -0
- package/lib/commonjs/hooks/useChatFonts.js.map +1 -0
- package/lib/commonjs/hooks/useUnreadMessagesCounter.js +4 -2
- package/lib/commonjs/hooks/useUnreadMessagesCounter.js.map +1 -1
- package/lib/commonjs/main.js +7 -0
- package/lib/commonjs/main.js.map +1 -1
- package/lib/commonjs/roomStore/roomsSlice.js +9 -1
- package/lib/commonjs/roomStore/roomsSlice.js.map +1 -1
- package/lib/module/components/MainComponents/ReduxWrapper.js +4 -0
- package/lib/module/components/MainComponents/ReduxWrapper.js.map +1 -1
- package/lib/module/context/xmppProvider.js +5 -1
- package/lib/module/context/xmppProvider.js.map +1 -1
- package/lib/module/helpers/historyPreloadScheduler.js +119 -114
- package/lib/module/helpers/historyPreloadScheduler.js.map +1 -1
- package/lib/module/hooks/useChatFonts.js +132 -0
- package/lib/module/hooks/useChatFonts.js.map +1 -0
- package/lib/module/hooks/useUnreadMessagesCounter.js +4 -2
- package/lib/module/hooks/useUnreadMessagesCounter.js.map +1 -1
- package/lib/module/main.js +2 -0
- package/lib/module/main.js.map +1 -1
- package/lib/module/roomStore/roomsSlice.js +7 -0
- package/lib/module/roomStore/roomsSlice.js.map +1 -1
- package/lib/typescript/components/MainComponents/ReduxWrapper.d.ts.map +1 -1
- package/lib/typescript/context/xmppProvider.d.ts.map +1 -1
- package/lib/typescript/helpers/historyPreloadScheduler.d.ts.map +1 -1
- package/lib/typescript/hooks/useChatFonts.d.ts +23 -0
- package/lib/typescript/hooks/useChatFonts.d.ts.map +1 -0
- package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts +1 -0
- package/lib/typescript/hooks/useUnreadMessagesCounter.d.ts.map +1 -1
- package/lib/typescript/main.d.ts +2 -1
- package/lib/typescript/main.d.ts.map +1 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts +3 -1
- package/lib/typescript/roomStore/roomsSlice.d.ts.map +1 -1
- package/lib/typescript/types/types.d.ts +39 -0
- package/lib/typescript/types/types.d.ts.map +1 -1
- package/package.json +5 -1
- package/src/components/MainComponents/ReduxWrapper.tsx +4 -0
- package/src/context/xmppProvider.tsx +5 -0
- package/src/helpers/historyPreloadScheduler.ts +7 -1
- package/src/hooks/useChatFonts.ts +153 -0
- package/src/hooks/useUnreadMessagesCounter.ts +5 -2
- package/src/main.ts +4 -0
- package/src/roomStore/roomsSlice.ts +11 -0
- package/src/types/types.ts +41 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { AppState } from 'react-native';
|
|
4
4
|
import { store } from '../roomStore';
|
|
5
|
-
import { applyRoomsPreloadBatch } from '../roomStore/roomsSlice';
|
|
5
|
+
import { applyRoomsPreloadBatch, setUnreadSyncing } from '../roomStore/roomsSlice';
|
|
6
6
|
const DEFAULT_CONCURRENCY = 3;
|
|
7
7
|
// Fetch the most recent ~20 on re-entry (mirrors web). A larger first page
|
|
8
8
|
// also means more id-overlap with cache, so the merge in
|
|
@@ -94,132 +94,137 @@ export const runHistoryPreloadScheduler = async options => {
|
|
|
94
94
|
if (signal?.aborted) {
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const readyItems = queue.filter(item => item.readyAt <= now && !inFlightByRoom.has(item.jid));
|
|
132
|
-
if (readyItems.length === 0) {
|
|
133
|
-
await sleep(60);
|
|
134
|
-
continue;
|
|
135
|
-
}
|
|
136
|
-
const batch = readyItems.slice(0, Math.max(1, concurrency));
|
|
137
|
-
|
|
138
|
-
// Snapshot each room's historyPreloadState BEFORE marking the
|
|
139
|
-
// batch as 'loading'. Without this snapshot the per-task
|
|
140
|
-
// `currentRoom.historyPreloadState === 'done'` skip check below
|
|
141
|
-
// is dead — the dispatch immediately overwrites 'done' with
|
|
142
|
-
// 'loading', so the task never sees the original value and
|
|
143
|
-
// always re-fetches.
|
|
144
|
-
const preBatchPreloadStateByJid = new Map(batch.map(item => [item.jid, store.getState().rooms.rooms[item.jid]?.historyPreloadState]));
|
|
145
|
-
store.dispatch(applyRoomsPreloadBatch({
|
|
146
|
-
rooms: batch.map(item => ({
|
|
147
|
-
jid: item.jid,
|
|
148
|
-
historyPreloadState: 'loading'
|
|
149
|
-
}))
|
|
150
|
-
}));
|
|
151
|
-
await Promise.all(batch.map(async item => {
|
|
152
|
-
const queueIndex = queue.findIndex(queued => queued.jid === item.jid);
|
|
153
|
-
if (queueIndex !== -1) {
|
|
154
|
-
queue.splice(queueIndex, 1);
|
|
97
|
+
store.dispatch(setUnreadSyncing(true));
|
|
98
|
+
try {
|
|
99
|
+
const state = store.getState();
|
|
100
|
+
const rooms = state.rooms.rooms || {};
|
|
101
|
+
const defaultSet = new Set(defaultRoomJids);
|
|
102
|
+
const sortedQueue = Object.entries(rooms).map(([jid, room]) => ({
|
|
103
|
+
jid,
|
|
104
|
+
priority: getRoomPriority(jid, room, selectedRoomJid, defaultSet),
|
|
105
|
+
activityScore: getRoomLastActivityScore(room),
|
|
106
|
+
attempts: 0,
|
|
107
|
+
readyAt: Date.now()
|
|
108
|
+
})).sort((a, b) => {
|
|
109
|
+
if (a.priority !== b.priority) {
|
|
110
|
+
return a.priority - b.priority;
|
|
111
|
+
}
|
|
112
|
+
if (a.activityScore !== b.activityScore) {
|
|
113
|
+
return b.activityScore - a.activityScore;
|
|
114
|
+
}
|
|
115
|
+
return a.jid.localeCompare(b.jid);
|
|
116
|
+
});
|
|
117
|
+
const queue = roomLimit && roomLimit > 0 ? sortedQueue.slice(0, roomLimit) : sortedQueue;
|
|
118
|
+
const inFlightByRoom = new Map();
|
|
119
|
+
let consecutiveErrorCount = 0;
|
|
120
|
+
while (queue.length > 0) {
|
|
121
|
+
if (signal?.aborted) {
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
if (!client.isActiveRoomGateOpen()) {
|
|
125
|
+
await sleep(80);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (shouldPauseForVisibility()) {
|
|
129
|
+
await sleep(250);
|
|
130
|
+
continue;
|
|
155
131
|
}
|
|
156
|
-
const
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
132
|
+
const now = Date.now();
|
|
133
|
+
const readyItems = queue.filter(item => item.readyAt <= now && !inFlightByRoom.has(item.jid));
|
|
134
|
+
if (readyItems.length === 0) {
|
|
135
|
+
await sleep(60);
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const batch = readyItems.slice(0, Math.max(1, concurrency));
|
|
139
|
+
|
|
140
|
+
// Snapshot each room's historyPreloadState BEFORE marking the
|
|
141
|
+
// batch as 'loading'. Without this snapshot the per-task
|
|
142
|
+
// `currentRoom.historyPreloadState === 'done'` skip check below
|
|
143
|
+
// is dead — the dispatch immediately overwrites 'done' with
|
|
144
|
+
// 'loading', so the task never sees the original value and
|
|
145
|
+
// always re-fetches.
|
|
146
|
+
const preBatchPreloadStateByJid = new Map(batch.map(item => [item.jid, store.getState().rooms.rooms[item.jid]?.historyPreloadState]));
|
|
147
|
+
store.dispatch(applyRoomsPreloadBatch({
|
|
148
|
+
rooms: batch.map(item => ({
|
|
149
|
+
jid: item.jid,
|
|
150
|
+
historyPreloadState: 'loading'
|
|
151
|
+
}))
|
|
152
|
+
}));
|
|
153
|
+
await Promise.all(batch.map(async item => {
|
|
154
|
+
const queueIndex = queue.findIndex(queued => queued.jid === item.jid);
|
|
155
|
+
if (queueIndex !== -1) {
|
|
156
|
+
queue.splice(queueIndex, 1);
|
|
167
157
|
}
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
158
|
+
const task = (async () => {
|
|
159
|
+
const currentRoom = store.getState().rooms.rooms[item.jid];
|
|
160
|
+
const preState = preBatchPreloadStateByJid.get(item.jid);
|
|
161
|
+
if (!currentRoom || !forceReload && preState === 'done') {
|
|
162
|
+
store.dispatch(applyRoomsPreloadBatch({
|
|
163
|
+
rooms: [{
|
|
164
|
+
jid: item.jid,
|
|
165
|
+
historyPreloadState: 'done'
|
|
166
|
+
}]
|
|
167
|
+
}));
|
|
175
168
|
return;
|
|
176
169
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
store.dispatch(applyRoomsPreloadBatch({
|
|
183
|
-
rooms: [{
|
|
184
|
-
jid: item.jid,
|
|
185
|
-
messages: fetchedMessages || [],
|
|
186
|
-
unreadCapped,
|
|
187
|
-
historyPreloadState: 'done'
|
|
188
|
-
}]
|
|
189
|
-
}));
|
|
190
|
-
consecutiveErrorCount = 0;
|
|
191
|
-
} catch {
|
|
192
|
-
const retries = item.attempts + 1;
|
|
193
|
-
const canRetry = retries <= retryLimit;
|
|
194
|
-
if (canRetry) {
|
|
195
|
-
const jitter = Math.floor(Math.random() * 120);
|
|
196
|
-
const backoff = Math.min(1600, 240 * 2 ** item.attempts) + jitter;
|
|
197
|
-
queue.push({
|
|
198
|
-
...item,
|
|
199
|
-
attempts: retries,
|
|
200
|
-
readyAt: Date.now() + backoff
|
|
170
|
+
try {
|
|
171
|
+
const fetchedMessages = await client.getHistoryStanza(item.jid, pageSize, undefined, undefined, {
|
|
172
|
+
coalesceRoom: true,
|
|
173
|
+
skipIfPreloaded: !forceReload,
|
|
174
|
+
source: 'background'
|
|
201
175
|
});
|
|
202
|
-
|
|
176
|
+
if (signal?.aborted) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
if (typeof fetchedMessages === 'undefined') {
|
|
180
|
+
throw new Error('history_timeout');
|
|
181
|
+
}
|
|
182
|
+
const nextRoom = store.getState().rooms.rooms[item.jid];
|
|
183
|
+
const unreadCapped = computeUnreadCapped(nextRoom, fetchedMessages || [], pageSize);
|
|
203
184
|
store.dispatch(applyRoomsPreloadBatch({
|
|
204
185
|
rooms: [{
|
|
205
186
|
jid: item.jid,
|
|
206
|
-
|
|
187
|
+
messages: fetchedMessages || [],
|
|
188
|
+
unreadCapped,
|
|
189
|
+
historyPreloadState: 'done'
|
|
207
190
|
}]
|
|
208
191
|
}));
|
|
209
|
-
}
|
|
210
|
-
consecutiveErrorCount += 1;
|
|
211
|
-
if (consecutiveErrorCount >= 3) {
|
|
212
|
-
await sleep(300);
|
|
213
192
|
consecutiveErrorCount = 0;
|
|
193
|
+
} catch {
|
|
194
|
+
const retries = item.attempts + 1;
|
|
195
|
+
const canRetry = retries <= retryLimit;
|
|
196
|
+
if (canRetry) {
|
|
197
|
+
const jitter = Math.floor(Math.random() * 120);
|
|
198
|
+
const backoff = Math.min(1600, 240 * 2 ** item.attempts) + jitter;
|
|
199
|
+
queue.push({
|
|
200
|
+
...item,
|
|
201
|
+
attempts: retries,
|
|
202
|
+
readyAt: Date.now() + backoff
|
|
203
|
+
});
|
|
204
|
+
} else {
|
|
205
|
+
store.dispatch(applyRoomsPreloadBatch({
|
|
206
|
+
rooms: [{
|
|
207
|
+
jid: item.jid,
|
|
208
|
+
historyPreloadState: 'error'
|
|
209
|
+
}]
|
|
210
|
+
}));
|
|
211
|
+
}
|
|
212
|
+
consecutiveErrorCount += 1;
|
|
213
|
+
if (consecutiveErrorCount >= 3) {
|
|
214
|
+
await sleep(300);
|
|
215
|
+
consecutiveErrorCount = 0;
|
|
216
|
+
}
|
|
214
217
|
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
}));
|
|
218
|
+
})();
|
|
219
|
+
inFlightByRoom.set(item.jid, task);
|
|
220
|
+
await task.finally(() => inFlightByRoom.delete(item.jid));
|
|
221
|
+
}));
|
|
220
222
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
+
// Yield to JS event loop (no requestIdleCallback in RN).
|
|
224
|
+
await new Promise(r => setTimeout(r, 0));
|
|
225
|
+
}
|
|
226
|
+
} finally {
|
|
227
|
+
store.dispatch(setUnreadSyncing(false));
|
|
223
228
|
}
|
|
224
229
|
};
|
|
225
230
|
export default runHistoryPreloadScheduler;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["AppState","store","applyRoomsPreloadBatch","DEFAULT_CONCURRENCY","DEFAULT_PAGE_SIZE","DEFAULT_RETRY_LIMIT","sleep","ms","Promise","resolve","setTimeout","messageTimestamp","m","t","timestamp","Number","isFinite","id","getRoomLastActivityScore","room","messages","length","reduce","max","Math","computeUnreadCapped","pageSize","historyComplete","countable","filter","msg","pending","lastViewed","lastViewedTimestamp","oldestTs","minTs","ts","min","MAX_SAFE_INTEGER","getRoomPriority","jid","_room","selectedRoomJid","defaultRoomJids","has","shouldPauseForVisibility","currentState","runHistoryPreloadScheduler","options","client","signal","concurrency","retryLimit","roomLimit","forceReload","aborted","state","getState","rooms","defaultSet","Set","sortedQueue","Object","entries","map","priority","activityScore","attempts","readyAt","Date","now","sort","a","b","localeCompare","queue","slice","inFlightByRoom","Map","consecutiveErrorCount","isActiveRoomGateOpen","readyItems","item","batch","preBatchPreloadStateByJid","historyPreloadState","
|
|
1
|
+
{"version":3,"names":["AppState","store","applyRoomsPreloadBatch","setUnreadSyncing","DEFAULT_CONCURRENCY","DEFAULT_PAGE_SIZE","DEFAULT_RETRY_LIMIT","sleep","ms","Promise","resolve","setTimeout","messageTimestamp","m","t","timestamp","Number","isFinite","id","getRoomLastActivityScore","room","messages","length","reduce","max","Math","computeUnreadCapped","pageSize","historyComplete","countable","filter","msg","pending","lastViewed","lastViewedTimestamp","oldestTs","minTs","ts","min","MAX_SAFE_INTEGER","getRoomPriority","jid","_room","selectedRoomJid","defaultRoomJids","has","shouldPauseForVisibility","currentState","runHistoryPreloadScheduler","options","client","signal","concurrency","retryLimit","roomLimit","forceReload","aborted","dispatch","state","getState","rooms","defaultSet","Set","sortedQueue","Object","entries","map","priority","activityScore","attempts","readyAt","Date","now","sort","a","b","localeCompare","queue","slice","inFlightByRoom","Map","consecutiveErrorCount","isActiveRoomGateOpen","readyItems","item","batch","preBatchPreloadStateByJid","historyPreloadState","all","queueIndex","findIndex","queued","splice","task","currentRoom","preState","get","fetchedMessages","getHistoryStanza","undefined","coalesceRoom","skipIfPreloaded","source","Error","nextRoom","unreadCapped","retries","canRetry","jitter","floor","random","backoff","push","set","finally","delete","r"],"sourceRoot":"../../../src","sources":["helpers/historyPreloadScheduler.ts"],"mappings":";;AAAA,SAASA,QAAQ,QAAQ,cAAc;AAEvC,SAASC,KAAK,QAAQ,cAAc;AACpC,SAASC,sBAAsB,EAAEC,gBAAgB,QAAQ,yBAAyB;AAuBlF,MAAMC,mBAAmB,GAAG,CAAC;AAC7B;AACA;AACA;AACA,MAAMC,iBAAiB,GAAG,EAAE;AAC5B,MAAMC,mBAAmB,GAAG,CAAC;AAE7B,MAAMC,KAAK,GAAIC,EAAU,IAAK,IAAIC,OAAO,CAAEC,OAAO,IAAKC,UAAU,CAACD,OAAO,EAAEF,EAAE,CAAC,CAAC;AAE/E,MAAMI,gBAAgB,GAAIC,CAAW,IAAa;EAChD,IAAI,CAACA,CAAC,EAAE;IAAC,OAAO,CAAC;EAAC;EAClB,MAAMC,CAAC,GAAID,CAAC,CAASE,SAAS;EAC9B,IAAIC,MAAM,CAACC,QAAQ,CAACH,CAAC,CAAC,IAAIA,CAAC,GAAG,CAAC,EAAE;IAAC,OAAOE,MAAM,CAACF,CAAC,CAAC;EAAC;EACnD,MAAMI,EAAE,GAAGF,MAAM,CAACH,CAAC,CAACK,EAAE,CAAC;EACvB,IAAIF,MAAM,CAACC,QAAQ,CAACC,EAAE,CAAC,IAAIA,EAAE,GAAG,CAAC,EAAE;IAAC,OAAOA,EAAE;EAAC;EAC9C,OAAO,CAAC;AACV,CAAC;AAED,MAAMC,wBAAwB,GAAIC,IAAW,IAAa;EACxD,IAAI,CAACA,IAAI,EAAEC,QAAQ,EAAEC,MAAM,EAAE;IAAC,OAAO,CAAC;EAAC;EACvC,OAAOF,IAAI,CAACC,QAAQ,CAACE,MAAM,CAAC,CAACC,GAAG,EAAEX,CAAC,KAAKY,IAAI,CAACD,GAAG,CAACA,GAAG,EAAEZ,gBAAgB,CAACC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,MAAMa,mBAAmB,GAAGA,CAC1BN,IAAW,EACXC,QAAoB,EACpBM,QAAgB,KACJ;EACZ,IAAI,CAACP,IAAI,EAAE;IAAC,OAAO,KAAK;EAAC;EACzB,IAAI,CAACC,QAAQ,IAAIA,QAAQ,CAACC,MAAM,GAAGK,QAAQ,EAAE;IAAC,OAAO,KAAK;EAAC;EAC3D,IAAIP,IAAI,CAACQ,eAAe,KAAK,IAAI,EAAE;IAAC,OAAO,KAAK;EAAC;EAEjD,MAAMC,SAAS,GAAGR,QAAQ,CAACS,MAAM,CAC9BC,GAAG,IAAK,CAAC,CAACA,GAAG,IAAIA,GAAG,CAACb,EAAE,KAAK,eAAe,IAAI,CAACa,GAAG,CAACC,OACvD,CAAC;EACD,IAAIH,SAAS,CAACP,MAAM,GAAGK,QAAQ,EAAE;IAAC,OAAO,KAAK;EAAC;EAE/C,MAAMM,UAAU,GAAGjB,MAAM,CAACI,IAAI,CAACc,mBAAmB,CAAC,IAAI,CAAC;EACxD,IAAID,UAAU,IAAI,CAAC,EAAE;IAAC,OAAO,IAAI;EAAC;EAElC,MAAME,QAAQ,GAAGN,SAAS,CAACN,MAAM,CAAS,CAACa,KAAK,EAAEvB,CAAC,KAAK;IACtD,MAAMwB,EAAE,GAAGzB,gBAAgB,CAACC,CAAC,CAAC;IAC9B,IAAI,CAACG,MAAM,CAACC,QAAQ,CAACoB,EAAE,CAAC,IAAIA,EAAE,IAAI,CAAC,EAAE;MAAC,OAAOD,KAAK;IAAC;IACnD,OAAOX,IAAI,CAACa,GAAG,CAACF,KAAK,EAAEC,EAAE,CAAC;EAC5B,CAAC,EAAErB,MAAM,CAACuB,gBAAgB,CAAC;EAC3B,IAAI,CAACvB,MAAM,CAACC,QAAQ,CAACkB,QAAQ,CAAC,IAAIA,QAAQ,KAAKnB,MAAM,CAACuB,gBAAgB,EACpE;IAAC,OAAO,KAAK;EAAC;EAChB,OAAOJ,QAAQ,GAAGF,UAAU;AAC9B,CAAC;AAED,MAAMO,eAAe,GAAGA,CACtBC,GAAW,EACXC,KAAY,EACZC,eAA8B,EAC9BC,eAA4B,KACjB;EACX,IAAID,eAAe,IAAIA,eAAe,KAAKF,GAAG,EAAE;IAAC,OAAO,CAAC;EAAC;EAC1D,IAAIG,eAAe,CAACC,GAAG,CAACJ,GAAG,CAAC,EAAE;IAAC,OAAO,CAAC;EAAC;EACxC,OAAO,CAAC;AACV,CAAC;AAED,MAAMK,wBAAwB,GAAGA,CAAA,KAAe;EAC9C,OAAO9C,QAAQ,CAAC+C,YAAY,KAAK,QAAQ;AAC3C,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMC,0BAA0B,GAAG,MACxCC,OAAuC,IACrB;EAClB,MAAM;IACJC,MAAM;IACNC,MAAM;IACNC,WAAW,GAAGhD,mBAAmB;IACjCuB,QAAQ,GAAGtB,iBAAiB;IAC5BgD,UAAU,GAAG/C,mBAAmB;IAChCgD,SAAS;IACTX,eAAe,GAAG,IAAI;IACtBC,eAAe,GAAG,EAAE;IACpBW,WAAW,GAAG;EAChB,CAAC,GAAGN,OAAO;EAEX,IAAIE,MAAM,EAAEK,OAAO,EAAE;IAAC;EAAO;EAE7BvD,KAAK,CAACwD,QAAQ,CAACtD,gBAAgB,CAAC,IAAI,CAAC,CAAC;EACtC,IAAI;IAEJ,MAAMuD,KAAK,GAAGzD,KAAK,CAAC0D,QAAQ,CAAC,CAAC;IAC9B,MAAMC,KAAK,GAAIF,KAAK,CAACE,KAAK,CAACA,KAAK,IAAI,CAAC,CAA2B;IAChE,MAAMC,UAAU,GAAG,IAAIC,GAAG,CAAClB,eAAe,CAAC;IAE3C,MAAMmB,WAAwB,GAAGC,MAAM,CAACC,OAAO,CAACL,KAAK,CAAC,CACnDM,GAAG,CAAC,CAAC,CAACzB,GAAG,EAAErB,IAAI,CAAkB,MAAM;MACtCqB,GAAG;MACH0B,QAAQ,EAAE3B,eAAe,CAACC,GAAG,EAAErB,IAAI,EAAEuB,eAAe,EAAEkB,UAAU,CAAC;MACjEO,aAAa,EAAEjD,wBAAwB,CAACC,IAAI,CAAC;MAC7CiD,QAAQ,EAAE,CAAC;MACXC,OAAO,EAAEC,IAAI,CAACC,GAAG,CAAC;IACpB,CAAC,CAAC,CAAC,CACFC,IAAI,CAAC,CAACC,CAAC,EAAEC,CAAC,KAAK;MACd,IAAID,CAAC,CAACP,QAAQ,KAAKQ,CAAC,CAACR,QAAQ,EAAE;QAAC,OAAOO,CAAC,CAACP,QAAQ,GAAGQ,CAAC,CAACR,QAAQ;MAAC;MAC/D,IAAIO,CAAC,CAACN,aAAa,KAAKO,CAAC,CAACP,aAAa,EAAE;QACvC,OAAOO,CAAC,CAACP,aAAa,GAAGM,CAAC,CAACN,aAAa;MAC1C;MACA,OAAOM,CAAC,CAACjC,GAAG,CAACmC,aAAa,CAACD,CAAC,CAAClC,GAAG,CAAC;IACnC,CAAC,CAAC;IAEJ,MAAMoC,KAAkB,GACtBvB,SAAS,IAAIA,SAAS,GAAG,CAAC,GACtBS,WAAW,CAACe,KAAK,CAAC,CAAC,EAAExB,SAAS,CAAC,GAC/BS,WAAW;IAEjB,MAAMgB,cAAc,GAAG,IAAIC,GAAG,CAAwB,CAAC;IACvD,IAAIC,qBAAqB,GAAG,CAAC;IAE7B,OAAOJ,KAAK,CAACvD,MAAM,GAAG,CAAC,EAAE;MACvB,IAAI6B,MAAM,EAAEK,OAAO,EAAE;QAAC;MAAO;MAE7B,IAAI,CAACN,MAAM,CAACgC,oBAAoB,CAAC,CAAC,EAAE;QAClC,MAAM3E,KAAK,CAAC,EAAE,CAAC;QACf;MACF;MACA,IAAIuC,wBAAwB,CAAC,CAAC,EAAE;QAC9B,MAAMvC,KAAK,CAAC,GAAG,CAAC;QAChB;MACF;MAEA,MAAMiE,GAAG,GAAGD,IAAI,CAACC,GAAG,CAAC,CAAC;MACtB,MAAMW,UAAU,GAAGN,KAAK,CAAC/C,MAAM,CAC5BsD,IAAI,IAAKA,IAAI,CAACd,OAAO,IAAIE,GAAG,IAAI,CAACO,cAAc,CAAClC,GAAG,CAACuC,IAAI,CAAC3C,GAAG,CAC/D,CAAC;MACD,IAAI0C,UAAU,CAAC7D,MAAM,KAAK,CAAC,EAAE;QAC3B,MAAMf,KAAK,CAAC,EAAE,CAAC;QACf;MACF;MAEA,MAAM8E,KAAK,GAAGF,UAAU,CAACL,KAAK,CAAC,CAAC,EAAErD,IAAI,CAACD,GAAG,CAAC,CAAC,EAAE4B,WAAW,CAAC,CAAC;;MAE3D;MACA;MACA;MACA;MACA;MACA;MACA,MAAMkC,yBAAyB,GAAG,IAAIN,GAAG,CACvCK,KAAK,CAACnB,GAAG,CAAEkB,IAAI,IAAK,CAClBA,IAAI,CAAC3C,GAAG,EACRxC,KAAK,CAAC0D,QAAQ,CAAC,CAAC,CAACC,KAAK,CAACA,KAAK,CAACwB,IAAI,CAAC3C,GAAG,CAAC,EAAE8C,mBAAmB,CAC5D,CACH,CAAC;MAEDtF,KAAK,CAACwD,QAAQ,CACZvD,sBAAsB,CAAC;QACrB0D,KAAK,EAAEyB,KAAK,CAACnB,GAAG,CAAEkB,IAAI,KAAM;UAC1B3C,GAAG,EAAE2C,IAAI,CAAC3C,GAAG;UACb8C,mBAAmB,EAAE;QACvB,CAAC,CAAC;MACJ,CAAC,CACH,CAAC;MAED,MAAM9E,OAAO,CAAC+E,GAAG,CACfH,KAAK,CAACnB,GAAG,CAAC,MAAOkB,IAAI,IAAK;QACxB,MAAMK,UAAU,GAAGZ,KAAK,CAACa,SAAS,CAAEC,MAAM,IAAKA,MAAM,CAAClD,GAAG,KAAK2C,IAAI,CAAC3C,GAAG,CAAC;QACvE,IAAIgD,UAAU,KAAK,CAAC,CAAC,EAAE;UAACZ,KAAK,CAACe,MAAM,CAACH,UAAU,EAAE,CAAC,CAAC;QAAC;QAEpD,MAAMI,IAAI,GAAG,CAAC,YAAY;UACxB,MAAMC,WAAW,GAAG7F,KAAK,CAAC0D,QAAQ,CAAC,CAAC,CAACC,KAAK,CAACA,KAAK,CAACwB,IAAI,CAAC3C,GAAG,CAAC;UAC1D,MAAMsD,QAAQ,GAAGT,yBAAyB,CAACU,GAAG,CAACZ,IAAI,CAAC3C,GAAG,CAAC;UACxD,IACE,CAACqD,WAAW,IACX,CAACvC,WAAW,IAAIwC,QAAQ,KAAK,MAAO,EACrC;YACA9F,KAAK,CAACwD,QAAQ,CACZvD,sBAAsB,CAAC;cACrB0D,KAAK,EAAE,CAAC;gBAAEnB,GAAG,EAAE2C,IAAI,CAAC3C,GAAG;gBAAE8C,mBAAmB,EAAE;cAAO,CAAC;YACxD,CAAC,CACH,CAAC;YACD;UACF;UAEA,IAAI;YACF,MAAMU,eAAe,GAAG,MAAM/C,MAAM,CAACgD,gBAAgB,CACnDd,IAAI,CAAC3C,GAAG,EACRd,QAAQ,EACRwE,SAAS,EACTA,SAAS,EACT;cACEC,YAAY,EAAE,IAAI;cAClBC,eAAe,EAAE,CAAC9C,WAAW;cAC7B+C,MAAM,EAAE;YACV,CACF,CAAC;YACD,IAAInD,MAAM,EAAEK,OAAO,EAAE;cAAC;YAAO;YAC7B,IAAI,OAAOyC,eAAe,KAAK,WAAW,EAAE;cAC1C,MAAM,IAAIM,KAAK,CAAC,iBAAiB,CAAC;YACpC;YAEA,MAAMC,QAAQ,GAAGvG,KAAK,CAAC0D,QAAQ,CAAC,CAAC,CAACC,KAAK,CAACA,KAAK,CAACwB,IAAI,CAAC3C,GAAG,CAAC;YACvD,MAAMgE,YAAY,GAAG/E,mBAAmB,CACtC8E,QAAQ,EACRP,eAAe,IAAI,EAAE,EACrBtE,QACF,CAAC;YAED1B,KAAK,CAACwD,QAAQ,CACZvD,sBAAsB,CAAC;cACrB0D,KAAK,EAAE,CACL;gBACEnB,GAAG,EAAE2C,IAAI,CAAC3C,GAAG;gBACbpB,QAAQ,EAAE4E,eAAe,IAAI,EAAE;gBAC/BQ,YAAY;gBACZlB,mBAAmB,EAAE;cACvB,CAAC;YAEL,CAAC,CACH,CAAC;YACDN,qBAAqB,GAAG,CAAC;UAC3B,CAAC,CAAC,MAAM;YACN,MAAMyB,OAAO,GAAGtB,IAAI,CAACf,QAAQ,GAAG,CAAC;YACjC,MAAMsC,QAAQ,GAAGD,OAAO,IAAIrD,UAAU;YACtC,IAAIsD,QAAQ,EAAE;cACZ,MAAMC,MAAM,GAAGnF,IAAI,CAACoF,KAAK,CAACpF,IAAI,CAACqF,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC;cAC9C,MAAMC,OAAO,GAAGtF,IAAI,CAACa,GAAG,CAAC,IAAI,EAAE,GAAG,GAAG,CAAC,IAAI8C,IAAI,CAACf,QAAQ,CAAC,GAAGuC,MAAM;cACjE/B,KAAK,CAACmC,IAAI,CAAC;gBACT,GAAG5B,IAAI;gBACPf,QAAQ,EAAEqC,OAAO;gBACjBpC,OAAO,EAAEC,IAAI,CAACC,GAAG,CAAC,CAAC,GAAGuC;cACxB,CAAC,CAAC;YACJ,CAAC,MAAM;cACL9G,KAAK,CAACwD,QAAQ,CACZvD,sBAAsB,CAAC;gBACrB0D,KAAK,EAAE,CAAC;kBAAEnB,GAAG,EAAE2C,IAAI,CAAC3C,GAAG;kBAAE8C,mBAAmB,EAAE;gBAAQ,CAAC;cACzD,CAAC,CACH,CAAC;YACH;YACAN,qBAAqB,IAAI,CAAC;YAC1B,IAAIA,qBAAqB,IAAI,CAAC,EAAE;cAC9B,MAAM1E,KAAK,CAAC,GAAG,CAAC;cAChB0E,qBAAqB,GAAG,CAAC;YAC3B;UACF;QACF,CAAC,EAAE,CAAC;QAEJF,cAAc,CAACkC,GAAG,CAAC7B,IAAI,CAAC3C,GAAG,EAAEoD,IAAI,CAAC;QAClC,MAAMA,IAAI,CAACqB,OAAO,CAAC,MAAMnC,cAAc,CAACoC,MAAM,CAAC/B,IAAI,CAAC3C,GAAG,CAAC,CAAC;MAC3D,CAAC,CACH,CAAC;;MAED;MACA,MAAM,IAAIhC,OAAO,CAAE2G,CAAC,IAAKzG,UAAU,CAACyG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5C;EACA,CAAC,SAAS;IACRnH,KAAK,CAACwD,QAAQ,CAACtD,gBAAgB,CAAC,KAAK,CAAC,CAAC;EACzC;AACF,CAAC;AAED,eAAe6C,0BAA0B","ignoreList":[]}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { Text, TextInput } from 'react-native';
|
|
5
|
+
/**
|
|
6
|
+
* Loads and applies the host-provided font configuration for the chat UI.
|
|
7
|
+
*
|
|
8
|
+
* React Native has no web-style runtime `@font-face`, so a custom font must be
|
|
9
|
+
* registered with `expo-font` before it can be used. This hook:
|
|
10
|
+
* 1. loads every entry in `typography.fonts` via `expo-font` (remote URL or
|
|
11
|
+
* bundled `require(...)`), then
|
|
12
|
+
* 2. sets the resolved `fontFamily` as the default for all `<Text>` and
|
|
13
|
+
* `<TextInput>` rendered by the chat — mirroring how the web SDK sets a
|
|
14
|
+
* CSS variable. Individual components can still override per-style.
|
|
15
|
+
*
|
|
16
|
+
* `expo-font` is an optional peer dependency: if the host hasn't installed it,
|
|
17
|
+
* the hook degrades gracefully (font simply isn't loaded) instead of throwing.
|
|
18
|
+
*
|
|
19
|
+
* No-op when `typography` is undefined — the system font is kept, so existing
|
|
20
|
+
* integrations are unaffected.
|
|
21
|
+
*
|
|
22
|
+
* @returns `true` once fonts are ready (or when there's nothing to load), so
|
|
23
|
+
* callers can gate first paint to avoid a font "flash" if desired.
|
|
24
|
+
*/
|
|
25
|
+
export function useChatFonts(typography) {
|
|
26
|
+
const [ready, setReady] = useState(!typography?.fonts?.length);
|
|
27
|
+
applyDefaultFont(typography);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
let cancelled = false;
|
|
30
|
+
async function load() {
|
|
31
|
+
// Apply the default family immediately so already-available fonts
|
|
32
|
+
// (system, or host-loaded) take effect without waiting on a download.
|
|
33
|
+
applyDefaultFont(typography);
|
|
34
|
+
if (!typography?.fonts?.length) {
|
|
35
|
+
setReady(true);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
// Optional dependency — resolve lazily so apps that don't use custom
|
|
40
|
+
// fonts don't need expo-font installed.
|
|
41
|
+
const ExpoFont = await import('expo-font').catch(() => null);
|
|
42
|
+
if (!ExpoFont) {
|
|
43
|
+
if (!cancelled) setReady(true);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
const map = {};
|
|
47
|
+
for (const f of typography.fonts) map[f.family] = f.source;
|
|
48
|
+
await ExpoFont.loadAsync(map);
|
|
49
|
+
if (!cancelled) {
|
|
50
|
+
applyDefaultFont(typography);
|
|
51
|
+
setReady(true);
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
// Loading failed (e.g. bad URL) — keep the fallback font, don't block UI.
|
|
55
|
+
if (!cancelled) setReady(true);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
load();
|
|
59
|
+
return () => {
|
|
60
|
+
cancelled = true;
|
|
61
|
+
};
|
|
62
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
63
|
+
}, [typography?.fontFamily, JSON.stringify(typography?.fonts ?? []), JSON.stringify(typography?.weightFamilies ?? {})]);
|
|
64
|
+
return ready;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The family currently applied as the chat-wide default. Read at render time
|
|
69
|
+
* by the patched components below, so updating it (then triggering a re-render)
|
|
70
|
+
* restyles the whole tree.
|
|
71
|
+
*/
|
|
72
|
+
let activeFamily;
|
|
73
|
+
function wrapFactory(orig) {
|
|
74
|
+
if (typeof orig !== 'function') return orig;
|
|
75
|
+
if (orig.__ethoraFontWrapped) return orig;
|
|
76
|
+
const wrapped = function (type, props, ...rest) {
|
|
77
|
+
if (activeFamily && props && (type === Text || type === TextInput)) {
|
|
78
|
+
props = {
|
|
79
|
+
...props,
|
|
80
|
+
style: [{
|
|
81
|
+
fontFamily: activeFamily
|
|
82
|
+
}, props.style]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
return orig.call(this, type, props, ...rest);
|
|
86
|
+
};
|
|
87
|
+
wrapped.__ethoraFontWrapped = true;
|
|
88
|
+
return wrapped;
|
|
89
|
+
}
|
|
90
|
+
let factoriesPatched = false;
|
|
91
|
+
function ensurePatched() {
|
|
92
|
+
if (factoriesPatched) return;
|
|
93
|
+
let any = false;
|
|
94
|
+
const patchMod = mod => {
|
|
95
|
+
if (!mod) return;
|
|
96
|
+
for (const fn of ['jsx', 'jsxs', 'jsxDEV']) {
|
|
97
|
+
if (typeof mod[fn] === 'function' && !mod[fn].__ethoraFontWrapped) {
|
|
98
|
+
mod[fn] = wrapFactory(mod[fn]);
|
|
99
|
+
any = true;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
try {
|
|
104
|
+
patchMod(require('react/jsx-runtime'));
|
|
105
|
+
} catch {
|
|
106
|
+
/* ignore */
|
|
107
|
+
}
|
|
108
|
+
try {
|
|
109
|
+
patchMod(require('react/jsx-dev-runtime'));
|
|
110
|
+
} catch {
|
|
111
|
+
/* ignore */
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const React = require('react');
|
|
115
|
+
if (typeof React.createElement === 'function' && !React.createElement.__ethoraFontWrapped) {
|
|
116
|
+
React.createElement = wrapFactory(React.createElement);
|
|
117
|
+
any = true;
|
|
118
|
+
}
|
|
119
|
+
} catch {
|
|
120
|
+
/* ignore */
|
|
121
|
+
}
|
|
122
|
+
if (any) factoriesPatched = true;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Set (or clear) the chat-wide default font family.
|
|
127
|
+
*/
|
|
128
|
+
function applyDefaultFont(typography) {
|
|
129
|
+
activeFamily = typography?.fontFamily;
|
|
130
|
+
if (activeFamily) ensurePatched();
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=useChatFonts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["useEffect","useState","Text","TextInput","useChatFonts","typography","ready","setReady","fonts","length","applyDefaultFont","cancelled","load","ExpoFont","catch","map","f","family","source","loadAsync","fontFamily","JSON","stringify","weightFamilies","activeFamily","wrapFactory","orig","__ethoraFontWrapped","wrapped","type","props","rest","style","call","factoriesPatched","ensurePatched","any","patchMod","mod","fn","require","React","createElement"],"sourceRoot":"../../../src","sources":["hooks/useChatFonts.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -15,7 +15,8 @@ export const useUnreadMessagesCounter = () => {
|
|
|
15
15
|
// `rooms` slice reference stable across actions that don't touch it,
|
|
16
16
|
// so non-rooms dispatches still don't trigger a re-render.)
|
|
17
17
|
const subscribe = callback => store.subscribe(callback);
|
|
18
|
-
const
|
|
18
|
+
const roomsState = useSyncExternalStore(subscribe, () => store.getState().rooms);
|
|
19
|
+
const rooms = roomsState.rooms;
|
|
19
20
|
const unreadByRoom = {};
|
|
20
21
|
let totalCount = 0;
|
|
21
22
|
Object.entries(rooms).forEach(([roomJid, room]) => {
|
|
@@ -28,7 +29,8 @@ export const useUnreadMessagesCounter = () => {
|
|
|
28
29
|
return {
|
|
29
30
|
hasUnread: totalCount > 0,
|
|
30
31
|
totalCount,
|
|
31
|
-
unreadByRoom
|
|
32
|
+
unreadByRoom,
|
|
33
|
+
isLoading: !!roomsState.isUnreadSyncing || !!roomsState.isLoading
|
|
32
34
|
};
|
|
33
35
|
};
|
|
34
36
|
export { useUnreadMessagesCounter as useUnread };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useSyncExternalStore","store","useUnreadMessagesCounter","subscribe","callback","
|
|
1
|
+
{"version":3,"names":["useSyncExternalStore","store","useUnreadMessagesCounter","subscribe","callback","roomsState","getState","rooms","unreadByRoom","totalCount","Object","entries","forEach","roomJid","room","unreadCount","unreadMessages","hasUnread","isLoading","isUnreadSyncing","useUnread"],"sourceRoot":"../../../src","sources":["hooks/useUnreadMessagesCounter.ts"],"mappings":";;AAAA,SAASA,oBAAoB,QAAQ,OAAO;AAE5C,SAASC,KAAK,QAAQ,cAAc;AAapC,OAAO,MAAMC,wBAAwB,GAAGA,CAAA,KAA2B;EACjE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,MAAMC,SAAS,GAAIC,QAAoB,IAAKH,KAAK,CAACE,SAAS,CAACC,QAAQ,CAAC;EAErE,MAAMC,UAAU,GAAGL,oBAAoB,CACrCG,SAAS,EACT,MAAMF,KAAK,CAACK,QAAQ,CAAC,CAAC,CAACC,KACzB,CAAC;EAED,MAAMA,KAAK,GAAGF,UAAU,CAACE,KAAK;EAC9B,MAAMC,YAA+B,GAAG,CAAC,CAAC;EAC1C,IAAIC,UAAU,GAAG,CAAC;EAElBC,MAAM,CAACC,OAAO,CAACJ,KAAK,CAAC,CAACK,OAAO,CAAC,CAAC,CAACC,OAAO,EAAEC,IAAI,CAAkB,KAAK;IAClE,MAAMC,WAAW,GAAGD,IAAI,CAACE,cAAc,IAAI,CAAC;IAC5C,IAAID,WAAW,GAAG,CAAC,EAAE;MACnBP,YAAY,CAACK,OAAO,CAAC,GAAGE,WAAW;MACnCN,UAAU,IAAIM,WAAW;IAC3B;EACF,CAAC,CAAC;EAEF,OAAO;IACLE,SAAS,EAAER,UAAU,GAAG,CAAC;IACzBA,UAAU;IACVD,YAAY;IACZU,SAAS,EAAE,CAAC,CAACb,UAAU,CAACc,eAAe,IAAI,CAAC,CAACd,UAAU,CAACa;EAC1D,CAAC;AACH,CAAC;AAED,SAAShB,wBAAwB,IAAIkB,SAAS","ignoreList":[]}
|
package/lib/module/main.js
CHANGED
|
@@ -34,6 +34,8 @@ export { useChatRoomFocus } from './hooks/useChatRoomFocus';
|
|
|
34
34
|
export { logoutService } from './hooks/useLogout';
|
|
35
35
|
export { useQRCodeChat, handleQRChatId } from './hooks/useQRCodeChatHandler';
|
|
36
36
|
export { resendMessage } from './utils/resendMessage';
|
|
37
|
+
// Font loader — exposed so hosts can also load the font outside <Chat> if needed.
|
|
38
|
+
export { useChatFonts } from './hooks/useChatFonts';
|
|
37
39
|
|
|
38
40
|
// Public types — needed so consumers can type their `config` prop and
|
|
39
41
|
// any event handlers they pass in.
|
package/lib/module/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ReduxWrapper","Chat","XmppProvider","useUnread","useChatRoomFocus","logoutService","useQRCodeChat","handleQRChatId","resendMessage"],"sourceRoot":"../../src","sources":["main.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAO,gCAAgC;;AAEvC;AACA,SAASA,YAAY,IAAIC,IAAI,QAAQ,0CAA0C;AAC/E,SAASC,YAAY,QAAQ,wBAAwB;;AAErD;AACA,SAASC,SAAS,QAAQ,kCAAkC;AAC5D,SAASC,gBAAgB,QAAQ,0BAA0B;AAC3D,SAASC,aAAa,QAAQ,mBAAmB;AACjD,SAASC,aAAa,EAAEC,cAAc,QAAQ,8BAA8B;AAC5E,SAASC,aAAa,QAAQ,uBAAuB;;
|
|
1
|
+
{"version":3,"names":["ReduxWrapper","Chat","XmppProvider","useUnread","useChatRoomFocus","logoutService","useQRCodeChat","handleQRChatId","resendMessage","useChatFonts"],"sourceRoot":"../../src","sources":["main.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA,OAAO,gCAAgC;;AAEvC;AACA,SAASA,YAAY,IAAIC,IAAI,QAAQ,0CAA0C;AAC/E,SAASC,YAAY,QAAQ,wBAAwB;;AAErD;AACA,SAASC,SAAS,QAAQ,kCAAkC;AAC5D,SAASC,gBAAgB,QAAQ,0BAA0B;AAC3D,SAASC,aAAa,QAAQ,mBAAmB;AACjD,SAASC,aAAa,EAAEC,cAAc,QAAQ,8BAA8B;AAC5E,SAASC,aAAa,QAAQ,uBAAuB;AACrD;AACA,SAASC,YAAY,QAAQ,sBAAsB;;AAEnD;AACA","ignoreList":[]}
|
|
@@ -76,6 +76,7 @@ const initialState = {
|
|
|
76
76
|
activeRoomJID: null,
|
|
77
77
|
visibleRoomJID: null,
|
|
78
78
|
isLoading: false,
|
|
79
|
+
isUnreadSyncing: false,
|
|
79
80
|
editAction: {
|
|
80
81
|
isEdit: false,
|
|
81
82
|
roomJid: '',
|
|
@@ -306,6 +307,7 @@ const reducers = {
|
|
|
306
307
|
state.rooms = {};
|
|
307
308
|
state.visibleRoomJID = null;
|
|
308
309
|
state.privateStoreMarkers = {};
|
|
310
|
+
state.isUnreadSyncing = false;
|
|
309
311
|
},
|
|
310
312
|
setComposing(state, action) {
|
|
311
313
|
const {
|
|
@@ -328,6 +330,9 @@ const reducers = {
|
|
|
328
330
|
state.isLoading = loading;
|
|
329
331
|
state.loadingText = loadingText;
|
|
330
332
|
},
|
|
333
|
+
setUnreadSyncing: (state, action) => {
|
|
334
|
+
state.isUnreadSyncing = action.payload;
|
|
335
|
+
},
|
|
331
336
|
setLastViewedTimestamp: (state, action) => {
|
|
332
337
|
const {
|
|
333
338
|
chatJID,
|
|
@@ -466,6 +471,7 @@ const reducers = {
|
|
|
466
471
|
state.activeRoomJID = null;
|
|
467
472
|
state.visibleRoomJID = null;
|
|
468
473
|
state.isLoading = false;
|
|
474
|
+
state.isUnreadSyncing = false;
|
|
469
475
|
state.privateStoreMarkers = {};
|
|
470
476
|
},
|
|
471
477
|
setActiveMessage: (state, action) => {
|
|
@@ -638,6 +644,7 @@ export const {
|
|
|
638
644
|
editRoomMessage,
|
|
639
645
|
setComposing,
|
|
640
646
|
setIsLoading,
|
|
647
|
+
setUnreadSyncing,
|
|
641
648
|
setLastViewedTimestamp,
|
|
642
649
|
applyPrivateStoreMarkers,
|
|
643
650
|
setRoomNoMessages,
|