@@ -137,6 +137,9 @@ class BrowseFilesPresenter @Inject constructor( //
137
137
private lateinit var existingFilesForUpload: MutableMap <String , UploadFile >
138
138
private lateinit var downloadFiles: MutableList <DownloadFile >
139
139
140
+ private var availableThumbnailsThreads = MAX_CONCURRENT_THUMBNAILS_THREADS
141
+ private val filesBeingDownloaded: MutableSet <CloudFileModel > = mutableSetOf ()
142
+
140
143
private var resumedAfterAuthentication = false
141
144
142
145
@InjectIntent
@@ -161,48 +164,24 @@ class BrowseFilesPresenter @Inject constructor( //
161
164
@JvmField
162
165
var openWritableFileNotification: OpenWritableFileNotification ? = null
163
166
164
- fun thumbnailsForVisibleNodes (visibleCloudNodes : List <CloudNodeModel <* >>) {
165
- if (! sharedPreferencesHandler.useLruCache() || (sharedPreferencesHandler.generateThumbnails() != ThumbnailsOption .PER_FOLDER )) {
166
- return
167
- }
168
- val toDownload = ArrayList <CloudFileModel >()
169
- visibleCloudNodes.forEach { node ->
170
- if (node is CloudFileModel && isImageMediaType(node.name) && node.thumbnail == null ) {
171
- toDownload.add(node)
172
- }
173
- }
174
- if (toDownload.isEmpty()) {
175
- return
176
- }
177
- downloadAndGenerateThumbnails(toDownload)
178
- }
179
-
180
167
private fun downloadAndGenerateThumbnails (visibleCloudFiles : List <CloudFileModel >) {
181
- view?.showProgress(
182
- visibleCloudFiles, //
183
- ProgressModel (
184
- progressStateModelMapper.toModel( //
185
- DownloadState .download(visibleCloudFiles[0 ].toCloudNode())
186
- ), 0
187
- )
168
+ filesBeingDownloaded.addAll(visibleCloudFiles)
169
+ view?.replaceImagesWithDownloadIcon(
170
+ visibleCloudFiles
188
171
)
189
172
downloadFilesUseCase //
190
173
.withDownloadFiles(downloadFileUtil.createDownloadFilesFor(this , visibleCloudFiles)) //
191
174
.run (object : DefaultProgressAwareResultHandler <List <CloudFile >, DownloadState > () {
192
175
override fun onFinished () {
193
- view?.hideProgress(visibleCloudFiles)
176
+ availableThumbnailsThreads++ // releasing the passed baton
177
+ Timber .tag(" THUMBNAILS" ).i(" [RELEASE] downloadAndGen (${availableThumbnailsThreads} /${MAX_CONCURRENT_THUMBNAILS_THREADS } )" )
194
178
}
195
179
196
180
override fun onProgress (progress : Progress <DownloadState >) {
197
- if (! progress.isOverallComplete) {
198
- view?.showProgress(
199
- cloudFileModelMapper.toModel(progress.state().file()), //
200
- progressModelMapper.toModel(progress)
201
- )
202
- }
203
181
if (progress.isCompleteAndHasState) {
204
182
val cloudFile = progress.state().file()
205
183
val cloudFileModel = cloudFileModelMapper.toModel(cloudFile)
184
+ filesBeingDownloaded.remove(cloudFileModel)
206
185
view?.addOrUpdateCloudNode(cloudFileModel)
207
186
}
208
187
}
@@ -236,6 +215,9 @@ class BrowseFilesPresenter @Inject constructor( //
236
215
237
216
fun onBackPressed () {
238
217
unsubscribeAll()
218
+ Timber .tag(" THUMBNAILS" ).i(" [RESET] unsubscribe to all" )
219
+ availableThumbnailsThreads = MAX_CONCURRENT_THUMBNAILS_THREADS
220
+ filesBeingDownloaded.clear()
239
221
}
240
222
241
223
fun onFolderDisplayed (folder : CloudFolderModel ) {
@@ -258,7 +240,10 @@ class BrowseFilesPresenter @Inject constructor( //
258
240
clearCloudList()
259
241
} else {
260
242
showCloudNodesCollectionInView(cloudNodes)
261
- associateThumbnails(cloudNodes)
243
+ val images = view?.renderedCloudNodes()?.filterIsInstance<CloudFileModel >()?.filter { file ->
244
+ isImageMediaType(file.name)
245
+ } ? : return
246
+ associateThumbnails(images.take(10 ))
262
247
}
263
248
view?.showLoading(false )
264
249
}
@@ -287,26 +272,60 @@ class BrowseFilesPresenter @Inject constructor( //
287
272
})
288
273
}
289
274
290
- private fun associateThumbnails (cloudNodes : List <CloudNode >) {
275
+ fun associateThumbnails (cloudNodes : List <CloudNodeModel < * > >) {
291
276
if (! sharedPreferencesHandler.useLruCache() || sharedPreferencesHandler.generateThumbnails() == ThumbnailsOption .NEVER ) {
292
277
return
293
278
}
294
- associateThumbnailsUseCase.withList(cloudNodes)
279
+ if (cloudNodes.isEmpty()) {
280
+ return
281
+ }
282
+ if (availableThumbnailsThreads == 0 ) {
283
+ Timber .tag(" THUMBNAILS" ).i(" [DROP] all threads are in use!" )
284
+ return
285
+ }
286
+
287
+ availableThumbnailsThreads--
288
+ Timber .tag(" THUMBNAILS" ).i(" [ACQUIRE] associate (${availableThumbnailsThreads} /${MAX_CONCURRENT_THUMBNAILS_THREADS } )" )
289
+
290
+ val associatedCloudNodes = ArrayList <CloudNodeModel <* >>()
291
+ associateThumbnailsUseCase.withList(cloudNodeModelMapper.fromModels(cloudNodes))
295
292
.run (object : DefaultProgressAwareResultHandler <Void , FileTransferState >() {
296
293
override fun onProgress (progress : Progress <FileTransferState >) {
297
294
val state = progress.state()
295
+ Timber .tag(" THUMBNAILS" ).i(" associateThumbnailsUseCase - onProgress" )
296
+
298
297
state?.let { state ->
299
- view?.addOrUpdateCloudNode(cloudFileModelMapper.toModel(state.file()))
298
+ val file = cloudFileModelMapper.toModel(state.file())
299
+ view?.addOrUpdateCloudNode(file)
300
+ associatedCloudNodes.add(file)
300
301
}
301
302
}
302
303
303
304
override fun onFinished () {
304
- val images = view?.renderedCloudNodes()?.filterIsInstance<CloudFileModel >()?.filter { file -> isImageMediaType(file.name) } ? : return
305
- images.take(10 ).filter { img -> img.thumbnail == null }.let { firstImagesWithoutThumbnails ->
306
- if (firstImagesWithoutThumbnails.isNotEmpty()) {
307
- thumbnailsForVisibleNodes(firstImagesWithoutThumbnails)
305
+ Timber .tag(" THUMBNAILS" ).i(" associateThumbnailsUseCase - onFinished" )
306
+
307
+ if (sharedPreferencesHandler.generateThumbnails() != ThumbnailsOption .PER_FOLDER ) {
308
+ availableThumbnailsThreads++
309
+ Timber .tag(" THUMBNAILS" ).i(" [RELEASE] associate (${availableThumbnailsThreads} /${MAX_CONCURRENT_THUMBNAILS_THREADS } )" )
310
+ return
311
+ }
312
+ val toDownload = ArrayList <CloudFileModel >()
313
+ cloudNodes.filter { node -> ! associatedCloudNodes.contains(node) }.forEach { node ->
314
+ if (node is CloudFileModel && isImageMediaType(node.name) && node.thumbnail == null ) {
315
+ if (filesBeingDownloaded.contains(node)) {
316
+ Timber .tag(" THUMBNAILS" ).i(" [SKIP] No double download!" )
317
+ } else {
318
+ toDownload.add(node)
319
+ }
308
320
}
309
321
}
322
+ if (toDownload.isEmpty()) {
323
+ availableThumbnailsThreads++
324
+ Timber .tag(" THUMBNAILS" ).i(" [RELEASE] associate (${availableThumbnailsThreads} /${MAX_CONCURRENT_THUMBNAILS_THREADS } )" )
325
+ return
326
+ }
327
+
328
+ downloadAndGenerateThumbnails(toDownload) // passing of the baton, do not increase the number of threads
310
329
}
311
330
})
312
331
}
@@ -970,6 +989,9 @@ class BrowseFilesPresenter @Inject constructor( //
970
989
971
990
fun onFolderClicked (cloudFolderModel : CloudFolderModel ) {
972
991
unsubscribeAll()
992
+ Timber .tag(" THUMBNAILS" ).i(" [RESET] unsubscribe to all" )
993
+ availableThumbnailsThreads = MAX_CONCURRENT_THUMBNAILS_THREADS
994
+ filesBeingDownloaded.clear()
973
995
view?.navigateTo(cloudFolderModel)
974
996
}
975
997
@@ -1342,6 +1364,7 @@ class BrowseFilesPresenter @Inject constructor( //
1342
1364
companion object {
1343
1365
1344
1366
const val OPEN_FILE_FINISHED = 12
1367
+ private const val MAX_CONCURRENT_THUMBNAILS_THREADS = 2
1345
1368
1346
1369
val EXPORT_AFTER_APP_CHOOSER : ExportOperation = object : ExportOperation {
1347
1370
override fun export (presenter : BrowseFilesPresenter , downloadFiles : List <DownloadFile >) {
0 commit comments