Skip to content

Commit 0dedd86

Browse files
committed
Add state event sync stuff
1 parent fd273ca commit 0dedd86

File tree

5 files changed

+128
-9
lines changed

5 files changed

+128
-9
lines changed

Sources/MatrixClient/API/Sync.swift

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ public struct MatrixSyncRequest: MatrixRequest {
1616
}
1717

1818
// TODO: fullState
19-
// TODO: presence
19+
if let presence = parameters.presence {
20+
queryItems.append(URLQueryItem(name: "set_presence", value: presence.rawValue))
21+
}
2022

2123
if let timeout = parameters.timeout {
2224
queryItems.append(URLQueryItem(name: "timeout", value: String(timeout)))
@@ -36,11 +38,11 @@ public struct MatrixSyncRequest: MatrixRequest {
3638
public static var requiresAuth = true
3739

3840
public struct Parameters {
39-
public let filter: String?
40-
public let since: String?
41-
public let fullState: Bool?
42-
public let presence: Presence?
43-
public let timeout: Int?
41+
public var filter: String?
42+
public var since: String?
43+
public var fullState: Bool?
44+
public var presence: Presence?
45+
public var timeout: Int?
4446

4547
public enum Presence: String {
4648
case online
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Finn Behrens on 26.04.22.
6+
//
7+
8+
import Foundation
9+
import MatrixClient
10+
11+
@available(macOS 12.0, iOS 15.0, watchOS 8.0, tvOS 15.0, *)
12+
public extension MatrixCore {
13+
/// Start a task to sync
14+
///
15+
/// - Throws: ``MatrixCoreError`` if sync is already running
16+
func startSync() throws {
17+
guard syncTask == nil else {
18+
throw MatrixCoreError.syncAlreadyStarted
19+
}
20+
21+
syncTask = buildSyncTask()
22+
}
23+
24+
private nonisolated func buildSyncTask() -> Task<Void, Never> {
25+
Task(priority: .background) { [self] in
26+
var parameters = MatrixSyncRequest.Parameters(timeout: 45 * 1000)
27+
while true {
28+
do {
29+
parameters = try await self.runSync(parameters: parameters)
30+
31+
parameters.presence = await self.presence
32+
33+
try Task.checkCancellation()
34+
} catch is CancellationError {
35+
return
36+
} catch {
37+
MatrixCoreLogger.logger.fault("Sync task: \(error.localizedDescription)")
38+
}
39+
}
40+
}
41+
}
42+
43+
nonisolated func runSync(parameters: MatrixSyncRequest.Parameters) async throws -> MatrixSyncRequest.Parameters {
44+
var parameters = parameters
45+
let client = await self.client
46+
let sync = try await client.sync(parameters: parameters)
47+
48+
try await parseSync(sync)
49+
50+
parameters.since = sync.nextBatch
51+
return parameters
52+
}
53+
54+
nonisolated func parseSync(_ sync: MatrixSync) async throws {
55+
guard let rooms = sync.rooms else {
56+
return
57+
}
58+
59+
var acountRooms: [String] = []
60+
61+
guard let joinedRooms = rooms.joined else {
62+
return
63+
}
64+
65+
for (roomId, room) in joinedRooms {
66+
try await parseRoom(roomId: roomId, room: room)
67+
acountRooms.append(roomId)
68+
}
69+
70+
// TODO: save account <-> roomId mapping
71+
}
72+
73+
nonisolated func parseRoom(roomId: String, room: MatrixSync.JoinedRoom) async throws {
74+
MatrixCoreLogger.logger.trace("Parsing room \(roomId)")
75+
76+
if let timeline = room.timeline {
77+
for event in timeline.events ?? [] {
78+
if let event = event as? MatrixStateEvent {
79+
try await store.addRoomState(state: .init(roomId: roomId, event: event))
80+
}
81+
}
82+
}
83+
}
84+
85+
/// Stop the sync task
86+
///
87+
/// - Throws: ``MatrixCoreError`` if the sync task is not running
88+
func stopSync() throws {
89+
guard let syncTask = self.syncTask,
90+
!syncTask.isCancelled
91+
else {
92+
throw MatrixCoreError.syncNotRunning
93+
}
94+
syncTask.cancel()
95+
self.syncTask = nil
96+
}
97+
}

Sources/MatrixCore/MatrixCore.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,16 @@ public class MatrixCore<T: MatrixStore> {
1717

1818
public var client: MatrixClient
1919

20+
// MARK: sync
21+
22+
internal var syncTask: Task<Void, Never>?
23+
public var presence: MatrixSyncRequest.Parameters.Presence = .offline
24+
25+
deinit {
26+
// cancel unconditionally if the task is not nil
27+
self.syncTask?.cancel()
28+
}
29+
2030
// MARK: - computed variables
2131

2232
public var id: T.AccountInfo.AccountIdentifier {

Sources/MatrixCore/MatrixCoreError.swift

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@
88
import Foundation
99

1010
public enum MatrixCoreError: Error {
11-
case actorMissing
1211
case missingData
12+
case syncAlreadyStarted
13+
case syncNotRunning
14+
15+
case actorMissing
1316
case creationError
1417
case batchInsertError
1518
case batchDeleteError
@@ -21,13 +24,18 @@ public enum MatrixCoreError: Error {
2124
extension MatrixCoreError: LocalizedError {
2225
public var errorDescription: String? {
2326
switch self {
24-
case .actorMissing:
25-
return NSLocalizedString("Did not found MatrixCore instance to use for request", comment: "")
2627
case .missingData:
2728
return NSLocalizedString(
2829
"Found and will discard a quake missing a valid code, magnitude, place, or time.",
2930
comment: ""
3031
)
32+
case .syncAlreadyStarted:
33+
return NSLocalizedString("Sync Task already started", comment: "MatrixCore.startSync()")
34+
case .syncNotRunning:
35+
return NSLocalizedString("Sync Task not running", comment: "MatrixCore.stopSync()")
36+
37+
case .actorMissing:
38+
return NSLocalizedString("Did not found MatrixCore instance to use for request", comment: "")
3139
case .creationError:
3240
return NSLocalizedString("Failed to create a new Quake object.", comment: "")
3341
case .batchInsertError:

Sources/MatrixCore/MatrixStoreRoomState.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ public protocol MatrixStoreRoomState {
1414
var stateKey: String { get }
1515
var sender: MatrixFullUserIdentifier? { get }
1616
var content: MatrixStateEventType { get }
17+
18+
init(roomId: String, event: MatrixStateEvent) throws
1719
}

0 commit comments

Comments
 (0)