convert ItemsFragment to kotlin
This commit is contained in:
parent
f5257a0c8a
commit
5a76dd5db2
|
@ -1,498 +0,0 @@
|
|||
package com.simplemobiletools.filemanager.fragments;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Color;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.design.widget.CoordinatorLayout;
|
||||
import android.support.design.widget.Snackbar;
|
||||
import android.support.v4.provider.DocumentFile;
|
||||
import android.support.v4.widget.SwipeRefreshLayout;
|
||||
import android.util.SparseBooleanArray;
|
||||
import android.view.ActionMode;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.webkit.MimeTypeMap;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.simplemobiletools.filemanager.Config;
|
||||
import com.simplemobiletools.filemanager.Constants;
|
||||
import com.simplemobiletools.filemanager.R;
|
||||
import com.simplemobiletools.filemanager.Utils;
|
||||
import com.simplemobiletools.filemanager.activities.SimpleActivity;
|
||||
import com.simplemobiletools.filemanager.adapters.ItemsAdapter;
|
||||
import com.simplemobiletools.filemanager.dialogs.CopyDialog;
|
||||
import com.simplemobiletools.filemanager.dialogs.CreateNewItemDialog;
|
||||
import com.simplemobiletools.filemanager.dialogs.RenameItemDialog;
|
||||
import com.simplemobiletools.filepicker.asynctasks.CopyMoveTask;
|
||||
import com.simplemobiletools.filepicker.models.FileDirItem;
|
||||
import com.simplemobiletools.fileproperties.dialogs.PropertiesDialog;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import butterknife.OnClick;
|
||||
|
||||
public class ItemsFragment extends android.support.v4.app.Fragment
|
||||
implements AdapterView.OnItemClickListener, SwipeRefreshLayout.OnRefreshListener, ListView.MultiChoiceModeListener,
|
||||
ListView.OnTouchListener {
|
||||
@BindView(R.id.items_list) ListView mListView;
|
||||
@BindView(R.id.items_swipe_refresh) SwipeRefreshLayout mSwipeRefreshLayout;
|
||||
@BindView(R.id.items_holder) CoordinatorLayout mCoordinatorLayout;
|
||||
|
||||
private static Map<String, Parcelable> mStates;
|
||||
|
||||
private List<FileDirItem> mItems;
|
||||
private ItemInteractionListener mListener;
|
||||
private List<String> mToBeDeleted;
|
||||
private String mPath;
|
||||
private Snackbar mSnackbar;
|
||||
private Config mConfig;
|
||||
|
||||
private boolean mShowHidden;
|
||||
private int mSelectedItemsCnt;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
final View view = inflater.inflate(R.layout.items_fragment, container, false);
|
||||
ButterKnife.bind(this, view);
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
if (mStates == null)
|
||||
mStates = new HashMap<>();
|
||||
mConfig = Config.Companion.newInstance(getContext());
|
||||
mShowHidden = mConfig.getShowHidden();
|
||||
mItems = new ArrayList<>();
|
||||
mToBeDeleted = new ArrayList<>();
|
||||
fillItems();
|
||||
mSwipeRefreshLayout.setOnRefreshListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
if (mShowHidden != mConfig.getShowHidden()) {
|
||||
mShowHidden = !mShowHidden;
|
||||
mStates.remove(mPath);
|
||||
fillItems();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
deleteItems();
|
||||
mStates.put(mPath, mListView.onSaveInstanceState());
|
||||
}
|
||||
|
||||
private void fillItems() {
|
||||
mPath = getArguments().getString(Constants.INSTANCE.getPATH());
|
||||
final List<FileDirItem> newItems = getItems(mPath);
|
||||
Collections.sort(newItems);
|
||||
if (mItems != null && newItems.toString().equals(mItems.toString())) {
|
||||
return;
|
||||
}
|
||||
|
||||
mItems = newItems;
|
||||
|
||||
final ItemsAdapter adapter = new ItemsAdapter(getContext(), mItems);
|
||||
mListView.setAdapter(adapter);
|
||||
mListView.setOnItemClickListener(this);
|
||||
mListView.setMultiChoiceModeListener(this);
|
||||
mListView.setOnTouchListener(this);
|
||||
|
||||
if (mStates != null && mStates.get(mPath) != null) {
|
||||
mListView.onRestoreInstanceState(mStates.get(mPath));
|
||||
}
|
||||
}
|
||||
|
||||
public void setListener(ItemInteractionListener listener) {
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
private List<FileDirItem> getItems(String path) {
|
||||
final List<FileDirItem> items = new ArrayList<>();
|
||||
final File base = new File(path);
|
||||
File[] files = base.listFiles();
|
||||
if (files != null) {
|
||||
for (File file : files) {
|
||||
final String curPath = file.getAbsolutePath();
|
||||
final String curName = Utils.Companion.getFilename(curPath);
|
||||
if (!mShowHidden && curName.startsWith("."))
|
||||
continue;
|
||||
|
||||
if (mToBeDeleted.contains(curPath))
|
||||
continue;
|
||||
|
||||
int children = getChildren(file);
|
||||
long size = file.length();
|
||||
|
||||
items.add(new FileDirItem(curPath, curName, file.isDirectory(), children, size));
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private int getChildren(File file) {
|
||||
if (file.listFiles() == null)
|
||||
return 0;
|
||||
|
||||
if (file.isDirectory()) {
|
||||
if (mShowHidden) {
|
||||
return file.listFiles().length;
|
||||
} else {
|
||||
return file.listFiles(new FileFilter() {
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
return !file.isHidden();
|
||||
}
|
||||
}).length;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
||||
final FileDirItem item = mItems.get(position);
|
||||
if (item.isDirectory()) {
|
||||
if (mListener != null)
|
||||
mListener.itemClicked(item);
|
||||
} else {
|
||||
final String path = item.getPath();
|
||||
final File file = new File(path);
|
||||
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(Utils.Companion.getFileExtension(path));
|
||||
if (mimeType == null)
|
||||
mimeType = "text/plain";
|
||||
|
||||
final Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(Uri.fromFile(file), mimeType);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
if (!tryGenericMimeType(intent, mimeType, file)) {
|
||||
Utils.Companion.showToast(getContext(), R.string.no_app_found);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean tryGenericMimeType(Intent intent, String mimeType, File file) {
|
||||
final String genericMimeType = getGenericMimeType(mimeType);
|
||||
intent.setDataAndType(Uri.fromFile(file), genericMimeType);
|
||||
try {
|
||||
startActivity(intent);
|
||||
return true;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@OnClick(R.id.items_fab)
|
||||
public void fabClicked(View view) {
|
||||
new CreateNewItemDialog(getContext(), mPath, new CreateNewItemDialog.OnCreateNewItemListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
fillItems();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRefresh() {
|
||||
fillItems();
|
||||
mSwipeRefreshLayout.setRefreshing(false);
|
||||
}
|
||||
|
||||
private String getGenericMimeType(String mimeType) {
|
||||
if (!mimeType.contains("/"))
|
||||
return mimeType;
|
||||
|
||||
final String type = mimeType.substring(0, mimeType.indexOf("/"));
|
||||
return type + "/*";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
|
||||
if (checked) {
|
||||
mSelectedItemsCnt++;
|
||||
} else {
|
||||
mSelectedItemsCnt--;
|
||||
}
|
||||
|
||||
if (mSelectedItemsCnt > 0) {
|
||||
mode.setTitle(String.valueOf(mSelectedItemsCnt));
|
||||
}
|
||||
|
||||
mode.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||
mode.getMenuInflater().inflate(R.menu.cab, menu);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||
MenuItem menuItem = menu.findItem(R.id.cab_rename);
|
||||
menuItem.setVisible(mSelectedItemsCnt == 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.cab_rename:
|
||||
displayRenameDialog();
|
||||
mode.finish();
|
||||
break;
|
||||
case R.id.cab_properties:
|
||||
displayPropertiesDialog();
|
||||
break;
|
||||
case R.id.cab_share:
|
||||
shareFiles();
|
||||
break;
|
||||
case R.id.cab_copy:
|
||||
displayCopyDialog();
|
||||
mode.finish();
|
||||
break;
|
||||
case R.id.cab_delete:
|
||||
prepareForDeleting();
|
||||
mode.finish();
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void shareFiles() {
|
||||
final List<Integer> itemIndexes = getSelectedItemIndexes();
|
||||
if (itemIndexes.isEmpty())
|
||||
return;
|
||||
|
||||
final ArrayList<Uri> uris = new ArrayList<>(itemIndexes.size());
|
||||
for (int i : itemIndexes) {
|
||||
final File file = new File(mItems.get(i).getPath());
|
||||
if (!file.isDirectory())
|
||||
uris.add(Uri.fromFile(file));
|
||||
}
|
||||
|
||||
if (uris.isEmpty()) {
|
||||
Utils.Companion.showToast(getContext(), R.string.no_files_selected);
|
||||
return;
|
||||
}
|
||||
|
||||
final String shareTitle = getResources().getString(R.string.share_via);
|
||||
final Intent sendIntent = new Intent();
|
||||
sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
|
||||
sendIntent.putExtra(Intent.EXTRA_SUBJECT, getResources().getString(R.string.shared_files));
|
||||
sendIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
|
||||
sendIntent.setType("*/*");
|
||||
startActivity(Intent.createChooser(sendIntent, shareTitle));
|
||||
}
|
||||
|
||||
private void displayPropertiesDialog() {
|
||||
final List<Integer> itemIndexes = getSelectedItemIndexes();
|
||||
if (itemIndexes.isEmpty())
|
||||
return;
|
||||
|
||||
if (itemIndexes.size() == 1) {
|
||||
showOneItemProperties();
|
||||
} else {
|
||||
showMultipleItemProperties(itemIndexes);
|
||||
}
|
||||
}
|
||||
|
||||
private void showOneItemProperties() {
|
||||
final FileDirItem item = getSelectedItem();
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
new PropertiesDialog(getActivity(), item.getPath(), mConfig.getShowHidden());
|
||||
}
|
||||
|
||||
private void showMultipleItemProperties(List<Integer> itemIndexes) {
|
||||
final List<String> paths = new ArrayList<>(itemIndexes.size());
|
||||
for (int i : itemIndexes) {
|
||||
paths.add(mItems.get(i).getPath());
|
||||
}
|
||||
new PropertiesDialog(getActivity(), paths, mConfig.getShowHidden());
|
||||
}
|
||||
|
||||
private void displayRenameDialog() {
|
||||
final FileDirItem item = getSelectedItem();
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
new RenameItemDialog(getContext(), mPath, item, new RenameItemDialog.OnRenameItemListener() {
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
fillItems();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayCopyDialog() {
|
||||
final List<Integer> fileIndexes = getSelectedItemIndexes();
|
||||
if (fileIndexes.isEmpty())
|
||||
return;
|
||||
|
||||
final ArrayList<File> files = new ArrayList<>(fileIndexes.size());
|
||||
for (Integer i : fileIndexes) {
|
||||
FileDirItem item = mItems.get(i);
|
||||
files.add(new File(item.getPath()));
|
||||
}
|
||||
|
||||
new CopyDialog((SimpleActivity) getActivity(), files, new CopyMoveTask.CopyMoveListener() {
|
||||
@Override
|
||||
public void copySucceeded(boolean deleted, boolean copiedAll) {
|
||||
int msgId;
|
||||
if (deleted) {
|
||||
msgId = copiedAll ? R.string.moving_success : R.string.moving_success_partial;
|
||||
} else {
|
||||
msgId = copiedAll? R.string.copying_success : R.string.copying_success_partial;
|
||||
}
|
||||
fillItems();
|
||||
Utils.Companion.showToast(getContext(), msgId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void copyFailed() {
|
||||
Utils.Companion.showToast(getContext(), R.string.copy_move_failed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private FileDirItem getSelectedItem() {
|
||||
final List<Integer> itemIndexes = getSelectedItemIndexes();
|
||||
if (itemIndexes.isEmpty())
|
||||
return null;
|
||||
|
||||
final int itemIndex = itemIndexes.get(0);
|
||||
return mItems.get(itemIndex);
|
||||
}
|
||||
|
||||
private List<Integer> getSelectedItemIndexes() {
|
||||
final List<Integer> selectedItems = new ArrayList<>();
|
||||
final SparseBooleanArray items = mListView.getCheckedItemPositions();
|
||||
int cnt = items.size();
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
selectedItems.add(items.keyAt(i));
|
||||
}
|
||||
}
|
||||
return selectedItems;
|
||||
}
|
||||
|
||||
private void prepareForDeleting() {
|
||||
mToBeDeleted.clear();
|
||||
final SparseBooleanArray items = mListView.getCheckedItemPositions();
|
||||
final int cnt = items.size();
|
||||
int deletedCnt = 0;
|
||||
for (int i = 0; i < cnt; i++) {
|
||||
if (items.valueAt(i)) {
|
||||
final int id = items.keyAt(i);
|
||||
final String path = mItems.get(id).getPath();
|
||||
mToBeDeleted.add(path);
|
||||
deletedCnt++;
|
||||
}
|
||||
}
|
||||
|
||||
notifyDeletion(deletedCnt);
|
||||
}
|
||||
|
||||
private void notifyDeletion(int cnt) {
|
||||
final Resources res = getResources();
|
||||
final String msg = res.getQuantityString(R.plurals.items_deleted, cnt, cnt);
|
||||
mSnackbar = Snackbar.make(mCoordinatorLayout, msg, Snackbar.LENGTH_INDEFINITE);
|
||||
mSnackbar.setAction(res.getString(R.string.undo), undoDeletion);
|
||||
mSnackbar.setActionTextColor(Color.WHITE);
|
||||
mSnackbar.show();
|
||||
fillItems();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouch(View v, MotionEvent event) {
|
||||
if (mSnackbar != null && mSnackbar.isShown()) {
|
||||
deleteItems();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void deleteItems() {
|
||||
if (mToBeDeleted == null || mToBeDeleted.isEmpty())
|
||||
return;
|
||||
|
||||
if (mSnackbar != null) {
|
||||
mSnackbar.dismiss();
|
||||
}
|
||||
|
||||
for (String delPath : mToBeDeleted) {
|
||||
final File file = new File(delPath);
|
||||
if (file.exists()) {
|
||||
deleteItem(file);
|
||||
}
|
||||
}
|
||||
|
||||
mToBeDeleted.clear();
|
||||
}
|
||||
|
||||
private void deleteItem(File item) {
|
||||
if (item.isDirectory()) {
|
||||
for (File child : item.listFiles()) {
|
||||
deleteItem(child);
|
||||
}
|
||||
}
|
||||
|
||||
if (Utils.Companion.needsStupidWritePermissions(getContext(), item.getAbsolutePath())) {
|
||||
final DocumentFile document = Utils.Companion.getFileDocument(getContext(), item.getAbsolutePath(), mConfig.getTreeUri());
|
||||
document.delete();
|
||||
} else {
|
||||
item.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private View.OnClickListener undoDeletion = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mToBeDeleted.clear();
|
||||
mSnackbar.dismiss();
|
||||
fillItems();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void onDestroyActionMode(ActionMode mode) {
|
||||
mSelectedItemsCnt = 0;
|
||||
}
|
||||
|
||||
public interface ItemInteractionListener {
|
||||
void itemClicked(FileDirItem item);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package com.simplemobiletools.filemanager
|
||||
|
||||
val PATH = "path"
|
||||
|
||||
// shared preferences
|
||||
val PREFS_KEY = "File Manager"
|
||||
val IS_FIRST_RUN = "is_first_run"
|
||||
|
@ -9,7 +11,3 @@ val TREE_URI = "tree_uri"
|
|||
|
||||
// global intents
|
||||
val OPEN_DOCUMENT_TREE = 1000
|
||||
|
||||
object Constants {
|
||||
val PATH = "path"
|
||||
}
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
package com.simplemobiletools.filemanager
|
||||
|
||||
import android.content.Context
|
||||
import com.simplemobiletools.filepicker.extensions.getFileDocument
|
||||
import com.simplemobiletools.filepicker.extensions.needsStupidWritePermissions
|
||||
import com.simplemobiletools.filepicker.extensions.scanFile
|
||||
import com.simplemobiletools.filepicker.extensions.toast
|
||||
import java.io.File
|
||||
|
||||
class Utils {
|
||||
companion object {
|
||||
fun getFilename(path: String) = path.substring(path.lastIndexOf("/") + 1)
|
||||
|
||||
fun getFileExtension(fileName: String) = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length).toLowerCase()
|
||||
|
||||
fun showToast(context: Context, resId: Int) = context.toast(resId)
|
||||
|
||||
fun needsStupidWritePermissions(context: Context, path: String) = context.needsStupidWritePermissions(path)
|
||||
|
||||
fun getFileDocument(context: Context, path: String, treeUri: String) = context.getFileDocument(path, treeUri)
|
||||
|
||||
fun scanFile(context: Context, file: File) = context.scanFile(file) {}
|
||||
}
|
||||
}
|
|
@ -8,7 +8,7 @@ import android.os.Handler
|
|||
import android.support.v4.app.ActivityCompat
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.simplemobiletools.filemanager.Constants
|
||||
import com.simplemobiletools.filemanager.PATH
|
||||
import com.simplemobiletools.filemanager.R
|
||||
import com.simplemobiletools.filemanager.fragments.ItemsFragment
|
||||
import com.simplemobiletools.filepicker.dialogs.StoragePickerDialog
|
||||
|
@ -50,7 +50,7 @@ class MainActivity : SimpleActivity(), ItemsFragment.ItemInteractionListener, Br
|
|||
private fun openPath(path: String) {
|
||||
breadcrumbs.setBreadcrumb(path)
|
||||
val bundle = Bundle()
|
||||
bundle.putString(Constants.PATH, path)
|
||||
bundle.putString(PATH, path)
|
||||
|
||||
val fragment = ItemsFragment()
|
||||
fragment.arguments = bundle
|
||||
|
|
|
@ -0,0 +1,400 @@
|
|||
package com.simplemobiletools.filemanager.fragments
|
||||
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.Intent
|
||||
import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.webkit.MimeTypeMap
|
||||
import android.widget.AdapterView
|
||||
import com.simplemobiletools.filemanager.Config
|
||||
import com.simplemobiletools.filemanager.PATH
|
||||
import com.simplemobiletools.filemanager.R
|
||||
import com.simplemobiletools.filemanager.activities.SimpleActivity
|
||||
import com.simplemobiletools.filemanager.adapters.ItemsAdapter
|
||||
import com.simplemobiletools.filemanager.dialogs.CopyDialog
|
||||
import com.simplemobiletools.filemanager.dialogs.CreateNewItemDialog
|
||||
import com.simplemobiletools.filemanager.dialogs.RenameItemDialog
|
||||
import com.simplemobiletools.filepicker.asynctasks.CopyMoveTask
|
||||
import com.simplemobiletools.filepicker.extensions.*
|
||||
import com.simplemobiletools.filepicker.models.FileDirItem
|
||||
import com.simplemobiletools.fileproperties.dialogs.PropertiesDialog
|
||||
import kotlinx.android.synthetic.main.items_fragment.*
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
class ItemsFragment : android.support.v4.app.Fragment(), AdapterView.OnItemClickListener, /*ListView.MultiChoiceModeListener, */View.OnTouchListener {
|
||||
private var mListener: ItemInteractionListener? = null
|
||||
private var mSnackbar: Snackbar? = null
|
||||
|
||||
lateinit var mItems: List<FileDirItem>
|
||||
lateinit var mConfig: Config
|
||||
lateinit var mToBeDeleted: MutableList<String>
|
||||
|
||||
private var mPath = ""
|
||||
private var mShowHidden = false
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?) =
|
||||
inflater!!.inflate(R.layout.items_fragment, container, false)
|
||||
|
||||
override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
mConfig = Config.newInstance(context)
|
||||
mShowHidden = mConfig.showHidden
|
||||
mItems = ArrayList<FileDirItem>()
|
||||
mToBeDeleted = ArrayList<String>()
|
||||
fillItems()
|
||||
|
||||
items_swipe_refresh.setOnRefreshListener({ fillItems() })
|
||||
items_fab.setOnClickListener { createNewItem() }
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
if (mShowHidden != mConfig.showHidden) {
|
||||
mShowHidden = !mShowHidden
|
||||
fillItems()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
deleteItems()
|
||||
}
|
||||
|
||||
private fun fillItems() {
|
||||
mPath = arguments.getString(PATH)
|
||||
val newItems = getItems(mPath)
|
||||
Collections.sort(newItems)
|
||||
items_swipe_refresh.isRefreshing = false
|
||||
if (newItems.toString() == mItems.toString()) {
|
||||
return
|
||||
}
|
||||
|
||||
mItems = newItems
|
||||
|
||||
val adapter = ItemsAdapter(context, mItems)
|
||||
items_list.adapter = adapter
|
||||
items_list.onItemClickListener = this
|
||||
items_list.setOnTouchListener(this)
|
||||
}
|
||||
|
||||
fun setListener(listener: ItemInteractionListener) {
|
||||
mListener = listener
|
||||
}
|
||||
|
||||
private fun getItems(path: String): List<FileDirItem> {
|
||||
val items = ArrayList<FileDirItem>()
|
||||
val files = File(path).listFiles()
|
||||
if (files != null) {
|
||||
for (file in files) {
|
||||
val curPath = file.absolutePath
|
||||
val curName = curPath.getFilenameFromPath()
|
||||
if (!mShowHidden && curName.startsWith("."))
|
||||
continue
|
||||
|
||||
if (mToBeDeleted.contains(curPath))
|
||||
continue
|
||||
|
||||
val children = getChildren(file)
|
||||
val size = file.length()
|
||||
|
||||
items.add(FileDirItem(curPath, curName, file.isDirectory, children, size))
|
||||
}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
private fun getChildren(file: File): Int {
|
||||
if (file.listFiles() == null)
|
||||
return 0
|
||||
|
||||
if (file.isDirectory) {
|
||||
return if (mShowHidden) {
|
||||
file.listFiles().size
|
||||
} else {
|
||||
file.listFiles { file -> !file.isHidden }.size
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
override fun onItemClick(parent: AdapterView<*>, view: View, position: Int, id: Long) {
|
||||
val item = mItems[position]
|
||||
if (item.isDirectory) {
|
||||
mListener?.itemClicked(item)
|
||||
} else {
|
||||
val path = item.path
|
||||
val file = File(path)
|
||||
var mimeType: String? = MimeTypeMap.getSingleton().getMimeTypeFromExtension(path.getFilenameExtension().toLowerCase())
|
||||
if (mimeType == null)
|
||||
mimeType = "text/plain"
|
||||
|
||||
Intent(Intent.ACTION_VIEW).apply {
|
||||
setDataAndType(Uri.fromFile(file), mimeType)
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK
|
||||
try {
|
||||
startActivity(this)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
if (!tryGenericMimeType(this, mimeType!!, file)) {
|
||||
context.toast(R.string.no_app_found)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun tryGenericMimeType(intent: Intent, mimeType: String, file: File): Boolean {
|
||||
val genericMimeType = getGenericMimeType(mimeType)
|
||||
intent.setDataAndType(Uri.fromFile(file), genericMimeType)
|
||||
return try {
|
||||
startActivity(intent)
|
||||
true
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun createNewItem() {
|
||||
CreateNewItemDialog(context, mPath, object : CreateNewItemDialog.OnCreateNewItemListener {
|
||||
override fun onSuccess() {
|
||||
fillItems()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun getGenericMimeType(mimeType: String): String {
|
||||
if (!mimeType.contains("/"))
|
||||
return mimeType
|
||||
|
||||
val type = mimeType.substring(0, mimeType.indexOf("/"))
|
||||
return type + "/*"
|
||||
}
|
||||
|
||||
/*override fun onItemCheckedStateChanged(mode: ActionMode, position: Int, id: Long, checked: Boolean) {
|
||||
if (checked) {
|
||||
mSelectedItemsCnt++
|
||||
} else {
|
||||
mSelectedItemsCnt--
|
||||
}
|
||||
|
||||
if (mSelectedItemsCnt > 0) {
|
||||
mode.title = mSelectedItemsCnt.toString()
|
||||
}
|
||||
|
||||
mode.invalidate()
|
||||
}
|
||||
|
||||
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
mode.menuInflater.inflate(R.menu.cab, menu)
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean {
|
||||
val menuItem = menu.findItem(R.id.cab_rename)
|
||||
menuItem.isVisible = mSelectedItemsCnt == 1
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.cab_rename -> {
|
||||
displayRenameDialog()
|
||||
mode.finish()
|
||||
}
|
||||
R.id.cab_properties -> displayPropertiesDialog()
|
||||
R.id.cab_share -> shareFiles()
|
||||
R.id.cab_copy -> {
|
||||
displayCopyDialog()
|
||||
mode.finish()
|
||||
}
|
||||
R.id.cab_delete -> {
|
||||
prepareForDeleting()
|
||||
mode.finish()
|
||||
}
|
||||
else -> return false
|
||||
}
|
||||
|
||||
return true
|
||||
}*/
|
||||
|
||||
private fun shareFiles() {
|
||||
val itemIndexes = getSelectedItemIndexes()
|
||||
if (itemIndexes.isEmpty())
|
||||
return
|
||||
|
||||
val uris = ArrayList<Uri>(itemIndexes.size)
|
||||
itemIndexes.map { File(mItems[it].path) }
|
||||
.filterNot { it.isDirectory }
|
||||
.mapTo(uris) { Uri.fromFile(it) }
|
||||
|
||||
if (uris.isEmpty()) {
|
||||
context.toast(R.string.no_files_selected)
|
||||
return
|
||||
}
|
||||
|
||||
val shareTitle = resources.getString(R.string.share_via)
|
||||
Intent().apply {
|
||||
action = Intent.ACTION_SEND_MULTIPLE
|
||||
putExtra(Intent.EXTRA_SUBJECT, resources.getString(R.string.shared_files))
|
||||
putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris)
|
||||
type = "*/*"
|
||||
startActivity(Intent.createChooser(this, shareTitle))
|
||||
}
|
||||
}
|
||||
|
||||
private fun displayPropertiesDialog() {
|
||||
val itemIndexes = getSelectedItemIndexes()
|
||||
if (itemIndexes.isEmpty())
|
||||
return
|
||||
|
||||
if (itemIndexes.size == 1) {
|
||||
showOneItemProperties()
|
||||
} else {
|
||||
showMultipleItemProperties(itemIndexes)
|
||||
}
|
||||
}
|
||||
|
||||
private fun showOneItemProperties() {
|
||||
val item = getSelectedItem() ?: return
|
||||
PropertiesDialog(activity, item.path, mConfig.showHidden)
|
||||
}
|
||||
|
||||
private fun showMultipleItemProperties(itemIndexes: List<Int>) {
|
||||
val paths = ArrayList<String>(itemIndexes.size)
|
||||
itemIndexes.mapTo(paths) { mItems[it].path }
|
||||
PropertiesDialog(activity, paths, mConfig.showHidden)
|
||||
}
|
||||
|
||||
private fun displayRenameDialog() {
|
||||
val item = getSelectedItem() ?: return
|
||||
|
||||
RenameItemDialog(context, mPath, item, object : RenameItemDialog.OnRenameItemListener {
|
||||
override fun onSuccess() {
|
||||
fillItems()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun displayCopyDialog() {
|
||||
val fileIndexes = getSelectedItemIndexes()
|
||||
if (fileIndexes.isEmpty())
|
||||
return
|
||||
|
||||
val files = ArrayList<File>(fileIndexes.size)
|
||||
fileIndexes.mapTo(files) { File(mItems[it].path) }
|
||||
|
||||
CopyDialog(activity as SimpleActivity, files, object : CopyMoveTask.CopyMoveListener {
|
||||
override fun copySucceeded(deleted: Boolean, copiedAll: Boolean) {
|
||||
if (deleted) {
|
||||
context.toast(if (copiedAll) R.string.moving_success else R.string.moving_success_partial)
|
||||
} else {
|
||||
context.toast(if (copiedAll) R.string.copying_success else R.string.copying_success_partial)
|
||||
}
|
||||
fillItems()
|
||||
}
|
||||
|
||||
override fun copyFailed() {
|
||||
context.toast(R.string.copy_move_failed)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun getSelectedItem(): FileDirItem? {
|
||||
val itemIndexes = getSelectedItemIndexes()
|
||||
if (itemIndexes.isEmpty())
|
||||
return null
|
||||
|
||||
val itemIndex = itemIndexes[0]
|
||||
return mItems[itemIndex]
|
||||
}
|
||||
|
||||
private fun getSelectedItemIndexes(): List<Int> {
|
||||
val items = items_list.checkedItemPositions
|
||||
val cnt = items.size()
|
||||
val selectedItems = (0..cnt - 1)
|
||||
.filter { items.valueAt(it) }
|
||||
.map { items.keyAt(it) }
|
||||
return selectedItems
|
||||
}
|
||||
|
||||
private fun prepareForDeleting() {
|
||||
mToBeDeleted.clear()
|
||||
val items = items_list.checkedItemPositions
|
||||
val cnt = items.size()
|
||||
var deletedCnt = 0
|
||||
for (i in 0..cnt - 1) {
|
||||
if (items.valueAt(i)) {
|
||||
val id = items.keyAt(i)
|
||||
val path = mItems[id].path
|
||||
mToBeDeleted.add(path)
|
||||
deletedCnt++
|
||||
}
|
||||
}
|
||||
|
||||
notifyDeletion(deletedCnt)
|
||||
}
|
||||
|
||||
private fun notifyDeletion(cnt: Int) {
|
||||
val res = resources
|
||||
val msg = res.getQuantityString(R.plurals.items_deleted, cnt, cnt)
|
||||
mSnackbar = Snackbar.make(items_holder, msg, Snackbar.LENGTH_INDEFINITE)
|
||||
mSnackbar!!.apply {
|
||||
setAction(res.getString(R.string.undo), undoDeletion)
|
||||
setActionTextColor(Color.WHITE)
|
||||
show()
|
||||
}
|
||||
fillItems()
|
||||
}
|
||||
|
||||
override fun onTouch(v: View, event: MotionEvent): Boolean {
|
||||
if (mSnackbar != null && mSnackbar!!.isShown) {
|
||||
deleteItems()
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun deleteItems() {
|
||||
if (mToBeDeleted.isEmpty())
|
||||
return
|
||||
|
||||
mSnackbar?.dismiss()
|
||||
mToBeDeleted
|
||||
.map(::File)
|
||||
.filter(File::exists)
|
||||
.forEach { deleteItem(it) }
|
||||
|
||||
mToBeDeleted.clear()
|
||||
}
|
||||
|
||||
private fun deleteItem(item: File) {
|
||||
if (item.isDirectory) {
|
||||
for (child in item.listFiles()) {
|
||||
deleteItem(child)
|
||||
}
|
||||
}
|
||||
|
||||
if (context.needsStupidWritePermissions(item.absolutePath)) {
|
||||
val document = context.getFileDocument(item.absolutePath, mConfig.treeUri)
|
||||
document.delete()
|
||||
} else {
|
||||
item.delete()
|
||||
}
|
||||
}
|
||||
|
||||
private val undoDeletion = View.OnClickListener {
|
||||
mToBeDeleted.clear()
|
||||
mSnackbar!!.dismiss()
|
||||
fillItems()
|
||||
}
|
||||
|
||||
interface ItemInteractionListener {
|
||||
fun itemClicked(item: FileDirItem)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue