mirror of https://github.com/oxen-io/session-ios
commit
cc49eca233
@ -0,0 +1,46 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc(SNOpenGroupServerIdLookup)
|
||||
public final class OpenGroupServerIdLookup: NSObject, NSCoding { // NSObject/NSCoding conformance is needed for YapDatabase compatibility
|
||||
@objc public let id: String
|
||||
@objc public let serverId: UInt64
|
||||
@objc public let tsMessageId: String
|
||||
|
||||
// MARK: - Initialization
|
||||
|
||||
@objc public init(server: String, room: String, serverId: UInt64, tsMessageId: String) {
|
||||
self.id = OpenGroupServerIdLookup.id(serverId: serverId, in: room, on: server)
|
||||
self.serverId = serverId
|
||||
self.tsMessageId = tsMessageId
|
||||
|
||||
super.init()
|
||||
}
|
||||
|
||||
private override init() { preconditionFailure("Use init(blindedId:sessionId:) instead.") }
|
||||
|
||||
// MARK: - Coding
|
||||
|
||||
public required init?(coder: NSCoder) {
|
||||
guard let id: String = coder.decodeObject(forKey: "id") as! String? else { return nil }
|
||||
guard let serverId: UInt64 = coder.decodeObject(forKey: "serverId") as! UInt64? else { return nil }
|
||||
guard let tsMessageId: String = coder.decodeObject(forKey: "tsMessageId") as! String? else { return nil }
|
||||
|
||||
self.id = id
|
||||
self.serverId = serverId
|
||||
self.tsMessageId = tsMessageId
|
||||
}
|
||||
|
||||
public func encode(with coder: NSCoder) {
|
||||
coder.encode(id, forKey: "id")
|
||||
coder.encode(serverId, forKey: "serverId")
|
||||
coder.encode(tsMessageId, forKey: "tsMessageId")
|
||||
}
|
||||
|
||||
// MARK: - Convenience
|
||||
|
||||
static func id(serverId: UInt64, in room: String, on server: String) -> String {
|
||||
return "\(server).\(room).\(serverId)"
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
import Foundation
|
||||
|
||||
// MARK: - Atomic<Value>
|
||||
/// The `Atomic<Value>` wrapper is a generic wrapper providing a thread-safe way to get and set a value
|
||||
///
|
||||
/// A write-up on the need for this class and it's approach can be found here:
|
||||
/// https://www.vadimbulavin.com/swift-atomic-properties-with-property-wrappers/
|
||||
/// there is also another approach which can be taken but it requires separate types for collections and results in
|
||||
/// a somewhat inconsistent interface between different `Atomic` wrappers
|
||||
@propertyWrapper
|
||||
public class Atomic<Value> {
|
||||
private let queue: DispatchQueue = DispatchQueue(label: "io.oxen.\(UUID().uuidString)")
|
||||
private var value: Value
|
||||
|
||||
/// In order to change the value you **must** use the `mutate` function
|
||||
public var wrappedValue: Value {
|
||||
return queue.sync { return value }
|
||||
}
|
||||
|
||||
/// For more information see https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md#projections
|
||||
public var projectedValue: Atomic<Value> {
|
||||
return self
|
||||
}
|
||||
|
||||
// MARK: - Initialization
|
||||
public init(_ initialValue: Value) {
|
||||
self.value = initialValue
|
||||
}
|
||||
|
||||
// MARK: - Functions
|
||||
|
||||
public func mutate(_ mutation: (inout Value) -> Void) {
|
||||
return queue.sync {
|
||||
mutation(&value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Atomic where Value: CustomDebugStringConvertible {
|
||||
var debugDescription: String {
|
||||
return value.debugDescription
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc(SNOpenGroupServerIdLookupMigration)
|
||||
public class OpenGroupServerIdLookupMigration: OWSDatabaseMigration {
|
||||
@objc
|
||||
class func migrationId() -> String {
|
||||
return "003"
|
||||
}
|
||||
|
||||
override public func runUp(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
self.doMigrationAsync(completion: completion)
|
||||
}
|
||||
|
||||
private func doMigrationAsync(completion: @escaping OWSDatabaseMigrationCompletion) {
|
||||
var lookups: [OpenGroupServerIdLookup] = []
|
||||
|
||||
Storage.write(with: { transaction in
|
||||
TSGroupThread.enumerateCollectionObjects(with: transaction) { object, _ in
|
||||
guard let thread: TSGroupThread = object as? TSGroupThread else { return }
|
||||
guard let threadId: String = thread.uniqueId else { return }
|
||||
guard let openGroup: OpenGroupV2 = Storage.shared.getV2OpenGroup(for: threadId) else { return }
|
||||
|
||||
thread.enumerateInteractions(with: transaction) { interaction, _ in
|
||||
guard let tsMessage: TSMessage = interaction as? TSMessage else { return }
|
||||
guard let tsMessageId: String = tsMessage.uniqueId else { return }
|
||||
|
||||
lookups.append(
|
||||
OpenGroupServerIdLookup(
|
||||
server: openGroup.server,
|
||||
room: openGroup.room,
|
||||
serverId: tsMessage.openGroupServerMessageID,
|
||||
tsMessageId: tsMessageId
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
lookups.forEach { lookup in
|
||||
Storage.shared.addOpenGroupServerIdLookup(lookup, using: transaction)
|
||||
}
|
||||
self.save(with: transaction) // Intentionally capture self
|
||||
}, completion: {
|
||||
completion()
|
||||
})
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue