@@ -11,14 +11,25 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
1111 var enumeratedItemIdentifier : NSFileProviderItemIdentifier
1212 var serverUrl : String ?
1313 var anchor : UInt64 = 0
14+ var readCapabilities : Bool = false
1415
1516 // X-NC-PAGINATE
16- var recordsPerPage : Int = 100
17+ #if DEBUG
18+ var recordsPerPage : Int = 50
19+ #else
20+ var recordsPerPage : Int = 200
21+ #endif
1722 // X-NC-PAGINATE
1823
1924 var paginateToken : String ?
2025 var paginatedTotal : Int = 0
2126
27+ struct PageInfo {
28+ let page : Int
29+ let items : Int
30+ }
31+ var paginateItems : [ PageInfo ] = [ ]
32+
2233 init ( enumeratedItemIdentifier: NSFileProviderItemIdentifier ) {
2334 self . enumeratedItemIdentifier = enumeratedItemIdentifier
2435 super. init ( )
@@ -90,14 +101,13 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
90101 pageNumber = intPage
91102 }
92103
93- let ( items, countItems , isPaginated ) = await fetchItemsForPage ( session: session,
94- serverUrl: serverUrl,
95- pageNumber: pageNumber)
104+ let ( items, ncPaginated ) = await fetchItemsForPage ( session: session,
105+ serverUrl: serverUrl,
106+ pageNumber: pageNumber)
96107 observer. didEnumerate ( items)
97108
98109 if !items. isEmpty,
99- isPaginated,
100- countItems == self . recordsPerPage {
110+ ncPaginated {
101111 pageNumber += 1
102112 observer. finishEnumerating ( upTo: NSFileProviderPage ( Data ( " \( pageNumber) " . utf8) ) )
103113 } else {
@@ -149,131 +159,134 @@ class FileProviderEnumerator: NSObject, NSFileProviderEnumerator {
149159 completionHandler ( NSFileProviderSyncAnchor ( data) )
150160 }
151161
152- func fetchItemsForPage( session: NCSession . Session , serverUrl: String , pageNumber: Int ) async -> ( items: [ NSFileProviderItem ] , countItems : Int , isPaginated : Bool ) {
153- let homeServerUrl = NCUtilityFileSystem ( ) . getHomeServer ( urlBase : session . urlBase , userId : session . userId )
154- let predicate = NSPredicate ( format : " account == %@ AND serverUrl == %@ AND status == %d " , session . account , serverUrl , NCGlobal . shared . metadataStatusNormal )
162+ func fetchItemsForPage( session: NCSession . Session , serverUrl: String , pageNumber: Int ) async -> ( items: [ NSFileProviderItem ] , ncPaginate : Bool ) {
163+ let fileProviderUtility = fileProviderUtility ( )
164+ let createMetadata = NCManageDatabaseCreateMetadata ( )
155165
156- func getItemsFromDatabase ( ) async -> ( items : [ NSFileProviderItem ] , countItems : Int ) {
166+ func getItemsFrom ( metadatas : [ tableMetadata ] , addOnDB : Bool ) async -> [ NSFileProviderItem ] {
157167 var items : [ NSFileProviderItem ] = [ ]
158- let directoryServerUrl = await NCManageDatabase . shared. getTableDirectoryAsync ( predicate: NSPredicate ( format: " account == %@ AND serverUrl == %@ " , session. account, serverUrl) )
159- let parentItemIdentifier = await fileProviderUtility ( ) . getParentItemIdentifierAsync ( session: session, directory: directoryServerUrl)
160- guard let parentItemIdentifier,
161- let metadatas = await NCManageDatabase . shared. getResultsMetadatasAsync ( predicate: predicate) else {
162- return ( [ ] , 0 )
168+
169+ // Get parentItemIdentifier
170+ guard let directory = await NCManageDatabase . shared. getTableDirectoryAsync ( predicate: NSPredicate ( format: " account == %@ AND serverUrl == %@ " , session. account, serverUrl) ) ,
171+ let parentItemIdentifier = await fileProviderUtility. getParentItemIdentifierAsync (
172+ session: session,
173+ directory: directory
174+ ) else {
175+ return ( [ ] )
163176 }
177+
178+ // make items
164179 for metadata in metadatas {
165- // Not include root filename
166- //
167- if metadata. fileName == NextcloudKit . shared. nkCommonInstance. rootFileName || metadata. e2eEncrypted {
180+ // NO E2EE OR NO VIDEO PART OF LIVE PHOTO
181+ if metadata. e2eEncrypted || ( metadata. classFile == NKTypeClassFile . video. rawValue && !metadata. livePhotoFile. isEmpty) {
168182 continue
169183 }
184+
185+ if addOnDB {
186+ if metadata. directory {
187+ await NCManageDatabase . shared. createDirectory ( metadata: metadata)
188+ }
189+ await NCManageDatabase . shared. addMetadataAsync ( metadata)
190+ }
191+
170192 autoreleasepool {
171193 let item = FileProviderItem ( metadata: metadata, parentItemIdentifier: parentItemIdentifier)
172194 items. append ( item)
173195 }
174196 }
175-
176- return ( items, metadatas. count)
197+ return items
177198 }
178199
179- if pageNumber == 0 {
180- // Read root directory
181- //
182- let resultsDirectory = await NextcloudKit . shared. readFileOrFolderAsync ( serverUrlFileName: serverUrl, depth: " 0 " , account: session. account)
183- guard resultsDirectory. error == . success else {
184- let ( items, countItems) = await getItemsFromDatabase ( )
185- return ( items, countItems, false )
186- }
187-
188- // Check etag
189- //
190- if let file = resultsDirectory. files? . first,
191- let directory = await NCManageDatabase . shared. getTableDirectoryAsync ( ocId: file. ocId) ,
192- file. etag == directory. etag {
193- let ( items, countItems) = await getItemsFromDatabase ( )
194- return ( items, countItems, false )
195- }
196- }
197-
198- var isPaginated : Bool = false
199- var offset = pageNumber * recordsPerPage
200+ // Request pagination
201+ //
202+ let showHiddenFiles = NCPreferences ( ) . getShowHiddenFiles ( account: session. account)
203+ var offset = 0
200204 if pageNumber > 0 {
201- offset += 1
205+ offset = getOffset ( for : pageNumber )
202206 }
203- let showHiddenFiles = NCPreferences ( ) . getShowHiddenFiles ( account : session. account )
204- let options = NKRequestOptions ( paginate: false ,
207+ let optionsPaginate = await FileProviderData . shared . isPaginatedAvailabile ( serverUrl : serverUrl , session: session )
208+ let options = NKRequestOptions ( paginate: optionsPaginate ,
205209 paginateToken: self . paginateToken,
206210 paginateOffset: offset,
207211 paginateCount: recordsPerPage,
208- queue: NextcloudKit . shared. nkCommonInstance. backgroundQueue)
212+ queue: NextcloudKit . shared. nkCommonInstance. backgroundQueue
213+ )
209214
210215 // Read folder metadata
211216 //
212- let resultsRead = await NextcloudKit . shared. readFileOrFolderAsync ( serverUrlFileName: serverUrl,
213- depth: " 1 " ,
214- showHiddenFiles: showHiddenFiles,
215- account: session. account,
216- options: options)
217+ let resultsRead = await NextcloudKit . shared. readFileOrFolderAsync (
218+ serverUrlFileName: serverUrl,
219+ depth: " 1 " ,
220+ showHiddenFiles: showHiddenFiles,
221+ account: session. account,
222+ options: options
223+ )
217224
218225 print ( " PAGINATE OFFSET: \( offset) COUNT: \( resultsRead. files? . count ?? 0 ) PAGE NUMBER: \( pageNumber) TOTAL: \( self . paginatedTotal) SERVERURL: \( serverUrl) " )
219226
220227 // Header for paginate
221228 //
229+ var ncPaginate : Bool = false
222230 if let headers = resultsRead. responseData? . response? . allHeaderFields as? [ String : String ] {
223231 let normalizedHeaders = Dictionary ( uniqueKeysWithValues: headers. map { ( $0. key. lowercased ( ) , $0. value) } )
224- isPaginated = Bool ( normalizedHeaders [ " x-nc-paginate " ] ?? " false " ) ?? false
232+ ncPaginate = Bool ( normalizedHeaders [ " x-nc-paginate " ] ?? " false " ) ?? false
225233 self . paginateToken = normalizedHeaders [ " x-nc-paginate-token " ]
226- self . paginatedTotal = Int ( normalizedHeaders [ " x-nc-paginate-total " ] ?? " 0 " ) ?? 0
234+ if let totalString = normalizedHeaders [ " x-nc-paginate-total " ] ,
235+ let total = Int ( totalString) {
236+ self . paginatedTotal = total
237+ }
227238 }
228239
229240 if resultsRead. error == . success, let files = resultsRead. files {
230- var items : [ NSFileProviderItem ] = [ ]
231- var parentItemIdentifier : NSFileProviderItemIdentifier ?
241+ let ( metadataFolder, metadatas) = await createMetadata. convertFilesToMetadatasAsync ( files, serverUrlMetadataFolder: pageNumber == 0 ? serverUrl : nil )
242+ self . paginateItems. append ( PageInfo ( page: pageNumber, items: metadatas. count) )
243+
232244 if pageNumber == 0 {
233- await NCManageDatabase . shared. deleteMetadataAsync ( predicate: predicate)
245+ await NCManageDatabase . shared. deleteMetadataAsync ( predicate: NSPredicate ( format: " account == %@ AND serverUrl == %@ AND status == %d " , session. account, serverUrl, NCGlobal . shared. metadataStatusNormal) )
246+ await NCManageDatabase . shared. createDirectory ( metadata: metadataFolder)
234247 }
235248
236- // Parent Item Identifier
237- //
238- if serverUrl == homeServerUrl {
239- parentItemIdentifier = NSFileProviderItemIdentifier ( NSFileProviderItemIdentifier . rootContainer. rawValue)
240- } else {
241- let filtered = files. filter { file in
242- let serverUrlFileName = NCUtilityFileSystem ( ) . createServerUrl ( serverUrl: file. serverUrl, fileName: file. fileName)
243- return serverUrlFileName == serverUrl
244- }
245- if let file = filtered. first {
246- parentItemIdentifier = NSFileProviderItemIdentifier ( file. ocId)
247- }
249+ let items = await getItemsFrom ( metadatas: Array ( metadatas) , addOnDB: true )
250+ if self . totalItems ( ) >= self . paginatedTotal {
251+ ncPaginate = false
248252 }
249-
250- // Must have parentItemIdentifier
251- //
252- guard let parentItemIdentifier else {
253- return ( [ ] , 0 , false )
253+ return ( items, ncPaginate)
254+ } else {
255+ let predicate = NSPredicate (
256+ format: """
257+ account == %@ AND
258+ serverUrl == %@ AND
259+ status == %d AND
260+ (
261+ classFile != 'video' OR
262+ (classFile == 'video' AND livePhotoFile == '')
263+ )
264+ """ ,
265+ session. account,
266+ serverUrl,
267+ NCGlobal . shared. metadataStatusNormal
268+ )
269+
270+ guard let metadatas = await NCManageDatabase . shared. getResultsMetadatasAsync ( predicate: predicate) else {
271+ return ( [ ] , false )
254272 }
273+ let items = await getItemsFrom ( metadatas: Array ( metadatas) , addOnDB: false )
274+ return ( items, false )
275+ }
276+ }
255277
256- for file in files {
257- let metadata = await NCManageDatabaseCreateMetadata ( ) . convertFileToMetadataAsync ( file)
258- await NCManageDatabase . shared. addMetadataAsync ( metadata)
259- if metadata. directory {
260- await NCManageDatabase . shared. createDirectory ( metadata: metadata, withEtag: false )
261- }
262- // Not include root filename or E2EE
263- //
264- if metadata. fileName == NextcloudKit . shared. nkCommonInstance. rootFileName || metadata. e2eEncrypted {
265- continue
266- }
267- autoreleasepool {
268- let item = FileProviderItem ( metadata: metadata, parentItemIdentifier: parentItemIdentifier)
269- items. append ( item)
270- }
271- }
278+ func getOffset( for page: Int ) -> Int {
279+ let items = paginateItems
280+ . filter { $0. page < page }
281+ . map { $0. items }
282+ . reduce ( 0 , + )
283+ // + 1 for the next
284+ return items == 0 ? 0 : items + 1
285+ }
272286
273- return ( items, resultsRead. files? . count ?? 0 , isPaginated)
274- } else {
275- let ( items, countItems) = await getItemsFromDatabase ( )
276- return ( items, countItems, false )
277- }
287+ func totalItems( ) -> Int {
288+ let total = paginateItems. map { $0. items } . reduce ( 0 , + )
289+ // + 1 for the first "root directory"
290+ return total == 0 ? 0 : total + 1
278291 }
279292}
0 commit comments