mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Further work on the JobRunner
Moved the JobRunner into SessionUtilitiesKit so it can be used by SessionSnodeKit Exposed a 'sharedLokiProject' value on UserDefaults to remove the hard-coded group name used everywhere Added "blocking" job support for 'OnLaunch' and 'OnActive' jobs to the JobRunner (will retry until it succeeds) Added the UpdateProfilePicture and RetrieveDefaultOpenGroupRooms jobs
This commit is contained in:
parent
94742c80ec
commit
3baeb981d9
|
@ -33,6 +33,8 @@ public enum SNMessagingKit { // Just to make the external API nice
|
||||||
JobRunner.add(executor: DisappearingMessagesJob.self, for: .disappearingMessages)
|
JobRunner.add(executor: DisappearingMessagesJob.self, for: .disappearingMessages)
|
||||||
JobRunner.add(executor: FailedMessagesJob.self, for: .failedMessages)
|
JobRunner.add(executor: FailedMessagesJob.self, for: .failedMessages)
|
||||||
JobRunner.add(executor: FailedAttachmentDownloadsJob.self, for: .failedAttachmentDownloads)
|
JobRunner.add(executor: FailedAttachmentDownloadsJob.self, for: .failedAttachmentDownloads)
|
||||||
|
JobRunner.add(executor: UpdateProfilePictureJob.self, for: .updateProfilePicture)
|
||||||
|
JobRunner.add(executor: RetrieveDefaultOpenGroupRoomsJob.self, for: .retrieveDefaultOpenGroupRooms)
|
||||||
JobRunner.add(executor: MessageSendJob.self, for: .messageSend)
|
JobRunner.add(executor: MessageSendJob.self, for: .messageSend)
|
||||||
JobRunner.add(executor: MessageReceiveJob.self, for: .messageReceive)
|
JobRunner.add(executor: MessageReceiveJob.self, for: .messageReceive)
|
||||||
JobRunner.add(executor: NotifyPushServerJob.self, for: .notifyPushServer)
|
JobRunner.add(executor: NotifyPushServerJob.self, for: .notifyPushServer)
|
|
@ -751,7 +751,7 @@
|
||||||
FD17D7A027F40CC800122BE0 /* _001_InitialSetupMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */; };
|
FD17D7A027F40CC800122BE0 /* _001_InitialSetupMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */; };
|
||||||
FD17D7A127F40D2500122BE0 /* GRDBStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F527EAD44C00FF65E7 /* GRDBStorage.swift */; };
|
FD17D7A127F40D2500122BE0 /* GRDBStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F527EAD44C00FF65E7 /* GRDBStorage.swift */; };
|
||||||
FD17D7A227F40F0500122BE0 /* _001_InitialSetupMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79527F3E04600122BE0 /* _001_InitialSetupMigration.swift */; };
|
FD17D7A227F40F0500122BE0 /* _001_InitialSetupMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D79527F3E04600122BE0 /* _001_InitialSetupMigration.swift */; };
|
||||||
FD17D7A427F40F8100122BE0 /* _002_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A327F40F8100122BE0 /* _002_YDBToGRDBMigration.swift */; };
|
FD17D7A427F40F8100122BE0 /* _003_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A327F40F8100122BE0 /* _003_YDBToGRDBMigration.swift */; };
|
||||||
FD17D7A727F41AF000122BE0 /* SSKLegacyModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A627F41AF000122BE0 /* SSKLegacyModels.swift */; };
|
FD17D7A727F41AF000122BE0 /* SSKLegacyModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A627F41AF000122BE0 /* SSKLegacyModels.swift */; };
|
||||||
FD17D7AA27F41BF500122BE0 /* SnodeSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A927F41BF500122BE0 /* SnodeSet.swift */; };
|
FD17D7AA27F41BF500122BE0 /* SnodeSet.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7A927F41BF500122BE0 /* SnodeSet.swift */; };
|
||||||
FD17D7AE27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7AD27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift */; };
|
FD17D7AE27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7AD27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift */; };
|
||||||
|
@ -772,7 +772,7 @@
|
||||||
FD17D7D827F658E200122BE0 /* SSKDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7D727F658E200122BE0 /* SSKDestination.swift */; };
|
FD17D7D827F658E200122BE0 /* SSKDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7D727F658E200122BE0 /* SSKDestination.swift */; };
|
||||||
FD17D7E127F67BD400122BE0 /* SnodeReceivedMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E027F67BD400122BE0 /* SnodeReceivedMessage.swift */; };
|
FD17D7E127F67BD400122BE0 /* SnodeReceivedMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E027F67BD400122BE0 /* SnodeReceivedMessage.swift */; };
|
||||||
FD17D7E527F6A09900122BE0 /* Identity.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E427F6A09900122BE0 /* Identity.swift */; };
|
FD17D7E527F6A09900122BE0 /* Identity.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E427F6A09900122BE0 /* Identity.swift */; };
|
||||||
FD17D7E727F6A16700122BE0 /* _002_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E627F6A16700122BE0 /* _002_YDBToGRDBMigration.swift */; };
|
FD17D7E727F6A16700122BE0 /* _003_YDBToGRDBMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E627F6A16700122BE0 /* _003_YDBToGRDBMigration.swift */; };
|
||||||
FD17D7EA27F6A1C600122BE0 /* SUKLegacyModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E927F6A1C600122BE0 /* SUKLegacyModels.swift */; };
|
FD17D7EA27F6A1C600122BE0 /* SUKLegacyModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD17D7E927F6A1C600122BE0 /* SUKLegacyModels.swift */; };
|
||||||
FD28A4F227E990E800FF65E7 /* BlockingManagerRemovalMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F127E990E800FF65E7 /* BlockingManagerRemovalMigration.swift */; };
|
FD28A4F227E990E800FF65E7 /* BlockingManagerRemovalMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F127E990E800FF65E7 /* BlockingManagerRemovalMigration.swift */; };
|
||||||
FD28A4F427EA79F800FF65E7 /* BlockListUIUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */; };
|
FD28A4F427EA79F800FF65E7 /* BlockListUIUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */; };
|
||||||
|
@ -781,6 +781,9 @@
|
||||||
FD5D200F27AA2B6000FEA984 /* MessageRequestResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5D200E27AA2B6000FEA984 /* MessageRequestResponse.swift */; };
|
FD5D200F27AA2B6000FEA984 /* MessageRequestResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5D200E27AA2B6000FEA984 /* MessageRequestResponse.swift */; };
|
||||||
FD5D201127AA331F00FEA984 /* ConfigurationMessage+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5D201027AA331F00FEA984 /* ConfigurationMessage+Convenience.swift */; };
|
FD5D201127AA331F00FEA984 /* ConfigurationMessage+Convenience.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD5D201027AA331F00FEA984 /* ConfigurationMessage+Convenience.swift */; };
|
||||||
FD659AC027A7649600F12C02 /* MessageRequestsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD659ABF27A7649600F12C02 /* MessageRequestsViewController.swift */; };
|
FD659AC027A7649600F12C02 /* MessageRequestsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD659ABF27A7649600F12C02 /* MessageRequestsViewController.swift */; };
|
||||||
|
FD6A7A692818BE7300035AC1 /* RetrieveDefaultOpenGroupRoomsJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD6A7A682818BE7300035AC1 /* RetrieveDefaultOpenGroupRoomsJob.swift */; };
|
||||||
|
FD6A7A6B2818C17C00035AC1 /* UpdateProfilePictureJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD6A7A6A2818C17C00035AC1 /* UpdateProfilePictureJob.swift */; };
|
||||||
|
FD6A7A6D2818C61500035AC1 /* _002_SetupStandardJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD6A7A6C2818C61500035AC1 /* _002_SetupStandardJobs.swift */; };
|
||||||
FD705A8C278CDB5600F16121 /* SAEScreenLockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD705A8B278CDB5600F16121 /* SAEScreenLockViewController.swift */; };
|
FD705A8C278CDB5600F16121 /* SAEScreenLockViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD705A8B278CDB5600F16121 /* SAEScreenLockViewController.swift */; };
|
||||||
FD705A8E278CE29800F16121 /* String+Localization.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD705A8D278CE29800F16121 /* String+Localization.swift */; };
|
FD705A8E278CE29800F16121 /* String+Localization.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD705A8D278CE29800F16121 /* String+Localization.swift */; };
|
||||||
FD705A90278CEBBC00F16121 /* ShareAppExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD705A8F278CEBBC00F16121 /* ShareAppExtensionContext.swift */; };
|
FD705A90278CEBBC00F16121 /* ShareAppExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD705A8F278CEBBC00F16121 /* ShareAppExtensionContext.swift */; };
|
||||||
|
@ -790,6 +793,11 @@
|
||||||
FD859F0027C4691300510D0C /* MockDataGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD859EFF27C4691300510D0C /* MockDataGenerator.swift */; };
|
FD859F0027C4691300510D0C /* MockDataGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD859EFF27C4691300510D0C /* MockDataGenerator.swift */; };
|
||||||
FD88BAD927A7439C00BBC442 /* MessageRequestsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD88BAD827A7439C00BBC442 /* MessageRequestsCell.swift */; };
|
FD88BAD927A7439C00BBC442 /* MessageRequestsCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD88BAD827A7439C00BBC442 /* MessageRequestsCell.swift */; };
|
||||||
FD88BADB27A750F200BBC442 /* MessageRequestsMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */; };
|
FD88BADB27A750F200BBC442 /* MessageRequestsMigration.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */; };
|
||||||
|
FD90040F2818AB6D00ABAAF6 /* GetSnodePoolJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */; };
|
||||||
|
FD9004122818ABDC00ABAAF6 /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73F280402C4004C14C5 /* Job.swift */; };
|
||||||
|
FD9004142818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */; };
|
||||||
|
FD9004152818B46300ABAAF6 /* JobRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7432804EF1B004C14C5 /* JobRunner.swift */; };
|
||||||
|
FD9004162818B46700ABAAF6 /* JobRunnerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE77F68280F9EDA002CFC5D /* JobRunnerError.swift */; };
|
||||||
FDA8EAFE280E8B78002B68E5 /* FailedMessagesJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EAFD280E8B78002B68E5 /* FailedMessagesJob.swift */; };
|
FDA8EAFE280E8B78002B68E5 /* FailedMessagesJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EAFD280E8B78002B68E5 /* FailedMessagesJob.swift */; };
|
||||||
FDA8EB00280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */; };
|
FDA8EB00280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */; };
|
||||||
FDA8EB09280E90FB002B68E5 /* AppSetup.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF287255B6D85007E1867 /* AppSetup.m */; };
|
FDA8EB09280E90FB002B68E5 /* AppSetup.m in Sources */ = {isa = PBXBuildFile; fileRef = C38EF287255B6D85007E1867 /* AppSetup.m */; };
|
||||||
|
@ -798,12 +806,9 @@
|
||||||
FDC4389E27BA2B8A00C60D73 /* SessionUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A679255388CC00C340D1 /* SessionUtilitiesKit.framework */; };
|
FDC4389E27BA2B8A00C60D73 /* SessionUtilitiesKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C3C2A679255388CC00C340D1 /* SessionUtilitiesKit.framework */; };
|
||||||
FDCDB8DE2810F73B00352A0C /* Differentiable+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCDB8DD2810F73B00352A0C /* Differentiable+Utilities.swift */; };
|
FDCDB8DE2810F73B00352A0C /* Differentiable+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCDB8DD2810F73B00352A0C /* Differentiable+Utilities.swift */; };
|
||||||
FDCDB8E02811007F00352A0C /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCDB8DF2811007F00352A0C /* HomeViewModel.swift */; };
|
FDCDB8E02811007F00352A0C /* HomeViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDCDB8DF2811007F00352A0C /* HomeViewModel.swift */; };
|
||||||
FDE77F69280F9EDA002CFC5D /* JobRunnerError.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE77F68280F9EDA002CFC5D /* JobRunnerError.swift */; };
|
|
||||||
FDE77F6B280FEB28002CFC5D /* ControlMessageProcessRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */; };
|
FDE77F6B280FEB28002CFC5D /* ControlMessageProcessRecord.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */; };
|
||||||
FDF0B73C27FFD3D6004C14C5 /* LinkPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73B27FFD3D6004C14C5 /* LinkPreview.swift */; };
|
FDF0B73C27FFD3D6004C14C5 /* LinkPreview.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73B27FFD3D6004C14C5 /* LinkPreview.swift */; };
|
||||||
FDF0B740280402C4004C14C5 /* Job.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B73F280402C4004C14C5 /* Job.swift */; };
|
|
||||||
FDF0B7422804EA4F004C14C5 /* _002_SetupStandardJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7412804EA4F004C14C5 /* _002_SetupStandardJobs.swift */; };
|
FDF0B7422804EA4F004C14C5 /* _002_SetupStandardJobs.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7412804EA4F004C14C5 /* _002_SetupStandardJobs.swift */; };
|
||||||
FDF0B7442804EF1B004C14C5 /* JobRunner.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7432804EF1B004C14C5 /* JobRunner.swift */; };
|
|
||||||
FDF0B7472804F0CE004C14C5 /* DisappearingMessagesJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7462804F0CE004C14C5 /* DisappearingMessagesJob.swift */; };
|
FDF0B7472804F0CE004C14C5 /* DisappearingMessagesJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B7462804F0CE004C14C5 /* DisappearingMessagesJob.swift */; };
|
||||||
FDF0B74928060D13004C14C5 /* QuotedReplyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B74828060D13004C14C5 /* QuotedReplyModel.swift */; };
|
FDF0B74928060D13004C14C5 /* QuotedReplyModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B74828060D13004C14C5 /* QuotedReplyModel.swift */; };
|
||||||
FDF0B74B28061F7A004C14C5 /* InteractionAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B74A28061F7A004C14C5 /* InteractionAttachment.swift */; };
|
FDF0B74B28061F7A004C14C5 /* InteractionAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = FDF0B74A28061F7A004C14C5 /* InteractionAttachment.swift */; };
|
||||||
|
@ -1815,7 +1820,7 @@
|
||||||
FD17D79827F40AB800122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
|
FD17D79827F40AB800122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
|
||||||
FD17D79B27F40B2E00122BE0 /* SMKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMKLegacyModels.swift; sourceTree = "<group>"; };
|
FD17D79B27F40B2E00122BE0 /* SMKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SMKLegacyModels.swift; sourceTree = "<group>"; };
|
||||||
FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _001_InitialSetupMigration.swift; sourceTree = "<group>"; };
|
FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _001_InitialSetupMigration.swift; sourceTree = "<group>"; };
|
||||||
FD17D7A327F40F8100122BE0 /* _002_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _002_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
|
FD17D7A327F40F8100122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
|
||||||
FD17D7A627F41AF000122BE0 /* SSKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKLegacyModels.swift; sourceTree = "<group>"; };
|
FD17D7A627F41AF000122BE0 /* SSKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKLegacyModels.swift; sourceTree = "<group>"; };
|
||||||
FD17D7A927F41BF500122BE0 /* SnodeSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeSet.swift; sourceTree = "<group>"; };
|
FD17D7A927F41BF500122BE0 /* SnodeSet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeSet.swift; sourceTree = "<group>"; };
|
||||||
FD17D7AD27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeReceivedMessageInfo.swift; sourceTree = "<group>"; };
|
FD17D7AD27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeReceivedMessageInfo.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1836,7 +1841,7 @@
|
||||||
FD17D7D727F658E200122BE0 /* SSKDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKDestination.swift; sourceTree = "<group>"; };
|
FD17D7D727F658E200122BE0 /* SSKDestination.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSKDestination.swift; sourceTree = "<group>"; };
|
||||||
FD17D7E027F67BD400122BE0 /* SnodeReceivedMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeReceivedMessage.swift; sourceTree = "<group>"; };
|
FD17D7E027F67BD400122BE0 /* SnodeReceivedMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SnodeReceivedMessage.swift; sourceTree = "<group>"; };
|
||||||
FD17D7E427F6A09900122BE0 /* Identity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identity.swift; sourceTree = "<group>"; };
|
FD17D7E427F6A09900122BE0 /* Identity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Identity.swift; sourceTree = "<group>"; };
|
||||||
FD17D7E627F6A16700122BE0 /* _002_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _002_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
|
FD17D7E627F6A16700122BE0 /* _003_YDBToGRDBMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _003_YDBToGRDBMigration.swift; sourceTree = "<group>"; };
|
||||||
FD17D7E927F6A1C600122BE0 /* SUKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SUKLegacyModels.swift; sourceTree = "<group>"; };
|
FD17D7E927F6A1C600122BE0 /* SUKLegacyModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SUKLegacyModels.swift; sourceTree = "<group>"; };
|
||||||
FD28A4F127E990E800FF65E7 /* BlockingManagerRemovalMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockingManagerRemovalMigration.swift; sourceTree = "<group>"; };
|
FD28A4F127E990E800FF65E7 /* BlockingManagerRemovalMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockingManagerRemovalMigration.swift; sourceTree = "<group>"; };
|
||||||
FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListUIUtils.swift; sourceTree = "<group>"; };
|
FD28A4F327EA79F800FF65E7 /* BlockListUIUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlockListUIUtils.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1846,6 +1851,9 @@
|
||||||
FD5D200E27AA2B6000FEA984 /* MessageRequestResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestResponse.swift; sourceTree = "<group>"; };
|
FD5D200E27AA2B6000FEA984 /* MessageRequestResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestResponse.swift; sourceTree = "<group>"; };
|
||||||
FD5D201027AA331F00FEA984 /* ConfigurationMessage+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfigurationMessage+Convenience.swift"; sourceTree = "<group>"; };
|
FD5D201027AA331F00FEA984 /* ConfigurationMessage+Convenience.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ConfigurationMessage+Convenience.swift"; sourceTree = "<group>"; };
|
||||||
FD659ABF27A7649600F12C02 /* MessageRequestsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsViewController.swift; sourceTree = "<group>"; };
|
FD659ABF27A7649600F12C02 /* MessageRequestsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsViewController.swift; sourceTree = "<group>"; };
|
||||||
|
FD6A7A682818BE7300035AC1 /* RetrieveDefaultOpenGroupRoomsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RetrieveDefaultOpenGroupRoomsJob.swift; sourceTree = "<group>"; };
|
||||||
|
FD6A7A6A2818C17C00035AC1 /* UpdateProfilePictureJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateProfilePictureJob.swift; sourceTree = "<group>"; };
|
||||||
|
FD6A7A6C2818C61500035AC1 /* _002_SetupStandardJobs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _002_SetupStandardJobs.swift; sourceTree = "<group>"; };
|
||||||
FD705A8B278CDB5600F16121 /* SAEScreenLockViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SAEScreenLockViewController.swift; sourceTree = "<group>"; };
|
FD705A8B278CDB5600F16121 /* SAEScreenLockViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SAEScreenLockViewController.swift; sourceTree = "<group>"; };
|
||||||
FD705A8D278CE29800F16121 /* String+Localization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Localization.swift"; sourceTree = "<group>"; };
|
FD705A8D278CE29800F16121 /* String+Localization.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Localization.swift"; sourceTree = "<group>"; };
|
||||||
FD705A8F278CEBBC00F16121 /* ShareAppExtensionContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAppExtensionContext.swift; sourceTree = "<group>"; };
|
FD705A8F278CEBBC00F16121 /* ShareAppExtensionContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareAppExtensionContext.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1855,6 +1863,8 @@
|
||||||
FD859EFF27C4691300510D0C /* MockDataGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDataGenerator.swift; sourceTree = "<group>"; };
|
FD859EFF27C4691300510D0C /* MockDataGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockDataGenerator.swift; sourceTree = "<group>"; };
|
||||||
FD88BAD827A7439C00BBC442 /* MessageRequestsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsCell.swift; sourceTree = "<group>"; };
|
FD88BAD827A7439C00BBC442 /* MessageRequestsCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsCell.swift; sourceTree = "<group>"; };
|
||||||
FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsMigration.swift; sourceTree = "<group>"; };
|
FD88BADA27A750F200BBC442 /* MessageRequestsMigration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageRequestsMigration.swift; sourceTree = "<group>"; };
|
||||||
|
FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GetSnodePoolJob.swift; sourceTree = "<group>"; };
|
||||||
|
FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = _002_SetupStandardJobs.swift; sourceTree = "<group>"; };
|
||||||
FD9039443F7CB729CF71350E /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
FD9039443F7CB729CF71350E /* Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension/Pods-GlobalDependencies-FrameworkAndExtensionDependencies-SessionNotificationServiceExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
FDA8EAFD280E8B78002B68E5 /* FailedMessagesJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedMessagesJob.swift; sourceTree = "<group>"; };
|
FDA8EAFD280E8B78002B68E5 /* FailedMessagesJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedMessagesJob.swift; sourceTree = "<group>"; };
|
||||||
FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedAttachmentDownloadsJob.swift; sourceTree = "<group>"; };
|
FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FailedAttachmentDownloadsJob.swift; sourceTree = "<group>"; };
|
||||||
|
@ -2853,8 +2863,6 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
FDF0B7452804F0A8004C14C5 /* Types */,
|
FDF0B7452804F0A8004C14C5 /* Types */,
|
||||||
FDF0B7432804EF1B004C14C5 /* JobRunner.swift */,
|
|
||||||
FDE77F68280F9EDA002CFC5D /* JobRunnerError.swift */,
|
|
||||||
C352A2F425574B4700338F3E /* LegacyJob.swift */,
|
C352A2F425574B4700338F3E /* LegacyJob.swift */,
|
||||||
C352A3922557883D00338F3E /* JobDelegate.swift */,
|
C352A3922557883D00338F3E /* JobDelegate.swift */,
|
||||||
C352A3882557876500338F3E /* JobQueue.swift */,
|
C352A3882557876500338F3E /* JobQueue.swift */,
|
||||||
|
@ -3272,6 +3280,7 @@
|
||||||
C3C2A5BA255385ED00C340D1 /* OnionRequestAPI.swift */,
|
C3C2A5BA255385ED00C340D1 /* OnionRequestAPI.swift */,
|
||||||
C3C2A5BB255385ED00C340D1 /* OnionRequestAPI+Encryption.swift */,
|
C3C2A5BB255385ED00C340D1 /* OnionRequestAPI+Encryption.swift */,
|
||||||
C3C2A5BE255385EE00C340D1 /* SnodeAPI.swift */,
|
C3C2A5BE255385EE00C340D1 /* SnodeAPI.swift */,
|
||||||
|
FD90040E2818AB6D00ABAAF6 /* GetSnodePoolJob.swift */,
|
||||||
C3C2A5B6255385EC00C340D1 /* SnodeMessage.swift */,
|
C3C2A5B6255385EC00C340D1 /* SnodeMessage.swift */,
|
||||||
C3C2A5CD255385F300C340D1 /* Utilities */,
|
C3C2A5CD255385F300C340D1 /* Utilities */,
|
||||||
);
|
);
|
||||||
|
@ -3306,6 +3315,7 @@
|
||||||
B8A582AC258C653C00AFD84C /* Crypto */,
|
B8A582AC258C653C00AFD84C /* Crypto */,
|
||||||
B8A582AB258C64E800AFD84C /* Database */,
|
B8A582AB258C64E800AFD84C /* Database */,
|
||||||
B8A582B0258C66C900AFD84C /* General */,
|
B8A582B0258C66C900AFD84C /* General */,
|
||||||
|
FD9004102818ABB000ABAAF6 /* JobRunner */,
|
||||||
B8A582AF258C665E00AFD84C /* Media */,
|
B8A582AF258C665E00AFD84C /* Media */,
|
||||||
B8A582B9258C696200AFD84C /* Messaging */,
|
B8A582B9258C696200AFD84C /* Messaging */,
|
||||||
B8A582AE258C65D000AFD84C /* Networking */,
|
B8A582AE258C65D000AFD84C /* Networking */,
|
||||||
|
@ -3331,7 +3341,6 @@
|
||||||
C3C2A7802553AA6300C340D1 /* Protos */,
|
C3C2A7802553AA6300C340D1 /* Protos */,
|
||||||
C3C2A70A25539DF900C340D1 /* Meta */,
|
C3C2A70A25539DF900C340D1 /* Meta */,
|
||||||
C32C5BB9256DC7C4003C73A2 /* To Do */,
|
C32C5BB9256DC7C4003C73A2 /* To Do */,
|
||||||
C3BBE0752554CDA60050F1E3 /* Configuration.swift */,
|
|
||||||
C3BBE07F2554CDD70050F1E3 /* Storage.swift */,
|
C3BBE07F2554CDD70050F1E3 /* Storage.swift */,
|
||||||
C32C5BCB256DC818003C73A2 /* Database */,
|
C32C5BCB256DC818003C73A2 /* Database */,
|
||||||
C300A5BB2554AFFB00555489 /* Messages */,
|
C300A5BB2554AFFB00555489 /* Messages */,
|
||||||
|
@ -3520,6 +3529,7 @@
|
||||||
C33FD9AC255A548A00E217F9 /* SignalUtilitiesKit */,
|
C33FD9AC255A548A00E217F9 /* SignalUtilitiesKit */,
|
||||||
C331FF1C2558F9D300070591 /* SessionUIKit */,
|
C331FF1C2558F9D300070591 /* SessionUIKit */,
|
||||||
C3C2A6F125539DE700C340D1 /* SessionMessagingKit */,
|
C3C2A6F125539DE700C340D1 /* SessionMessagingKit */,
|
||||||
|
C3BBE0752554CDA60050F1E3 /* Configuration.swift */,
|
||||||
C3C2A5A0255385C100C340D1 /* SessionSnodeKit */,
|
C3C2A5A0255385C100C340D1 /* SessionSnodeKit */,
|
||||||
C3C2A67A255388CC00C340D1 /* SessionUtilitiesKit */,
|
C3C2A67A255388CC00C340D1 /* SessionUtilitiesKit */,
|
||||||
D221A08C169C9E5E00537ABF /* Frameworks */,
|
D221A08C169C9E5E00537ABF /* Frameworks */,
|
||||||
|
@ -3648,7 +3658,6 @@
|
||||||
FD09799A27FFC82D00936362 /* Quote.swift */,
|
FD09799A27FFC82D00936362 /* Quote.swift */,
|
||||||
FDF0B73B27FFD3D6004C14C5 /* LinkPreview.swift */,
|
FDF0B73B27FFD3D6004C14C5 /* LinkPreview.swift */,
|
||||||
FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */,
|
FDE77F6A280FEB28002CFC5D /* ControlMessageProcessRecord.swift */,
|
||||||
FDF0B73F280402C4004C14C5 /* Job.swift */,
|
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3686,7 +3695,8 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */,
|
FD17D79F27F40CC800122BE0 /* _001_InitialSetupMigration.swift */,
|
||||||
FD17D7A327F40F8100122BE0 /* _002_YDBToGRDBMigration.swift */,
|
FD6A7A6C2818C61500035AC1 /* _002_SetupStandardJobs.swift */,
|
||||||
|
FD17D7A327F40F8100122BE0 /* _003_YDBToGRDBMigration.swift */,
|
||||||
);
|
);
|
||||||
path = Migrations;
|
path = Migrations;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3744,7 +3754,8 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
FD17D7C927F546D900122BE0 /* _001_InitialSetupMigration.swift */,
|
FD17D7C927F546D900122BE0 /* _001_InitialSetupMigration.swift */,
|
||||||
FD17D7E627F6A16700122BE0 /* _002_YDBToGRDBMigration.swift */,
|
FD9004132818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift */,
|
||||||
|
FD17D7E627F6A16700122BE0 /* _003_YDBToGRDBMigration.swift */,
|
||||||
);
|
);
|
||||||
path = Migrations;
|
path = Migrations;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -3753,6 +3764,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
FD17D7E427F6A09900122BE0 /* Identity.swift */,
|
FD17D7E427F6A09900122BE0 /* Identity.swift */,
|
||||||
|
FDF0B73F280402C4004C14C5 /* Job.swift */,
|
||||||
FD17D7CC27F546FF00122BE0 /* Setting.swift */,
|
FD17D7CC27F546FF00122BE0 /* Setting.swift */,
|
||||||
);
|
);
|
||||||
path = Models;
|
path = Models;
|
||||||
|
@ -3801,12 +3813,23 @@
|
||||||
path = Views;
|
path = Views;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
FD9004102818ABB000ABAAF6 /* JobRunner */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
FDF0B7432804EF1B004C14C5 /* JobRunner.swift */,
|
||||||
|
FDE77F68280F9EDA002CFC5D /* JobRunnerError.swift */,
|
||||||
|
);
|
||||||
|
path = JobRunner;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
FDF0B7452804F0A8004C14C5 /* Types */ = {
|
FDF0B7452804F0A8004C14C5 /* Types */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
FDF0B7462804F0CE004C14C5 /* DisappearingMessagesJob.swift */,
|
FDF0B7462804F0CE004C14C5 /* DisappearingMessagesJob.swift */,
|
||||||
FDA8EAFD280E8B78002B68E5 /* FailedMessagesJob.swift */,
|
FDA8EAFD280E8B78002B68E5 /* FailedMessagesJob.swift */,
|
||||||
FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */,
|
FDA8EAFF280E8D58002B68E5 /* FailedAttachmentDownloadsJob.swift */,
|
||||||
|
FD6A7A6A2818C17C00035AC1 /* UpdateProfilePictureJob.swift */,
|
||||||
|
FD6A7A682818BE7300035AC1 /* RetrieveDefaultOpenGroupRoomsJob.swift */,
|
||||||
C352A2FE25574B6300338F3E /* MessageSendJob.swift */,
|
C352A2FE25574B6300338F3E /* MessageSendJob.swift */,
|
||||||
C352A31225574F5200338F3E /* MessageReceiveJob.swift */,
|
C352A31225574F5200338F3E /* MessageReceiveJob.swift */,
|
||||||
C352A32E2557549C00338F3E /* NotifyPushServerJob.swift */,
|
C352A32E2557549C00338F3E /* NotifyPushServerJob.swift */,
|
||||||
|
@ -4792,7 +4815,7 @@
|
||||||
C3C2A5C7255385EE00C340D1 /* SnodeAPI.swift in Sources */,
|
C3C2A5C7255385EE00C340D1 /* SnodeAPI.swift in Sources */,
|
||||||
C3C2A5C6255385EE00C340D1 /* Notification+OnionRequestAPI.swift in Sources */,
|
C3C2A5C6255385EE00C340D1 /* Notification+OnionRequestAPI.swift in Sources */,
|
||||||
FD17D7AA27F41BF500122BE0 /* SnodeSet.swift in Sources */,
|
FD17D7AA27F41BF500122BE0 /* SnodeSet.swift in Sources */,
|
||||||
FD17D7A427F40F8100122BE0 /* _002_YDBToGRDBMigration.swift in Sources */,
|
FD17D7A427F40F8100122BE0 /* _003_YDBToGRDBMigration.swift in Sources */,
|
||||||
C3C2A5DC2553860B00C340D1 /* Promise+Threading.swift in Sources */,
|
C3C2A5DC2553860B00C340D1 /* Promise+Threading.swift in Sources */,
|
||||||
C3C2A5C4255385EE00C340D1 /* OnionRequestAPI+Encryption.swift in Sources */,
|
C3C2A5C4255385EE00C340D1 /* OnionRequestAPI+Encryption.swift in Sources */,
|
||||||
FD17D7D227F5797A00122BE0 /* SSKEndpoint.swift in Sources */,
|
FD17D7D227F5797A00122BE0 /* SSKEndpoint.swift in Sources */,
|
||||||
|
@ -4802,9 +4825,11 @@
|
||||||
FD17D7A727F41AF000122BE0 /* SSKLegacyModels.swift in Sources */,
|
FD17D7A727F41AF000122BE0 /* SSKLegacyModels.swift in Sources */,
|
||||||
C3C2A5C2255385EE00C340D1 /* Configuration.swift in Sources */,
|
C3C2A5C2255385EE00C340D1 /* Configuration.swift in Sources */,
|
||||||
FD17D7D827F658E200122BE0 /* SSKDestination.swift in Sources */,
|
FD17D7D827F658E200122BE0 /* SSKDestination.swift in Sources */,
|
||||||
|
FD6A7A6D2818C61500035AC1 /* _002_SetupStandardJobs.swift in Sources */,
|
||||||
FD17D7B327F51E5B00122BE0 /* SSKSetting.swift in Sources */,
|
FD17D7B327F51E5B00122BE0 /* SSKSetting.swift in Sources */,
|
||||||
FD17D7AE27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift in Sources */,
|
FD17D7AE27F41C4300122BE0 /* SnodeReceivedMessageInfo.swift in Sources */,
|
||||||
C3C2A5C3255385EE00C340D1 /* OnionRequestAPI.swift in Sources */,
|
C3C2A5C3255385EE00C340D1 /* OnionRequestAPI.swift in Sources */,
|
||||||
|
FD90040F2818AB6D00ABAAF6 /* GetSnodePoolJob.swift in Sources */,
|
||||||
FD17D7D427F6584600122BE0 /* SSKError.swift in Sources */,
|
FD17D7D427F6584600122BE0 /* SSKError.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
@ -4832,6 +4857,7 @@
|
||||||
B8856E09256F1676001CE70E /* UIDevice+featureSupport.swift in Sources */,
|
B8856E09256F1676001CE70E /* UIDevice+featureSupport.swift in Sources */,
|
||||||
B8856DEF256F161F001CE70E /* NSString+SSK.m in Sources */,
|
B8856DEF256F161F001CE70E /* NSString+SSK.m in Sources */,
|
||||||
FD09796727F6B0B600936362 /* Sodium+Conversion.swift in Sources */,
|
FD09796727F6B0B600936362 /* Sodium+Conversion.swift in Sources */,
|
||||||
|
FD9004122818ABDC00ABAAF6 /* Job.swift in Sources */,
|
||||||
FDF0B74D280664E9004C14C5 /* PersistableRecord+Utilities.swift in Sources */,
|
FDF0B74D280664E9004C14C5 /* PersistableRecord+Utilities.swift in Sources */,
|
||||||
FD09797927FAB7E800936362 /* ImageFormat.swift in Sources */,
|
FD09797927FAB7E800936362 /* ImageFormat.swift in Sources */,
|
||||||
C32C5DC9256DD935003C73A2 /* ProxiedContentDownloader.swift in Sources */,
|
C32C5DC9256DD935003C73A2 /* ProxiedContentDownloader.swift in Sources */,
|
||||||
|
@ -4839,6 +4865,7 @@
|
||||||
C3D9E43125676D3D0040E4F3 /* Configuration.swift in Sources */,
|
C3D9E43125676D3D0040E4F3 /* Configuration.swift in Sources */,
|
||||||
C32C5DD2256DD9E5003C73A2 /* LRUCache.swift in Sources */,
|
C32C5DD2256DD9E5003C73A2 /* LRUCache.swift in Sources */,
|
||||||
FD705A94278D052B00F16121 /* UITableView+ReusableView.swift in Sources */,
|
FD705A94278D052B00F16121 /* UITableView+ReusableView.swift in Sources */,
|
||||||
|
FD9004152818B46300ABAAF6 /* JobRunner.swift in Sources */,
|
||||||
C3A7211A2558BCA10043A11F /* DiffieHellman.swift in Sources */,
|
C3A7211A2558BCA10043A11F /* DiffieHellman.swift in Sources */,
|
||||||
C32C5FA1256DFED5003C73A2 /* NSArray+Functional.m in Sources */,
|
C32C5FA1256DFED5003C73A2 /* NSArray+Functional.m in Sources */,
|
||||||
C3A7225E2558C38D0043A11F /* Promise+Retaining.swift in Sources */,
|
C3A7225E2558C38D0043A11F /* Promise+Retaining.swift in Sources */,
|
||||||
|
@ -4886,16 +4913,18 @@
|
||||||
C32C5A48256DB8F0003C73A2 /* BuildConfiguration.swift in Sources */,
|
C32C5A48256DB8F0003C73A2 /* BuildConfiguration.swift in Sources */,
|
||||||
FD17D7BF27F51F8200122BE0 /* ColumnExpressible.swift in Sources */,
|
FD17D7BF27F51F8200122BE0 /* ColumnExpressible.swift in Sources */,
|
||||||
FD17D7E527F6A09900122BE0 /* Identity.swift in Sources */,
|
FD17D7E527F6A09900122BE0 /* Identity.swift in Sources */,
|
||||||
|
FD9004142818AD0B00ABAAF6 /* _002_SetupStandardJobs.swift in Sources */,
|
||||||
B87EF18126377A1D00124B3C /* Features.swift in Sources */,
|
B87EF18126377A1D00124B3C /* Features.swift in Sources */,
|
||||||
FD09797727FAB7A600936362 /* Data+Image.swift in Sources */,
|
FD09797727FAB7A600936362 /* Data+Image.swift in Sources */,
|
||||||
C300A60D2554B31900555489 /* Logging.swift in Sources */,
|
C300A60D2554B31900555489 /* Logging.swift in Sources */,
|
||||||
B8FF8EA625C11FEF004D1F22 /* IPv4.swift in Sources */,
|
B8FF8EA625C11FEF004D1F22 /* IPv4.swift in Sources */,
|
||||||
C3D9E35525675EE10040E4F3 /* MIMETypeUtil.m in Sources */,
|
C3D9E35525675EE10040E4F3 /* MIMETypeUtil.m in Sources */,
|
||||||
FD705A8E278CE29800F16121 /* String+Localization.swift in Sources */,
|
FD705A8E278CE29800F16121 /* String+Localization.swift in Sources */,
|
||||||
|
FD9004162818B46700ABAAF6 /* JobRunnerError.swift in Sources */,
|
||||||
FD09797227FAA2F500936362 /* Optional+Utilities.swift in Sources */,
|
FD09797227FAA2F500936362 /* Optional+Utilities.swift in Sources */,
|
||||||
C3A7219A2558C1660043A11F /* AnyPromise+Conversion.swift in Sources */,
|
C3A7219A2558C1660043A11F /* AnyPromise+Conversion.swift in Sources */,
|
||||||
C300A6322554B6D100555489 /* NSDate+Timestamp.mm in Sources */,
|
C300A6322554B6D100555489 /* NSDate+Timestamp.mm in Sources */,
|
||||||
FD17D7E727F6A16700122BE0 /* _002_YDBToGRDBMigration.swift in Sources */,
|
FD17D7E727F6A16700122BE0 /* _003_YDBToGRDBMigration.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -4909,7 +4938,6 @@
|
||||||
C3A3A156256E1B91004D228D /* ProtoUtils.m in Sources */,
|
C3A3A156256E1B91004D228D /* ProtoUtils.m in Sources */,
|
||||||
FD09799927FFC1A300936362 /* Attachment.swift in Sources */,
|
FD09799927FFC1A300936362 /* Attachment.swift in Sources */,
|
||||||
C3471ECB2555356A00297E91 /* MessageSender+Encryption.swift in Sources */,
|
C3471ECB2555356A00297E91 /* MessageSender+Encryption.swift in Sources */,
|
||||||
FDE77F69280F9EDA002CFC5D /* JobRunnerError.swift in Sources */,
|
|
||||||
FDF0B74928060D13004C14C5 /* QuotedReplyModel.swift in Sources */,
|
FDF0B74928060D13004C14C5 /* QuotedReplyModel.swift in Sources */,
|
||||||
C352A32F2557549C00338F3E /* NotifyPushServerJob.swift in Sources */,
|
C352A32F2557549C00338F3E /* NotifyPushServerJob.swift in Sources */,
|
||||||
7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */,
|
7B4C75CB26B37E0F0000AC89 /* UnsendRequest.swift in Sources */,
|
||||||
|
@ -4919,6 +4947,7 @@
|
||||||
FD5D201127AA331F00FEA984 /* ConfigurationMessage+Convenience.swift in Sources */,
|
FD5D201127AA331F00FEA984 /* ConfigurationMessage+Convenience.swift in Sources */,
|
||||||
C32C5A13256DB7A5003C73A2 /* PushNotificationAPI.swift in Sources */,
|
C32C5A13256DB7A5003C73A2 /* PushNotificationAPI.swift in Sources */,
|
||||||
C32A026325A801AA000ED5D4 /* NSData+messagePadding.m in Sources */,
|
C32A026325A801AA000ED5D4 /* NSData+messagePadding.m in Sources */,
|
||||||
|
FD6A7A6B2818C17C00035AC1 /* UpdateProfilePictureJob.swift in Sources */,
|
||||||
C352A3932557883D00338F3E /* JobDelegate.swift in Sources */,
|
C352A3932557883D00338F3E /* JobDelegate.swift in Sources */,
|
||||||
C32C5B84256DC54F003C73A2 /* SSKEnvironment.m in Sources */,
|
C32C5B84256DC54F003C73A2 /* SSKEnvironment.m in Sources */,
|
||||||
C3A3A108256E1A5C004D228D /* OWSIncomingMessageFinder.m in Sources */,
|
C3A3A108256E1A5C004D228D /* OWSIncomingMessageFinder.m in Sources */,
|
||||||
|
@ -4937,7 +4966,6 @@
|
||||||
C32C5CA4256DD1DC003C73A2 /* TSAccountManager.m in Sources */,
|
C32C5CA4256DD1DC003C73A2 /* TSAccountManager.m in Sources */,
|
||||||
C352A3892557876500338F3E /* JobQueue.swift in Sources */,
|
C352A3892557876500338F3E /* JobQueue.swift in Sources */,
|
||||||
C3BBE0B52554F0E10050F1E3 /* ProofOfWork.swift in Sources */,
|
C3BBE0B52554F0E10050F1E3 /* ProofOfWork.swift in Sources */,
|
||||||
FDF0B740280402C4004C14C5 /* Job.swift in Sources */,
|
|
||||||
C32C59C1256DB41F003C73A2 /* TSGroupThread.m in Sources */,
|
C32C59C1256DB41F003C73A2 /* TSGroupThread.m in Sources */,
|
||||||
C3A3A08F256E1728004D228D /* FullTextSearchFinder.swift in Sources */,
|
C3A3A08F256E1728004D228D /* FullTextSearchFinder.swift in Sources */,
|
||||||
FDF0B7472804F0CE004C14C5 /* DisappearingMessagesJob.swift in Sources */,
|
FDF0B7472804F0CE004C14C5 /* DisappearingMessagesJob.swift in Sources */,
|
||||||
|
@ -4990,6 +5018,7 @@
|
||||||
C32C5E15256DDC78003C73A2 /* SSKPreferences.swift in Sources */,
|
C32C5E15256DDC78003C73A2 /* SSKPreferences.swift in Sources */,
|
||||||
C32C5D9C256DD6DC003C73A2 /* OWSOutgoingReceiptManager.m in Sources */,
|
C32C5D9C256DD6DC003C73A2 /* OWSOutgoingReceiptManager.m in Sources */,
|
||||||
C32C5C4F256DCC36003C73A2 /* Storage+OpenGroups.swift in Sources */,
|
C32C5C4F256DCC36003C73A2 /* Storage+OpenGroups.swift in Sources */,
|
||||||
|
FD6A7A692818BE7300035AC1 /* RetrieveDefaultOpenGroupRoomsJob.swift in Sources */,
|
||||||
C3DA9C0725AE7396008F7C7E /* ConfigurationMessage.swift in Sources */,
|
C3DA9C0725AE7396008F7C7E /* ConfigurationMessage.swift in Sources */,
|
||||||
B8856CEE256F1054001CE70E /* OWSAudioPlayer.m in Sources */,
|
B8856CEE256F1054001CE70E /* OWSAudioPlayer.m in Sources */,
|
||||||
FD5D200F27AA2B6000FEA984 /* MessageRequestResponse.swift in Sources */,
|
FD5D200F27AA2B6000FEA984 /* MessageRequestResponse.swift in Sources */,
|
||||||
|
@ -5018,7 +5047,6 @@
|
||||||
C3A3A0EC256E1949004D228D /* OWSRecipientIdentity.m in Sources */,
|
C3A3A0EC256E1949004D228D /* OWSRecipientIdentity.m in Sources */,
|
||||||
FDF0B74B28061F7A004C14C5 /* InteractionAttachment.swift in Sources */,
|
FDF0B74B28061F7A004C14C5 /* InteractionAttachment.swift in Sources */,
|
||||||
B8F5F56525EC8453003BF8D4 /* Notification+Contacts.swift in Sources */,
|
B8F5F56525EC8453003BF8D4 /* Notification+Contacts.swift in Sources */,
|
||||||
FDF0B7442804EF1B004C14C5 /* JobRunner.swift in Sources */,
|
|
||||||
C32C5AB2256DBE8F003C73A2 /* TSMessage.m in Sources */,
|
C32C5AB2256DBE8F003C73A2 /* TSMessage.m in Sources */,
|
||||||
FD09796E27FA6D0000936362 /* Contact.swift in Sources */,
|
FD09796E27FA6D0000936362 /* Contact.swift in Sources */,
|
||||||
C3A3A0FE256E1A3C004D228D /* TSDatabaseSecondaryIndexes.m in Sources */,
|
C3A3A0FE256E1A3C004D228D /* TSDatabaseSecondaryIndexes.m in Sources */,
|
||||||
|
|
|
@ -165,16 +165,10 @@ final class HomeVC: BaseVC, UITableViewDataSource, UITableViewDelegate, NewConve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-populate snode pool if needed
|
|
||||||
SnodeAPI.getSnodePool().retainUntilComplete()
|
|
||||||
|
|
||||||
// Onion request path countries cache
|
// Onion request path countries cache
|
||||||
DispatchQueue.global(qos: .utility).sync {
|
DispatchQueue.global(qos: .utility).sync {
|
||||||
let _ = IP2Country.shared.populateCacheIfNeeded()
|
let _ = IP2Country.shared.populateCacheIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get default open group rooms if needed
|
|
||||||
OpenGroupAPIV2.getDefaultRoomsIfNeeded()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillAppear(_ animated: Bool) {
|
override func viewWillAppear(_ animated: Bool) {
|
||||||
|
|
|
@ -162,9 +162,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||||
func applicationDidBecomeActive(_ application: UIApplication) {
|
func applicationDidBecomeActive(_ application: UIApplication) {
|
||||||
guard !CurrentAppContext().isRunningTests else { return }
|
guard !CurrentAppContext().isRunningTests else { return }
|
||||||
|
|
||||||
// FIXME: We should move this somewhere to prevent typos from breaking it
|
UserDefaults.sharedLokiProject?[.isMainAppActive] = true
|
||||||
let sharedUserDefaults: UserDefaults? = UserDefaults(suiteName: "group.com.loki-project.loki-messenger")
|
|
||||||
sharedUserDefaults?[.isMainAppActive] = true
|
|
||||||
|
|
||||||
ensureRootViewController()
|
ensureRootViewController()
|
||||||
adapt(appMode: AppModeManager.getAppModeOrSystemDefault())
|
adapt(appMode: AppModeManager.getAppModeOrSystemDefault())
|
||||||
|
@ -186,8 +184,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||||
func applicationWillResignActive(_ application: UIApplication) {
|
func applicationWillResignActive(_ application: UIApplication) {
|
||||||
clearAllNotificationsAndRestoreBadgeCount()
|
clearAllNotificationsAndRestoreBadgeCount()
|
||||||
|
|
||||||
let sharedUserDefaults: UserDefaults? = UserDefaults(suiteName: "group.com.loki-project.loki-messenger")
|
UserDefaults.sharedLokiProject?[.isMainAppActive] = false
|
||||||
sharedUserDefaults?[.isMainAppActive] = false
|
|
||||||
|
|
||||||
DDLog.flushLog()
|
DDLog.flushLog()
|
||||||
}
|
}
|
||||||
|
@ -258,7 +255,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterD
|
||||||
enableBackgroundRefreshIfNecessary()
|
enableBackgroundRefreshIfNecessary()
|
||||||
JobRunner.appDidBecomeActive()
|
JobRunner.appDidBecomeActive()
|
||||||
|
|
||||||
SnodeAPI.getSnodePool().retainUntilComplete()
|
|
||||||
startPollersIfNeeded()
|
startPollersIfNeeded()
|
||||||
|
|
||||||
if CurrentAppContext().isMainApp {
|
if CurrentAppContext().isMainApp {
|
||||||
|
|
|
@ -226,9 +226,8 @@ NSString *const ReportedApplicationStateDidChangeNotification = @"ReportedApplic
|
||||||
- (void)setMainAppBadgeNumber:(NSInteger)value
|
- (void)setMainAppBadgeNumber:(NSInteger)value
|
||||||
{
|
{
|
||||||
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:value];
|
[[UIApplication sharedApplication] setApplicationIconBadgeNumber:value];
|
||||||
NSUserDefaults *sharedUserDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.loki-project.loki-messenger"];
|
[[NSUserDefaults sharedLokiProject] setInteger:value forKey:@"currentBadgeNumber"];
|
||||||
[sharedUserDefaults setInteger:value forKey:@"currentBadgeNumber"];
|
[[NSUserDefaults sharedLokiProject] synchronize];
|
||||||
[sharedUserDefaults synchronize];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (nullable UIViewController *)frontmostViewController
|
- (nullable UIViewController *)frontmostViewController
|
||||||
|
|
|
@ -8,7 +8,7 @@ import SessionMessagingKit
|
||||||
import SessionUtilitiesKit
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
public enum SyncPushTokensJob: JobExecutor {
|
public enum SyncPushTokensJob: JobExecutor {
|
||||||
public static let maxFailureCount: UInt = 0
|
public static let maxFailureCount: Int = -1
|
||||||
public static let requiresThreadId: Bool = false
|
public static let requiresThreadId: Bool = false
|
||||||
public static let requiresInteractionId: Bool = false
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
@ -18,12 +18,8 @@ public enum SyncPushTokensJob: JobExecutor {
|
||||||
failure: @escaping (Job, Error?, Bool) -> (),
|
failure: @escaping (Job, Error?, Bool) -> (),
|
||||||
deferred: @escaping (Job) -> ()
|
deferred: @escaping (Job) -> ()
|
||||||
) {
|
) {
|
||||||
// Don't schedule run when inactive or not in main app
|
// Don't run when inactive or not in main app
|
||||||
var isMainAppActive = false
|
guard (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) else {
|
||||||
if let sharedUserDefaults = UserDefaults(suiteName: "group.com.loki-project.loki-messenger") {
|
|
||||||
isMainAppActive = sharedUserDefaults[.isMainAppActive]
|
|
||||||
}
|
|
||||||
guard isMainAppActive else {
|
|
||||||
deferred(job) // Don't need to do anything if it's not the main app
|
deferred(job) // Don't need to do anything if it's not the main app
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,29 +278,5 @@ enum _001_InitialSetupMigration: Migration {
|
||||||
|
|
||||||
t.uniqueKey([.threadId, .sentTimestampMs, .serverHash, .openGroupMessageServerId])
|
t.uniqueKey([.threadId, .sentTimestampMs, .serverHash, .openGroupMessageServerId])
|
||||||
}
|
}
|
||||||
|
|
||||||
try db.create(table: Job.self) { t in
|
|
||||||
t.column(.id, .integer)
|
|
||||||
.notNull()
|
|
||||||
.primaryKey(autoincrement: true)
|
|
||||||
t.column(.failureCount, .integer)
|
|
||||||
.notNull()
|
|
||||||
.defaults(to: 0)
|
|
||||||
t.column(.variant, .integer)
|
|
||||||
.notNull()
|
|
||||||
.indexed() // Quicker querying
|
|
||||||
t.column(.behaviour, .integer).notNull() // TODO: Indexed???
|
|
||||||
t.column(.nextRunTimestamp, .double)
|
|
||||||
.notNull() // TODO: Should this just be nullable??? (or do we want to fetch by this?)
|
|
||||||
.indexed() // Quicker querying
|
|
||||||
.defaults(to: 0)
|
|
||||||
t.column(.threadId, .text)
|
|
||||||
.indexed() // Quicker querying
|
|
||||||
.references(SessionThread.self, onDelete: .cascade) // Delete if thread deleted
|
|
||||||
t.column(.interactionId, .text)
|
|
||||||
.indexed() // Quicker querying
|
|
||||||
.references(Interaction.self, onDelete: .cascade) // Delete if interaction deleted
|
|
||||||
t.column(.details, .blob)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,32 +17,28 @@ enum _002_SetupStandardJobs: Migration {
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
// TODO: Add additional jobs from the AppDelegate
|
// TODO: Add additional jobs from the AppDelegate
|
||||||
_ = try Job(
|
_ = try Job(
|
||||||
failureCount: 0,
|
|
||||||
variant: .disappearingMessages,
|
variant: .disappearingMessages,
|
||||||
behaviour: .recurringOnLaunch,
|
behaviour: .recurringOnLaunchBlockingOncePerSession
|
||||||
nextRunTimestamp: 0
|
|
||||||
).inserted(db)
|
).inserted(db)
|
||||||
|
|
||||||
_ = try Job(
|
_ = try Job(
|
||||||
failureCount: 0,
|
|
||||||
variant: .failedMessages,
|
variant: .failedMessages,
|
||||||
behaviour: .recurringOnLaunch,
|
behaviour: .recurringOnLaunchBlocking
|
||||||
nextRunTimestamp: 0
|
|
||||||
).inserted(db)
|
).inserted(db)
|
||||||
|
|
||||||
_ = try Job(
|
_ = try Job(
|
||||||
failureCount: 0,
|
|
||||||
variant: .failedAttachmentDownloads,
|
variant: .failedAttachmentDownloads,
|
||||||
behaviour: .recurringOnLaunch,
|
behaviour: .recurringOnLaunchBlocking
|
||||||
nextRunTimestamp: 0
|
|
||||||
).inserted(db)
|
).inserted(db)
|
||||||
|
|
||||||
// Note: This job exists in the 'Session' target but that doesn't have it's own migrations
|
|
||||||
_ = try Job(
|
_ = try Job(
|
||||||
failureCount: 0,
|
variant: .updateProfilePicture,
|
||||||
variant: .syncPushTokens,
|
behaviour: .recurringOnActive
|
||||||
behaviour: .recurringOnLaunch,
|
).inserted(db)
|
||||||
nextRunTimestamp: 0
|
|
||||||
|
_ = try Job(
|
||||||
|
variant: .retrieveDefaultOpenGroupRooms,
|
||||||
|
behaviour: .recurringOnActive
|
||||||
).inserted(db)
|
).inserted(db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,6 +334,11 @@ public struct Interaction: Codable, Identifiable, Equatable, FetchableRecord, Mu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete any jobs associated to this interaction
|
||||||
|
try Job
|
||||||
|
.filter(Job.Columns.interactionId == id)
|
||||||
|
.deleteAll(db)
|
||||||
|
|
||||||
return try performDelete(db)
|
return try performDelete(db)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,6 +120,17 @@ public struct SessionThread: Codable, Identifiable, Equatable, FetchableRecord,
|
||||||
self.notificationSound = notificationSound
|
self.notificationSound = notificationSound
|
||||||
self.mutedUntilTimestamp = mutedUntilTimestamp
|
self.mutedUntilTimestamp = mutedUntilTimestamp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - Custom Database Interaction
|
||||||
|
|
||||||
|
public func delete(_ db: Database) throws -> Bool {
|
||||||
|
// Delete any jobs associated to this thread
|
||||||
|
try Job
|
||||||
|
.filter(Job.Columns.threadId == id)
|
||||||
|
.deleteAll(db)
|
||||||
|
|
||||||
|
return try performDelete(db)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - GRDB Interactions
|
// MARK: - GRDB Interactions
|
||||||
|
|
|
@ -7,7 +7,7 @@ import SessionSnodeKit
|
||||||
import SignalCoreKit
|
import SignalCoreKit
|
||||||
|
|
||||||
public enum AttachmentDownloadJob: JobExecutor {
|
public enum AttachmentDownloadJob: JobExecutor {
|
||||||
public static var maxFailureCount: UInt = 10
|
public static var maxFailureCount: Int = 10
|
||||||
public static var requiresThreadId: Bool = true
|
public static var requiresThreadId: Bool = true
|
||||||
public static let requiresInteractionId: Bool = true
|
public static let requiresInteractionId: Bool = true
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import GRDB
|
||||||
import SessionUtilitiesKit
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
public enum DisappearingMessagesJob: JobExecutor {
|
public enum DisappearingMessagesJob: JobExecutor {
|
||||||
public static let maxFailureCount: UInt = 0
|
public static let maxFailureCount: Int = -1
|
||||||
public static let requiresThreadId: Bool = false
|
public static let requiresThreadId: Bool = false
|
||||||
public static let requiresInteractionId: Bool = false
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
@ -25,8 +25,15 @@ public enum DisappearingMessagesJob: JobExecutor {
|
||||||
.filter(sql: "(\(Interaction.Columns.expiresStartedAtMs) + (\(Interaction.Columns.expiresInSeconds) * 1000) <= \(timestampNowMs)")
|
.filter(sql: "(\(Interaction.Columns.expiresStartedAtMs) + (\(Interaction.Columns.expiresInSeconds) * 1000) <= \(timestampNowMs)")
|
||||||
.deleteAll(db)
|
.deleteAll(db)
|
||||||
|
|
||||||
// Update the next run timestamp for the DisappearingMessagesJob
|
// Update the next run timestamp for the DisappearingMessagesJob (if the call
|
||||||
|
// to 'updateNextRunIfNeeded' returns 'nil' then it doesn't need to re-run so
|
||||||
|
// should have it's 'nextRunTimestamp' cleared)
|
||||||
return updateNextRunIfNeeded(db)
|
return updateNextRunIfNeeded(db)
|
||||||
|
.defaulting(
|
||||||
|
to: try job
|
||||||
|
.with(nextRunTimestamp: 0)
|
||||||
|
.saved(db)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
success(updatedJob ?? job, false)
|
success(updatedJob ?? job, false)
|
||||||
|
@ -40,12 +47,8 @@ public enum DisappearingMessagesJob: JobExecutor {
|
||||||
|
|
||||||
public extension DisappearingMessagesJob {
|
public extension DisappearingMessagesJob {
|
||||||
@discardableResult static func updateNextRunIfNeeded(_ db: Database) -> Job? {
|
@discardableResult static func updateNextRunIfNeeded(_ db: Database) -> Job? {
|
||||||
// Don't schedule run when inactive or not in main app
|
// Don't run when inactive or not in main app
|
||||||
var isMainAppActive = false
|
guard (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) else { return nil }
|
||||||
if let sharedUserDefaults = UserDefaults(suiteName: "group.com.loki-project.loki-messenger") {
|
|
||||||
isMainAppActive = sharedUserDefaults[.isMainAppActive]
|
|
||||||
}
|
|
||||||
guard isMainAppActive else { return nil }
|
|
||||||
|
|
||||||
// If there is another expiring message then update the job to run 1 second after it's meant to expire
|
// If there is another expiring message then update the job to run 1 second after it's meant to expire
|
||||||
let nextExpirationTimestampMs: Double? = try? Double
|
let nextExpirationTimestampMs: Double? = try? Double
|
||||||
|
|
|
@ -6,7 +6,7 @@ import SignalCoreKit
|
||||||
import SessionUtilitiesKit
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
public enum FailedAttachmentDownloadsJob: JobExecutor {
|
public enum FailedAttachmentDownloadsJob: JobExecutor {
|
||||||
public static let maxFailureCount: UInt = 0
|
public static let maxFailureCount: Int = -1
|
||||||
public static let requiresThreadId: Bool = false
|
public static let requiresThreadId: Bool = false
|
||||||
public static let requiresInteractionId: Bool = false
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import SignalCoreKit
|
||||||
import SessionUtilitiesKit
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
public enum FailedMessagesJob: JobExecutor {
|
public enum FailedMessagesJob: JobExecutor {
|
||||||
public static let maxFailureCount: UInt = 0
|
public static let maxFailureCount: Int = -1
|
||||||
public static let requiresThreadId: Bool = false
|
public static let requiresThreadId: Bool = false
|
||||||
public static let requiresInteractionId: Bool = false
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import PromiseKit
|
||||||
import SessionUtilitiesKit
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
public enum MessageReceiveJob: JobExecutor {
|
public enum MessageReceiveJob: JobExecutor {
|
||||||
public static var maxFailureCount: UInt = 10
|
public static var maxFailureCount: Int = 10
|
||||||
public static var requiresThreadId: Bool = true
|
public static var requiresThreadId: Bool = true
|
||||||
public static let requiresInteractionId: Bool = false
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import SessionUtilitiesKit
|
||||||
import SessionSnodeKit
|
import SessionSnodeKit
|
||||||
|
|
||||||
public enum MessageSendJob: JobExecutor {
|
public enum MessageSendJob: JobExecutor {
|
||||||
public static var maxFailureCount: UInt = 10
|
public static var maxFailureCount: Int = 10
|
||||||
public static var requiresThreadId: Bool = true
|
public static var requiresThreadId: Bool = true
|
||||||
public static let requiresInteractionId: Bool = false // Some messages don't have interactions
|
public static let requiresInteractionId: Bool = false // Some messages don't have interactions
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import SessionSnodeKit
|
||||||
import SessionUtilitiesKit
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
public enum NotifyPushServerJob: JobExecutor {
|
public enum NotifyPushServerJob: JobExecutor {
|
||||||
public static var maxFailureCount: UInt = 20
|
public static var maxFailureCount: Int = 20
|
||||||
public static var requiresThreadId: Bool = false
|
public static var requiresThreadId: Bool = false
|
||||||
public static let requiresInteractionId: Bool = false
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import GRDB
|
||||||
|
import SignalCoreKit
|
||||||
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
|
public enum RetrieveDefaultOpenGroupRoomsJob: JobExecutor {
|
||||||
|
public static let maxFailureCount: Int = -1
|
||||||
|
public static let requiresThreadId: Bool = false
|
||||||
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
public static func run(
|
||||||
|
_ job: Job,
|
||||||
|
success: @escaping (Job, Bool) -> (),
|
||||||
|
failure: @escaping (Job, Error?, Bool) -> (),
|
||||||
|
deferred: @escaping (Job) -> ()
|
||||||
|
) {
|
||||||
|
// Don't run when inactive or not in main app
|
||||||
|
guard (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) else {
|
||||||
|
deferred(job) // Don't need to do anything if it's not the main app
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGroupAPIV2.getDefaultRoomsIfNeeded()
|
||||||
|
.done { _ in success(job, false) }
|
||||||
|
.catch { error in failure(job, error, false) }
|
||||||
|
.retainUntilComplete()
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,7 +6,7 @@ import PromiseKit
|
||||||
import SessionUtilitiesKit
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
public enum SendReadReceiptsJob: JobExecutor {
|
public enum SendReadReceiptsJob: JobExecutor {
|
||||||
public static let maxFailureCount: UInt = 0
|
public static let maxFailureCount: Int = -1
|
||||||
public static let requiresThreadId: Bool = false
|
public static let requiresThreadId: Bool = false
|
||||||
public static let requiresInteractionId: Bool = false
|
public static let requiresInteractionId: Bool = false
|
||||||
private static let minRunFrequency: TimeInterval = 3
|
private static let minRunFrequency: TimeInterval = 3
|
||||||
|
|
46
SessionMessagingKit/Jobs/Types/UpdateProfilePictureJob.swift
Normal file
46
SessionMessagingKit/Jobs/Types/UpdateProfilePictureJob.swift
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import GRDB
|
||||||
|
import SignalCoreKit
|
||||||
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
|
public enum UpdateProfilePictureJob: JobExecutor {
|
||||||
|
public static let maxFailureCount: Int = -1
|
||||||
|
public static let requiresThreadId: Bool = false
|
||||||
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
public static func run(
|
||||||
|
_ job: Job,
|
||||||
|
success: @escaping (Job, Bool) -> (),
|
||||||
|
failure: @escaping (Job, Error?, Bool) -> (),
|
||||||
|
deferred: @escaping (Job) -> ()
|
||||||
|
) {
|
||||||
|
// Don't run when inactive or not in main app
|
||||||
|
guard (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) else {
|
||||||
|
deferred(job) // Don't need to do anything if it's not the main app
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only re-upload the profile picture if enough time has passed since the last upload
|
||||||
|
guard
|
||||||
|
let lastProfilePictureUpload: Date = UserDefaults.standard[.lastProfilePictureUpload],
|
||||||
|
Date().timeIntervalSince(lastProfilePictureUpload) > (14 * 24 * 60 * 60)
|
||||||
|
else {
|
||||||
|
deferred(job)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: The user defaults flag is updated in ProfileManager
|
||||||
|
let profile: Profile = Profile.fetchOrCreateCurrentUser()
|
||||||
|
let profilePicture: UIImage? = ProfileManager.profileAvatar(id: profile.id)
|
||||||
|
|
||||||
|
ProfileManager.updateLocal(
|
||||||
|
profileName: profile.name,
|
||||||
|
avatarImage: profilePicture,
|
||||||
|
requiredSync: true,
|
||||||
|
success: { success(job, false) },
|
||||||
|
failure: { error in failure(job, error, false) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,9 +11,4 @@ extension OpenGroupAPIV2 {
|
||||||
public static func objc_isUserModerator(_ publicKey: String, for room: String, on server: String) -> Bool {
|
public static func objc_isUserModerator(_ publicKey: String, for room: String, on server: String) -> Bool {
|
||||||
return isUserModerator(publicKey, for: room, on: server)
|
return isUserModerator(publicKey, for: room, on: server)
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc(getDefaultRoomsIfNeeded)
|
|
||||||
public static func objc_getDefaultRoomsIfNeeded() {
|
|
||||||
getDefaultRoomsIfNeeded()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ extension MessageReceiver {
|
||||||
///
|
///
|
||||||
/// **Note:** This is a slightly optimised version of the `decryptWithSessionProtocol` function which just skips
|
/// **Note:** This is a slightly optimised version of the `decryptWithSessionProtocol` function which just skips
|
||||||
/// the validation (handled when the job actually runs) and doesn't throw
|
/// the validation (handled when the job actually runs) and doesn't throw
|
||||||
internal static func extractSenderPublicKey(_ db: Database, from envelope: SNProtoEnvelope) -> String? {
|
public static func extractSenderPublicKey(_ db: Database, from envelope: SNProtoEnvelope) -> String? {
|
||||||
guard
|
guard
|
||||||
let ciphertext: Data = envelope.content,
|
let ciphertext: Data = envelope.content,
|
||||||
let userX25519KeyPair: Box.KeyPair = Identity.fetchUserKeyPair(db)
|
let userX25519KeyPair: Box.KeyPair = Identity.fetchUserKeyPair(db)
|
||||||
|
|
|
@ -29,11 +29,7 @@ extension MessageReceiver {
|
||||||
default: fatalError()
|
default: fatalError()
|
||||||
}
|
}
|
||||||
|
|
||||||
var isMainAppActive = false
|
guard (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) else { return }
|
||||||
if let sharedUserDefaults = UserDefaults(suiteName: "group.com.loki-project.loki-messenger") {
|
|
||||||
isMainAppActive = sharedUserDefaults[.isMainAppActive]
|
|
||||||
}
|
|
||||||
guard isMainAppActive else { return }
|
|
||||||
|
|
||||||
// Touch the thread to update the home screen preview
|
// Touch the thread to update the home screen preview
|
||||||
let storage = SNMessagingKitConfiguration.shared.storage
|
let storage = SNMessagingKitConfiguration.shared.storage
|
||||||
|
@ -399,11 +395,7 @@ extension MessageReceiver {
|
||||||
|
|
||||||
// Note: `message.sentTimestamp` is in ms
|
// Note: `message.sentTimestamp` is in ms
|
||||||
let messageSentTimestamp: TimeInterval = TimeInterval((message.sentTimestamp ?? 0) / 1000)
|
let messageSentTimestamp: TimeInterval = TimeInterval((message.sentTimestamp ?? 0) / 1000)
|
||||||
|
let isMainAppActive: Bool = (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false)
|
||||||
var isMainAppActive = false
|
|
||||||
if let sharedUserDefaults = UserDefaults(suiteName: "group.com.loki-project.loki-messenger") {
|
|
||||||
isMainAppActive = sharedUserDefaults[.isMainAppActive]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse & persist attachments
|
// Parse & persist attachments
|
||||||
|
|
||||||
|
|
|
@ -89,10 +89,7 @@ public final class MessageSender : NSObject {
|
||||||
let (promise, seal) = Promise<Void>.pending()
|
let (promise, seal) = Promise<Void>.pending()
|
||||||
let userPublicKey: String = getUserHexEncodedPublicKey(db)
|
let userPublicKey: String = getUserHexEncodedPublicKey(db)
|
||||||
|
|
||||||
var isMainAppActive = false
|
let isMainAppActive: Bool = (UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false)
|
||||||
if let sharedUserDefaults = UserDefaults(suiteName: "group.com.loki-project.loki-messenger") {
|
|
||||||
isMainAppActive = sharedUserDefaults[.isMainAppActive]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the timestamp, sender and recipient
|
// Set the timestamp, sender and recipient
|
||||||
if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set
|
if message.sentTimestamp == nil { // Visible messages will already have their sent timestamp set
|
||||||
|
|
|
@ -124,31 +124,39 @@ public final class ClosedGroupPoller : NSObject {
|
||||||
SNLog("Received \(messages.count) new message(s) in closed group with public key: \(groupPublicKey).")
|
SNLog("Received \(messages.count) new message(s) in closed group with public key: \(groupPublicKey).")
|
||||||
|
|
||||||
GRDBStorage.shared.write { db in
|
GRDBStorage.shared.write { db in
|
||||||
|
var jobDetailMessages: [MessageReceiveJob.Details.MessageInfo] = []
|
||||||
|
|
||||||
messages.forEach { message in
|
messages.forEach { message in
|
||||||
guard let envelope = SNProtoEnvelope.from(message) else { return }
|
guard let envelope = SNProtoEnvelope.from(message) else { return }
|
||||||
|
|
||||||
do {
|
do {
|
||||||
JobRunner.add(
|
jobDetailMessages.append(
|
||||||
db,
|
MessageReceiveJob.Details.MessageInfo(
|
||||||
job: Job(
|
data: try envelope.serializedData(),
|
||||||
variant: .messageReceive,
|
serverHash: message.info.hash
|
||||||
behaviour: .runOnce,
|
|
||||||
threadId: groupPublicKey,
|
|
||||||
details: MessageReceiveJob.Details(
|
|
||||||
data: try envelope.serializedData(),
|
|
||||||
serverHash: message.info.hash,
|
|
||||||
isBackgroundPoll: false
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Persist the received message after the MessageReceiveJob is created
|
// Persist the received message after the MessageReceiveJob is created
|
||||||
try message.info.save(db)
|
_ = try message.info.saved(db)
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
SNLog("Failed to deserialize envelope due to error: \(error).")
|
SNLog("Failed to deserialize envelope due to error: \(error).")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JobRunner.add(
|
||||||
|
db,
|
||||||
|
job: Job(
|
||||||
|
variant: .messageReceive,
|
||||||
|
behaviour: .runOnce,
|
||||||
|
threadId: groupPublicKey,
|
||||||
|
details: MessageReceiveJob.Details(
|
||||||
|
messages: jobDetailMessages,
|
||||||
|
isBackgroundPoll: false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,9 @@ public final class Poller : NSObject {
|
||||||
|
|
||||||
private func poll(_ snode: Snode, seal longTermSeal: Resolver<Void>) -> Promise<Void> {
|
private func poll(_ snode: Snode, seal longTermSeal: Resolver<Void>) -> Promise<Void> {
|
||||||
guard isPolling else { return Promise { $0.fulfill(()) } }
|
guard isPolling else { return Promise { $0.fulfill(()) } }
|
||||||
|
|
||||||
let userPublicKey = getUserHexEncodedPublicKey()
|
let userPublicKey = getUserHexEncodedPublicKey()
|
||||||
|
|
||||||
return SnodeAPI.getRawMessages(from: snode, associatedWith: userPublicKey)
|
return SnodeAPI.getRawMessages(from: snode, associatedWith: userPublicKey)
|
||||||
.then(on: Threading.pollerQueue) { [weak self] rawResponse -> Promise<Void> in
|
.then(on: Threading.pollerQueue) { [weak self] rawResponse -> Promise<Void> in
|
||||||
guard let strongSelf = self, strongSelf.isPolling else { return Promise { $0.fulfill(()) } }
|
guard let strongSelf = self, strongSelf.isPolling else { return Promise { $0.fulfill(()) } }
|
||||||
|
@ -106,6 +108,8 @@ public final class Poller : NSObject {
|
||||||
SNLog("Received \(messages.count) new message(s).")
|
SNLog("Received \(messages.count) new message(s).")
|
||||||
|
|
||||||
GRDBStorage.shared.write { db in
|
GRDBStorage.shared.write { db in
|
||||||
|
var threadMessages: [String: [MessageReceiveJob.Details.MessageInfo]] = [:]
|
||||||
|
|
||||||
messages.forEach { message in
|
messages.forEach { message in
|
||||||
guard let envelope = SNProtoEnvelope.from(message) else { return }
|
guard let envelope = SNProtoEnvelope.from(message) else { return }
|
||||||
|
|
||||||
|
@ -117,27 +121,36 @@ public final class Poller : NSObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
JobRunner.add(
|
threadMessages[threadId ?? ""] = (threadMessages[threadId ?? ""] ?? [])
|
||||||
db,
|
.appending(
|
||||||
job: Job(
|
MessageReceiveJob.Details.MessageInfo(
|
||||||
variant: .messageReceive,
|
|
||||||
behaviour: .runOnce,
|
|
||||||
threadId: threadId,
|
|
||||||
details: MessageReceiveJob.Details(
|
|
||||||
data: try envelope.serializedData(),
|
data: try envelope.serializedData(),
|
||||||
serverHash: message.info.hash,
|
serverHash: message.info.hash
|
||||||
isBackgroundPoll: false
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
|
|
||||||
// Persist the received message after the MessageReceiveJob is created
|
// Persist the received message after the MessageReceiveJob is created
|
||||||
try message.info.save(db)
|
_ = try message.info.saved(db)
|
||||||
}
|
}
|
||||||
catch {
|
catch {
|
||||||
SNLog("Failed to deserialize envelope due to error: \(error).")
|
SNLog("Failed to deserialize envelope due to error: \(error).")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
threadMessages.forEach { threadId, threadMessages in
|
||||||
|
JobRunner.add(
|
||||||
|
db,
|
||||||
|
job: Job(
|
||||||
|
variant: .messageReceive,
|
||||||
|
behaviour: .runOnce,
|
||||||
|
threadId: threadId,
|
||||||
|
details: MessageReceiveJob.Details(
|
||||||
|
messages: threadMessages,
|
||||||
|
isBackgroundPoll: false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,11 +19,9 @@ public final class NotificationServiceExtension : UNNotificationServiceExtension
|
||||||
self.notificationContent = request.content.mutableCopy() as? UNMutableNotificationContent
|
self.notificationContent = request.content.mutableCopy() as? UNMutableNotificationContent
|
||||||
|
|
||||||
// Abort if the main app is running
|
// Abort if the main app is running
|
||||||
var isMainAppActive = false
|
guard !(UserDefaults.sharedLokiProject?[.isMainAppActive]).defaulting(to: false) else {
|
||||||
if let sharedUserDefaults = UserDefaults(suiteName: "group.com.loki-project.loki-messenger") {
|
return self.completeSilenty()
|
||||||
isMainAppActive = sharedUserDefaults.bool(forKey: "isMainAppActive")
|
|
||||||
}
|
}
|
||||||
guard !isMainAppActive else { return self.completeSilenty() }
|
|
||||||
|
|
||||||
// Perform main setup
|
// Perform main setup
|
||||||
DispatchQueue.main.sync { self.setUpIfNecessary() { } }
|
DispatchQueue.main.sync { self.setUpIfNecessary() { } }
|
||||||
|
|
|
@ -13,15 +13,18 @@ public enum SNSnodeKit { // Just to make the external API nice
|
||||||
identifier: .snodeKit,
|
identifier: .snodeKit,
|
||||||
migrations: [
|
migrations: [
|
||||||
[
|
[
|
||||||
_001_InitialSetupMigration.self
|
_001_InitialSetupMigration.self,
|
||||||
|
_002_SetupStandardJobs.self
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
_002_YDBToGRDBMigration.self
|
_003_YDBToGRDBMigration.self
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func configure() {
|
public static func configure() {
|
||||||
|
// Configure the job executors
|
||||||
|
JobRunner.add(executor: GetSnodePoolJob.self, for: .getSnodePool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import GRDB
|
||||||
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
|
/// This migration sets up the standard jobs, since we want these jobs to run before any "once-off" jobs we do this migration
|
||||||
|
/// before running the `YDBToGRDBMigration`
|
||||||
|
enum _002_SetupStandardJobs: Migration {
|
||||||
|
static let identifier: String = "SetupStandardJobs"
|
||||||
|
|
||||||
|
static func migrate(_ db: Database) throws {
|
||||||
|
try autoreleasepool {
|
||||||
|
_ = try Job(
|
||||||
|
variant: .getSnodePool,
|
||||||
|
behaviour: .recurringOnActiveBlocking
|
||||||
|
).inserted(db)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,7 +4,7 @@ import Foundation
|
||||||
import GRDB
|
import GRDB
|
||||||
import SessionUtilitiesKit
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
enum _002_YDBToGRDBMigration: Migration {
|
enum _003_YDBToGRDBMigration: Migration {
|
||||||
static let identifier: String = "YDBToGRDBMigration"
|
static let identifier: String = "YDBToGRDBMigration"
|
||||||
|
|
||||||
static func migrate(_ db: Database) throws {
|
static func migrate(_ db: Database) throws {
|
||||||
|
@ -103,6 +103,7 @@ enum _002_YDBToGRDBMigration: Migration {
|
||||||
var lastMessageResults: [String: (hash: String, json: JSON)] = [:]
|
var lastMessageResults: [String: (hash: String, json: JSON)] = [:]
|
||||||
var receivedMessageResults: [String: Set<String>] = [:]
|
var receivedMessageResults: [String: Set<String>] = [:]
|
||||||
|
|
||||||
|
// TODO: Move into the top read block???
|
||||||
Storage.read { transaction in
|
Storage.read { transaction in
|
||||||
// Extract the received message hashes
|
// Extract the received message hashes
|
||||||
transaction.enumerateKeysAndObjects(inCollection: Legacy.receivedMessagesCollection) { key, object, _ in
|
transaction.enumerateKeysAndObjects(inCollection: Legacy.receivedMessagesCollection) { key, object, _ in
|
24
SessionSnodeKit/GetSnodePoolJob.swift
Normal file
24
SessionSnodeKit/GetSnodePoolJob.swift
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import GRDB
|
||||||
|
import SignalCoreKit
|
||||||
|
import SessionUtilitiesKit
|
||||||
|
|
||||||
|
public enum GetSnodePoolJob: JobExecutor {
|
||||||
|
public static let maxFailureCount: Int = -1
|
||||||
|
public static let requiresThreadId: Bool = false
|
||||||
|
public static let requiresInteractionId: Bool = false
|
||||||
|
|
||||||
|
public static func run(
|
||||||
|
_ job: Job,
|
||||||
|
success: @escaping (Job, Bool) -> (),
|
||||||
|
failure: @escaping (Job, Error?, Bool) -> (),
|
||||||
|
deferred: @escaping (Job) -> ()
|
||||||
|
) {
|
||||||
|
SnodeAPI.getSnodePool()
|
||||||
|
.done { _ in success(job, false) }
|
||||||
|
.catch { error in failure(job, error, false) }
|
||||||
|
.retainUntilComplete()
|
||||||
|
}
|
||||||
|
}
|
|
@ -258,7 +258,9 @@ public final class SnodeAPI : NSObject {
|
||||||
public static func getSnodePool() -> Promise<Set<Snode>> {
|
public static func getSnodePool() -> Promise<Set<Snode>> {
|
||||||
loadSnodePoolIfNeeded()
|
loadSnodePoolIfNeeded()
|
||||||
let now = Date()
|
let now = Date()
|
||||||
let hasSnodePoolExpired = given(GRDBStorage.shared[.lastSnodePoolRefreshDate]) { now.timeIntervalSince($0) > 2 * 60 * 60 } ?? true
|
let hasSnodePoolExpired = given(GRDBStorage.shared[.lastSnodePoolRefreshDate]) {
|
||||||
|
now.timeIntervalSince($0) > 2 * 60 * 60
|
||||||
|
}.defaulting(to: true)
|
||||||
let snodePool = SnodeAPI.snodePool
|
let snodePool = SnodeAPI.snodePool
|
||||||
let hasInsufficientSnodes = (snodePool.count < minSnodePoolCount)
|
let hasInsufficientSnodes = (snodePool.count < minSnodePoolCount)
|
||||||
|
|
||||||
|
@ -441,6 +443,7 @@ public final class SnodeAPI : NSObject {
|
||||||
// "pubkey_ed25519" : ed25519PublicKey,
|
// "pubkey_ed25519" : ed25519PublicKey,
|
||||||
// "signature" : signature.toBase64()!
|
// "signature" : signature.toBase64()!
|
||||||
]
|
]
|
||||||
|
|
||||||
return invoke(.getMessages, on: snode, associatedWith: publicKey, parameters: parameters)
|
return invoke(.getMessages, on: snode, associatedWith: publicKey, parameters: parameters)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,11 +18,12 @@ public enum SNUtilitiesKit { // Just to make the external API nice
|
||||||
identifier: .utilitiesKit,
|
identifier: .utilitiesKit,
|
||||||
migrations: [
|
migrations: [
|
||||||
[
|
[
|
||||||
// Intentionally including the '_002_YDBToGRDBMigration' in the first migration
|
// Intentionally including the '_003_YDBToGRDBMigration' in the first migration
|
||||||
// set to ensure the 'Identity' data is migrated before any other migrations are
|
// set to ensure the 'Identity' data is migrated before any other migrations are
|
||||||
// run (some need access to the users publicKey)
|
// run (some need access to the users publicKey)
|
||||||
_001_InitialSetupMigration.self,
|
_001_InitialSetupMigration.self,
|
||||||
_002_YDBToGRDBMigration.self
|
_002_SetupStandardJobs.self,
|
||||||
|
_003_YDBToGRDBMigration.self
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -15,6 +15,30 @@ enum _001_InitialSetupMigration: Migration {
|
||||||
t.column(.data, .blob).notNull()
|
t.column(.data, .blob).notNull()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try db.create(table: Job.self) { t in
|
||||||
|
t.column(.id, .integer)
|
||||||
|
.notNull()
|
||||||
|
.primaryKey(autoincrement: true)
|
||||||
|
t.column(.failureCount, .integer)
|
||||||
|
.notNull()
|
||||||
|
.defaults(to: 0)
|
||||||
|
t.column(.variant, .integer)
|
||||||
|
.notNull()
|
||||||
|
.indexed() // Quicker querying
|
||||||
|
t.column(.behaviour, .integer)
|
||||||
|
.notNull()
|
||||||
|
.indexed() // Quicker querying
|
||||||
|
t.column(.nextRunTimestamp, .double)
|
||||||
|
.notNull()
|
||||||
|
.indexed() // Quicker querying
|
||||||
|
.defaults(to: 0)
|
||||||
|
t.column(.threadId, .text)
|
||||||
|
.indexed() // Quicker querying
|
||||||
|
t.column(.interactionId, .text)
|
||||||
|
.indexed() // Quicker querying
|
||||||
|
t.column(.details, .blob)
|
||||||
|
}
|
||||||
|
|
||||||
try db.create(table: Setting.self) { t in
|
try db.create(table: Setting.self) { t in
|
||||||
t.column(.key, .text)
|
t.column(.key, .text)
|
||||||
.notNull()
|
.notNull()
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright © 2022 Rangeproof Pty Ltd. All rights reserved.
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import GRDB
|
||||||
|
import Curve25519Kit
|
||||||
|
|
||||||
|
/// This migration sets up the standard jobs, since we want these jobs to run before any "once-off" jobs we do this migration
|
||||||
|
/// before running the `YDBToGRDBMigration`
|
||||||
|
enum _002_SetupStandardJobs: Migration {
|
||||||
|
static let identifier: String = "SetupStandardJobs"
|
||||||
|
|
||||||
|
static func migrate(_ db: Database) throws {
|
||||||
|
try autoreleasepool {
|
||||||
|
// Note: This job exists in the 'Session' target but that doesn't have it's own migrations
|
||||||
|
_ = try Job(
|
||||||
|
variant: .syncPushTokens,
|
||||||
|
behaviour: .recurringOnLaunch
|
||||||
|
).inserted(db)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import GRDB
|
import GRDB
|
||||||
|
|
||||||
enum _002_YDBToGRDBMigration: Migration {
|
enum _003_YDBToGRDBMigration: Migration {
|
||||||
static let identifier: String = "YDBToGRDBMigration"
|
static let identifier: String = "YDBToGRDBMigration"
|
||||||
|
|
||||||
static func migrate(_ db: Database) throws {
|
static func migrate(_ db: Database) throws {
|
||||||
|
@ -65,6 +65,7 @@ enum _002_YDBToGRDBMigration: Migration {
|
||||||
|
|
||||||
throw GRDBStorageError.migrationFailed
|
throw GRDBStorageError.migrationFailed
|
||||||
}
|
}
|
||||||
|
print("RAWR publicKey \(userX25519KeyPair.publicKey.toHexString())")
|
||||||
try autoreleasepool {
|
try autoreleasepool {
|
||||||
// Insert the data into GRDB
|
// Insert the data into GRDB
|
||||||
try Identity(
|
try Identity(
|
|
@ -2,21 +2,9 @@
|
||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
import GRDB
|
import GRDB
|
||||||
import SessionUtilitiesKit
|
|
||||||
import SwiftProtobuf
|
|
||||||
|
|
||||||
public struct Job: Codable, Equatable, Identifiable, FetchableRecord, MutablePersistableRecord, TableRecord, ColumnExpressible {
|
public struct Job: Codable, Equatable, Identifiable, FetchableRecord, MutablePersistableRecord, TableRecord, ColumnExpressible {
|
||||||
public static var databaseTableName: String { "job" }
|
public static var databaseTableName: String { "job" }
|
||||||
internal static let threadForeignKey = ForeignKey(
|
|
||||||
[Columns.threadId],
|
|
||||||
to: [SessionThread.Columns.id]
|
|
||||||
)
|
|
||||||
internal static let interactionForeignKey = ForeignKey(
|
|
||||||
[Columns.interactionId],
|
|
||||||
to: [Interaction.Columns.id]
|
|
||||||
)
|
|
||||||
internal static let thread = hasOne(SessionThread.self, using: Job.threadForeignKey)
|
|
||||||
internal static let interaction = hasOne(Interaction.self, using: Job.interactionForeignKey)
|
|
||||||
|
|
||||||
public typealias Columns = CodingKeys
|
public typealias Columns = CodingKeys
|
||||||
public enum CodingKeys: String, CodingKey, ColumnExpression {
|
public enum CodingKeys: String, CodingKey, ColumnExpression {
|
||||||
|
@ -35,13 +23,31 @@ public struct Job: Codable, Equatable, Identifiable, FetchableRecord, MutablePer
|
||||||
/// at the timestamp of the next disappearing message
|
/// at the timestamp of the next disappearing message
|
||||||
case disappearingMessages
|
case disappearingMessages
|
||||||
|
|
||||||
|
/// This is a recurring job that ensures the app retrieves a service node pool on active
|
||||||
|
///
|
||||||
|
/// **Note:** This is a blocking job so it will run before any other jobs and prevent them from
|
||||||
|
/// running until it's complete
|
||||||
|
case getSnodePool
|
||||||
|
|
||||||
|
/// This is a recurring job that checks if the user needs to update their profile picture on launch, and if so
|
||||||
|
/// attempt to download the latest
|
||||||
|
case updateProfilePicture
|
||||||
|
|
||||||
|
/// This is a recurring job that ensures the app fetches the default open group rooms on launch
|
||||||
|
case retrieveDefaultOpenGroupRooms
|
||||||
|
|
||||||
/// This is a recurring job that runs on launch and flags any messages marked as 'sending' to
|
/// This is a recurring job that runs on launch and flags any messages marked as 'sending' to
|
||||||
/// be in their 'failed' state
|
/// be in their 'failed' state
|
||||||
|
///
|
||||||
|
/// **Note:** This is a blocking job so it will run before any other jobs and prevent them from
|
||||||
|
/// running until it's complete
|
||||||
case failedMessages = 1000
|
case failedMessages = 1000
|
||||||
|
|
||||||
/// This is a recurring job that runs on launch and flags any attachments marked as 'uploading' to
|
/// This is a recurring job that runs on launch and flags any attachments marked as 'uploading' to
|
||||||
/// be in their 'failed' state
|
/// be in their 'failed' state
|
||||||
|
///
|
||||||
|
/// **Note:** This is a blocking job so it will run before any other jobs and prevent them from
|
||||||
|
/// running until it's complete
|
||||||
case failedAttachmentDownloads
|
case failedAttachmentDownloads
|
||||||
|
|
||||||
/// This is a recurring job that runs on return from background and registeres and uploads the
|
/// This is a recurring job that runs on return from background and registeres and uploads the
|
||||||
|
@ -84,11 +90,26 @@ public struct Job: Codable, Equatable, Identifiable, FetchableRecord, MutablePer
|
||||||
/// the future) in order to be run again
|
/// the future) in order to be run again
|
||||||
case recurring
|
case recurring
|
||||||
|
|
||||||
/// This job will run once each launch
|
/// This job will run once each launch and may run again during the same session if `nextRunTimestamp`
|
||||||
|
/// gets set
|
||||||
case recurringOnLaunch
|
case recurringOnLaunch
|
||||||
|
|
||||||
/// This job will run once each whenever the app becomes active (launch and return from background)
|
/// This job will run once each launch and may run again during the same session if `nextRunTimestamp`
|
||||||
|
/// gets set, it also must complete before any other jobs can run
|
||||||
|
case recurringOnLaunchBlocking
|
||||||
|
|
||||||
|
/// This job will run once each launch and may run again during the same session if `nextRunTimestamp`
|
||||||
|
/// gets set, it also must complete before any other jobs can run
|
||||||
|
case recurringOnLaunchBlockingOncePerSession
|
||||||
|
|
||||||
|
/// This job will run once each whenever the app becomes active (launch and return from background) and
|
||||||
|
/// may run again during the same session if `nextRunTimestamp` gets set
|
||||||
case recurringOnActive
|
case recurringOnActive
|
||||||
|
|
||||||
|
/// This job will run once each whenever the app becomes active (launch and return from background) and
|
||||||
|
/// may run again during the same session if `nextRunTimestamp` gets set, it also must complete before
|
||||||
|
/// any other jobs can run
|
||||||
|
case recurringOnActiveBlocking
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The `id` value is auto incremented by the database, if the `Job` hasn't been inserted into
|
/// The `id` value is auto incremented by the database, if the `Job` hasn't been inserted into
|
||||||
|
@ -122,16 +143,6 @@ public struct Job: Codable, Equatable, Identifiable, FetchableRecord, MutablePer
|
||||||
/// JSON encoded data required for the job
|
/// JSON encoded data required for the job
|
||||||
public let details: Data?
|
public let details: Data?
|
||||||
|
|
||||||
// MARK: - Relationships
|
|
||||||
|
|
||||||
public var thread: QueryInterfaceRequest<SessionThread> {
|
|
||||||
request(for: Job.thread)
|
|
||||||
}
|
|
||||||
|
|
||||||
public var interaction: QueryInterfaceRequest<Interaction> {
|
|
||||||
request(for: Job.interaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Initialization
|
// MARK: - Initialization
|
||||||
|
|
||||||
fileprivate init(
|
fileprivate init(
|
||||||
|
@ -201,26 +212,72 @@ public struct Job: Codable, Equatable, Identifiable, FetchableRecord, MutablePer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - GRDB Interactions
|
||||||
|
|
||||||
|
extension Job {
|
||||||
|
internal static func filterPendingJobs(excludeFutureJobs: Bool = true) -> QueryInterfaceRequest<Job> {
|
||||||
|
let query: QueryInterfaceRequest<Job> = Job
|
||||||
|
.filter(
|
||||||
|
// TODO: Should this include other behaviours? (what happens if one of the other types fails???? Just leave it until the next launch/active???) Set a 'failureCount' and use that to determine if it should run? (reset on success)
|
||||||
|
// Retrieve all 'runOnce' and 'recurring' jobs
|
||||||
|
[
|
||||||
|
Job.Behaviour.runOnce,
|
||||||
|
Job.Behaviour.recurring
|
||||||
|
].contains(Job.Columns.behaviour) || (
|
||||||
|
// Retrieve any 'recurringOnLaunch' and 'recurringOnActive' jobs that have a
|
||||||
|
// 'nextRunTimestamp'
|
||||||
|
[
|
||||||
|
Job.Behaviour.recurringOnLaunch,
|
||||||
|
Job.Behaviour.recurringOnLaunchBlocking,
|
||||||
|
Job.Behaviour.recurringOnActive,
|
||||||
|
Job.Behaviour.recurringOnActiveBlocking
|
||||||
|
].contains(Job.Columns.behaviour) &&
|
||||||
|
Job.Columns.nextRunTimestamp > 0
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.order(Job.Columns.nextRunTimestamp)
|
||||||
|
.order(Job.Columns.id)
|
||||||
|
|
||||||
|
guard excludeFutureJobs else {
|
||||||
|
return query
|
||||||
|
}
|
||||||
|
|
||||||
|
return query
|
||||||
|
.filter(Job.Columns.nextRunTimestamp <= Date().timeIntervalSince1970)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - Convenience
|
// MARK: - Convenience
|
||||||
|
|
||||||
public extension Job {
|
public extension Job {
|
||||||
internal func with(
|
var isBlocking: Bool {
|
||||||
|
switch self.behaviour {
|
||||||
|
case .recurringOnLaunchBlocking,
|
||||||
|
.recurringOnLaunchBlockingOncePerSession,
|
||||||
|
.recurringOnActiveBlocking:
|
||||||
|
return true
|
||||||
|
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func with(
|
||||||
failureCount: UInt = 0,
|
failureCount: UInt = 0,
|
||||||
nextRunTimestamp: TimeInterval?
|
nextRunTimestamp: TimeInterval
|
||||||
) -> Job {
|
) -> Job {
|
||||||
return Job(
|
return Job(
|
||||||
id: id,
|
id: id,
|
||||||
failureCount: failureCount,
|
failureCount: failureCount,
|
||||||
variant: variant,
|
variant: variant,
|
||||||
behaviour: behaviour,
|
behaviour: behaviour,
|
||||||
nextRunTimestamp: (nextRunTimestamp ?? self.nextRunTimestamp),
|
nextRunTimestamp: nextRunTimestamp,
|
||||||
threadId: threadId,
|
threadId: threadId,
|
||||||
interactionId: interactionId,
|
interactionId: interactionId,
|
||||||
details: details
|
details: details
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal func with<T: Encodable>(details: T) -> Job? {
|
func with<T: Encodable>(details: T) -> Job? {
|
||||||
guard let detailsData: Data = try? JSONEncoder().encode(details) else { return nil }
|
guard let detailsData: Data = try? JSONEncoder().encode(details) else { return nil }
|
||||||
|
|
||||||
return Job(
|
return Job(
|
|
@ -34,6 +34,9 @@ public enum SNUserDefaults {
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension UserDefaults {
|
public extension UserDefaults {
|
||||||
|
@objc static var sharedLokiProject: UserDefaults? {
|
||||||
|
UserDefaults(suiteName: "group.com.loki-project.loki-messenger")
|
||||||
|
}
|
||||||
|
|
||||||
subscript(bool: SNUserDefaults.Bool) -> Bool {
|
subscript(bool: SNUserDefaults.Bool) -> Bool {
|
||||||
get { return self.bool(forKey: bool.rawValue) }
|
get { return self.bool(forKey: bool.rawValue) }
|
||||||
|
|
|
@ -3,10 +3,12 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
import GRDB
|
import GRDB
|
||||||
import SignalCoreKit
|
import SignalCoreKit
|
||||||
import SessionUtilitiesKit
|
|
||||||
|
|
||||||
public protocol JobExecutor {
|
public protocol JobExecutor {
|
||||||
static var maxFailureCount: UInt { get }
|
/// The maximum number of times the job can fail before it fails permanently
|
||||||
|
///
|
||||||
|
/// **Note:** A value of `-1` means it will retry indefinitely
|
||||||
|
static var maxFailureCount: Int { get }
|
||||||
static var requiresThreadId: Bool { get }
|
static var requiresThreadId: Bool { get }
|
||||||
static var requiresInteractionId: Bool { get }
|
static var requiresInteractionId: Bool { get }
|
||||||
|
|
||||||
|
@ -57,8 +59,8 @@ public final class JobRunner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Could this be a bottleneck? (single serial queue to process all these jobs? Group by thread?)
|
// TODO: Could this be a bottleneck? (single serial queue to process all these jobs? Group by thread?).
|
||||||
// TODO: Multi-thread support
|
// TODO: Multi-thread support.
|
||||||
private static let queueKey: DispatchSpecificKey = DispatchSpecificKey<String>()
|
private static let queueKey: DispatchSpecificKey = DispatchSpecificKey<String>()
|
||||||
private static let queueContext: String = "JobRunner"
|
private static let queueContext: String = "JobRunner"
|
||||||
private static let internalQueue: DispatchQueue = {
|
private static let internalQueue: DispatchQueue = {
|
||||||
|
@ -74,6 +76,7 @@ public final class JobRunner {
|
||||||
private static var jobQueue: Atomic<[Job]> = Atomic([])
|
private static var jobQueue: Atomic<[Job]> = Atomic([])
|
||||||
|
|
||||||
private static var jobsCurrentlyRunning: Atomic<Set<Int64>> = Atomic([])
|
private static var jobsCurrentlyRunning: Atomic<Set<Int64>> = Atomic([])
|
||||||
|
private static var perSessionJobsCompleted: Atomic<Set<Int64>> = Atomic([])
|
||||||
|
|
||||||
// MARK: - Configuration
|
// MARK: - Configuration
|
||||||
|
|
||||||
|
@ -182,27 +185,64 @@ public final class JobRunner {
|
||||||
.filter(
|
.filter(
|
||||||
[
|
[
|
||||||
Job.Behaviour.recurringOnLaunch,
|
Job.Behaviour.recurringOnLaunch,
|
||||||
|
Job.Behaviour.recurringOnLaunchBlocking,
|
||||||
|
Job.Behaviour.recurringOnLaunchBlockingOncePerSession,
|
||||||
Job.Behaviour.runOnceNextLaunch
|
Job.Behaviour.runOnceNextLaunch
|
||||||
].contains(Job.Columns.behaviour)
|
].contains(Job.Columns.behaviour)
|
||||||
)
|
)
|
||||||
|
.order(Job.Columns.id)
|
||||||
.fetchAll(db)
|
.fetchAll(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let jobsToRun: [Job] = maybeJobsToRun else { return }
|
guard let jobsToRun: [Job] = maybeJobsToRun else { return }
|
||||||
|
|
||||||
jobQueue.mutate { $0.append(contentsOf: jobsToRun) }
|
jobQueue.mutate {
|
||||||
|
// Insert any blocking jobs after any existing blocking jobs then add
|
||||||
|
// the remaining jobs to the end of the queue
|
||||||
|
let lastBlockingIndex = $0.lastIndex(where: { $0.isBlocking })
|
||||||
|
.defaulting(to: $0.startIndex.advanced(by: -1))
|
||||||
|
.advanced(by: 1)
|
||||||
|
|
||||||
|
$0.insert(
|
||||||
|
contentsOf: jobsToRun.filter { $0.isBlocking },
|
||||||
|
at: lastBlockingIndex
|
||||||
|
)
|
||||||
|
$0.append(
|
||||||
|
contentsOf: jobsToRun.filter { !$0.isBlocking }
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func appDidBecomeActive() {
|
public static func appDidBecomeActive() {
|
||||||
let maybeJobsToRun: [Job]? = GRDBStorage.shared.read { db in
|
let maybeJobsToRun: [Job]? = GRDBStorage.shared.read { db in
|
||||||
try Job
|
try Job
|
||||||
.filter(Job.Columns.behaviour == Job.Behaviour.recurringOnActive)
|
.filter(
|
||||||
|
[
|
||||||
|
Job.Behaviour.recurringOnActive,
|
||||||
|
Job.Behaviour.recurringOnActiveBlocking
|
||||||
|
].contains(Job.Columns.behaviour)
|
||||||
|
)
|
||||||
|
.order(Job.Columns.id)
|
||||||
.fetchAll(db)
|
.fetchAll(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let jobsToRun: [Job] = maybeJobsToRun else { return }
|
guard let jobsToRun: [Job] = maybeJobsToRun else { return }
|
||||||
|
|
||||||
jobQueue.mutate { $0.append(contentsOf: jobsToRun) }
|
jobQueue.mutate {
|
||||||
|
// Insert any blocking jobs after any existing blocking jobs then add
|
||||||
|
// the remaining jobs to the end of the queue
|
||||||
|
let lastBlockingIndex = $0.lastIndex(where: { $0.isBlocking })
|
||||||
|
.defaulting(to: $0.startIndex.advanced(by: -1))
|
||||||
|
.advanced(by: 1)
|
||||||
|
|
||||||
|
$0.insert(
|
||||||
|
contentsOf: jobsToRun.filter { $0.isBlocking },
|
||||||
|
at: lastBlockingIndex
|
||||||
|
)
|
||||||
|
$0.append(
|
||||||
|
contentsOf: jobsToRun.filter { !$0.isBlocking }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Start the job runner if needed
|
// Start the job runner if needed
|
||||||
if !isRunning.wrappedValue {
|
if !isRunning.wrappedValue {
|
||||||
|
@ -228,21 +268,14 @@ public final class JobRunner {
|
||||||
guard DispatchQueue.getSpecific(key: queueKey) == queueContext else {
|
guard DispatchQueue.getSpecific(key: queueKey) == queueContext else {
|
||||||
internalQueue.async {
|
internalQueue.async {
|
||||||
start()
|
start()
|
||||||
}
|
}// TODO: Want to have multiple threads for this (attachment download should be separate - do we even use attachment upload anymore???)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get any pending jobs
|
// Get any pending jobs
|
||||||
let maybeJobsToRun: [Job]? = GRDBStorage.shared.read { db in
|
let maybeJobsToRun: [Job]? = GRDBStorage.shared.read { db in
|
||||||
try Job
|
try Job// TODO: Test this
|
||||||
.filter(
|
.filterPendingJobs()
|
||||||
[
|
|
||||||
Job.Behaviour.runOnce,
|
|
||||||
Job.Behaviour.recurring
|
|
||||||
].contains(Job.Columns.behaviour)
|
|
||||||
)
|
|
||||||
.filter(Job.Columns.nextRunTimestamp <= Date().timeIntervalSince1970)
|
|
||||||
.order(Job.Columns.nextRunTimestamp)
|
|
||||||
.fetchAll(db)
|
.fetchAll(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,6 +333,12 @@ public final class JobRunner {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the 'nextRunTimestamp' for the job is in the future then don't run it yet
|
||||||
|
guard nextJob.nextRunTimestamp <= Date().timeIntervalSince1970 else {
|
||||||
|
handleJobDeferred(nextJob)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Update the state to indicate it's running
|
// Update the state to indicate it's running
|
||||||
//
|
//
|
||||||
// Note: We need to store 'numJobsRemaining' in it's own variable because
|
// Note: We need to store 'numJobsRemaining' in it's own variable because
|
||||||
|
@ -324,21 +363,17 @@ public final class JobRunner {
|
||||||
try TimeInterval
|
try TimeInterval
|
||||||
.fetchOne(
|
.fetchOne(
|
||||||
db,
|
db,
|
||||||
Job
|
Job// TODO: Test this works as expected
|
||||||
|
.filterPendingJobs(excludeFutureJobs: false)
|
||||||
.select(Job.Columns.nextRunTimestamp)
|
.select(Job.Columns.nextRunTimestamp)
|
||||||
.filter(
|
|
||||||
[
|
|
||||||
Job.Behaviour.runOnce,
|
|
||||||
Job.Behaviour.recurring
|
|
||||||
].contains(Job.Columns.behaviour)
|
|
||||||
)
|
|
||||||
.order(Job.Columns.nextRunTimestamp)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
guard let nextJobTimestamp: TimeInterval = nextJobTimestamp else { return }
|
guard let nextJobTimestamp: TimeInterval = nextJobTimestamp else { return }
|
||||||
|
|
||||||
// If the next job isn't scheduled in the future then just restart the JobRunner immediately
|
// If the next job isn't scheduled in the future then just restart the JobRunner immediately
|
||||||
let secondsUntilNextJob: TimeInterval = (nextJobTimestamp - Date().timeIntervalSince1970)
|
let secondsUntilNextJob: TimeInterval = (nextJobTimestamp - Date().timeIntervalSince1970)
|
||||||
|
|
||||||
guard secondsUntilNextJob > 0 else {
|
guard secondsUntilNextJob > 0 else {
|
||||||
SNLog("[JobRunner] Restarting immediately for job scheduled \(Int(ceil(abs(secondsUntilNextJob)))) second\(Int(ceil(abs(secondsUntilNextJob))) == 1 ? "" : "s")) ago")
|
SNLog("[JobRunner] Restarting immediately for job scheduled \(Int(ceil(abs(secondsUntilNextJob)))) second\(Int(ceil(abs(secondsUntilNextJob))) == 1 ? "" : "s")) ago")
|
||||||
|
|
||||||
|
@ -378,6 +413,9 @@ public final class JobRunner {
|
||||||
.saved(db)
|
.saved(db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case .recurringOnLaunchBlockingOncePerSession:
|
||||||
|
perSessionJobsCompleted.mutate { $0 = $0.inserting(job.id) }
|
||||||
|
|
||||||
default: break
|
default: break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,17 +431,48 @@ public final class JobRunner {
|
||||||
guard GRDBStorage.shared.read({ db in try Job.exists(db, id: job.id ?? -1) }) == true else {
|
guard GRDBStorage.shared.read({ db in try Job.exists(db, id: job.id ?? -1) }) == true else {
|
||||||
SNLog("[JobRunner] \(job.variant) job canceled")
|
SNLog("[JobRunner] \(job.variant) job canceled")
|
||||||
jobsCurrentlyRunning.mutate { $0 = $0.removing(job.id) }
|
jobsCurrentlyRunning.mutate { $0 = $0.removing(job.id) }
|
||||||
runNextJob()
|
|
||||||
|
internalQueue.async {
|
||||||
|
runNextJob()
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch job.behaviour {
|
||||||
|
// If a "blocking" job failed then rerun it immediately
|
||||||
|
case .recurringOnLaunchBlocking, .recurringOnActiveBlocking:
|
||||||
|
SNLog("[JobRunner] blocking \(job.variant) job failed; retrying immediately")
|
||||||
|
jobQueue.mutate({ $0.insert(job, at: 0) })
|
||||||
|
|
||||||
|
internalQueue.async {
|
||||||
|
runNextJob()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
// For "blocking once per session" jobs only rerun it immediately if it hasn't already
|
||||||
|
// run this session
|
||||||
|
case .recurringOnLaunchBlockingOncePerSession:
|
||||||
|
guard !perSessionJobsCompleted.wrappedValue.contains(job.id ?? -1) else { break }
|
||||||
|
|
||||||
|
SNLog("[JobRunner] blocking \(job.variant) job failed; retrying immediately")
|
||||||
|
perSessionJobsCompleted.mutate { $0 = $0.inserting(job.id) }
|
||||||
|
jobQueue.mutate({ $0.insert(job, at: 0) })
|
||||||
|
|
||||||
|
internalQueue.async {
|
||||||
|
runNextJob()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
|
||||||
GRDBStorage.shared.write { db in
|
GRDBStorage.shared.write { db in
|
||||||
// Check if the job has a 'maxFailureCount' (a value of '0' means it will always retry)
|
// Get the max failure count for the job (a value of '-1' means it will retry indefinitely)
|
||||||
let maxFailureCount: UInt = (executorMap.wrappedValue[job.variant]?.maxFailureCount ?? 0)
|
let maxFailureCount: Int = (executorMap.wrappedValue[job.variant]?.maxFailureCount ?? 0)
|
||||||
|
|
||||||
guard
|
guard
|
||||||
!permanentFailure &&
|
!permanentFailure &&
|
||||||
maxFailureCount > 0 &&
|
maxFailureCount >= 0 &&
|
||||||
job.failureCount + 1 < maxFailureCount
|
job.failureCount + 1 < maxFailureCount
|
||||||
else {
|
else {
|
||||||
// If the job permanently failed or we have performed all of our retry attempts
|
// If the job permanently failed or we have performed all of our retry attempts
|
||||||
|
@ -422,7 +491,9 @@ public final class JobRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
jobsCurrentlyRunning.mutate { $0 = $0.removing(job.id) }
|
jobsCurrentlyRunning.mutate { $0 = $0.removing(job.id) }
|
||||||
runNextJob()
|
internalQueue.async {
|
||||||
|
runNextJob()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This function is called when a job neither succeeds or fails (this should only occur if the job has specific logic that makes it dependant
|
/// This function is called when a job neither succeeds or fails (this should only occur if the job has specific logic that makes it dependant
|
Loading…
Reference in a new issue