Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions app/src/main/java/com/nextcloud/client/database/dao/FileDao.kt
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,23 @@ interface FileDao {
)
suspend fun getGalleryItemsSuspended(startDate: Long, endDate: Long, fileOwner: String): List<FileEntity>

@Query(
"SELECT * FROM filelist" +
" WHERE (content_type LIKE 'image/%' OR content_type LIKE 'video/%')" +
" AND file_owner = :fileOwner" +
" AND path LIKE :pathPrefix || '%'" +
" AND (:mimeFilter IS NULL OR content_type LIKE :mimeFilter)" +
" ORDER BY modified DESC" +
" LIMIT :limit OFFSET :offset"
)
suspend fun getGalleryItemsPageSuspended(
fileOwner: String,
pathPrefix: String,
mimeFilter: String?,
limit: Int,
offset: Int
): List<FileEntity>

@Query("SELECT * FROM filelist WHERE file_owner = :fileOwner ORDER BY ${ProviderTableMeta.FILE_DEFAULT_SORT_ORDER}")
fun getAllFiles(fileOwner: String): List<FileEntity>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,33 @@ suspend fun FileDataStorageManager.saveShares(shares: List<OCShare>, accountName
}
}

suspend fun FileDataStorageManager.getAllGalleryItemsSuspended(): List<OCFile> {
val fileEntities = fileDao.getGalleryItemsSuspended(0, Long.MAX_VALUE, user.accountName)
return fileEntities.map { createFileInstance(it) }
private const val GALLERY_DB_CHUNK_SIZE = 500

suspend fun FileDataStorageManager.getGalleryItemsPageSuspended(
pathPrefix: String,
mimeFilter: String?,
limit: Int
): List<OCFile> {
val result = ArrayList<OCFile>(minOf(limit, GALLERY_DB_CHUNK_SIZE))
var offset = 0

while (offset < limit) {
val chunkLimit = minOf(GALLERY_DB_CHUNK_SIZE, limit - offset)
val entities = fileDao.getGalleryItemsPageSuspended(
user.accountName,
pathPrefix,
mimeFilter,
chunkLimit,
offset
)

entities.mapTo(result) { createFileInstance(it) }
offset += entities.size

if (entities.size < chunkLimit) break
}

return result
}

fun FileDataStorageManager.searchFilesByName(file: OCFile, accountName: String, query: String): List<OCFile> =
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2023 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-FileCopyrightText: 2023 TSI-mc
* SPDX-FileCopyrightText: 2019 Tobias Kaminsky <tobias@kaminsky.me>
* SPDX-FileCopyrightText: 2019 Nextcloud GmbH
Expand Down Expand Up @@ -28,7 +29,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.nextcloud.utils.extensions.getAllGalleryItemsSuspended
import com.nextcloud.utils.extensions.getGalleryItemsPageSuspended
import com.nextcloud.utils.extensions.getParcelableArgument
import kotlinx.coroutines.Job
import com.nextcloud.utils.extensions.getTypedActivity
Expand All @@ -47,7 +48,6 @@ import com.owncloud.android.ui.adapter.GalleryAdapter
import com.owncloud.android.ui.asynctasks.GallerySearchTask
import com.owncloud.android.ui.events.ChangeMenuEvent
import com.owncloud.android.ui.fragment.GalleryFragmentBottomSheetDialog.MediaState
import com.owncloud.android.utils.MimeTypeUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
Expand All @@ -61,6 +61,7 @@ class GalleryFragment :
private var showGalleryJob: Job? = null
private var endDate: Long = 0
private val limit = 150
private var loadedItemCount = INITIAL_GALLERY_WINDOW
private var adapter: GalleryAdapter? = null

private var bottomSheet: GalleryFragmentBottomSheetDialog? = null
Expand Down Expand Up @@ -241,6 +242,8 @@ class GalleryFragment :
prepareCurrentSearch(searchEvent)
setEmptyListMessage(EmptyListState.LOADING)

loadedItemCount = INITIAL_GALLERY_WINDOW

// always show first stored items
showAllGalleryItems()

Expand Down Expand Up @@ -367,8 +370,10 @@ class GalleryFragment :
Log_OC.d(this, "Gallery swipe: retrieve items because end of gallery display")
}

// Almost reached the end, continue to load new photos
// Almost reached the end, widen the display window and continue to load new photos
endDate = lastItemTimestamp
loadedItemCount += GALLERY_WINDOW_INCREMENT
showAllGalleryItems()
isPhotoSearchQueryRunning = true
runGallerySearchTask()
}
Expand All @@ -381,23 +386,22 @@ class GalleryFragment :
fun showAllGalleryItems() {
val mediaState = bottomSheet?.currMediaState ?: return

val mimeFilter = when (mediaState) {
MediaState.MEDIA_STATE_PHOTOS_ONLY -> IMAGE_MIME_FILTER
MediaState.MEDIA_STATE_VIDEOS_ONLY -> VIDEO_MIME_FILTER
else -> null
}

showGalleryJob?.cancel()
showGalleryJob = lifecycleScope.launch(Dispatchers.Default) {
val remotePath = preferences.getLastSelectedMediaFolder()
val items = mContainerActivity.storageManager.getAllGalleryItemsSuspended()
val items = mContainerActivity.storageManager.getGalleryItemsPageSuspended(
remotePath,
mimeFilter,
loadedItemCount
)

val isPhotosOnly = mediaState == MediaState.MEDIA_STATE_PHOTOS_ONLY
val isVideosOnly = mediaState == MediaState.MEDIA_STATE_VIDEOS_ONLY

val filteredItems = items.filter {
if (!it.remotePath.startsWith(remotePath)) return@filter false
if (isPhotosOnly) return@filter MimeTypeUtil.isImage(it.mimeType)
if (isVideosOnly) return@filter MimeTypeUtil.isVideo(it.mimeType)
true
}

val galleryItems =
filteredItems.toGalleryItems(columnsCount, ThumbnailsCacheManager.getThumbnailDimension())
val galleryItems = items.toGalleryItems(columnsCount, ThumbnailsCacheManager.getThumbnailDimension())

withContext(Dispatchers.Main) {
if (galleryItems.isEmpty()) {
Expand Down Expand Up @@ -448,6 +452,11 @@ class GalleryFragment :
private const val MAX_ITEMS_PER_ROW = 10
private const val FRAGMENT_TAG_BOTTOM_SHEET = "data"

private const val INITIAL_GALLERY_WINDOW = 500
private const val GALLERY_WINDOW_INCREMENT = 500
private const val IMAGE_MIME_FILTER = "image/%"
private const val VIDEO_MIME_FILTER = "video/%"

private var lastMediaItemPosition: Int? = null
const val REFRESH_SEARCH_EVENT_RECEIVER: String = "refreshSearchEventReceiver"

Expand Down
Loading