com.duy.pascal.ui.file.fragment.FileListPagerFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.duy.pascal.ui.file.fragment.FileListPagerFragment.java

Source

/*
 *  Copyright (c) 2017 Tran Le Duy
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.duy.pascal.ui.file.fragment;

import android.content.Context;
import android.content.SharedPreferences;
import android.databinding.DataBindingUtil;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import com.duy.pascal.ui.R;
import com.duy.pascal.ui.common.listeners.OnItemClickListener;
import com.duy.pascal.ui.common.task.JecAsyncTask;
import com.duy.pascal.ui.common.task.TaskListener;
import com.duy.pascal.ui.common.task.TaskResult;
import com.duy.pascal.ui.common.utils.UIUtils;
import com.duy.pascal.ui.databinding.FileExplorerFragmentBinding;
import com.duy.pascal.ui.editor.EditorActivity;
import com.duy.pascal.ui.file.ExplorerContext;
import com.duy.pascal.ui.file.FileActionListener;
import com.duy.pascal.ui.file.FileClipboard;
import com.duy.pascal.ui.file.FileExplorerAction;
import com.duy.pascal.ui.file.FileExplorerView;
import com.duy.pascal.ui.file.Pref;
import com.duy.pascal.ui.file.activities.FileExplorerActivity;
import com.duy.pascal.ui.file.adapter.FileListItemAdapter;
import com.duy.pascal.ui.file.adapter.PathButtonAdapter;
import com.duy.pascal.ui.file.listener.OnClipboardPasteFinishListener;
import com.duy.pascal.ui.file.util.FileListSorter;
import com.duy.pascal.ui.utils.DLog;
import com.yqritc.recyclerviewflexibledivider.HorizontalDividerItemDecoration;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author Jecelyin Peng <jecelyin@gmail.com>
 */
public class FileListPagerFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener,
        OnItemClickListener, FileExplorerView, ExplorerContext, SharedPreferences.OnSharedPreferenceChangeListener {
    public static final String TAG = "FileListPagerFragment";
    private FileListItemAdapter mAdapter;
    @Nullable
    private File mPath;
    private FileExplorerFragmentBinding binding;
    private PathButtonAdapter mPathAdapter;
    private ScanFilesTask mTask;
    private FileExplorerAction mAction;

    public static Fragment newFragment(File path) {
        DLog.d(TAG, "newFragment() called with: path = [" + path + "]");

        FileListPagerFragment f = new FileListPagerFragment();
        Bundle b = new Bundle();
        b.putSerializable("path", path);
        f.setArguments(b);
        return f;
    }

    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        mPath = (File) getArguments().getSerializable("path");
        binding = DataBindingUtil.inflate(inflater, R.layout.file_explorer_fragment, container, false);
        return binding.getRoot();
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        FileClipboard fileClipboard = ((FileActionListener) getActivity()).getFileClipboard();
        mAction = new FileExplorerAction(getContext(), this, fileClipboard, this);
        mAdapter = new FileListItemAdapter();
        mAdapter.setOnCheckedChangeListener(mAction);
        mAdapter.setOnItemClickListener(this);
        mAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onChanged() {
                binding.emptyLayout.post(new Runnable() {
                    @Override
                    public void run() {
                        binding.emptyLayout.setVisibility(mAdapter.getItemCount() > 0 ? View.GONE : View.VISIBLE);
                    }
                });

            }
        });

        binding.pathScrollView
                .setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
        mPathAdapter = new PathButtonAdapter();
        mPathAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
            @Override
            public void onChanged() {
                binding.pathScrollView.scrollToPosition(mPathAdapter.getItemCount() - 1);
            }
        });
        mPathAdapter.setPath(mPath);
        mPathAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(int position, View view) {
                File file = mPathAdapter.getItem(position);
                switchToPath(file);
            }

            @Override
            public boolean onItemLongClick(int position, View view) {
                return false;
            }
        });
        binding.pathScrollView.setAdapter(mPathAdapter);

        binding.explorerSwipeRefreshLayout.setOnRefreshListener(this);
        binding.recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
        binding.recyclerView.setAdapter(mAdapter);
        binding.recyclerView.addItemDecoration(new HorizontalDividerItemDecoration.Builder(getContext())
                .margin(getResources().getDimensionPixelSize(R.dimen.file_list_item_divider_left_margin), 0)
                .build());
        binding.explorerSwipeRefreshLayout.post(new Runnable() {
            @Override
            public void run() {
                binding.explorerSwipeRefreshLayout.setRefreshing(true);
            }
        });
        binding.nameFilterEditText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mAdapter.filter(s);
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
        onRefresh();
    }

    @Override
    public void onStart() {
        super.onStart();
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
        pref.registerOnSharedPreferenceChangeListener(this);
    }

    @Override
    public void onDestroyView() {
        SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
        pref.unregisterOnSharedPreferenceChangeListener(this);
        if (mAction != null) {
            mAction.destroy();
        }
        super.onDestroyView();
    }

    @Override
    public void onStop() {
        super.onStop();
        if (mTask != null) {
            mTask.cancel(true);
            mTask = null;
        }
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.paste_menu) {
            final FileClipboard fileClipboard = ((FileExplorerActivity) getActivity()).getFileClipboard();
            fileClipboard.paste(getContext(), getCurrentDirectory(), new OnClipboardPasteFinishListener() {
                @Override
                public void onFinish(int count, String error) {
                    onRefresh();
                    fileClipboard.showPasteResult(getContext(), count, error);
                }
            });
            item.setVisible(false);
        } else if (item.getItemId() == R.id.add_folder_menu) {
            mAction.doCreateFolder(null);
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onRefresh() {
        DLog.d(TAG, "onRefresh() called");

        UpdateRootInfo updateRootInfo = new UpdateRootInfo() {
            @Override
            public void onUpdate(File f) {
                mPath = f;
            }
        };
        mTask = new ScanFilesTask(getActivity(), mPath, updateRootInfo);
        mTask.setTaskListener(new TaskListener<File[]>() {
            @Override
            public void onCompleted() {
                if (binding.explorerSwipeRefreshLayout != null) {
                    binding.explorerSwipeRefreshLayout.postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            binding.explorerSwipeRefreshLayout.setRefreshing(false);
                        }
                    }, 300);
                }
            }

            @Override
            public void onSuccess(File[] result) {
                if (mAdapter != null) {
                    mAdapter.setData(result);
                }
            }

            @Override
            public void onError(Exception e) {
                e.printStackTrace();
                if (binding.explorerSwipeRefreshLayout == null) {
                    return;
                }
                binding.explorerSwipeRefreshLayout.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        binding.explorerSwipeRefreshLayout.setRefreshing(false);
                    }
                }, 300);
                UIUtils.toast(getContext(), e);
            }
        });
        mTask.execute();
    }

    @Override
    public void onItemClick(int position, View view) {
        try {
            File file = mAdapter.getItem(position);
            FileActionListener callback = (FileActionListener) getActivity();
            if (!callback.onFileSelected(new File(file.getPath()))) {
                if (file.isDirectory()) {
                    switchToPath(file);
                }
            }
        } catch (ClassCastException e) {
        }
    }

    @Override
    public boolean onItemLongClick(int position, View view) {
        //        try {
        //            File file = adapter.getItem(position);
        //            FileActionListener callback = (FileActionListener) getActivity();
        //            return callback.onFileLongClick(new File(file.getPath()));
        //        } catch (ClassCastException ignored) {
        //        }
        return false;
    }

    public boolean onBackPressed() {
        File parent = mPath.getParentFile();
        if (parent == null || parent.getPath().startsWith(mPath.getPath())) {
            switchToPath(parent);
            return true;
        }
        return false;
    }

    private void switchToPath(File file) {
        mPath = file;
        mPathAdapter.setPath(file);
        Pref.getInstance(getContext()).setLastOpenPath(file.getPath());
        onRefresh();
    }

    @Override
    public ActionMode startActionMode(ActionMode.Callback callback) {
        return ((AppCompatActivity) getActivity()).startSupportActionMode(callback);
    }

    @Override
    public void setSelectAll(boolean checked) {
        mAdapter.checkAll(checked);
    }

    @Override
    public void refresh() {
        onRefresh();
    }

    @Override
    public void finish() {
        FragmentActivity activity = getActivity();
        if (activity != null) {
            activity.finish();
        }
    }

    @Override
    public void createNewFolder() {
        mAction.doCreateFolder((FileActionListener) getActivity());
    }

    @Override
    public void createNewFile() {
        mAction.showDialogCreateFile((FileActionListener) getActivity());
    }

    @Override
    public void onPrepareDeleteFile(File file) {
        EditorActivity activity = (EditorActivity) getActivity();
        if (activity != null) {
            activity.onPrepareDeleteFile(file);
        }
    }

    @Override
    public void show(File file) {
        mPath = file;
        onRefresh();
    }

    @Override
    public File getCurrentDirectory() {
        return mPath;
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        switch (key) {
        case "show_hidden_files":
        case "show_file_sort":
            onRefresh();
            break;
        }
    }

    private interface UpdateRootInfo {
        void onUpdate(File path);
    }

    private static class ScanFilesTask extends JecAsyncTask<Void, Void, File[]> {
        private UpdateRootInfo mUpdateRootInfo;
        private Context mContext;
        private File mPath;

        private ScanFilesTask(Context context, File path, UpdateRootInfo updateRootInfo) {
            this.mContext = context.getApplicationContext();
            this.mPath = path;
            this.mUpdateRootInfo = updateRootInfo;
        }

        @Override
        protected void onRun(final TaskResult<File[]> taskResult, Void... params) throws Exception {
            Pref pref = Pref.getInstance(mContext);
            final boolean showHiddenFiles = pref.isShowHiddenFiles();
            final int sortType = pref.getFileSortType();
            mUpdateRootInfo.onUpdate(mPath);
            File[] result = mPath.listFiles();
            if (result.length == 0) {
                taskResult.setResult(result);
                return;
            }
            if (!showHiddenFiles) {
                List<File> list = new ArrayList<>(result.length);
                for (File file : result) {
                    if (file.getName().charAt(0) == '.') {
                        continue;
                    }
                    list.add(file);
                }
                result = new File[list.size()];
                list.toArray(result);
            }
            Arrays.sort(result, new FileListSorter(true, sortType, true));
            taskResult.setResult(result);
        }
    }
}