diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/RemoteDestinationDialog.java b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/RemoteDestinationDialog.java index 2a1cb193..e56d7e59 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/RemoteDestinationDialog.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/RemoteDestinationDialog.java @@ -119,7 +119,7 @@ public Dialog onCreateDialog(Bundle savedInstanceState) { recyclerView.setLayoutManager(new LinearLayoutManager(context)); View emptyFolderView = view.findViewById(R.id.empty_folder_view); View noSearchResultsView = view.findViewById(R.id.no_search_results_view); - recyclerViewAdapter = new FileExplorerRecyclerViewAdapter(context, emptyFolderView, noSearchResultsView, this); + recyclerViewAdapter = new FileExplorerRecyclerViewAdapter(context, emptyFolderView, noSearchResultsView, this, R.layout.fragment_file_explorer_item_linear); recyclerViewAdapter.disableFileOptions(); recyclerView.setAdapter(recyclerViewAdapter); recyclerViewAdapter.setMoveMode(true); diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java index ceace632..dbc50e46 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java @@ -6,14 +6,12 @@ import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.net.Uri; import android.os.AsyncTask; import android.os.Bundle; -import android.os.Parcel; import android.text.Editable; import android.text.TextWatcher; import android.util.Base64; @@ -26,7 +24,6 @@ import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; -import android.webkit.MimeTypeMap; import android.widget.EditText; import android.widget.Toast; import androidx.annotation.NonNull; @@ -42,6 +39,7 @@ import androidx.fragment.app.FragmentActivity; import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.preference.PreferenceManager; +import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; @@ -89,7 +87,6 @@ import java.io.File; import java.io.IOException; import java.net.ServerSocket; -import java.net.URL; import java.security.SecureRandom; import java.util.ArrayList; import java.util.Collections; @@ -97,6 +94,7 @@ import java.util.List; import java.util.Map; import java.util.Stack; +import java.util.concurrent.Callable; import static ca.pkay.rcloneexplorer.ActivityHelper.tryStartActivity; import static ca.pkay.rcloneexplorer.ActivityHelper.tryStartActivityForResult; @@ -115,6 +113,7 @@ public class FileExplorerFragment extends Fragment implements FileExplorerRecy private static final String TAG = "FileExplorerFragment"; private static final String ARG_REMOTE = "remote_param"; private static final String SHARED_PREFS_SORT_ORDER = "ca.pkay.rcexplorer.sort_order"; + private static final String SHARED_PREFS_VIEW_MOE = "ca.pkay.rcexplorer.view_mode"; private static final int FILE_PICKER_UPLOAD_RESULT = 186; private static final int FILE_PICKER_DOWNLOAD_RESULT = 204; private static final int FILE_PICKER_SYNC_RESULT = 45; @@ -142,8 +141,10 @@ public class FileExplorerFragment extends Fragment implements FileExplorerRecy private Rclone rclone; private RemoteItem remote; private String remoteName; + private RecyclerView recyclerView; private FileExplorerRecyclerViewAdapter recyclerViewAdapter; - private LinearLayoutManager recyclerViewLinearLayoutManager; + private RecyclerView.LayoutManager recyclerViewLayoutManager; + private int recyclerViewLayoutManagerViewModeCurrentIndex = 0; private SwipeRefreshLayout swipeRefreshLayout; private View searchBar; private AsyncTask fetchDirectoryTask; @@ -233,6 +234,7 @@ public void onCreate(@Nullable Bundle savedInstanceState) { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); sortOrder = sharedPreferences.getInt(SHARED_PREFS_SORT_ORDER, SortDialog.ALPHA_ASCENDING); + recyclerViewLayoutManagerViewModeCurrentIndex = sharedPreferences.getInt(SHARED_PREFS_VIEW_MOE, 0); showThumbnails = sharedPreferences.getBoolean(getString(R.string.pref_key_show_thumbnails), false); isDarkTheme = sharedPreferences.getBoolean(getString(R.string.pref_key_dark_theme), false); goToDefaultSet = sharedPreferences.getBoolean(getString(R.string.pref_key_go_to_default_set), false); @@ -274,16 +276,15 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c Context context = view.getContext(); - RecyclerView recyclerView = view.findViewById(R.id.file_explorer_list); - recyclerViewLinearLayoutManager = new LinearLayoutManager(context); + recyclerView = view.findViewById(R.id.file_explorer_list); recyclerView.setItemAnimator(new LandingAnimator()); - recyclerView.setLayoutManager(recyclerViewLinearLayoutManager); View emptyFolderView = view.findViewById(R.id.empty_folder_view); View noSearchResultsView = view.findViewById(R.id.no_search_results_view); - recyclerViewAdapter = new FileExplorerRecyclerViewAdapter(context, emptyFolderView, noSearchResultsView, this); + recyclerViewAdapter = new FileExplorerRecyclerViewAdapter(context, emptyFolderView, noSearchResultsView, this, R.layout.fragment_file_explorer_item_linear); recyclerViewAdapter.showThumbnails(showThumbnails); recyclerViewAdapter.setWrapFileNames(wrapFilenames); recyclerView.setAdapter(recyclerViewAdapter); + recyclerViewSetLayoutManager(recyclerViewLayoutManagerViewModeCurrentIndex); if (remote.isRemoteType(RemoteItem.SFTP) && !goToDefaultSet & savedInstanceState == null) { showSFTPgoToDialog(); @@ -347,6 +348,42 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c return view; } + private void recyclerViewSetLayoutManager(int index) { + Callable[] recyclerViewLayoutManagerSetters = new Callable[] { + () -> { + recyclerViewAdapter.setLayoutRes(R.layout.fragment_file_explorer_item_linear); + recyclerViewLayoutManager = new LinearLayoutManager(FileExplorerFragment.this.getContext()); + recyclerView.setAdapter(recyclerViewAdapter); + recyclerView.setLayoutManager(recyclerViewLayoutManager); + return null; + }, + () -> { + recyclerViewAdapter.setLayoutRes(R.layout.fragment_file_explorer_item_grid); + recyclerViewLayoutManager = new GridLayoutManager(FileExplorerFragment.this.getContext(), 2); + recyclerView.setAdapter(recyclerViewAdapter); + recyclerView.setLayoutManager(recyclerViewLayoutManager); + return null; + }, + () -> { + recyclerViewAdapter.setLayoutRes(R.layout.fragment_file_explorer_item_grid); + recyclerViewLayoutManager = new GridLayoutManager(FileExplorerFragment.this.getContext(), 3); + recyclerView.setAdapter(recyclerViewAdapter); + recyclerView.setLayoutManager(recyclerViewLayoutManager); + return null; + } , + }; + + if (index >= recyclerViewLayoutManagerSetters.length) { + index = 0; + recyclerViewLayoutManagerViewModeCurrentIndex = 0; + } + try { + recyclerViewLayoutManagerSetters[index].call(); + } catch (Exception e) { + new RuntimeException(e); + } + } + @Override public void onStart() { super.onStart(); @@ -628,6 +665,9 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.action_sort: showSortMenu(); return true; + case R.id.action_view_mode: + toggleViewMode(); + return true; case R.id.action_select_all: recyclerViewAdapter.toggleSelectAll(); return true; @@ -660,6 +700,12 @@ public boolean onOptionsItemSelected(MenuItem item) { } } + private void toggleViewMode() { + recyclerViewSetLayoutManager(++recyclerViewLayoutManagerViewModeCurrentIndex); + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); + sharedPreferences.edit().putInt(SHARED_PREFS_VIEW_MOE, recyclerViewLayoutManagerViewModeCurrentIndex).apply(); + } + private void serve() { ServeDialog serveDialog = new ServeDialog(); serveDialog.setDarkTheme(isDarkTheme); @@ -1173,7 +1219,7 @@ public boolean onBackButtonPressed() { recyclerViewAdapter.newData(directoryObject.getDirectoryContent()); if (directoryPosition.containsKey(directoryObject.getCurrentPath())) { int position = directoryPosition.get(directoryObject.getCurrentPath()); - recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, 10); + recyclerViewScrollToPositionWithOffset(position, 10); } fetchDirectoryTask = new FetchDirectoryContent(true).execute(); } else if (directoryObject.isPathInCache(path)) { @@ -1182,7 +1228,7 @@ public boolean onBackButtonPressed() { recyclerViewAdapter.newData(directoryObject.getDirectoryContent()); if (directoryPosition.containsKey(directoryObject.getCurrentPath())) { int position = directoryPosition.get(directoryObject.getCurrentPath()); - recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, 10); + recyclerViewScrollToPositionWithOffset(position, 10); } } else { directoryObject.setPath(path); @@ -1191,6 +1237,16 @@ public boolean onBackButtonPressed() { return true; } + private void recyclerViewScrollToPositionWithOffset(int position, int offset) { + if (recyclerViewLayoutManager instanceof LinearLayoutManager) { + ((LinearLayoutManager) recyclerViewLayoutManager).scrollToPositionWithOffset(position, offset); + } else if (recyclerViewLayoutManager instanceof LinearLayoutManager) { + ((GridLayoutManager) recyclerViewLayoutManager).scrollToPositionWithOffset(position, offset); + } else { + recyclerViewLayoutManager.scrollToPosition(position); + } + } + @Override public void onFileClicked(FileItem fileItem) { String type = fileItem.getMimeType(); @@ -1407,7 +1463,7 @@ public void onBreadCrumbClicked(String path) { recyclerViewAdapter.newData(directoryObject.getDirectoryContent()); if (directoryPosition.containsKey(directoryObject.getCurrentPath())) { int position = directoryPosition.get(directoryObject.getCurrentPath()); - recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, 10); + recyclerViewScrollToPositionWithOffset(position, 10); } fetchDirectoryTask = new FetchDirectoryContent(true).execute(); } else if (directoryObject.isPathInCache(path)) { @@ -1416,7 +1472,7 @@ public void onBreadCrumbClicked(String path) { recyclerViewAdapter.newData(directoryObject.getDirectoryContent()); if (directoryPosition.containsKey(directoryObject.getCurrentPath())) { int position = directoryPosition.get(directoryObject.getCurrentPath()); - recyclerViewLinearLayoutManager.scrollToPositionWithOffset(position, 10); + recyclerViewScrollToPositionWithOffset(position, 10); } } else { fetchDirectoryTask = new FetchDirectoryContent().execute(); diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/ShareFragment.java b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/ShareFragment.java index c0259b04..abc9a9e9 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/ShareFragment.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/ShareFragment.java @@ -148,7 +148,7 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c recyclerView.setLayoutManager(new LinearLayoutManager(context)); View emptyFolderView = view.findViewById(R.id.empty_folder_view); View noSearchResultsView = view.findViewById(R.id.no_search_results_view); - recyclerViewAdapter = new FileExplorerRecyclerViewAdapter(context, emptyFolderView, noSearchResultsView, this); + recyclerViewAdapter = new FileExplorerRecyclerViewAdapter(context, emptyFolderView, noSearchResultsView, this, R.layout.fragment_file_explorer_item_linear); recyclerViewAdapter.disableFileOptions(); recyclerView.setAdapter(recyclerViewAdapter); recyclerViewAdapter.setMoveMode(true); diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/RecyclerViewAdapters/FileExplorerRecyclerViewAdapter.java b/app/src/main/java/ca/pkay/rcloneexplorer/RecyclerViewAdapters/FileExplorerRecyclerViewAdapter.java index e966e4be..a69efaf5 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/RecyclerViewAdapters/FileExplorerRecyclerViewAdapter.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/RecyclerViewAdapters/FileExplorerRecyclerViewAdapter.java @@ -11,12 +11,16 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.TextView; + +import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import androidx.preference.PreferenceManager; import androidx.recyclerview.widget.RecyclerView; + import ca.pkay.rcloneexplorer.Items.FileItem; import ca.pkay.rcloneexplorer.Items.RemoteItem; import ca.pkay.rcloneexplorer.R; + import com.bumptech.glide.Glide; import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.load.model.GlideUrl; @@ -50,6 +54,7 @@ public class FileExplorerRecyclerViewAdapter extends RecyclerView.Adapter(); this.context = context; this.emptyView = emptyView; this.noSearchResultsView = noSearchResultsView; this.listener = listener; + this.layoutRes = layoutRes; isInSelectMode = false; selectedItems = new ArrayList<>(); isInMoveMode = false; @@ -89,7 +96,7 @@ public FileExplorerRecyclerViewAdapter(Context context, View emptyView, View noS @NonNull @Override public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.fragment_file_explorer_item, parent, false); + View view = LayoutInflater.from(parent.getContext()).inflate(this.layoutRes, parent, false); return new ViewHolder(view); } @@ -147,7 +154,7 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { holder.fileModTime.setVisibility(View.VISIBLE); holder.fileModTime.setText(item.getHumanReadableModTime()); } - + holder.fileName.setText(item.getName()); if (isInSelectMode) { @@ -202,9 +209,16 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { return true; }); + holder.icons.setOnLongClickListener(v -> { + listener.onFileOptionsClicked(v, item); + return true; + }); + holder.icons.setOnClickListener(v -> { - if (!isInMoveMode && canSelect) { + if (isInSelectMode) { onLongClickAction(item, holder); + } else { + onClickAction(item, holder.getAdapterPosition()); } }); } @@ -454,6 +468,10 @@ private void onLongClickAction(FileItem item, ViewHolder holder) { notifyDataSetChanged(); } + public void setLayoutRes(@LayoutRes int layoutRes) { + this.layoutRes = layoutRes; + } + public class ViewHolder extends RecyclerView.ViewHolder { public final View view; diff --git a/app/src/main/res/drawable/ic_file.xml b/app/src/main/res/drawable/ic_file.xml index 5ff7528d..e570e4f1 100644 --- a/app/src/main/res/drawable/ic_file.xml +++ b/app/src/main/res/drawable/ic_file.xml @@ -1,6 +1,6 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout-sw720dp/dialog_remote_dest.xml b/app/src/main/res/layout-sw720dp/dialog_remote_dest.xml index e60d1390..35f9bcdb 100644 --- a/app/src/main/res/layout-sw720dp/dialog_remote_dest.xml +++ b/app/src/main/res/layout-sw720dp/dialog_remote_dest.xml @@ -101,7 +101,7 @@ android:clipToPadding="false" android:paddingBottom="54dp" app:layoutManager="LinearLayoutManager" - tools:listitem="@layout/fragment_file_explorer_item" /> + tools:listitem="@layout/fragment_file_explorer_item_grid" /> diff --git a/app/src/main/res/layout-sw720dp/fragment_file_explorer_list.xml b/app/src/main/res/layout-sw720dp/fragment_file_explorer_list.xml index 81246ed5..5d80a5a0 100644 --- a/app/src/main/res/layout-sw720dp/fragment_file_explorer_list.xml +++ b/app/src/main/res/layout-sw720dp/fragment_file_explorer_list.xml @@ -30,7 +30,7 @@ android:clipToPadding="false" android:paddingBottom="54dp" app:layoutManager="LinearLayoutManager" - tools:listitem="@layout/fragment_file_explorer_item" /> + tools:listitem="@layout/fragment_file_explorer_item_grid" /> + tools:listitem="@layout/fragment_file_explorer_item_grid" /> + tools:listitem="@layout/fragment_file_explorer_item_grid" /> diff --git a/app/src/main/res/layout/fragment_file_explorer_item_grid.xml b/app/src/main/res/layout/fragment_file_explorer_item_grid.xml new file mode 100644 index 00000000..0058d43a --- /dev/null +++ b/app/src/main/res/layout/fragment_file_explorer_item_grid.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_file_explorer_item.xml b/app/src/main/res/layout/fragment_file_explorer_item_linear.xml similarity index 100% rename from app/src/main/res/layout/fragment_file_explorer_item.xml rename to app/src/main/res/layout/fragment_file_explorer_item_linear.xml diff --git a/app/src/main/res/layout/fragment_file_explorer_list.xml b/app/src/main/res/layout/fragment_file_explorer_list.xml index 52aa0767..e78a3a47 100644 --- a/app/src/main/res/layout/fragment_file_explorer_list.xml +++ b/app/src/main/res/layout/fragment_file_explorer_list.xml @@ -28,7 +28,7 @@ android:clipToPadding="false" android:paddingBottom="54dp" app:layoutManager="LinearLayoutManager" - tools:listitem="@layout/fragment_file_explorer_item" + tools:listitem="@layout/fragment_file_explorer_item_grid" android:focusable="true"/> diff --git a/app/src/main/res/layout/fragment_share_list.xml b/app/src/main/res/layout/fragment_share_list.xml index ec0b6367..7b251d21 100644 --- a/app/src/main/res/layout/fragment_share_list.xml +++ b/app/src/main/res/layout/fragment_share_list.xml @@ -24,7 +24,7 @@ android:clipToPadding="false" android:paddingBottom="54dp" app:layoutManager="LinearLayoutManager" - tools:listitem="@layout/fragment_file_explorer_item" /> + tools:listitem="@layout/fragment_file_explorer_item_grid" /> + Export rclone config About Sort + Switch between grid or linear mode Select all Serveā€¦ Name