mirror of
				https://github.com/SimpleMobileTools/Simple-File-Manager.git
				synced 2025-06-05 22:09:15 +02:00 
			
		
		
		
	convert ItemsFragment to kotlin
This commit is contained in:
		| @@ -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) | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user