mirror of https://github.com/oxen-io/session-ios
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			129 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Swift
		
	
			
		
		
	
	
			129 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Swift
		
	
| // Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
 | |
| 
 | |
| import Foundation
 | |
| import GRDB
 | |
| import SessionUtilitiesKit
 | |
| 
 | |
| // MARK: - ConfigColumnAssignment
 | |
| 
 | |
| public struct ConfigColumnAssignment {
 | |
|     var column: ColumnExpression
 | |
|     var assignment: ColumnAssignment
 | |
|     
 | |
|     init(
 | |
|         column: ColumnExpression,
 | |
|         assignment: ColumnAssignment
 | |
|     ) {
 | |
|         self.column = column
 | |
|         self.assignment = assignment
 | |
|     }
 | |
| }
 | |
| 
 | |
| // MARK: - ColumnExpression
 | |
| 
 | |
| extension ColumnExpression {
 | |
|     public func set(to value: (any SQLExpressible)?) -> ConfigColumnAssignment {
 | |
|         ConfigColumnAssignment(column: self, assignment: self.set(to: value))
 | |
|     }
 | |
| }
 | |
| 
 | |
| // MARK: - QueryInterfaceRequest
 | |
| 
 | |
| public extension QueryInterfaceRequest where RowDecoder: FetchableRecord & TableRecord {
 | |
|     
 | |
|     // MARK: -- updateAll
 | |
|     
 | |
|     @discardableResult
 | |
|     func updateAll(
 | |
|         _ db: Database,
 | |
|         _ assignments: ConfigColumnAssignment...
 | |
|     ) throws -> Int {
 | |
|         return try updateAll(db, assignments)
 | |
|     }
 | |
|     
 | |
|     @discardableResult
 | |
|     func updateAll(
 | |
|         _ db: Database,
 | |
|         _ assignments: [ConfigColumnAssignment]
 | |
|     ) throws -> Int {
 | |
|         return try self.updateAll(db, assignments.map { $0.assignment })
 | |
|     }
 | |
|     
 | |
|     @discardableResult
 | |
|     func updateAllAndConfig(
 | |
|         _ db: Database,
 | |
|         calledFromConfig: Bool = false,
 | |
|         _ assignments: ConfigColumnAssignment...
 | |
|     ) throws -> Int {
 | |
|         return try updateAllAndConfig(db, calledFromConfig: calledFromConfig, assignments)
 | |
|     }
 | |
|     
 | |
|     @discardableResult
 | |
|     func updateAllAndConfig(
 | |
|         _ db: Database,
 | |
|         calledFromConfig: Bool = false,
 | |
|         _ assignments: [ConfigColumnAssignment]
 | |
|     ) throws -> Int {
 | |
|         let targetAssignments: [ColumnAssignment] = assignments.map { $0.assignment }
 | |
|         
 | |
|         // Before we do anything custom make sure the changes actually do need to be synced
 | |
|         guard SessionUtil.assignmentsRequireConfigUpdate(assignments) else {
 | |
|             return try self.updateAll(db, targetAssignments)
 | |
|         }
 | |
|         
 | |
|         return try self.updateAndFetchAllAndUpdateConfig(db, calledFromConfig: calledFromConfig, assignments).count
 | |
|     }
 | |
|     
 | |
|     // MARK: -- updateAndFetchAll
 | |
|     
 | |
|     @discardableResult
 | |
|     func updateAndFetchAllAndUpdateConfig(
 | |
|         _ db: Database,
 | |
|         calledFromConfig: Bool = false,
 | |
|         _ assignments: ConfigColumnAssignment...
 | |
|     ) throws -> [RowDecoder] {
 | |
|         return try updateAndFetchAllAndUpdateConfig(db, calledFromConfig: calledFromConfig, assignments)
 | |
|     }
 | |
|     
 | |
|     @discardableResult
 | |
|     func updateAndFetchAllAndUpdateConfig(
 | |
|         _ db: Database,
 | |
|         calledFromConfig: Bool = false,
 | |
|         _ assignments: [ConfigColumnAssignment]
 | |
|     ) throws -> [RowDecoder] {
 | |
|         // First perform the actual updates
 | |
|         let updatedData: [RowDecoder] = try self.updateAndFetchAll(db, assignments.map { $0.assignment })
 | |
|         
 | |
|         // Then check if any of the changes could affect the config
 | |
|         guard
 | |
|             !calledFromConfig &&
 | |
|             SessionUtil.assignmentsRequireConfigUpdate(assignments)
 | |
|         else { return updatedData }
 | |
|         
 | |
|         defer {
 | |
|             // If we changed a column that requires a config update then we may as well automatically
 | |
|             // enqueue a new config sync job once the transaction completes (but only enqueue it once
 | |
|             // per transaction - doing it more than once is pointless)
 | |
|             let userPublicKey: String = getUserHexEncodedPublicKey(db)
 | |
|             
 | |
|             db.afterNextTransactionNestedOnce(dedupeId: SessionUtil.syncDedupeId(userPublicKey)) { db in
 | |
|                 ConfigurationSyncJob.enqueue(db, publicKey: userPublicKey)
 | |
|             }
 | |
|         }
 | |
|         
 | |
|         // Update the config dump state where needed
 | |
|         switch self {
 | |
|             case is QueryInterfaceRequest<Contact>:
 | |
|                 return try SessionUtil.updatingContacts(db, updatedData)
 | |
|                 
 | |
|             case is QueryInterfaceRequest<Profile>:
 | |
|                 return try SessionUtil.updatingProfiles(db, updatedData)
 | |
|                 
 | |
|             case is QueryInterfaceRequest<SessionThread>:
 | |
|                 return try SessionUtil.updatingThreads(db, updatedData)
 | |
|                 
 | |
|             default: return updatedData
 | |
|         }
 | |
|     }
 | |
| }
 |