2022-03-29 16:00:59 +03:00
/*
* Copyright ( C ) 2022 by Claudio Cambra < claudio . cambra @ nextcloud . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* for more details .
*/
import FileProvider
2023-01-26 22:50:40 +03:00
import NextcloudKit
2023-03-14 23:03:49 +03:00
import OSLog
2022-03-29 16:00:59 +03:00
class FileProviderEnumerator : NSObject , NSFileProviderEnumerator {
private let enumeratedItemIdentifier : NSFileProviderItemIdentifier
2023-03-08 01:30:50 +03:00
private var enumeratedItemMetadata : NextcloudItemMetadataTable ?
private var enumeratingSystemIdentifier : Bool {
2024-01-22 09:40:47 +03:00
FileProviderEnumerator . isSystemIdentifier ( enumeratedItemIdentifier )
2023-03-08 01:30:50 +03:00
}
2024-01-22 09:40:47 +03:00
private let anchor = NSFileProviderSyncAnchor ( Date ( ) . description . data ( using : . utf8 ) ! ) // TODO: a c t u a l l y u s e t h i s i n N C K i t a n d s e r v e r r e q u e s t s
2023-01-26 22:50:40 +03:00
private static let maxItemsPerFileProviderPage = 100
2023-02-02 22:13:35 +03:00
let ncAccount : NextcloudAccount
let ncKit : NextcloudKit
2023-01-27 04:26:27 +03:00
var serverUrl : String = " "
2023-03-18 18:05:34 +03:00
var isInvalidated = false
2023-03-08 01:30:50 +03:00
private static func isSystemIdentifier ( _ identifier : NSFileProviderItemIdentifier ) -> Bool {
2024-01-22 09:40:47 +03:00
identifier = = . rootContainer || identifier = = . trashContainer || identifier = = . workingSet
2023-03-08 01:30:50 +03:00
}
2024-01-22 09:40:47 +03:00
init (
enumeratedItemIdentifier : NSFileProviderItemIdentifier , ncAccount : NextcloudAccount ,
ncKit : NextcloudKit
) {
2022-03-29 16:00:59 +03:00
self . enumeratedItemIdentifier = enumeratedItemIdentifier
2023-01-26 22:50:40 +03:00
self . ncAccount = ncAccount
2023-02-02 22:13:35 +03:00
self . ncKit = ncKit
2023-01-10 22:25:26 +03:00
2023-03-08 01:30:50 +03:00
if FileProviderEnumerator . isSystemIdentifier ( enumeratedItemIdentifier ) {
2024-01-22 09:40:47 +03:00
Logger . enumeration . debug (
" Providing enumerator for a system defined container: \( enumeratedItemIdentifier . rawValue , privacy : . public ) "
)
serverUrl = ncAccount . davFilesUrl
2023-01-10 22:25:26 +03:00
} else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . debug (
" Providing enumerator for item with identifier: \( enumeratedItemIdentifier . rawValue , privacy : . public ) "
)
2023-01-10 22:25:26 +03:00
let dbManager = NextcloudFilesDatabaseManager . shared
2023-03-09 04:09:39 +03:00
2024-01-22 09:40:47 +03:00
enumeratedItemMetadata = dbManager . itemMetadataFromFileProviderItemIdentifier (
enumeratedItemIdentifier )
2023-03-09 04:09:39 +03:00
if enumeratedItemMetadata != nil {
2024-01-22 09:40:47 +03:00
serverUrl =
enumeratedItemMetadata ! . serverUrl + " / " + enumeratedItemMetadata ! . fileName
2023-02-01 20:24:23 +03:00
} else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . error (
" Could not find itemMetadata for file with identifier: \( enumeratedItemIdentifier . rawValue , privacy : . public ) "
)
2023-01-10 22:25:26 +03:00
}
}
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Set up enumerator for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) "
)
2022-03-29 16:00:59 +03:00
super . init ( )
}
func invalidate ( ) {
2024-01-22 09:40:47 +03:00
Logger . enumeration . debug (
" Enumerator is being invalidated for item with identifier: \( self . enumeratedItemIdentifier . rawValue , privacy : . public ) "
)
isInvalidated = true
2022-03-29 16:00:59 +03:00
}
2023-01-12 23:49:28 +03:00
// MARK: - P r o t o c o l m e t h o d s
2024-01-22 09:40:47 +03:00
func enumerateItems (
for observer : NSFileProviderEnumerationObserver , startingAt page : NSFileProviderPage
) {
Logger . enumeration . debug (
" Received enumerate items request for enumerator with user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) "
)
2023-03-14 23:03:49 +03:00
/*
- inspect the page to determine whether this is an initial or a follow - up request ( TODO )
2024-01-22 09:40:47 +03:00
2022-03-29 16:00:59 +03:00
If this is an enumerator for a directory , the root container or all directories :
- perform a server request to fetch directory contents
2023-03-14 23:03:49 +03:00
If this is an enumerator for the working set :
2022-03-29 16:00:59 +03:00
- perform a server request to update your local database
2023-03-14 23:03:49 +03:00
- fetch the working set from your local database
2024-01-22 09:40:47 +03:00
2022-03-29 16:00:59 +03:00
- inform the observer about the items returned by the server ( possibly multiple times )
- inform the observer that you are finished with this page
*/
2023-01-26 22:50:40 +03:00
2023-03-18 21:01:10 +03:00
if enumeratedItemIdentifier = = . trashContainer {
2024-01-22 09:40:47 +03:00
Logger . enumeration . debug (
" Enumerating trash set for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) "
)
2023-03-08 00:40:52 +03:00
// T O D O !
2023-01-26 22:50:40 +03:00
observer . finishEnumerating ( upTo : nil )
return
}
2023-03-18 21:01:10 +03:00
// H a n d l e t h e w o r k i n g s e t a s i f i t w e r e t h e r o o t c o n t a i n e r
// I f w e d o a f u l l s e r v e r s c a n p e r t h e r e c o m m e n d a t i o n s o f t h e F i l e P r o v i d e r d o c u m e n t a t i o n ,
// w e w i l l b e s t u c k f o r a h u g e p e r i o d o f t i m e w i t h o u t b e i n g a b l e t o a c c e s s f i l e s a s t h e
// e n t i r e s e r v e r g e t s s c a n n e d . I n s t e a d , t r e a t t h e w o r k i n g s e t a s t h e r o o t c o n t a i n e r h e r e .
// T h e n , w h e n w e e n u m e r a t e c h a n g e s , w e ' l l g o t h r o u g h e v e r y t h i n g - - w h i l e w e c a n s t i l l
// n a v i g a t e a l i t t l e b i t i n F i n d e r , f i l e p i c k e r , e t c
2023-03-09 03:19:00 +03:00
guard serverUrl != " " else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . error (
" Enumerator has empty serverUrl -- can't enumerate that! For identifier: \( self . enumeratedItemIdentifier . rawValue , privacy : . public ) "
)
2023-03-09 03:19:00 +03:00
observer . finishEnumeratingWithError ( NSFileProviderError ( . noSuchItem ) )
return
}
2023-03-18 21:01:10 +03:00
// TODO: M a k e b e t t e r u s e o f p a g i n a t i o n a n d h a n d l e p a g i n g p r o p e r l y
2024-01-22 09:40:47 +03:00
if page = = NSFileProviderPage . initialPageSortedByDate as NSFileProviderPage
|| page = = NSFileProviderPage . initialPageSortedByName as NSFileProviderPage
{
Logger . enumeration . debug (
" Enumerating initial page for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) "
)
2023-01-26 22:50:40 +03:00
2024-01-22 09:40:47 +03:00
FileProviderEnumerator . readServerUrl ( serverUrl , ncAccount : ncAccount , ncKit : ncKit ) {
metadatas , _ , _ , _ , readError in
2023-03-09 03:19:00 +03:00
guard readError = = nil else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . error (
" Finishing enumeration for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) with error \( readError ! . localizedDescription , privacy : . public ) "
)
2023-03-13 16:27:17 +03:00
2023-03-13 17:09:43 +03:00
let nkReadError = NKError ( error : readError ! )
2023-03-21 15:21:51 +03:00
observer . finishEnumeratingWithError ( nkReadError . fileProviderError )
2023-03-09 04:09:39 +03:00
return
2023-03-09 03:19:00 +03:00
}
2024-01-22 09:40:47 +03:00
guard let metadatas else {
Logger . enumeration . error (
" Finishing enumeration for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) with invalid metadatas. "
)
2023-03-19 01:35:10 +03:00
observer . finishEnumeratingWithError ( NSFileProviderError ( . cannotSynchronize ) )
2023-03-09 04:09:39 +03:00
return
}
2023-03-09 03:19:00 +03:00
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Finished reading serverUrl: \( self . serverUrl , privacy : . public ) for user: \( self . ncAccount . ncKitAccount , privacy : . public ) . Processed \( metadatas . count ) metadatas "
)
2023-03-09 03:19:00 +03:00
2024-01-22 09:40:47 +03:00
FileProviderEnumerator . completeEnumerationObserver (
observer , ncKit : self . ncKit , numPage : 1 , itemMetadatas : metadatas )
2023-01-26 22:50:40 +03:00
}
2023-01-27 04:44:34 +03:00
2024-01-22 09:40:47 +03:00
return
2023-01-26 22:50:40 +03:00
}
2023-01-27 04:44:34 +03:00
let numPage = Int ( String ( data : page . rawValue , encoding : . utf8 ) ! ) !
2024-01-22 09:40:47 +03:00
Logger . enumeration . debug (
" Enumerating page \( numPage , privacy : . public ) for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) "
)
2023-03-09 03:19:00 +03:00
// TODO: H a n d l e p a g i n g p r o p e r l y
// F i l e P r o v i d e r E n u m e r a t o r . c o m p l e t e O b s e r v e r ( o b s e r v e r , n c K i t : n c K i t , n u m P a g e : n u m P a g e , i t e m M e t a d a t a s : n i l )
observer . finishEnumerating ( upTo : nil )
2022-03-29 16:00:59 +03:00
}
2024-01-22 09:40:47 +03:00
func enumerateChanges (
for observer : NSFileProviderChangeObserver , from anchor : NSFileProviderSyncAnchor
) {
Logger . enumeration . debug (
" Received enumerate changes request for enumerator for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) "
)
2023-03-09 15:14:03 +03:00
/*
2023-03-14 23:03:49 +03:00
- query the server for updates since the passed - in sync anchor ( TODO )
2024-01-22 09:40:47 +03:00
2023-03-14 23:03:49 +03:00
If this is an enumerator for the working set :
2022-03-29 16:00:59 +03:00
- note the changes in your local database
2024-01-22 09:40:47 +03:00
2022-03-29 16:00:59 +03:00
- inform the observer about item deletions and updates ( modifications + insertions )
- inform the observer when you have finished enumerating up to a subsequent sync anchor
*/
2023-03-09 15:14:03 +03:00
if enumeratedItemIdentifier = = . workingSet {
2024-01-22 09:40:47 +03:00
Logger . enumeration . debug (
" Enumerating changes in working set for user: \( self . ncAccount . ncKitAccount , privacy : . public ) "
)
2023-03-09 15:14:03 +03:00
2023-03-18 18:44:30 +03:00
// U n l i k e w h e n e n u m e r a t i n g i t e m s w e c a n ' t p r o g r e s s i v e l y e n u m e r a t e i t e m s a s w e n e e d t o w a i t t o r e s o l v e w h i c h i t e m s a r e t r u l y d e l e t e d a n d w h i c h
// h a v e j u s t b e e n m o v e d e l s e w h e r e .
2024-01-22 09:40:47 +03:00
fullRecursiveScan (
ncAccount : ncAccount ,
ncKit : ncKit ,
scanChangesOnly : true
) { _ , newMetadatas , updatedMetadatas , deletedMetadatas , error in
2023-03-18 18:05:34 +03:00
if self . isInvalidated {
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Enumerator invalidated during working set change scan. For user: \( self . ncAccount . ncKitAccount , privacy : . public ) "
)
2023-03-18 18:05:34 +03:00
observer . finishEnumeratingWithError ( NSFileProviderError ( . cannotSynchronize ) )
return
}
2023-03-18 15:57:02 +03:00
guard error = = nil else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Finished recursive change enumeration of working set for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with error: \( error ! . errorDescription , privacy : . public ) "
)
2023-03-21 15:21:51 +03:00
observer . finishEnumeratingWithError ( error ! . fileProviderError )
2023-03-18 18:05:34 +03:00
return
2023-03-18 15:57:02 +03:00
}
2023-03-15 16:37:53 +03:00
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Finished recursive change enumeration of working set for user: \( self . ncAccount . ncKitAccount , privacy : . public ) . Enumerating items. "
)
FileProviderEnumerator . completeChangesObserver (
observer ,
anchor : anchor ,
ncKit : self . ncKit ,
newMetadatas : newMetadatas ,
updatedMetadatas : updatedMetadatas ,
deletedMetadatas : deletedMetadatas )
2023-03-15 16:37:53 +03:00
}
2023-03-09 15:14:03 +03:00
return
} else if enumeratedItemIdentifier = = . trashContainer {
2024-01-22 09:40:47 +03:00
Logger . enumeration . debug (
" Enumerating changes in trash set for user: \( self . ncAccount . ncKitAccount , privacy : . public ) "
)
2023-03-09 15:14:03 +03:00
// T O D O !
observer . finishEnumeratingChanges ( upTo : anchor , moreComing : false )
return
}
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Enumerating changes for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) "
)
2023-03-09 15:14:03 +03:00
2023-03-09 15:27:57 +03:00
// N o m a t t e r w h a t h a p p e n s h e r e w e f i n i s h e n u m e r a t i o n i n s o m e w a y , e i t h e r f r o m t h e e r r o r
// h a n d l i n g b e l o w o r f r o m t h e c o m p l e t e C h a n g e s O b s e r v e r
2023-03-19 01:36:25 +03:00
// TODO: M o v e t o t h e s y n c e n g i n e e x t e n s i o n
2024-01-22 09:40:47 +03:00
FileProviderEnumerator . readServerUrl (
serverUrl , ncAccount : ncAccount , ncKit : ncKit , stopAtMatchingEtags : true
) { _ , newMetadatas , updatedMetadatas , deletedMetadatas , readError in
2023-03-18 15:24:37 +03:00
// I f w e g e t a 4 0 4 w e m i g h t a d d m o r e d e l e t e d m e t a d a t a s
var currentDeletedMetadatas : [ NextcloudItemMetadataTable ] = [ ]
if let notNilDeletedMetadatas = deletedMetadatas {
currentDeletedMetadatas = notNilDeletedMetadatas
}
2023-03-09 15:14:03 +03:00
guard readError = = nil else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . error (
" Finishing enumeration of changes for user: \( self . ncAccount . ncKitAccount , privacy : . public ) with serverUrl: \( self . serverUrl , privacy : . public ) with error: \( readError ! . localizedDescription , privacy : . public ) "
)
2023-03-09 18:51:31 +03:00
2023-03-13 17:09:43 +03:00
let nkReadError = NKError ( error : readError ! )
2023-03-21 15:21:51 +03:00
let fpError = nkReadError . fileProviderError
2023-03-13 16:15:32 +03:00
2023-03-13 17:09:43 +03:00
if nkReadError . isNotFoundError {
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" 404 error means item no longer exists. Deleting metadata and reporting \( self . serverUrl , privacy : . public ) as deletion without error "
)
2023-03-09 18:51:31 +03:00
2023-03-13 17:09:43 +03:00
guard let itemMetadata = self . enumeratedItemMetadata else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . error (
" Invalid enumeratedItemMetadata, could not delete metadata nor report deletion "
)
2023-03-13 17:09:43 +03:00
observer . finishEnumeratingWithError ( fpError )
2023-03-13 16:15:32 +03:00
return
2023-03-09 18:51:31 +03:00
}
2023-03-13 16:27:17 +03:00
2023-03-13 17:09:43 +03:00
let dbManager = NextcloudFilesDatabaseManager . shared
if itemMetadata . directory {
2024-01-22 09:40:47 +03:00
if let deletedDirectoryMetadatas =
dbManager . deleteDirectoryAndSubdirectoriesMetadata (
ocId : itemMetadata . ocId )
{
2023-03-18 15:24:37 +03:00
currentDeletedMetadatas += deletedDirectoryMetadatas
} else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . error (
" Something went wrong when recursively deleting directory not found. "
)
2023-03-18 15:24:37 +03:00
}
2023-03-13 17:09:43 +03:00
} else {
dbManager . deleteItemMetadata ( ocId : itemMetadata . ocId )
}
2024-01-22 09:40:47 +03:00
FileProviderEnumerator . completeChangesObserver (
observer , anchor : anchor , ncKit : self . ncKit , newMetadatas : nil ,
updatedMetadatas : nil ,
deletedMetadatas : [ itemMetadata ] )
2023-03-13 16:27:17 +03:00
return
2024-01-22 09:40:47 +03:00
} else if nkReadError . isNoChangesError { // A l l i s w e l l , j u s t n o c h a n g e d e t a g s
Logger . enumeration . info (
" Error was to say no changed files -- not bad error. Finishing change enumeration. "
)
2023-03-13 17:09:43 +03:00
observer . finishEnumeratingChanges ( upTo : anchor , moreComing : false )
2024-01-22 09:40:47 +03:00
return
2023-03-09 18:51:31 +03:00
}
2023-03-13 17:09:43 +03:00
observer . finishEnumeratingWithError ( fpError )
2023-03-09 15:14:03 +03:00
return
}
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Finished reading serverUrl: \( self . serverUrl , privacy : . public ) for user: \( self . ncAccount . ncKitAccount , privacy : . public ) "
)
2023-03-09 15:14:03 +03:00
2024-01-22 09:40:47 +03:00
FileProviderEnumerator . completeChangesObserver (
observer , anchor : anchor , ncKit : self . ncKit , newMetadatas : newMetadatas ,
updatedMetadatas : updatedMetadatas , deletedMetadatas : deletedMetadatas )
2023-03-09 15:14:03 +03:00
}
2022-03-29 16:00:59 +03:00
}
func currentSyncAnchor ( completionHandler : @ escaping ( NSFileProviderSyncAnchor ? ) -> Void ) {
completionHandler ( anchor )
}
2023-01-12 23:50:35 +03:00
// MARK: - H e l p e r m e t h o d s
2024-01-22 09:40:47 +03:00
private static func metadatasToFileProviderItems (
_ itemMetadatas : [ NextcloudItemMetadataTable ] , ncKit : NextcloudKit ,
completionHandler : @ escaping ( _ items : [ NSFileProviderItem ] ) -> Void
) {
2023-01-12 23:50:35 +03:00
var items : [ NSFileProviderItem ] = [ ]
2024-01-22 09:40:47 +03:00
let conversionQueue = DispatchQueue (
label : " metadataToItemConversionQueue " , qos : . userInitiated , attributes : . concurrent )
let appendQueue = DispatchQueue ( label : " enumeratorItemAppendQueue " , qos : . userInitiated ) // S e r i a l q u e u e
2023-03-18 23:35:12 +03:00
let dispatchGroup = DispatchGroup ( )
2023-03-09 03:19:00 +03:00
for itemMetadata in itemMetadatas {
2023-03-20 15:16:24 +03:00
conversionQueue . async ( group : dispatchGroup ) {
2023-03-18 23:35:12 +03:00
if itemMetadata . e2eEncrypted {
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Skipping encrypted metadata in enumeration: \( itemMetadata . ocId , privacy : . public ) \( itemMetadata . fileName , privacy : . public ) "
)
2023-03-18 23:35:12 +03:00
return
}
2024-01-22 09:40:47 +03:00
if let parentItemIdentifier = NextcloudFilesDatabaseManager . shared
. parentItemIdentifierFromMetadata ( itemMetadata )
{
let item = FileProviderItem (
metadata : itemMetadata , parentItemIdentifier : parentItemIdentifier ,
ncKit : ncKit )
Logger . enumeration . debug (
" Will enumerate item with ocId: \( itemMetadata . ocId , privacy : . public ) and name: \( itemMetadata . fileName , privacy : . public ) "
)
2023-03-20 15:16:24 +03:00
appendQueue . async ( group : dispatchGroup ) {
items . append ( item )
}
2023-03-18 23:35:12 +03:00
} else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . error (
" Could not get valid parentItemIdentifier for item with ocId: \( itemMetadata . ocId , privacy : . public ) and name: \( itemMetadata . fileName , privacy : . public ) , skipping enumeration "
)
2023-03-18 23:35:12 +03:00
}
2023-01-12 23:50:35 +03:00
}
}
2023-03-18 23:35:12 +03:00
dispatchGroup . notify ( queue : DispatchQueue . main ) {
completionHandler ( items )
}
2023-03-18 18:27:32 +03:00
}
2023-03-18 18:35:59 +03:00
private static func fileProviderPageforNumPage ( _ numPage : Int ) -> NSFileProviderPage {
2024-01-22 09:40:47 +03:00
NSFileProviderPage ( " \( numPage ) " . data ( using : . utf8 ) ! )
2023-03-18 18:35:59 +03:00
}
2024-01-22 09:40:47 +03:00
private static func completeEnumerationObserver (
_ observer : NSFileProviderEnumerationObserver , ncKit : NextcloudKit , numPage : Int ,
itemMetadatas : [ NextcloudItemMetadataTable ]
) {
2023-03-18 23:35:12 +03:00
metadatasToFileProviderItems ( itemMetadatas , ncKit : ncKit ) { items in
observer . didEnumerate ( items )
Logger . enumeration . info ( " Did enumerate \( items . count ) items " )
// TODO: H a n d l e p a g i n g p r o p e r l y
/*
if items . count = = maxItemsPerFileProviderPage {
let nextPage = numPage + 1
let providerPage = NSFileProviderPage ( " \( nextPage ) " . data ( using : . utf8 ) ! )
observer . finishEnumerating ( upTo : providerPage )
} else {
observer . finishEnumerating ( upTo : nil )
}
*/
observer . finishEnumerating ( upTo : fileProviderPageforNumPage ( numPage ) )
2023-01-12 23:50:35 +03:00
}
}
2023-01-26 22:50:40 +03:00
2024-01-22 09:40:47 +03:00
private static func completeChangesObserver (
_ observer : NSFileProviderChangeObserver , anchor : NSFileProviderSyncAnchor ,
ncKit : NextcloudKit ,
newMetadatas : [ NextcloudItemMetadataTable ] ? ,
updatedMetadatas : [ NextcloudItemMetadataTable ] ? ,
deletedMetadatas : [ NextcloudItemMetadataTable ] ?
) {
2023-03-09 17:45:38 +03:00
guard newMetadatas != nil || updatedMetadatas != nil || deletedMetadatas != nil else {
2024-01-22 09:40:47 +03:00
Logger . enumeration . error (
" Received invalid newMetadatas, updatedMetadatas or deletedMetadatas. Finished enumeration of changes with error. "
)
2023-03-09 15:27:57 +03:00
observer . finishEnumeratingWithError ( NSFileProviderError ( . noSuchItem ) )
return
}
2023-03-09 17:45:38 +03:00
// O b s e r v e r d o e s n o t c a r e a b o u t n e w v s u p d a t e d , s o j o i n
var allUpdatedMetadatas : [ NextcloudItemMetadataTable ] = [ ]
var allDeletedMetadatas : [ NextcloudItemMetadataTable ] = [ ]
2024-01-22 09:40:47 +03:00
if let newMetadatas {
2023-03-09 17:45:38 +03:00
allUpdatedMetadatas += newMetadatas
}
2024-01-22 09:40:47 +03:00
if let updatedMetadatas {
2023-03-09 17:45:38 +03:00
allUpdatedMetadatas += updatedMetadatas
}
2024-01-22 09:40:47 +03:00
if let deletedMetadatas {
2023-03-09 17:45:38 +03:00
allDeletedMetadatas = deletedMetadatas
}
2024-01-22 09:40:47 +03:00
let allFpItemDeletionsIdentifiers = Array (
allDeletedMetadatas . map { NSFileProviderItemIdentifier ( $0 . ocId ) } )
2023-03-18 23:35:12 +03:00
if ! allFpItemDeletionsIdentifiers . isEmpty {
observer . didDeleteItems ( withIdentifiers : allFpItemDeletionsIdentifiers )
}
2023-03-09 15:27:57 +03:00
2023-03-18 23:35:12 +03:00
metadatasToFileProviderItems ( allUpdatedMetadatas , ncKit : ncKit ) { updatedItems in
2023-03-09 15:27:57 +03:00
2023-03-18 23:35:12 +03:00
if ! updatedItems . isEmpty {
observer . didUpdate ( updatedItems )
2023-03-10 20:36:25 +03:00
}
2023-03-11 00:25:28 +03:00
2024-01-22 09:40:47 +03:00
Logger . enumeration . info (
" Processed \( updatedItems . count ) new or updated metadatas, \( allDeletedMetadatas . count ) deleted metadatas. "
)
2023-03-18 23:35:12 +03:00
observer . finishEnumeratingChanges ( upTo : anchor , moreComing : false )
2023-03-09 17:45:38 +03:00
}
2023-03-09 15:27:57 +03:00
}
2022-03-29 16:00:59 +03:00
}