Merge pull request #9985 from nextcloud/fastscrollWithLib

Fastscroll for all lists
This commit is contained in:
Tobias Kaminsky 2022-04-13 08:30:03 +02:00 committed by GitHub
commit 31dda2e0fb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 102 additions and 15 deletions

View file

@ -281,6 +281,8 @@ dependencies {
implementation "com.google.android.exoplayer:exoplayer:$exoplayerVersion"
implementation "com.google.android.exoplayer:extension-okhttp:$exoplayerVersion"
implementation 'com.simplecityapps:recyclerview-fastscroll:2.0.1'
// Shimmer animation
implementation 'com.elyeproj.libraries:loaderviewlibrary:2.0.0'

View file

@ -70,6 +70,7 @@ class UploadFilesActivityIT : AbstractIT() {
}
waitForIdleSync()
shortSleep()
screenshot(sut)
}

View file

@ -25,14 +25,14 @@ import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
/**
* Extends RecyclerView to show a custom view if no data is available
* Inspired by http://alexzh.com/tutorials/how-to-setemptyview-to-recyclerview
* Extends RecyclerView to show a custom view if no data is available Inspired by http://alexzh.com/tutorials/how-to-setemptyview-to-recyclerview
*/
public class EmptyRecyclerView extends RecyclerView {
public class EmptyRecyclerView extends FastScrollRecyclerView {
private View mEmptyView;
private boolean hasFooter = false;

View file

@ -485,7 +485,7 @@ public class FileDisplayActivity extends FileActivity
SearchEvent searchEvent = intent.getParcelableExtra(OCFileListFragment.SEARCH_EVENT);
if (searchEvent != null) {
if (SearchRemoteOperation.SearchType.PHOTO_SEARCH.equals(searchEvent.getSearchType())) {
if (SearchRemoteOperation.SearchType.PHOTO_SEARCH == searchEvent.getSearchType()) {
Log_OC.d(this, "Switch to photo search fragment");
GalleryFragment photoFragment = new GalleryFragment();
@ -493,7 +493,7 @@ public class FileDisplayActivity extends FileActivity
bundle.putParcelable(OCFileListFragment.SEARCH_EVENT, searchEvent);
photoFragment.setArguments(bundle);
setLeftFragment(photoFragment);
} else if (searchEvent.getSearchType().equals(SearchRemoteOperation.SearchType.SHARED_FILTER)) {
} else if (searchEvent.getSearchType() == SearchRemoteOperation.SearchType.SHARED_FILTER) {
Log_OC.d(this, "Switch to shared fragment");
SharedListFragment sharedListFragment = new SharedListFragment();
Bundle bundle = new Bundle();

View file

@ -84,10 +84,13 @@ import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.theme.CapabilityUtils;
import com.owncloud.android.utils.theme.ThemeColorUtils;
import com.owncloud.android.utils.theme.ThemeDrawableUtils;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
@ -104,7 +107,7 @@ import androidx.recyclerview.widget.RecyclerView;
* This Adapter populates a RecyclerView with all files and folders in a Nextcloud instance.
*/
public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
implements DisplayUtils.AvatarGenerationListener {
implements DisplayUtils.AvatarGenerationListener, FastScrollRecyclerView.SectionedAdapter {
private static final int showFilenameColumnThreshold = 4;
private final ComponentsGetter transferServiceGetter;
@ -137,6 +140,9 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
private boolean showShareAvatar = false;
private OCFile highlightedItem;
private boolean showMetadata = true;
private FileSortOrder sortOrder;
private final SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM yyyy", Locale.getDefault());
public OCFileListAdapter(
Activity activity,
@ -370,6 +376,11 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
OCFile file = getItem(position);
if (file == null) {
Log_OC.e(this, "Cannot bind on view holder on a null file");
return;
}
boolean gridImage = MimeTypeUtil.isImage(file) || MimeTypeUtil.isVideo(file);
gridViewHolder.getThumbnail().setTag(file.getFileId());
@ -770,13 +781,18 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
return output;
}
public OCFile getItem(int position) {
public @Nullable
OCFile getItem(int position) {
int newPosition = position;
if (shouldShowHeader() && position > 0) {
newPosition = position - 1;
}
if (newPosition >= mFiles.size()) {
return null;
}
return mFiles.get(newPosition);
}
@ -812,7 +828,12 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
}
}
if (MimeTypeUtil.isImageOrVideo(getItem(position))) {
OCFile item = getItem(position);
if (item == null) {
return VIEWTYPE_ITEM;
}
if (MimeTypeUtil.isImageOrVideo(item)) {
return VIEWTYPE_IMAGE;
} else {
return VIEWTYPE_ITEM;
@ -875,7 +896,7 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
if (!limitToMimeType.isEmpty()) {
mFiles = filterByMimeType(mFiles, limitToMimeType);
}
FileSortOrder sortOrder = preferences.getSortOrderByFolder(directory);
sortOrder = preferences.getSortOrderByFolder(directory);
mFiles = sortOrder.sortCloudFiles(mFiles);
mFilesAll.clear();
mFilesAll.addAll(mFiles);
@ -941,7 +962,7 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
searchType == SearchType.RECENTLY_MODIFIED_SEARCH) {
mFiles = FileStorageUtils.sortOcFolderDescDateModifiedWithoutFavoritesFirst(mFiles);
} else if (searchType != SearchType.SHARED_FILTER) {
FileSortOrder sortOrder = preferences.getSortOrderByFolder(folder);
sortOrder = preferences.getSortOrderByFolder(folder);
mFiles = sortOrder.sortCloudFiles(mFiles);
}
@ -1067,6 +1088,8 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
preferences.setSortOrder(folder, sortOrder);
mFiles = sortOrder.sortCloudFiles(mFiles);
notifyDataSetChanged();
this.sortOrder = sortOrder;
}
public Set<OCFile> getCheckedItems() {
@ -1149,7 +1172,7 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
if (!preferences.isShowHiddenFilesEnabled()) {
mFiles = filterHiddenFiles(mFiles);
}
FileSortOrder sortOrder = preferences.getSortOrderByFolder(currentDirectory);
sortOrder = preferences.getSortOrderByFolder(currentDirectory);
mFiles = sortOrder.sortCloudFiles(mFiles);
}
@ -1209,6 +1232,27 @@ public class OCFileListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol
showMetadata = bool;
}
@NonNull
@Override
public String getSectionName(int position) {
OCFile file = getItem(position);
if (file == null) {
return "";
}
if (sortOrder.getType() == FileSortOrder.SortType.ALPHABET) {
return String.valueOf(file.getFileName().charAt(0)).toUpperCase(Locale.getDefault());
} else if (sortOrder.getType() == FileSortOrder.SortType.DATE) {
long milliseconds = file.getModificationTimestamp();
Date date = new Date(milliseconds);
return dateFormat.format(date);
} else {
// Size
return DisplayUtils.bytesToHumanReadable(file.getFileLength());
}
}
@VisibleForTesting
public void setShowShareAvatar(boolean bool) {
showShareAvatar = bool;

View file

@ -213,6 +213,10 @@ public class GalleryFragment extends OCFileListFragment {
// Almost reached the end, continue to load new photos
OCFile lastFile = mAdapter.getItem(lastVisibleItem - 1);
if (lastFile == null) {
return;
}
daySpan = 30;
endDate = lastFile.getModificationTimestamp() / 1000;
startDate = endDate - (daySpan * 24 * 60 * 60);
@ -229,4 +233,9 @@ public class GalleryFragment extends OCFileListFragment {
}
}
}
@Override
public boolean isGalleryFragment() {
return true;
}
}

View file

@ -1638,7 +1638,7 @@ public class OCFileListFragment extends ExtendedListFragment implements
@Override
public void onRefresh() {
if (isSearchEventSet(searchEvent) && searchFragment) {
if (searchFragment && isSearchEventSet(searchEvent)) {
handleSearchEvent(searchEvent);
mRefreshListLayout.setRefreshing(false);
@ -1656,6 +1656,11 @@ public class OCFileListFragment extends ExtendedListFragment implements
return searchFragment;
}
@Override
public boolean isGalleryFragment() {
return false;
}
/**
* De-/select all elements in the current list view.
*

View file

@ -50,4 +50,6 @@ public interface OCFileListFragmentInterface {
void onHeaderClicked();
boolean isSearchFragment();
boolean isGalleryFragment();
}

View file

@ -38,6 +38,10 @@ open class FileSortOrder(@JvmField var name: String, var isAscending: Boolean) {
trashBinView, localFileListView
}
enum class SortType {
SIZE, ALPHABET, DATE
}
companion object {
const val sort_a_to_z_id = "sort_a_to_z"
const val sort_z_to_a_id = "sort_z_to_a"
@ -106,4 +110,19 @@ open class FileSortOrder(@JvmField var name: String, var isAscending: Boolean) {
open fun sortTrashbinFiles(files: MutableList<TrashbinFile>): List<TrashbinFile> {
return files
}
open fun getType(): SortType {
return when (name) {
sort_z_to_a_id,
sort_a_to_z_id -> SortType.ALPHABET
sort_small_to_big_id,
sort_big_to_small_id -> SortType.SIZE
sort_new_to_old_id,
sort_old_to_new_id -> SortType.DATE
else -> SortType.ALPHABET
}
}
}

View file

@ -33,7 +33,12 @@
<com.owncloud.android.ui.EmptyRecyclerView
android:id="@+id/list_root"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="match_parent"
app:fastScrollPopupBgColor="@color/color_accent"
app:fastScrollPopupTextColor="@color/login_text_color"
app:fastScrollThumbColor="@color/color_accent"
app:fastScrollAutoHide="true"
app:fastScrollAutoHideDelay="1500" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<include

View file

@ -1 +1 @@
628
626