@tagea/capacitor-matrix 1.2.0 → 1.3.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/README.md +26 -12
- package/android/src/main/kotlin/de/tremaze/capacitor/matrix/CapMatrix.kt +168 -9
- package/dist/docs.json +69 -0
- package/dist/esm/definitions.d.ts +10 -0
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/web.d.ts +1 -0
- package/dist/esm/web.js +43 -4
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +43 -4
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +43 -4
- package/dist/plugin.js.map +1 -1
- package/ios/Sources/CapMatrixPlugin/CapMatrix.swift +76 -16
- package/package.json +1 -1
|
@@ -32,6 +32,8 @@ class MatrixSDKBridge {
|
|
|
32
32
|
private var syncStateObserver: SyncStateObserverProxy?
|
|
33
33
|
private let subscriptionLock = NSLock()
|
|
34
34
|
private var receiptSyncTask: Task<Void, Never>?
|
|
35
|
+
private var roomCreatedAtCache: [String: UInt64] = [:]
|
|
36
|
+
private let createdAtLock = NSLock()
|
|
35
37
|
// Rooms currently being paginated by getRoomMessages — live listener suppresses events for these
|
|
36
38
|
private var paginatingRooms = Set<String>()
|
|
37
39
|
private let paginatingLock = NSLock()
|
|
@@ -603,11 +605,51 @@ class MatrixSDKBridge {
|
|
|
603
605
|
}
|
|
604
606
|
var result: [[String: Any]] = []
|
|
605
607
|
for room in c.rooms() {
|
|
606
|
-
|
|
608
|
+
var dict = try await Self.serializeRoom(room)
|
|
609
|
+
if dict["lastEventTs"] as? UInt64 == nil {
|
|
610
|
+
if let ts = await fetchRoomCreatedAt(roomId: room.id()) {
|
|
611
|
+
dict["createdAt"] = ts
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
result.append(dict)
|
|
607
615
|
}
|
|
608
616
|
return result
|
|
609
617
|
}
|
|
610
618
|
|
|
619
|
+
private func fetchRoomCreatedAt(roomId: String) async -> UInt64? {
|
|
620
|
+
createdAtLock.lock()
|
|
621
|
+
let cached = roomCreatedAtCache[roomId]
|
|
622
|
+
createdAtLock.unlock()
|
|
623
|
+
if let cached { return cached }
|
|
624
|
+
guard let session = sessionStore.load() else { return nil }
|
|
625
|
+
let baseUrl = session.homeserverUrl.hasSuffix("/")
|
|
626
|
+
? String(session.homeserverUrl.dropLast())
|
|
627
|
+
: session.homeserverUrl
|
|
628
|
+
guard let encodedRoomId = roomId.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed),
|
|
629
|
+
let url = URL(string: "\(baseUrl)/_matrix/client/v3/rooms/\(encodedRoomId)/state") else {
|
|
630
|
+
return nil
|
|
631
|
+
}
|
|
632
|
+
var request = URLRequest(url: url)
|
|
633
|
+
request.httpMethod = "GET"
|
|
634
|
+
request.setValue("Bearer \(session.accessToken)", forHTTPHeaderField: "Authorization")
|
|
635
|
+
guard let (data, response) = try? await URLSession.shared.data(for: request),
|
|
636
|
+
let statusCode = (response as? HTTPURLResponse)?.statusCode,
|
|
637
|
+
statusCode >= 200, statusCode < 300,
|
|
638
|
+
let events = try? JSONSerialization.jsonObject(with: data) as? [[String: Any]] else {
|
|
639
|
+
return nil
|
|
640
|
+
}
|
|
641
|
+
for event in events {
|
|
642
|
+
if event["type"] as? String == "m.room.create",
|
|
643
|
+
let ts = event["origin_server_ts"] as? UInt64 {
|
|
644
|
+
createdAtLock.lock()
|
|
645
|
+
roomCreatedAtCache[roomId] = ts
|
|
646
|
+
createdAtLock.unlock()
|
|
647
|
+
return ts
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
return nil
|
|
651
|
+
}
|
|
652
|
+
|
|
611
653
|
func getRoomMembers(roomId: String) async throws -> [[String: Any]] {
|
|
612
654
|
let room = try requireRoom(roomId: roomId)
|
|
613
655
|
let iterator = try await room.members()
|
|
@@ -728,7 +770,9 @@ class MatrixSDKBridge {
|
|
|
728
770
|
|
|
729
771
|
// Reset cursor on initial load
|
|
730
772
|
if !isPagination {
|
|
773
|
+
paginatingLock.lock()
|
|
731
774
|
oldestReturnedEventId.removeValue(forKey: roomId)
|
|
775
|
+
paginatingLock.unlock()
|
|
732
776
|
}
|
|
733
777
|
|
|
734
778
|
// Paginate when: first load with too few items, OR explicit pagination request
|
|
@@ -763,7 +807,11 @@ class MatrixSDKBridge {
|
|
|
763
807
|
let allEvents = collector.events
|
|
764
808
|
var events: [[String: Any]]
|
|
765
809
|
|
|
766
|
-
|
|
810
|
+
paginatingLock.lock()
|
|
811
|
+
let cursorId = oldestReturnedEventId[roomId]
|
|
812
|
+
paginatingLock.unlock()
|
|
813
|
+
|
|
814
|
+
if let cursorId = cursorId, from != nil {
|
|
767
815
|
if let cursorIdx = allEvents.firstIndex(where: { ($0["eventId"] as? String) == cursorId }) {
|
|
768
816
|
let available = Array(allEvents.prefix(cursorIdx))
|
|
769
817
|
events = Array(available.suffix(limit))
|
|
@@ -776,7 +824,9 @@ class MatrixSDKBridge {
|
|
|
776
824
|
}
|
|
777
825
|
|
|
778
826
|
if let oldest = events.first, let eid = oldest["eventId"] as? String {
|
|
827
|
+
paginatingLock.lock()
|
|
779
828
|
oldestReturnedEventId[roomId] = eid
|
|
829
|
+
paginatingLock.unlock()
|
|
780
830
|
}
|
|
781
831
|
|
|
782
832
|
// Apply receipt watermark
|
|
@@ -1475,7 +1525,7 @@ class MatrixSDKBridge {
|
|
|
1475
1525
|
return dir.path
|
|
1476
1526
|
}
|
|
1477
1527
|
|
|
1478
|
-
|
|
1528
|
+
static func serializeRoom(_ room: Room) async throws -> [String: Any] {
|
|
1479
1529
|
let info = try await room.roomInfo()
|
|
1480
1530
|
let encrypted = await room.isEncrypted()
|
|
1481
1531
|
let membership: String = {
|
|
@@ -1651,6 +1701,7 @@ private func serializeEventTimelineItem(_ eventItem: EventTimelineItem, roomId:
|
|
|
1651
1701
|
|
|
1652
1702
|
var contentDict: [String: Any] = [:]
|
|
1653
1703
|
var eventType = "m.room.message"
|
|
1704
|
+
var stateKey: String? = nil
|
|
1654
1705
|
|
|
1655
1706
|
let content = eventItem.content
|
|
1656
1707
|
switch content {
|
|
@@ -1707,6 +1758,7 @@ private func serializeEventTimelineItem(_ eventItem: EventTimelineItem, roomId:
|
|
|
1707
1758
|
}
|
|
1708
1759
|
case .roomMembership(let userId, let userDisplayName, let change, _):
|
|
1709
1760
|
eventType = "m.room.member"
|
|
1761
|
+
stateKey = userId
|
|
1710
1762
|
let membership: String
|
|
1711
1763
|
switch change {
|
|
1712
1764
|
case .joined, .invitationAccepted:
|
|
@@ -1726,8 +1778,8 @@ private func serializeEventTimelineItem(_ eventItem: EventTimelineItem, roomId:
|
|
|
1726
1778
|
}
|
|
1727
1779
|
contentDict["membership"] = membership
|
|
1728
1780
|
contentDict["displayname"] = userDisplayName ?? userId
|
|
1729
|
-
|
|
1730
|
-
|
|
1781
|
+
case .state(let sk, let stateContent):
|
|
1782
|
+
stateKey = sk
|
|
1731
1783
|
switch stateContent {
|
|
1732
1784
|
case .roomCreate:
|
|
1733
1785
|
eventType = "m.room.create"
|
|
@@ -1767,7 +1819,13 @@ private func serializeEventTimelineItem(_ eventItem: EventTimelineItem, roomId:
|
|
|
1767
1819
|
}
|
|
1768
1820
|
}
|
|
1769
1821
|
|
|
1770
|
-
|
|
1822
|
+
// Build unsigned dict — include transaction_id when available
|
|
1823
|
+
var unsignedDict: [String: Any]? = nil
|
|
1824
|
+
if case .transactionId(let txnId) = eventItem.eventOrTransactionId {
|
|
1825
|
+
unsignedDict = ["transaction_id": txnId]
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
var result: [String: Any] = [
|
|
1771
1829
|
"eventId": eventId,
|
|
1772
1830
|
"roomId": roomId,
|
|
1773
1831
|
"senderId": eventItem.sender,
|
|
@@ -1777,6 +1835,13 @@ private func serializeEventTimelineItem(_ eventItem: EventTimelineItem, roomId:
|
|
|
1777
1835
|
"status": status,
|
|
1778
1836
|
"readBy": readBy as Any,
|
|
1779
1837
|
]
|
|
1838
|
+
if let sk = stateKey {
|
|
1839
|
+
result["stateKey"] = sk
|
|
1840
|
+
}
|
|
1841
|
+
if let ud = unsignedDict {
|
|
1842
|
+
result["unsigned"] = ud
|
|
1843
|
+
}
|
|
1844
|
+
return result
|
|
1780
1845
|
}
|
|
1781
1846
|
|
|
1782
1847
|
// MARK: - Live Timeline Listener (for sync subscriptions)
|
|
@@ -1796,19 +1861,14 @@ class LiveTimelineListener: TimelineListener {
|
|
|
1796
1861
|
self.isPaginating = isPaginating
|
|
1797
1862
|
}
|
|
1798
1863
|
|
|
1799
|
-
/// Emit a room update with
|
|
1864
|
+
/// Emit a room update with full room summary.
|
|
1800
1865
|
private func emitRoomUpdate() {
|
|
1801
1866
|
Task {
|
|
1802
|
-
let
|
|
1803
|
-
if let
|
|
1804
|
-
|
|
1867
|
+
let summary: [String: Any]
|
|
1868
|
+
if let s = try? await MatrixSDKBridge.serializeRoom(room) {
|
|
1869
|
+
summary = s
|
|
1805
1870
|
} else {
|
|
1806
|
-
|
|
1807
|
-
}
|
|
1808
|
-
var summary: [String: Any] = ["roomId": roomId, "unreadCount": unreadCount]
|
|
1809
|
-
let latestEvent = await room.latestEvent()
|
|
1810
|
-
if let le = serializeLatestEventValue(latestEvent, roomId: roomId) {
|
|
1811
|
-
summary["latestEvent"] = le
|
|
1871
|
+
summary = ["roomId": roomId]
|
|
1812
1872
|
}
|
|
1813
1873
|
onRoomUpdate(roomId, summary)
|
|
1814
1874
|
}
|