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 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 15:58:27 +03:00
// W h e n e n u m e r a t i n g i t e m s i n t h e w o r k i n g s e t , w e a r e e x p e c t e d t o p r o v i d e a n a c c o u n t o f t h e
// w h o l e s e r v e r a n d a l l i t s f i l e s .
if enumeratedItemIdentifier = = . workingSet {
2023-03-10 05:21:01 +03:00
if page = = NSFileProviderPage . initialPageSortedByDate as NSFileProviderPage ||
page = = NSFileProviderPage . initialPageSortedByName as NSFileProviderPage {
2023-03-08 00:40:52 +03:00
2023-03-18 15:58:27 +03:00
fullRecursiveScan ( ncAccount : self . ncAccount , ncKit : self . ncKit , scanChangesOnly : false ) { metadatas , _ , _ , _ , error in
2023-03-10 04:09:24 +03:00
2023-03-18 15:58:27 +03:00
if self . isInvalidated {
Logger . enumeration . info ( " Enumerator invalidated during working set item enumeration. For user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
observer . finishEnumeratingWithError ( NSFileProviderError ( . cannotSynchronize ) )
2023-03-15 16:03:19 +03:00
return
}
2023-03-18 15:58:27 +03:00
guard error = = nil else {
Logger . enumeration . info ( " Finished recursive iteme enumeration of working set for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with error: \( error ! . errorDescription , privacy : . public ) " )
observer . finishEnumeratingWithError ( error ! . toFileProviderError ( ) )
return ;
}
2023-03-15 16:03:19 +03:00
2023-03-18 15:58:27 +03:00
Logger . enumeration . info ( " Finished recursive item enumeration of working set for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) . Enumerating items. " )
2023-03-15 16:03:19 +03:00
2023-03-18 15:58:27 +03:00
FileProviderEnumerator . completeEnumerationObserver ( observer , ncKit : self . ncKit , numPage : 1 , itemMetadatas : metadatas )
2023-03-10 04:09:24 +03:00
}
2023-03-10 05:21:01 +03:00
2023-03-15 16:03:19 +03:00
return
2023-03-10 05:21:01 +03:00
} else {
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Enumerating page \( page . rawValue ) of working set for user: \( self . ncAccount . ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
2023-03-14 23:03:49 +03:00
// T O D O !
2023-03-10 05:21:01 +03:00
observer . finishEnumerating ( upTo : nil )
2023-03-10 04:09:24 +03:00
}
2023-03-08 00:40:52 +03:00
return
} else 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-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-10 03:16:23 +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 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
FileProviderEnumerator . readServerUrl ( serverUrl , ncAccount : ncAccount , ncKit : ncKit ) { _ , _ , _ , _ , readError in
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
}
let ncKitAccount = self . ncAccount . ncKitAccount
// R e t u r n a l l n o w k n o w n m e t a d a t a s
2023-03-09 04:09:39 +03:00
var metadatas : [ NextcloudItemMetadataTable ]
if self . enumeratingSystemIdentifier || ( self . enumeratedItemMetadata != nil && self . enumeratedItemMetadata ! . directory ) {
metadatas = NextcloudFilesDatabaseManager . shared . itemMetadatas ( account : ncKitAccount , serverUrl : self . serverUrl )
} else if ( self . enumeratedItemMetadata != nil ) {
guard let updatedEnumeratedItemMetadata = NextcloudFilesDatabaseManager . shared . itemMetadataFromOcId ( self . enumeratedItemMetadata ! . ocId ) else {
2023-03-14 23:26:52 +03:00
Logger . enumeration . error ( " Could not finish enumeration for user: \( ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) with serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) as the enumerated item could not be fetched from database. \( self . enumeratedItemIdentifier . rawValue , privacy : . public ) " )
2023-03-09 04:09:39 +03:00
observer . finishEnumeratingWithError ( NSFileProviderError ( . noSuchItem ) )
return
}
2023-03-09 14:54:18 +03:00
2023-03-09 04:09:39 +03:00
metadatas = [ updatedEnumeratedItemMetadata ]
2023-03-14 23:03:49 +03:00
} else { // W e n e e d t o h a v e a n e n u m e r a t e d I t e m M e t a d a t a t o h a v e a n o n e m p t y s e r v e r U r l
2023-03-14 23:26:52 +03:00
Logger . enumeration . error ( " Cannot finish enumeration for user: \( ncKitAccount , privacy : OSLogPrivacy . auto ( mask : . hash ) ) as we do not have a valid server URL. NOTE: this error should not be possible and indicates something is going wrong before. " )
2023-03-09 04:09:39 +03:00
observer . finishEnumeratingWithError ( NSFileProviderError ( . noSuchItem ) )
return
}
2023-03-09 03:19:00 +03:00
2023-03-14 23:26:52 +03:00
Logger . enumeration . info ( " Finished reading serverUrl: \( self . serverUrl , privacy : OSLogPrivacy . auto ( mask : . hash ) ) for user: \( 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:05:34 +03:00
fullRecursiveScan ( ncAccount : self . ncAccount , ncKit : self . ncKit , scanChangesOnly : true ) { _ , newMetadatas , updatedMetadatas , deletedMetadatas , error in
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-13 16:59:46 +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 {
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-15 14:47:08 +03:00
private static func completeEnumerationObserver ( _ observer : NSFileProviderEnumerationObserver , ncKit : NextcloudKit , numPage : Int , itemMetadatas : [ NextcloudItemMetadataTable ] ) {
2023-01-26 22:50:40 +03:00
2023-01-12 23:50:35 +03:00
var items : [ NSFileProviderItem ] = [ ]
2023-03-09 03:19:00 +03:00
for itemMetadata in itemMetadatas {
2023-01-27 04:44:34 +03:00
if itemMetadata . e2eEncrypted {
2023-03-14 23:26:52 +03:00
Logger . enumeration . info ( " Skipping encrypted metadata in enumeration: \( itemMetadata . ocId ) \( itemMetadata . fileName , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
2023-01-27 04:44:34 +03:00
continue
}
2023-01-12 23:50:35 +03:00
2023-03-13 14:34:05 +03:00
if let parentItemIdentifier = NextcloudFilesDatabaseManager . shared . parentItemIdentifierFromMetadata ( itemMetadata ) {
2023-02-02 22:13:35 +03:00
let item = FileProviderItem ( metadata : itemMetadata , parentItemIdentifier : parentItemIdentifier , ncKit : ncKit )
2023-03-14 23:26:52 +03:00
Logger . enumeration . debug ( " Will enumerate item with ocId: \( itemMetadata . ocId ) and name: \( itemMetadata . fileName , privacy : OSLogPrivacy . auto ( mask : . hash ) ) " )
2023-01-12 23:50:35 +03:00
items . append ( item )
2023-01-27 04:44:34 +03:00
} else {
2023-03-14 23:26:52 +03:00
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 " )
2023-01-12 23:50:35 +03:00
}
}
observer . didEnumerate ( items )
2023-03-14 23:03:49 +03:00
Logger . enumeration . info ( " Did enumerate \( items . count ) items " )
2023-01-12 23:50:35 +03:00
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
/*
2023-01-12 23:50:35 +03:00
if items . count = = maxItemsPerFileProviderPage {
let nextPage = numPage + 1
let providerPage = NSFileProviderPage ( " \( nextPage ) " . data ( using : . utf8 ) ! )
observer . finishEnumerating ( upTo : providerPage )
} else {
observer . finishEnumerating ( upTo : nil )
}
2023-03-09 03:19:00 +03:00
*/
observer . finishEnumerating ( upTo : NSFileProviderPage ( " \( numPage ) " . data ( using : . utf8 ) ! ) )
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
}
2023-03-09 15:27:57 +03:00
var allFpItemUpdates : [ FileProviderItem ] = [ ]
2023-03-09 17:45:38 +03:00
var allFpItemDeletionsIdentifiers = Array ( allDeletedMetadatas . map { NSFileProviderItemIdentifier ( $0 . ocId ) } )
2023-03-09 15:27:57 +03:00
2023-03-11 00:25:28 +03:00
for updMetadata in allUpdatedMetadatas {
2023-03-13 14:34:05 +03:00
guard let parentItemIdentifier = NextcloudFilesDatabaseManager . shared . parentItemIdentifierFromMetadata ( updMetadata ) else {
2023-03-14 23:26:52 +03:00
Logger . enumeration . warning ( " Not enumerating change for metadata: \( updMetadata . ocId ) \( updMetadata . fileName , privacy : OSLogPrivacy . auto ( mask : . hash ) ) as could not get parent item metadata. " )
2023-03-11 00:25:28 +03:00
continue
}
2023-03-09 15:27:57 +03:00
2023-03-11 00:25:28 +03:00
guard ! updMetadata . e2eEncrypted else {
// P r e c a u t i o n , i f a l l g o e s w e l l i n N K F i l e c o n v e r s i o n t h e n t h i s s h o u l d n o t h a p p e n
// TODO: R e m o v e w h e n E 2 E E s u p p o r t e d
2023-03-14 23:26:52 +03:00
Logger . enumeration . info ( " Encrypted metadata in changes enumeration \( updMetadata . ocId ) \( updMetadata . fileName , privacy : OSLogPrivacy . auto ( mask : . hash ) ) , adding to deletions " )
2023-03-11 00:25:28 +03:00
allFpItemDeletionsIdentifiers . append ( NSFileProviderItemIdentifier ( updMetadata . ocId ) )
continue
2023-03-10 20:36:25 +03:00
}
2023-03-11 00:25:28 +03:00
let fpItem = FileProviderItem ( metadata : updMetadata , parentItemIdentifier : parentItemIdentifier , ncKit : ncKit )
allFpItemUpdates . append ( fpItem )
2023-03-09 15:27:57 +03:00
}
2023-03-09 17:45:38 +03:00
if ! allFpItemUpdates . isEmpty {
observer . didUpdate ( allFpItemUpdates )
}
if ! allFpItemDeletionsIdentifiers . isEmpty {
observer . didDeleteItems ( withIdentifiers : allFpItemDeletionsIdentifiers )
}
2023-03-14 23:03:49 +03:00
Logger . enumeration . info ( " Processed \( allUpdatedMetadatas . count ) new or updated metadatas, \( allDeletedMetadatas . count ) deleted metadatas. " )
2023-03-09 17:45:38 +03:00
observer . finishEnumeratingChanges ( upTo : anchor , moreComing : false )
2023-03-09 15:27:57 +03:00
}
2022-03-29 16:00:59 +03:00
}