@college-africa/chat-ui-native 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cache/actions/createGroup.d.ts +20 -0
- package/dist/cache/actions/createGroup.d.ts.map +1 -0
- package/dist/cache/actions/createGroup.js +47 -0
- package/dist/cache/actions/groups.d.ts +29 -0
- package/dist/cache/actions/groups.d.ts.map +1 -0
- package/dist/cache/actions/groups.js +76 -0
- package/dist/cache/actions/index.d.ts +9 -0
- package/dist/cache/actions/index.d.ts.map +1 -0
- package/dist/cache/actions/index.js +24 -0
- package/dist/cache/actions/messages.d.ts +17 -0
- package/dist/cache/actions/messages.d.ts.map +1 -0
- package/dist/cache/actions/messages.js +127 -0
- package/dist/cache/actions/summaries.d.ts +22 -0
- package/dist/cache/actions/summaries.d.ts.map +1 -0
- package/dist/cache/actions/summaries.js +95 -0
- package/dist/cache/actions/users.d.ts +36 -0
- package/dist/cache/actions/users.d.ts.map +1 -0
- package/dist/cache/actions/users.js +96 -0
- package/dist/cache/api.d.ts +15 -0
- package/dist/cache/api.d.ts.map +1 -0
- package/dist/cache/api.js +43 -0
- package/dist/cache/database.d.ts +15 -0
- package/dist/cache/database.d.ts.map +1 -0
- package/dist/cache/database.js +40 -0
- package/dist/cache/index.d.ts +15 -0
- package/dist/cache/index.d.ts.map +1 -0
- package/dist/cache/index.js +37 -0
- package/dist/cache/models.d.ts +61 -0
- package/dist/cache/models.d.ts.map +1 -0
- package/dist/cache/models.js +150 -0
- package/dist/cache/schema.d.ts +77 -0
- package/dist/cache/schema.d.ts.map +1 -0
- package/dist/cache/schema.js +122 -0
- package/dist/components/Avatar.d.ts +24 -0
- package/dist/components/Avatar.d.ts.map +1 -0
- package/dist/components/Avatar.js +49 -0
- package/dist/components/ChatApp.d.ts +34 -0
- package/dist/components/ChatApp.d.ts.map +1 -0
- package/dist/components/ChatApp.js +115 -0
- package/dist/components/ChatContainer.d.ts +18 -0
- package/dist/components/ChatContainer.d.ts.map +1 -0
- package/dist/components/ChatContainer.js +39 -0
- package/dist/components/ChatHeader.d.ts +7 -0
- package/dist/components/ChatHeader.d.ts.map +1 -0
- package/dist/components/ChatHeader.js +35 -0
- package/dist/components/ChatIconButton.d.ts +25 -0
- package/dist/components/ChatIconButton.d.ts.map +1 -0
- package/dist/components/ChatIconButton.js +44 -0
- package/dist/components/ChatView.d.ts +8 -0
- package/dist/components/ChatView.d.ts.map +1 -0
- package/dist/components/ChatView.js +92 -0
- package/dist/components/ConversationItem.d.ts +7 -0
- package/dist/components/ConversationItem.d.ts.map +1 -0
- package/dist/components/ConversationItem.js +51 -0
- package/dist/components/ConversationList.d.ts +7 -0
- package/dist/components/ConversationList.d.ts.map +1 -0
- package/dist/components/ConversationList.js +99 -0
- package/dist/components/ConversationListView.d.ts +7 -0
- package/dist/components/ConversationListView.d.ts.map +1 -0
- package/dist/components/ConversationListView.js +80 -0
- package/dist/components/CreateGroupDialog.d.ts +14 -0
- package/dist/components/CreateGroupDialog.d.ts.map +1 -0
- package/dist/components/CreateGroupDialog.js +141 -0
- package/dist/components/Dropdown.d.ts +37 -0
- package/dist/components/Dropdown.d.ts.map +1 -0
- package/dist/components/Dropdown.js +88 -0
- package/dist/components/KeyboardAvoidingContainer.d.ts +13 -0
- package/dist/components/KeyboardAvoidingContainer.d.ts.map +1 -0
- package/dist/components/KeyboardAvoidingContainer.js +23 -0
- package/dist/components/MessageBubble.d.ts +18 -0
- package/dist/components/MessageBubble.d.ts.map +1 -0
- package/dist/components/MessageBubble.js +153 -0
- package/dist/components/MessageInput.d.ts +7 -0
- package/dist/components/MessageInput.d.ts.map +1 -0
- package/dist/components/MessageInput.js +84 -0
- package/dist/components/MessageList.d.ts +8 -0
- package/dist/components/MessageList.d.ts.map +1 -0
- package/dist/components/MessageList.js +128 -0
- package/dist/components/MessageStatus.d.ts +13 -0
- package/dist/components/MessageStatus.d.ts.map +1 -0
- package/dist/components/MessageStatus.js +65 -0
- package/dist/components/UserAutocomplete.d.ts +16 -0
- package/dist/components/UserAutocomplete.d.ts.map +1 -0
- package/dist/components/UserAutocomplete.js +182 -0
- package/dist/hooks/useConversationList.d.ts +12 -0
- package/dist/hooks/useConversationList.d.ts.map +1 -0
- package/dist/hooks/useConversationList.js +185 -0
- package/dist/hooks/useEffectAsync.d.ts +9 -0
- package/dist/hooks/useEffectAsync.d.ts.map +1 -0
- package/dist/hooks/useEffectAsync.js +19 -0
- package/dist/hooks/useMessages.d.ts +20 -0
- package/dist/hooks/useMessages.d.ts.map +1 -0
- package/dist/hooks/useMessages.js +188 -0
- package/dist/hooks/useSenderNames.d.ts +10 -0
- package/dist/hooks/useSenderNames.d.ts.map +1 -0
- package/dist/hooks/useSenderNames.js +54 -0
- package/dist/hooks/useUnreadCount.d.ts +6 -0
- package/dist/hooks/useUnreadCount.d.ts.map +1 -0
- package/dist/hooks/useUnreadCount.js +46 -0
- package/dist/hooks/useWebSocket.d.ts +27 -0
- package/dist/hooks/useWebSocket.d.ts.map +1 -0
- package/dist/hooks/useWebSocket.js +78 -0
- package/dist/hooks/useWebSocketMessages.d.ts +24 -0
- package/dist/hooks/useWebSocketMessages.d.ts.map +1 -0
- package/dist/hooks/useWebSocketMessages.js +71 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +44 -0
- package/dist/screens/ChatScreen.d.ts +10 -0
- package/dist/screens/ChatScreen.d.ts.map +1 -0
- package/dist/screens/ChatScreen.js +112 -0
- package/dist/screens/ConversationsScreen.d.ts +10 -0
- package/dist/screens/ConversationsScreen.d.ts.map +1 -0
- package/dist/screens/ConversationsScreen.js +25 -0
- package/dist/screens/CreateGroupScreen.d.ts +10 -0
- package/dist/screens/CreateGroupScreen.d.ts.map +1 -0
- package/dist/screens/CreateGroupScreen.js +263 -0
- package/dist/styles/index.d.ts +3 -0
- package/dist/styles/index.d.ts.map +1 -0
- package/dist/styles/index.js +18 -0
- package/dist/styles/responsive.d.ts +74 -0
- package/dist/styles/responsive.d.ts.map +1 -0
- package/dist/styles/responsive.js +98 -0
- package/dist/styles/theme.d.ts +10 -0
- package/dist/styles/theme.d.ts.map +1 -0
- package/dist/styles/theme.js +17 -0
- package/dist/theme/index.d.ts +16 -0
- package/dist/theme/index.d.ts.map +1 -0
- package/dist/theme/index.js +23 -0
- package/dist/types/index.d.ts +92 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/utils/date.d.ts +40 -0
- package/dist/utils/date.d.ts.map +1 -0
- package/dist/utils/date.js +150 -0
- package/dist/utils/messages.d.ts +49 -0
- package/dist/utils/messages.d.ts.map +1 -0
- package/dist/utils/messages.js +115 -0
- package/dist/utils/misc.d.ts +10 -0
- package/dist/utils/misc.d.ts.map +1 -0
- package/dist/utils/misc.js +31 -0
- package/dist/utils/sdk.d.ts +29 -0
- package/dist/utils/sdk.d.ts.map +1 -0
- package/dist/utils/sdk.js +78 -0
- package/package.json +52 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Create group action
|
|
3
|
+
* Creates a group via SDK and refreshes cache
|
|
4
|
+
*/
|
|
5
|
+
export interface CreateGroupData {
|
|
6
|
+
name: string;
|
|
7
|
+
read_only: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Create a new group and refresh cache
|
|
11
|
+
* Only available to admin/system users
|
|
12
|
+
*/
|
|
13
|
+
export declare const createGroup: (data: CreateGroupData) => Promise<import("sdk").Group>;
|
|
14
|
+
/**
|
|
15
|
+
* Join a group (admin only)
|
|
16
|
+
*/
|
|
17
|
+
export declare const joinGroup: (groupId: number, role?: "member" | "moderator") => Promise<{
|
|
18
|
+
message: string;
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=createGroup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createGroup.d.ts","sourceRoot":"","sources":["../../../src/cache/actions/createGroup.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAU,MAAM,eAAe,iCAkBtD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,GACpB,SAAS,MAAM,EACf,OAAM,QAAQ,GAAG,WAAsB;;EAgBxC,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Create group action
|
|
4
|
+
* Creates a group via SDK and refreshes cache
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.joinGroup = exports.createGroup = void 0;
|
|
8
|
+
const sdk_1 = require("../../utils/sdk");
|
|
9
|
+
const users_1 = require("./users");
|
|
10
|
+
const groups_1 = require("./groups");
|
|
11
|
+
const summaries_1 = require("./summaries");
|
|
12
|
+
/**
|
|
13
|
+
* Create a new group and refresh cache
|
|
14
|
+
* Only available to admin/system users
|
|
15
|
+
*/
|
|
16
|
+
const createGroup = async (data) => {
|
|
17
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
18
|
+
const currentUser = (0, users_1.getCurrentUser)();
|
|
19
|
+
if (!currentUser) {
|
|
20
|
+
throw new Error("No authenticated user found");
|
|
21
|
+
}
|
|
22
|
+
// Create the group via SDK
|
|
23
|
+
const group = await sdk.createGroup(currentUser.org, {
|
|
24
|
+
name: data.name,
|
|
25
|
+
read_only: data.read_only
|
|
26
|
+
});
|
|
27
|
+
// Refresh groups and summaries cache to include the new group
|
|
28
|
+
await Promise.all([(0, groups_1.fetchGroups)(currentUser.org), (0, summaries_1.fetchSummaries)()]);
|
|
29
|
+
return group;
|
|
30
|
+
};
|
|
31
|
+
exports.createGroup = createGroup;
|
|
32
|
+
/**
|
|
33
|
+
* Join a group (admin only)
|
|
34
|
+
*/
|
|
35
|
+
const joinGroup = async (groupId, role = "member") => {
|
|
36
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
37
|
+
const currentUser = (0, users_1.getCurrentUser)();
|
|
38
|
+
if (!currentUser) {
|
|
39
|
+
throw new Error("No authenticated user found");
|
|
40
|
+
}
|
|
41
|
+
// Join the group via SDK
|
|
42
|
+
const result = await sdk.joinGroup(currentUser.org, groupId, role);
|
|
43
|
+
// Refresh groups cache to update is_member status
|
|
44
|
+
await (0, groups_1.fetchGroups)(currentUser.org);
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
exports.joinGroup = joinGroup;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Group cache actions
|
|
3
|
+
* Fetches data from SDK and writes to Realm
|
|
4
|
+
*/
|
|
5
|
+
export interface CreateGroupData {
|
|
6
|
+
name: string;
|
|
7
|
+
read_only: boolean;
|
|
8
|
+
members?: Array<{
|
|
9
|
+
userId: number;
|
|
10
|
+
role: "moderator" | "member";
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Fetch groups from server and cache in Realm
|
|
15
|
+
* Clears existing groups first to remove groups user left
|
|
16
|
+
*/
|
|
17
|
+
export declare const fetchGroups: (orgId: number) => Promise<import("sdk").Group[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Create a new group and refresh cache
|
|
20
|
+
* Only available to admin/system users
|
|
21
|
+
*/
|
|
22
|
+
export declare const createGroup: (data: CreateGroupData) => Promise<import("sdk").Group>;
|
|
23
|
+
/**
|
|
24
|
+
* Join a group (admin only)
|
|
25
|
+
*/
|
|
26
|
+
export declare const joinGroup: (groupId: number, role?: "member" | "moderator") => Promise<{
|
|
27
|
+
message: string;
|
|
28
|
+
}>;
|
|
29
|
+
//# sourceMappingURL=groups.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"groups.d.ts","sourceRoot":"","sources":["../../../src/cache/actions/groups.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAQH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,KAAK,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,EAAE,WAAW,GAAG,QAAQ,CAAC;KAC9B,CAAC,CAAC;CACJ;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAU,OAAO,MAAM,mCAgB9C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAU,MAAM,eAAe,iCA8BtD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,GACpB,SAAS,MAAM,EACf,OAAM,QAAQ,GAAG,WAAsB;;EAgBxC,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Group cache actions
|
|
4
|
+
* Fetches data from SDK and writes to Realm
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.joinGroup = exports.createGroup = exports.fetchGroups = void 0;
|
|
11
|
+
const realm_1 = __importDefault(require("realm"));
|
|
12
|
+
const sdk_1 = require("../../utils/sdk");
|
|
13
|
+
const database_1 = require("../database");
|
|
14
|
+
const users_1 = require("./users");
|
|
15
|
+
const summaries_1 = require("./summaries");
|
|
16
|
+
/**
|
|
17
|
+
* Fetch groups from server and cache in Realm
|
|
18
|
+
* Clears existing groups first to remove groups user left
|
|
19
|
+
*/
|
|
20
|
+
const fetchGroups = async (orgId) => {
|
|
21
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
22
|
+
const realm = (0, database_1.getRealm)();
|
|
23
|
+
const groups = await sdk.getGroups(orgId);
|
|
24
|
+
// Clear and replace to remove groups user left
|
|
25
|
+
realm.write(() => {
|
|
26
|
+
realm.delete(realm.objects("Group"));
|
|
27
|
+
groups.forEach(group => {
|
|
28
|
+
realm.create("Group", group, realm_1.default.UpdateMode.Modified);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
return groups;
|
|
32
|
+
};
|
|
33
|
+
exports.fetchGroups = fetchGroups;
|
|
34
|
+
/**
|
|
35
|
+
* Create a new group and refresh cache
|
|
36
|
+
* Only available to admin/system users
|
|
37
|
+
*/
|
|
38
|
+
const createGroup = async (data) => {
|
|
39
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
40
|
+
const currentUser = (0, users_1.getCurrentUser)();
|
|
41
|
+
if (!currentUser) {
|
|
42
|
+
throw new Error("No authenticated user found");
|
|
43
|
+
}
|
|
44
|
+
// Create the group via SDK
|
|
45
|
+
const group = await sdk.createGroup(currentUser.org, {
|
|
46
|
+
name: data.name,
|
|
47
|
+
read_only: data.read_only
|
|
48
|
+
});
|
|
49
|
+
// Add members if any were selected
|
|
50
|
+
if (data.members && data.members.length > 0) {
|
|
51
|
+
await sdk.addGroupMembers(currentUser.org, group.id, data.members.map(m => ({
|
|
52
|
+
user: m.userId,
|
|
53
|
+
role: m.role
|
|
54
|
+
})));
|
|
55
|
+
}
|
|
56
|
+
// Refresh groups and summaries cache to include the new group
|
|
57
|
+
await Promise.all([(0, exports.fetchGroups)(currentUser.org), (0, summaries_1.fetchSummaries)()]);
|
|
58
|
+
return group;
|
|
59
|
+
};
|
|
60
|
+
exports.createGroup = createGroup;
|
|
61
|
+
/**
|
|
62
|
+
* Join a group (admin only)
|
|
63
|
+
*/
|
|
64
|
+
const joinGroup = async (groupId, role = "member") => {
|
|
65
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
66
|
+
const currentUser = (0, users_1.getCurrentUser)();
|
|
67
|
+
if (!currentUser) {
|
|
68
|
+
throw new Error("No authenticated user found");
|
|
69
|
+
}
|
|
70
|
+
// Join the group via SDK
|
|
71
|
+
const result = await sdk.joinGroup(currentUser.org, groupId, role);
|
|
72
|
+
// Refresh groups cache to update is_member status
|
|
73
|
+
await (0, exports.fetchGroups)(currentUser.org);
|
|
74
|
+
return result;
|
|
75
|
+
};
|
|
76
|
+
exports.joinGroup = joinGroup;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cache actions - fetch from SDK and write to Realm
|
|
3
|
+
* All actions follow the pattern: SDK fetch → Realm write → observers auto-update UI
|
|
4
|
+
*/
|
|
5
|
+
export * from './summaries';
|
|
6
|
+
export * from './groups';
|
|
7
|
+
export * from './messages';
|
|
8
|
+
export * from './users';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cache/actions/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,UAAU,CAAC;AACzB,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Cache actions - fetch from SDK and write to Realm
|
|
4
|
+
* All actions follow the pattern: SDK fetch → Realm write → observers auto-update UI
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
__exportStar(require("./summaries"), exports);
|
|
22
|
+
__exportStar(require("./groups"), exports);
|
|
23
|
+
__exportStar(require("./messages"), exports);
|
|
24
|
+
__exportStar(require("./users"), exports);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Message cache actions
|
|
3
|
+
* Fetches data from SDK and writes to Realm
|
|
4
|
+
*/
|
|
5
|
+
import type { GetMessagesParams, Message } from "sdk";
|
|
6
|
+
import { Conversation } from "../../utils/messages";
|
|
7
|
+
/**
|
|
8
|
+
* Fetch messages from server and cache in Realm
|
|
9
|
+
*/
|
|
10
|
+
export declare const fetchMessages: (conversation: Conversation, params?: Partial<GetMessagesParams>) => Promise<import("sdk").MessagePage>;
|
|
11
|
+
/**
|
|
12
|
+
* Fetch older messages using cursor-based pagination
|
|
13
|
+
* Reads stored cursor from MsgCursor and fetches messages before that timestamp
|
|
14
|
+
*/
|
|
15
|
+
export declare const fetchOlderMessages: (conversation: Conversation) => Promise<import("sdk").MessagePage>;
|
|
16
|
+
export declare const cacheIncomingMessage: (message: Message, currentUserId: number) => void;
|
|
17
|
+
//# sourceMappingURL=messages.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../../../src/cache/actions/messages.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,KAAK,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACtD,OAAO,EAAE,YAAY,EAAqB,MAAM,sBAAsB,CAAC;AAGvE;;GAEG;AACH,eAAO,MAAM,aAAa,GACxB,cAAc,YAAY,EAC1B,SAAQ,OAAO,CAAC,iBAAiB,CAAM,uCAgDxC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAU,cAAc,YAAY,uCAiBlE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAC/B,SAAS,OAAO,EAChB,eAAe,MAAM,SAkEtB,CAAC"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Message cache actions
|
|
4
|
+
* Fetches data from SDK and writes to Realm
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.cacheIncomingMessage = exports.fetchOlderMessages = exports.fetchMessages = void 0;
|
|
11
|
+
const realm_1 = __importDefault(require("realm"));
|
|
12
|
+
const sdk_1 = require("../../utils/sdk");
|
|
13
|
+
const database_1 = require("../database");
|
|
14
|
+
const messages_1 = require("../../utils/messages");
|
|
15
|
+
const summaries_1 = require("./summaries");
|
|
16
|
+
/**
|
|
17
|
+
* Fetch messages from server and cache in Realm
|
|
18
|
+
*/
|
|
19
|
+
const fetchMessages = async (conversation, params = {}) => {
|
|
20
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
21
|
+
const realm = (0, database_1.getRealm)();
|
|
22
|
+
const conversationId = (0, messages_1.getConversationId)(conversation);
|
|
23
|
+
// Set conversation params
|
|
24
|
+
if (conversation.type === "group") {
|
|
25
|
+
params.group = conversation.id;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
params.user = conversation.id;
|
|
29
|
+
}
|
|
30
|
+
const page = await sdk.getMessages(params);
|
|
31
|
+
// Write messages to Realm (observers will auto-update UI)
|
|
32
|
+
realm.write(() => {
|
|
33
|
+
page.messages.forEach(msg => {
|
|
34
|
+
realm.create("Message", {
|
|
35
|
+
id: msg.id,
|
|
36
|
+
conversation_id: conversationId,
|
|
37
|
+
sender: msg.sender,
|
|
38
|
+
receiver: msg.receiver,
|
|
39
|
+
group: msg.group,
|
|
40
|
+
content: msg.content,
|
|
41
|
+
created_at: new Date(msg.created_at).getTime()
|
|
42
|
+
}, realm_1.default.UpdateMode.Modified);
|
|
43
|
+
});
|
|
44
|
+
// Save cursor for pagination
|
|
45
|
+
if (page.cursor) {
|
|
46
|
+
realm.create("MsgCursor", {
|
|
47
|
+
conversation_id: conversationId,
|
|
48
|
+
cursor_type: page.cursor.type,
|
|
49
|
+
datetime: page.cursor.datetime
|
|
50
|
+
}, realm_1.default.UpdateMode.Modified);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
return page;
|
|
54
|
+
};
|
|
55
|
+
exports.fetchMessages = fetchMessages;
|
|
56
|
+
/**
|
|
57
|
+
* Fetch older messages using cursor-based pagination
|
|
58
|
+
* Reads stored cursor from MsgCursor and fetches messages before that timestamp
|
|
59
|
+
*/
|
|
60
|
+
const fetchOlderMessages = async (conversation) => {
|
|
61
|
+
const realm = (0, database_1.getRealm)();
|
|
62
|
+
const conversationId = (0, messages_1.getConversationId)(conversation);
|
|
63
|
+
// Get stored cursor for this conversation
|
|
64
|
+
const storedCursor = realm.objectForPrimaryKey("MsgCursor", conversationId);
|
|
65
|
+
if (!storedCursor || !storedCursor.datetime) {
|
|
66
|
+
// No cursor stored, no older messages to fetch
|
|
67
|
+
return { messages: [], cursor: null };
|
|
68
|
+
}
|
|
69
|
+
// Fetch messages before the stored cursor timestamp
|
|
70
|
+
return (0, exports.fetchMessages)(conversation, {
|
|
71
|
+
cursorType: "before",
|
|
72
|
+
cursorDatetime: storedCursor.datetime
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
exports.fetchOlderMessages = fetchOlderMessages;
|
|
76
|
+
const cacheIncomingMessage = (message, currentUserId) => {
|
|
77
|
+
const realm = (0, database_1.getRealm)();
|
|
78
|
+
// Determine conversation_id based on message type
|
|
79
|
+
let conversation_id = null;
|
|
80
|
+
if (message.group) {
|
|
81
|
+
// Group message
|
|
82
|
+
conversation_id = `group:${message.group}`;
|
|
83
|
+
}
|
|
84
|
+
else if (message.sender && message.receiver) {
|
|
85
|
+
// DM message - use the ID of the other person (not current user)
|
|
86
|
+
const otherUserId = message.sender === currentUserId ? message.receiver : message.sender;
|
|
87
|
+
conversation_id = `dm:${otherUserId}`;
|
|
88
|
+
}
|
|
89
|
+
if (!conversation_id) {
|
|
90
|
+
console.warn("Cannot cache message without valid conversation context:", message);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// Check if message already exists (to avoid conflicts with optimistic writes)
|
|
94
|
+
const existing = realm.objectForPrimaryKey("Message", message.id);
|
|
95
|
+
if (existing) {
|
|
96
|
+
// Message already exists, likely from an optimistic write
|
|
97
|
+
// No need to write it again
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
realm.write(() => {
|
|
102
|
+
// 1. Cache the message
|
|
103
|
+
realm.create("Message", {
|
|
104
|
+
id: message.id,
|
|
105
|
+
conversation_id,
|
|
106
|
+
sender: message.sender,
|
|
107
|
+
receiver: message.receiver,
|
|
108
|
+
group: message.group,
|
|
109
|
+
content: message.content,
|
|
110
|
+
created_at: new Date(message.created_at).getTime()
|
|
111
|
+
}, realm_1.default.UpdateMode.Modified);
|
|
112
|
+
// 2. Update summary (handled by summaries action)
|
|
113
|
+
(0, summaries_1.updateSummaryForMessage)(message, currentUserId);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
catch (err) {
|
|
117
|
+
// Handle case where Realm is already in a write transaction
|
|
118
|
+
// This can happen when sending a message optimistically
|
|
119
|
+
if (err instanceof Error &&
|
|
120
|
+
err.message.includes("already in a write transaction")) {
|
|
121
|
+
// Message is already being written by the sender, skip it
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
console.error("Failed to cache incoming message:", err);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
exports.cacheIncomingMessage = cacheIncomingMessage;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Summary cache actions
|
|
3
|
+
* Fetches data from SDK and writes to Realm
|
|
4
|
+
*/
|
|
5
|
+
import type { GetMessagesSummaryParams, Message } from "sdk";
|
|
6
|
+
/**
|
|
7
|
+
* Fetch summaries from server and cache in Realm
|
|
8
|
+
*/
|
|
9
|
+
export declare const fetchSummaries: (params?: GetMessagesSummaryParams) => Promise<import("sdk").ConversationSummary[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Update summary for an incoming message
|
|
12
|
+
* Creates new summary if it doesn't exist
|
|
13
|
+
* Increments message count and unread count, updates last_message_at
|
|
14
|
+
* Note: Must be called inside a Realm write transaction
|
|
15
|
+
*/
|
|
16
|
+
export declare const updateSummaryForMessage: (message: Message, currentUserId: number) => void;
|
|
17
|
+
/**
|
|
18
|
+
* Clear unread count for a conversation when user opens it
|
|
19
|
+
* @param conversationId - The conversation ID (format: "dm:123" or "group:456")
|
|
20
|
+
*/
|
|
21
|
+
export declare const clearUnreadCount: (conversationId: string) => void;
|
|
22
|
+
//# sourceMappingURL=summaries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summaries.d.ts","sourceRoot":"","sources":["../../../src/cache/actions/summaries.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH,OAAO,KAAK,EAAE,wBAAwB,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AAG7D;;GAEG;AACH,eAAO,MAAM,cAAc,GAAU,SAAQ,wBAA6B,iDAqBzE,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,OAAO,EAChB,eAAe,MAAM,SAsCtB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,gBAAgB,MAAM,SAuBtD,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Summary cache actions
|
|
4
|
+
* Fetches data from SDK and writes to Realm
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.clearUnreadCount = exports.updateSummaryForMessage = exports.fetchSummaries = void 0;
|
|
11
|
+
const realm_1 = __importDefault(require("realm"));
|
|
12
|
+
const sdk_1 = require("../../utils/sdk");
|
|
13
|
+
const database_1 = require("../database");
|
|
14
|
+
const misc_1 = require("../../utils/misc");
|
|
15
|
+
const messages_1 = require("../../utils/messages");
|
|
16
|
+
/**
|
|
17
|
+
* Fetch summaries from server and cache in Realm
|
|
18
|
+
*/
|
|
19
|
+
const fetchSummaries = async (params = {}) => {
|
|
20
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
21
|
+
const realm = (0, database_1.getRealm)();
|
|
22
|
+
const summaries = await sdk.getMessagesSummary(params);
|
|
23
|
+
// Write to Realm (observers will auto-update UI)
|
|
24
|
+
realm.write(() => {
|
|
25
|
+
summaries.forEach(summary => {
|
|
26
|
+
realm.create("Summary", {
|
|
27
|
+
id: (0, misc_1.getSummaryId)(summary),
|
|
28
|
+
...summary
|
|
29
|
+
}, realm_1.default.UpdateMode.Modified);
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
return summaries;
|
|
33
|
+
};
|
|
34
|
+
exports.fetchSummaries = fetchSummaries;
|
|
35
|
+
/**
|
|
36
|
+
* Update summary for an incoming message
|
|
37
|
+
* Creates new summary if it doesn't exist
|
|
38
|
+
* Increments message count and unread count, updates last_message_at
|
|
39
|
+
* Note: Must be called inside a Realm write transaction
|
|
40
|
+
*/
|
|
41
|
+
const updateSummaryForMessage = (message, currentUserId) => {
|
|
42
|
+
const realm = (0, database_1.getRealm)();
|
|
43
|
+
const otherUserId = message.sender === currentUserId ? message.receiver : message.sender;
|
|
44
|
+
if (!otherUserId && !message.group) {
|
|
45
|
+
console.warn("Cannot update summary: message has no group or valid user IDs");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const summaryId = (0, misc_1.getSummaryId)({
|
|
49
|
+
group: message.group,
|
|
50
|
+
user: otherUserId ?? undefined
|
|
51
|
+
});
|
|
52
|
+
const existingSummary = realm.objectForPrimaryKey("Summary", summaryId);
|
|
53
|
+
if (existingSummary) {
|
|
54
|
+
// Update existing summary
|
|
55
|
+
existingSummary.message_count += 1;
|
|
56
|
+
existingSummary.last_message_at = message.created_at;
|
|
57
|
+
existingSummary.unread_count += 1;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
// Create new summary if it doesn't exist
|
|
61
|
+
realm.create("Summary", {
|
|
62
|
+
id: summaryId,
|
|
63
|
+
group: message.group ?? undefined,
|
|
64
|
+
user: otherUserId ?? undefined,
|
|
65
|
+
last_message_at: message.created_at,
|
|
66
|
+
message_count: 1,
|
|
67
|
+
unread_count: 1
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
exports.updateSummaryForMessage = updateSummaryForMessage;
|
|
72
|
+
/**
|
|
73
|
+
* Clear unread count for a conversation when user opens it
|
|
74
|
+
* @param conversationId - The conversation ID (format: "dm:123" or "group:456")
|
|
75
|
+
*/
|
|
76
|
+
const clearUnreadCount = (conversationId) => {
|
|
77
|
+
const realm = (0, database_1.getRealm)();
|
|
78
|
+
try {
|
|
79
|
+
// Parse conversation ID using existing utility
|
|
80
|
+
const conversation = (0, messages_1.parseConversationId)(conversationId);
|
|
81
|
+
const summaryId = (0, misc_1.getSummaryId)(conversation.type === "group"
|
|
82
|
+
? { group: conversation.id }
|
|
83
|
+
: { user: conversation.id });
|
|
84
|
+
const summary = realm.objectForPrimaryKey("Summary", summaryId);
|
|
85
|
+
if (summary && summary.unread_count > 0) {
|
|
86
|
+
realm.write(() => {
|
|
87
|
+
summary.unread_count = 0;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
console.warn("Failed to clear unread count:", err);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
exports.clearUnreadCount = clearUnreadCount;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* User cache actions
|
|
3
|
+
* Fetches data from SDK and writes to Realm
|
|
4
|
+
*/
|
|
5
|
+
import { CurrentUser } from '../schema';
|
|
6
|
+
/**
|
|
7
|
+
* Fetch users from server and cache in Realm
|
|
8
|
+
*/
|
|
9
|
+
export declare const fetchUsers: (userIds: number[], options?: {
|
|
10
|
+
fields?: string[];
|
|
11
|
+
}) => Promise<import("sdk").User[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Fetch single user from server and cache in Realm
|
|
14
|
+
*/
|
|
15
|
+
export declare const fetchUser: (userId: number) => Promise<import("sdk").User>;
|
|
16
|
+
/**
|
|
17
|
+
* Get the current authenticated user from cache
|
|
18
|
+
* Returns null if not set
|
|
19
|
+
*/
|
|
20
|
+
export declare const getCurrentUser: () => CurrentUser | null;
|
|
21
|
+
/**
|
|
22
|
+
* Get the current authenticated user's ID from cache
|
|
23
|
+
* Returns null if not set
|
|
24
|
+
*/
|
|
25
|
+
export declare const getCurrentUserId: () => number | null;
|
|
26
|
+
/**
|
|
27
|
+
* Set the current authenticated user in cache
|
|
28
|
+
*/
|
|
29
|
+
export declare const setCurrentUser: (user: {
|
|
30
|
+
id: number;
|
|
31
|
+
org: number;
|
|
32
|
+
name: string;
|
|
33
|
+
email?: string;
|
|
34
|
+
role?: string;
|
|
35
|
+
}) => void;
|
|
36
|
+
//# sourceMappingURL=users.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"users.d.ts","sourceRoot":"","sources":["../../../src/cache/actions/users.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC;;GAEG;AACH,eAAO,MAAM,UAAU,GAAU,SAAS,MAAM,EAAE,EAAE,UAAS;IAAE,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAAO,kCA8BtF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,SAAS,GAAU,QAAQ,MAAM,gCAoB7C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,QAAO,WAAW,GAAG,IAI/C,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,QAAO,MAAM,GAAG,IAG5C,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,KAAG,IAoB/G,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* User cache actions
|
|
4
|
+
* Fetches data from SDK and writes to Realm
|
|
5
|
+
*/
|
|
6
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
7
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
8
|
+
};
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.setCurrentUser = exports.getCurrentUserId = exports.getCurrentUser = exports.fetchUser = exports.fetchUsers = void 0;
|
|
11
|
+
const realm_1 = __importDefault(require("realm"));
|
|
12
|
+
const sdk_1 = require("../../utils/sdk");
|
|
13
|
+
const database_1 = require("../database");
|
|
14
|
+
/**
|
|
15
|
+
* Fetch users from server and cache in Realm
|
|
16
|
+
*/
|
|
17
|
+
const fetchUsers = async (userIds, options = {}) => {
|
|
18
|
+
// Filter out invalid IDs (undefined, null, NaN, negative numbers)
|
|
19
|
+
const validIds = userIds.filter((id) => typeof id === 'number' && id > 0 && !isNaN(id));
|
|
20
|
+
if (validIds.length === 0) {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
24
|
+
const realm = (0, database_1.getRealm)();
|
|
25
|
+
const users = await sdk.getUsers(validIds, options);
|
|
26
|
+
// Write to Realm (observers will auto-update UI)
|
|
27
|
+
realm.write(() => {
|
|
28
|
+
users.forEach((user) => {
|
|
29
|
+
realm.create('User', {
|
|
30
|
+
id: user.id,
|
|
31
|
+
name: user.name,
|
|
32
|
+
email: user.email,
|
|
33
|
+
role: user.role,
|
|
34
|
+
}, realm_1.default.UpdateMode.Modified);
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
return users;
|
|
38
|
+
};
|
|
39
|
+
exports.fetchUsers = fetchUsers;
|
|
40
|
+
/**
|
|
41
|
+
* Fetch single user from server and cache in Realm
|
|
42
|
+
*/
|
|
43
|
+
const fetchUser = async (userId) => {
|
|
44
|
+
const sdk = (0, sdk_1.getSDK)();
|
|
45
|
+
const realm = (0, database_1.getRealm)();
|
|
46
|
+
const user = await sdk.getUser(userId);
|
|
47
|
+
realm.write(() => {
|
|
48
|
+
realm.create('User', {
|
|
49
|
+
id: user.id,
|
|
50
|
+
name: user.name,
|
|
51
|
+
email: user.email,
|
|
52
|
+
role: user.role,
|
|
53
|
+
}, realm_1.default.UpdateMode.Modified);
|
|
54
|
+
});
|
|
55
|
+
return user;
|
|
56
|
+
};
|
|
57
|
+
exports.fetchUser = fetchUser;
|
|
58
|
+
/**
|
|
59
|
+
* Get the current authenticated user from cache
|
|
60
|
+
* Returns null if not set
|
|
61
|
+
*/
|
|
62
|
+
const getCurrentUser = () => {
|
|
63
|
+
const realm = (0, database_1.getRealm)();
|
|
64
|
+
const users = realm.objects('CurrentUser');
|
|
65
|
+
return users.length > 0 ? users[0] : null;
|
|
66
|
+
};
|
|
67
|
+
exports.getCurrentUser = getCurrentUser;
|
|
68
|
+
/**
|
|
69
|
+
* Get the current authenticated user's ID from cache
|
|
70
|
+
* Returns null if not set
|
|
71
|
+
*/
|
|
72
|
+
const getCurrentUserId = () => {
|
|
73
|
+
const currentUser = (0, exports.getCurrentUser)();
|
|
74
|
+
return currentUser?.id ?? null;
|
|
75
|
+
};
|
|
76
|
+
exports.getCurrentUserId = getCurrentUserId;
|
|
77
|
+
/**
|
|
78
|
+
* Set the current authenticated user in cache
|
|
79
|
+
*/
|
|
80
|
+
const setCurrentUser = (user) => {
|
|
81
|
+
const realm = (0, database_1.getRealm)();
|
|
82
|
+
realm.write(() => {
|
|
83
|
+
// Delete any existing current user first
|
|
84
|
+
const existing = realm.objects('CurrentUser');
|
|
85
|
+
realm.delete(existing);
|
|
86
|
+
// Create the new current user
|
|
87
|
+
realm.create('CurrentUser', {
|
|
88
|
+
id: user.id,
|
|
89
|
+
org: user.org,
|
|
90
|
+
name: user.name,
|
|
91
|
+
email: user.email,
|
|
92
|
+
role: user.role
|
|
93
|
+
}, realm_1.default.UpdateMode.Modified);
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
exports.setCurrentUser = setCurrentUser;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Clear all cached data from the database
|
|
3
|
+
*/
|
|
4
|
+
export declare function deleteDatabase(): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Reset cache but keep user session
|
|
7
|
+
* Clears all tables without disconnecting SDK
|
|
8
|
+
*/
|
|
9
|
+
export declare function resetCache(): Promise<void>;
|
|
10
|
+
/**
|
|
11
|
+
* Complete logout: disconnect SDK and clear cache
|
|
12
|
+
* Recommended method for user logout
|
|
13
|
+
*/
|
|
14
|
+
export declare function logout(): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/cache/api.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAInD;AAED;;;GAGG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAgBhD;AAED;;;GAGG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAG5C"}
|