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 {
return FileProviderEnumerator . isSystemIdentifier ( enumeratedItemIdentifier )
}
2023-03-07 03:40:17 +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 {
return identifier = = . rootContainer ||
identifier = = . trashContainer ||
identifier = = . workingSet
}
2022-03-29 16:00:59 +03:00
2023-02-02 22:13:35 +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 ) {
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Providing enumerator for a system defined container: \( enumeratedItemIdentifier . rawValue , privacy : . public ) " )
2023-01-27 04:26:27 +03:00
self . serverUrl = ncAccount . davFilesUrl
2023-01-10 22:25:26 +03:00
} else {
2023-03-14 23:26:52 +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
enumeratedItemMetadata = dbManager . itemMetadataFromFileProviderItemIdentifier ( enumeratedItemIdentifier )
if enumeratedItemMetadata != nil {
self . serverUrl = enumeratedItemMetadata ! . serverUrl + " / " + enumeratedItemMetadata ! . fileName
2023-02-01 20:24:23 +03:00
} else {
2023-03-14 23:26:52 +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
}
}
2023-03-14 23:26:52 +03:00
Logger . enumeration . info ( " Set up enumerator for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
2022-03-29 16:00:59 +03:00
super . init ( )
}
func invalidate ( ) {
2023-03-18 20:04:19 +03:00
Logger . enumeration . debug ( " Enumerator is being invalidated for item with identifier: \( self . enumeratedItemIdentifier . rawValue , privacy : . public ) " )
2023-03-18 18:05:34 +03:00
self . 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
2022-03-29 16:00:59 +03:00
func enumerateItems ( for observer : NSFileProviderEnumerationObserver , startingAt page : NSFileProviderPage ) {
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Received enumerate items request for enumerator with user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
2023-03-14 23:03:49 +03:00
/*
- inspect the page to determine whether this is an initial or a follow - up request ( TODO )
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
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-10 03:16:23 +03:00
let dbManager = NextcloudFilesDatabaseManager . shared
2023-03-18 21:01:10 +03:00
if enumeratedItemIdentifier = = . trashContainer {
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Enumerating trash set for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
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 {
2023-03-14 23:26:52 +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
2023-01-26 22:50:40 +03:00
if page = = NSFileProviderPage . initialPageSortedByDate as NSFileProviderPage ||
page = = NSFileProviderPage . initialPageSortedByName as NSFileProviderPage {
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Enumerating initial page for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
2023-03-09 03:19:00 +03:00
2023-03-19 01:36:25 +03:00
FileProviderEnumerator . readServerUrl ( serverUrl , ncAccount : ncAccount , ncKit : ncKit ) { metadatas , _ , _ , _ , readError in
2023-03-09 03:19:00 +03:00
guard readError = = nil else {
2023-03-15 19:21:31 +03:00
Logger . enumeration . error ( " Finishing enumeration for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) 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 ! )
observer . finishEnumeratingWithError ( nkReadError . toFileProviderError ( ) )
2023-03-09 04:09:39 +03:00
return
2023-03-09 03:19:00 +03:00
}
2023-03-19 01:35:10 +03:00
guard let metadatas = metadatas else {
Logger . enumeration . error ( " Finishing enumeration for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with invalid metadatas. " )
observer . finishEnumeratingWithError ( NSFileProviderError ( . cannotSynchronize ) )
2023-03-09 04:09:39 +03:00
return
}
2023-03-09 03:19:00 +03:00
2023-03-19 01:35:10 +03:00
Logger . enumeration . info ( " Finished reading serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) . Processed \( metadatas . count ) metadatas " )
2023-03-09 03:19:00 +03:00
2023-03-09 14:54:18 +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
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 ) ! ) !
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Enumerating page \( numPage , privacy : . public ) for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
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
}
func enumerateChanges ( for observer : NSFileProviderChangeObserver , from anchor : NSFileProviderSyncAnchor ) {
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Received enumerate changes request for enumerator for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
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 )
2022-03-29 16:00:59 +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
- 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 {
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Enumerating changes in working set for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
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 .
2023-03-19 01:36:25 +03:00
fullRecursiveScan ( ncAccount : self . ncAccount ,
2023-03-18 18:44:30 +03:00
ncKit : self . ncKit ,
2023-03-18 21:01:10 +03:00
scanChangesOnly : true ) { _ , newMetadatas , updatedMetadatas , deletedMetadatas , error in
2023-03-18 18:05:34 +03:00
if self . isInvalidated {
Logger . enumeration . info ( " Enumerator invalidated during working set change scan. For user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
observer . finishEnumeratingWithError ( NSFileProviderError ( . cannotSynchronize ) )
return
}
2023-03-18 15:57:02 +03:00
guard error = = nil else {
Logger . enumeration . info ( " Finished recursive change enumeration of working set for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with error: \( error ! . errorDescription , privacy : . public ) " )
observer . finishEnumeratingWithError ( error ! . toFileProviderError ( ) )
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
Logger . enumeration . info ( " Finished recursive change enumeration of working set for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) . Enumerating items. " )
2023-03-17 22:37:22 +03:00
2023-03-15 16:37:53 +03:00
FileProviderEnumerator . completeChangesObserver ( observer ,
anchor : anchor ,
ncKit : self . ncKit ,
newMetadatas : newMetadatas ,
updatedMetadatas : updatedMetadatas ,
2023-03-18 16:10:24 +03:00
deletedMetadatas : deletedMetadatas )
2023-03-15 16:37:53 +03:00
}
2023-03-09 15:14:03 +03:00
return
} else if enumeratedItemIdentifier = = . trashContainer {
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Enumerating changes in trash set for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
2023-03-09 15:14:03 +03:00
// T O D O !
observer . finishEnumeratingChanges ( upTo : anchor , moreComing : false )
return
}
2023-03-14 23:26:52 +03:00
Logger . enumeration . info ( " Enumerating changes for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
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
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 {
2023-03-15 19:21:31 +03:00
Logger . enumeration . error ( " Finishing enumeration of changes for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) 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 ! )
let fpError = nkReadError . toFileProviderError ( )
2023-03-13 16:15:32 +03:00
2023-03-13 17:09:43 +03:00
if nkReadError . isNotFoundError {
2023-03-14 23:26:52 +03:00
Logger . enumeration . info ( " 404 error means item no longer exists. Deleting metadata and reporting \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) 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 {
2023-03-14 23:03:49 +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 {
2023-03-18 15:24:37 +03:00
if let deletedDirectoryMetadatas = dbManager . deleteDirectoryAndSubdirectoriesMetadata ( ocId : itemMetadata . ocId ) {
currentDeletedMetadatas += deletedDirectoryMetadatas
} else {
Logger . enumeration . error ( " Something went wrong when recursively deleting directory not found. " )
}
2023-03-13 17:09:43 +03:00
} else {
dbManager . deleteItemMetadata ( ocId : itemMetadata . ocId )
}
FileProviderEnumerator . completeChangesObserver ( observer , anchor : anchor , ncKit : self . ncKit , newMetadatas : nil , updatedMetadatas : nil , deletedMetadatas : [ itemMetadata ] )
2023-03-13 16:27:17 +03:00
return
2023-03-13 17:09:43 +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
2023-03-14 23:03:49 +03:00
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 )
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
}
2023-03-14 23:26:52 +03:00
Logger . enumeration . info ( " Finished reading serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
2023-03-09 15:14:03 +03:00
2023-03-10 03:16:23 +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
2023-03-18 23:35:12 +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 ] = [ ]
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-18 23:35:12 +03:00
dispatchGroup . enter ( )
2023-01-12 23:50:35 +03:00
2023-03-18 23:35:12 +03:00
DispatchQueue . global ( qos : . userInitiated ) . async {
if itemMetadata . e2eEncrypted {
Logger . enumeration . info ( " Skipping encrypted metadata in enumeration: \( itemMetadata . ocId , privacy : . public ) \( itemMetadata . fileName , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
dispatchGroup . leave ( )
return
}
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 : OSLogPrivacy . auto ( mask : . hash ) ) " )
items . append ( item )
} else {
Logger . enumeration . error ( " Could not get valid parentItemIdentifier for item with ocId: \( itemMetadata . ocId , privacy : . public ) and name: \( itemMetadata . fileName , privacy : OSLogPrivacy . auto ( mask : . hash ) ) , skipping enumeration " )
}
dispatchGroup . leave ( )
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 {
return NSFileProviderPage ( " \( numPage ) " . data ( using : . utf8 ) ! )
}
2023-03-18 18:27:32 +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
2023-03-09 17:45:38 +03:00
private static func completeChangesObserver ( _ observer : NSFileProviderChangeObserver , anchor : NSFileProviderSyncAnchor , ncKit : NextcloudKit , newMetadatas : [ NextcloudItemMetadataTable ] ? , updatedMetadatas : [ NextcloudItemMetadataTable ] ? , deletedMetadatas : [ NextcloudItemMetadataTable ] ? ) {
guard newMetadatas != nil || updatedMetadatas != nil || deletedMetadatas != nil else {
2023-03-14 23:03:49 +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 ] = [ ]
if let newMetadatas = newMetadatas {
allUpdatedMetadatas += newMetadatas
}
if let updatedMetadatas = updatedMetadatas {
allUpdatedMetadatas += updatedMetadatas
}
if let deletedMetadatas = deletedMetadatas {
allDeletedMetadatas = deletedMetadatas
}
var 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
2023-03-18 23:35:12 +03:00
Logger . enumeration . info ( " Processed \( updatedItems . count ) new or updated metadatas, \( allDeletedMetadatas . count ) deleted metadatas. " )
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
}