mirror of
https://github.com/nextcloud/android.git
synced 2024-11-22 13:15:35 +03:00
Merge pull request #9985 from nextcloud/fastscrollWithLib
Fastscroll for all lists
This commit is contained in:
commit
31dda2e0fb
11 changed files with 102 additions and 15 deletions
|
@ -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'
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ class UploadFilesActivityIT : AbstractIT() {
|
|||
}
|
||||
|
||||
waitForIdleSync()
|
||||
shortSleep()
|
||||
|
||||
screenshot(sut)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -50,4 +50,6 @@ public interface OCFileListFragmentInterface {
|
|||
void onHeaderClicked();
|
||||
|
||||
boolean isSearchFragment();
|
||||
|
||||
boolean isGalleryFragment();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1 +1 @@
|
|||
628
|
||||
626
|
Loading…
Reference in a new issue