com.amaze.filemanager.fragments.MainFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.amaze.filemanager.fragments.MainFragment.java

Source

/* Diego Felipe Lassa <diegoflassa@gmail.com>
 *
 * Copyright (C) 2014 Arpit Khurana <arpitkh96@gmail.com>, Vishal Nehra <vishalmeham2@gmail.com>,
 *                          Emmanuel Messulam <emmanuelbendavid@gmail.com>, Jens Klingenberg <mail@jensklingenberg.de>
 *
 * This file is part of Amaze File Manager.
 *
 * Amaze File Manager is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.amaze.filemanager.fragments;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.media.MediaScannerConnection;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.design.widget.AppBarLayout;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.pm.ShortcutInfoCompat;
import android.support.v4.content.pm.ShortcutManagerCompat;
import android.support.v4.graphics.drawable.IconCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.LinearLayoutManager;
import android.text.format.Formatter;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.afollestad.materialdialogs.MaterialDialog;
import com.amaze.filemanager.R;
import com.amaze.filemanager.activities.MainActivity;
import com.amaze.filemanager.activities.superclasses.ThemedActivity;
import com.amaze.filemanager.adapters.RecyclerAdapter;
import com.amaze.filemanager.adapters.data.LayoutElementParcelable;
import com.amaze.filemanager.asynchronous.asynctasks.DeleteTask;
import com.amaze.filemanager.asynchronous.asynctasks.LoadFilesListTask;
import com.amaze.filemanager.asynchronous.handlers.FileHandler;
import com.amaze.filemanager.database.CloudHandler;
import com.amaze.filemanager.database.CryptHandler;
import com.amaze.filemanager.database.SortHandler;
import com.amaze.filemanager.database.models.EncryptedEntry;
import com.amaze.filemanager.database.models.Tab;
import com.amaze.filemanager.filesystem.CustomFileObserver;
import com.amaze.filemanager.filesystem.FileUtil;
import com.amaze.filemanager.filesystem.HybridFile;
import com.amaze.filemanager.filesystem.HybridFileParcelable;
import com.amaze.filemanager.filesystem.MediaStoreHack;
import com.amaze.filemanager.filesystem.PasteHelper;
import com.amaze.filemanager.filesystem.ssh.SshClientUtils;
import com.amaze.filemanager.ui.dialogs.GeneralDialogCreation;
import com.amaze.filemanager.ui.icons.MimeTypes;
import com.amaze.filemanager.ui.views.DividerItemDecoration;
import com.amaze.filemanager.ui.views.FastScroller;
import com.amaze.filemanager.ui.views.RoundedImageView;
import com.amaze.filemanager.ui.views.WarnableTextInputValidator;
import com.amaze.filemanager.utils.BottomBarButtonPath;
import com.amaze.filemanager.utils.DataUtils;
import com.amaze.filemanager.utils.MainActivityHelper;
import com.amaze.filemanager.utils.OTGUtil;
import com.amaze.filemanager.utils.OpenMode;
import com.amaze.filemanager.utils.SmbStreamer.Streamer;
import com.amaze.filemanager.utils.Utils;
import com.amaze.filemanager.utils.cloud.CloudUtil;
import com.amaze.filemanager.utils.files.CryptUtil;
import com.amaze.filemanager.utils.files.EncryptDecryptUtils;
import com.amaze.filemanager.utils.files.FileListSorter;
import com.amaze.filemanager.utils.files.FileUtils;
import com.amaze.filemanager.utils.provider.UtilitiesProvider;
import com.amaze.filemanager.utils.theme.AppTheme;

import java.io.File;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

import jcifs.smb.SmbException;
import jcifs.smb.SmbFile;

import static com.amaze.filemanager.fragments.preference_fragments.PreferencesConstants.*;
import static com.amaze.filemanager.fragments.preference_fragments.PreferencesConstants.PREFERENCE_SHOW_DIVIDERS;
import static com.amaze.filemanager.fragments.preference_fragments.PreferencesConstants.PREFERENCE_SHOW_GOBACK_BUTTON;

public class MainFragment extends android.support.v4.app.Fragment implements BottomBarButtonPath {

    public ActionMode mActionMode;
    //TODO refactor
    public int sortby, dsort, asc;
    public String home;
    public boolean selection, results = false;
    public OpenMode openMode = OpenMode.FILE;

    /**
     * boolean to identify if the view is a list or grid
     */
    public boolean IS_LIST = true;
    public SwipeRefreshLayout mSwipeRefreshLayout;
    public int file_count, folder_count, columns;
    public String smbPath;
    public ArrayList<HybridFileParcelable> searchHelper = new ArrayList<>();
    public int no;

    private String CURRENT_PATH = "";
    /**
     * This is not an exact copy of the elements in the adapter
     */
    private ArrayList<LayoutElementParcelable> LIST_ELEMENTS;
    public RecyclerAdapter adapter;
    private SharedPreferences sharedPref;
    private Resources res;

    // ATTRIBUTES FOR APPEARANCE AND COLORS
    private int accentColor, primaryColor, primaryTwoColor;
    private LinearLayoutManager mLayoutManager;
    private GridLayoutManager mLayoutManagerGrid;
    private boolean addheader = false;
    private DividerItemDecoration dividerItemDecoration;
    private AppBarLayout mToolbarContainer;
    private boolean stopAnims = true;
    private SwipeRefreshLayout nofilesview;

    private android.support.v7.widget.RecyclerView listView;
    private UtilitiesProvider utilsProvider;
    private HashMap<String, Bundle> scrolls = new HashMap<>();
    private MainFragment ma = this;
    private View rootView;
    private View actionModeView;
    private FastScroller fastScroller;
    private CustomFileObserver customFileObserver;
    private DataUtils dataUtils;
    private boolean isEncryptOpen = false; // do we have to open a file when service is begin destroyed
    private HybridFileParcelable encryptBaseFile; // the cached base file which we're to open, delete it later

    /**
     *  a list of encrypted base files which are supposed to be deleted
     */
    private ArrayList<HybridFileParcelable> encryptBaseFiles = new ArrayList<>();
    private MediaScannerConnection mediaScannerConnection;

    // defines the current visible tab, default either 0 or 1
    //private int mCurrentTab;

    /*
     * boolean identifying if the search task should be re-run on back press after pressing on
     * any of the search result
     */
    private boolean mRetainSearchTask = false;

    /**
     * For caching the back button
     */
    private LayoutElementParcelable back = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setRetainInstance(true);

        dataUtils = DataUtils.getInstance();
        utilsProvider = getMainActivity().getUtilsProvider();
        sharedPref = PreferenceManager.getDefaultSharedPreferences(getActivity());
        res = getResources();

        no = getArguments().getInt("no", 1);
        home = getArguments().getString("home");
        CURRENT_PATH = getArguments().getString("lastpath");

        IS_LIST = dataUtils.getListOrGridForPath(CURRENT_PATH, DataUtils.LIST) == DataUtils.LIST;

        accentColor = getMainActivity().getAccent();
        primaryColor = getMainActivity().getCurrentColorPreference().primaryFirstTab;
        primaryTwoColor = getMainActivity().getCurrentColorPreference().primarySecondTab;
    }

    public void stopAnimation() {
        if ((!adapter.stoppedAnimation)) {
            for (int j = 0; j < listView.getChildCount(); j++) {
                View v = listView.getChildAt(j);
                if (v != null)
                    v.clearAnimation();
            }
        }
        adapter.stoppedAnimation = true;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        rootView = inflater.inflate(R.layout.main_frag, container, false);
        setRetainInstance(true);
        listView = rootView.findViewById(R.id.listView);
        mToolbarContainer = getMainActivity().getAppbar().getAppbarLayout();
        fastScroller = rootView.findViewById(R.id.fastscroll);
        fastScroller.setPressedHandleColor(accentColor);
        listView.setOnTouchListener((view, motionEvent) -> {
            if (adapter != null && stopAnims) {
                stopAnimation();
                stopAnims = false;
            }
            return false;
        });
        mToolbarContainer.setOnTouchListener((view, motionEvent) -> {
            if (adapter != null && stopAnims) {
                stopAnimation();
                stopAnims = false;
            }
            return false;
        });

        mSwipeRefreshLayout = rootView.findViewById(R.id.activity_main_swipe_refresh_layout);

        mSwipeRefreshLayout.setOnRefreshListener(() -> loadlist((CURRENT_PATH), false, openMode));

        //String itemsstring = res.getString(R.string.items);// TODO: 23/5/2017 use or delete
        mToolbarContainer.setBackgroundColor(MainActivity.currentTab == 1 ? primaryTwoColor : primaryColor);

        //   listView.setPadding(listView.getPaddingLeft(), paddingTop, listView.getPaddingRight(), listView.getPaddingBottom());
        return rootView;
    }

    @Override
    public void onActivityCreated(final Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        setHasOptionsMenu(false);
        //getMainActivity() = (MainActivity) getActivity();
        initNoFileLayout();
        getSortModes();
        this.setRetainInstance(false);
        HybridFile f = new HybridFile(OpenMode.UNKNOWN, CURRENT_PATH);
        f.generateMode(getActivity());
        getMainActivity().getAppbar().getBottomBar().setClickListener();

        if (utilsProvider.getAppTheme().equals(AppTheme.LIGHT) && !IS_LIST) {
            listView.setBackgroundColor(Utils.getColor(getContext(), R.color.grid_background_light));
        } else {
            listView.setBackgroundDrawable(null);
        }

        listView.setHasFixedSize(true);
        columns = Integer.parseInt(sharedPref.getString(PREFERENCE_GRID_COLUMNS, "-1"));
        if (IS_LIST) {
            mLayoutManager = new LinearLayoutManager(getContext());
            listView.setLayoutManager(mLayoutManager);
        } else {
            if (columns == -1 || columns == 0)
                mLayoutManagerGrid = new GridLayoutManager(getActivity(), 3);
            else
                mLayoutManagerGrid = new GridLayoutManager(getActivity(), columns);
            setGridLayoutSpanSizeLookup(mLayoutManagerGrid);
            listView.setLayoutManager(mLayoutManagerGrid);
        }
        // use a linear layout manager
        //View footerView = getActivity().getLayoutInflater().inflate(R.layout.divider, null);// TODO: 23/5/2017 use or delete
        dividerItemDecoration = new DividerItemDecoration(getActivity(), false,
                getBoolean(PREFERENCE_SHOW_DIVIDERS));
        listView.addItemDecoration(dividerItemDecoration);
        mSwipeRefreshLayout.setColorSchemeColors(accentColor);
        DefaultItemAnimator animator = new DefaultItemAnimator();
        listView.setItemAnimator(animator);
        mToolbarContainer.getViewTreeObserver()
                .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        if ((columns == 0 || columns == -1)) {
                            int screen_width = listView.getWidth();
                            int dptopx = Utils.dpToPx(getContext(), 115);
                            columns = screen_width / dptopx;
                            if (columns == 0 || columns == -1)
                                columns = 3;
                            if (!IS_LIST)
                                mLayoutManagerGrid.setSpanCount(columns);
                        }
                        if (savedInstanceState != null && !IS_LIST)
                            onSavedInstanceState(savedInstanceState);
                        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) {
                            mToolbarContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                        } else {
                            mToolbarContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                        }
                    }

                });

        if (savedInstanceState == null) {
            loadlist(CURRENT_PATH, false, openMode);
        } else {
            if (IS_LIST)
                onSavedInstanceState(savedInstanceState);
        }
    }

    void setGridLayoutSpanSizeLookup(GridLayoutManager mLayoutManagerGrid) {

        mLayoutManagerGrid.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {

            @Override
            public int getSpanSize(int position) {
                switch (adapter.getItemViewType(position)) {
                case RecyclerAdapter.TYPE_HEADER_FILES:
                case RecyclerAdapter.TYPE_HEADER_FOLDERS:
                    return columns;
                default:
                    return 1;
                }
            }
        });
    }

    void switchToGrid() {
        IS_LIST = false;

        if (utilsProvider.getAppTheme().equals(AppTheme.LIGHT)) {

            // will always be grid, set alternate white background
            listView.setBackgroundColor(Utils.getColor(getContext(), R.color.grid_background_light));
        }

        if (mLayoutManagerGrid == null)
            if (columns == -1 || columns == 0)
                mLayoutManagerGrid = new GridLayoutManager(getActivity(), 3);
            else
                mLayoutManagerGrid = new GridLayoutManager(getActivity(), columns);
        setGridLayoutSpanSizeLookup(mLayoutManagerGrid);
        listView.setLayoutManager(mLayoutManagerGrid);
        listView.clearOnScrollListeners();
        adapter = null;
    }

    void switchToList() {
        IS_LIST = true;

        if (utilsProvider.getAppTheme().equals(AppTheme.LIGHT)) {

            listView.setBackgroundDrawable(null);
        }

        if (mLayoutManager == null)
            mLayoutManager = new LinearLayoutManager(getActivity());
        listView.setLayoutManager(mLayoutManager);
        listView.clearOnScrollListeners();
        adapter = null;
    }

    public void switchView() {
        boolean isPathLayoutGrid = dataUtils.getListOrGridForPath(CURRENT_PATH, DataUtils.LIST) == DataUtils.GRID;
        reloadListElements(false, results, isPathLayoutGrid);
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        int index;
        View vi;
        if (listView != null) {
            if (IS_LIST) {
                index = (mLayoutManager).findFirstVisibleItemPosition();
                vi = listView.getChildAt(0);
            } else {
                index = (mLayoutManagerGrid).findFirstVisibleItemPosition();
                vi = listView.getChildAt(0);
            }

            int top = (vi == null) ? 0 : vi.getTop();

            outState.putInt("index", index);
            outState.putInt("top", top);
            outState.putParcelableArrayList("list", LIST_ELEMENTS);
            outState.putString("CURRENT_PATH", CURRENT_PATH);
            outState.putBoolean("selection", selection);
            outState.putInt("openMode", openMode.ordinal());
            outState.putInt("folder_count", folder_count);
            outState.putInt("file_count", file_count);

            if (selection) {
                outState.putIntegerArrayList("position", adapter.getCheckedItemsIndex());
            }

            outState.putBoolean("results", results);

            if (openMode == OpenMode.SMB) {
                outState.putString("SmbPath", smbPath);
            }
        }
    }

    void onSavedInstanceState(final Bundle savedInstanceState) {
        Bundle b = new Bundle();
        String cur = savedInstanceState.getString("CURRENT_PATH");

        if (cur != null) {
            b.putInt("index", savedInstanceState.getInt("index"));
            b.putInt("top", savedInstanceState.getInt("top"));
            scrolls.put(cur, b);

            openMode = OpenMode.getOpenMode(savedInstanceState.getInt("openMode", 0));
            if (openMode == OpenMode.SMB)
                smbPath = savedInstanceState.getString("SmbPath");
            LIST_ELEMENTS = savedInstanceState.getParcelableArrayList("list");
            CURRENT_PATH = cur;
            folder_count = savedInstanceState.getInt("folder_count", 0);
            file_count = savedInstanceState.getInt("file_count", 0);
            results = savedInstanceState.getBoolean("results");
            getMainActivity().getAppbar().getBottomBar().updatePath(CURRENT_PATH, results,
                    MainActivityHelper.SEARCH_TEXT, openMode, folder_count, file_count, this);
            reloadListElements(true, results, !IS_LIST);
            if (savedInstanceState.getBoolean("selection")) {
                for (Integer index : savedInstanceState.getIntegerArrayList("position")) {
                    adapter.toggleChecked(index, null);
                }
            }
        }
    }

    public ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {
        private void hideOption(int id, Menu menu) {
            MenuItem item = menu.findItem(id);
            item.setVisible(false);
        }

        private void showOption(int id, Menu menu) {
            MenuItem item = menu.findItem(id);
            item.setVisible(true);
        }

        void initMenu(Menu menu) {
            /*
            menu.findItem(R.id.cpy).setIcon(icons.getCopyDrawable());
            menu.findItem(R.id.cut).setIcon(icons.getCutDrawable());
            menu.findItem(R.id.delete).setIcon(icons.getDeleteDrawable());
            menu.findItem(R.id.all).setIcon(icons.getAllDrawable());
            */
        }

        // called when the action mode is created; startActionMode() was called
        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
            // Inflate a menu resource providing context menu items
            MenuInflater inflater = mode.getMenuInflater();
            actionModeView = getActivity().getLayoutInflater().inflate(R.layout.actionmode, null);
            mode.setCustomView(actionModeView);

            getMainActivity().setPagingEnabled(false);
            getMainActivity().floatingActionButton.getMenuButton().hide();

            // translates the drawable content down
            // if (getMainActivity().isDrawerLocked) getMainActivity().translateDrawerList(true);

            // assumes that you have "contexual.xml" menu resources
            inflater.inflate(R.menu.contextual, menu);
            initMenu(menu);
            hideOption(R.id.addshortcut, menu);
            hideOption(R.id.share, menu);
            hideOption(R.id.openwith, menu);
            if (getMainActivity().mReturnIntent)
                showOption(R.id.openmulti, menu);
            //hideOption(R.id.setringtone,menu);
            mode.setTitle(getResources().getString(R.string.select));

            getMainActivity().updateViews(new ColorDrawable(res.getColor(R.color.holo_dark_action_mode)));

            // do not allow drawer to open when item gets selected
            if (!getMainActivity().getDrawer().isLocked()) {
                getMainActivity().getDrawer().lock(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
            }
            return true;
        }

        /**
         * the following method is called each time
         * the action mode is shown. Always called after
         * onCreateActionMode, but
         * may be called multiple times if the mode is invalidated.
         */
        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
            ArrayList<LayoutElementParcelable> positions = adapter.getCheckedItems();
            TextView textView1 = actionModeView.findViewById(R.id.item_count);
            textView1.setText(String.valueOf(positions.size()));
            textView1.setOnClickListener(null);
            mode.setTitle(positions.size() + "");
            hideOption(R.id.openmulti, menu);
            menu.findItem(R.id.all).setTitle(
                    positions.size() == folder_count + file_count ? R.string.deselect_all : R.string.selectall);

            if (openMode != OpenMode.FILE) {
                hideOption(R.id.addshortcut, menu);
                hideOption(R.id.compress, menu);
                return true;
            }

            if (getMainActivity().mReturnIntent)
                if (Build.VERSION.SDK_INT >= 16)
                    showOption(R.id.openmulti, menu);
            //tv.setText(positions.size());
            if (!results) {
                hideOption(R.id.openparent, menu);
                if (positions.size() == 1) {
                    showOption(R.id.addshortcut, menu);
                    showOption(R.id.openwith, menu);
                    showOption(R.id.share, menu);

                    File x = new File(adapter.getCheckedItems().get(0).desc);

                    if (x.isDirectory()) {
                        hideOption(R.id.openwith, menu);
                        hideOption(R.id.share, menu);
                        hideOption(R.id.openmulti, menu);
                    }

                    if (getMainActivity().mReturnIntent)
                        if (Build.VERSION.SDK_INT >= 16)
                            showOption(R.id.openmulti, menu);

                } else {
                    try {
                        showOption(R.id.share, menu);
                        if (getMainActivity().mReturnIntent)
                            if (Build.VERSION.SDK_INT >= 16)
                                showOption(R.id.openmulti, menu);
                        for (LayoutElementParcelable e : adapter.getCheckedItems()) {
                            File x = new File(e.desc);
                            if (x.isDirectory()) {
                                hideOption(R.id.share, menu);
                                hideOption(R.id.openmulti, menu);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    hideOption(R.id.openwith, menu);
                    hideOption(R.id.addshortcut, menu);
                }
            } else {
                if (positions.size() == 1) {
                    showOption(R.id.addshortcut, menu);
                    showOption(R.id.openparent, menu);
                    showOption(R.id.openwith, menu);
                    showOption(R.id.share, menu);

                    File x = new File(adapter.getCheckedItems().get(0).desc);

                    if (x.isDirectory()) {
                        hideOption(R.id.openwith, menu);
                        hideOption(R.id.share, menu);
                        hideOption(R.id.openmulti, menu);
                    }
                    if (getMainActivity().mReturnIntent)
                        if (Build.VERSION.SDK_INT >= 16)
                            showOption(R.id.openmulti, menu);

                } else {
                    hideOption(R.id.openparent, menu);
                    hideOption(R.id.addshortcut, menu);

                    if (getMainActivity().mReturnIntent)
                        if (Build.VERSION.SDK_INT >= 16)
                            showOption(R.id.openmulti, menu);
                    try {
                        for (LayoutElementParcelable e : adapter.getCheckedItems()) {
                            File x = new File(e.desc);
                            if (x.isDirectory()) {
                                hideOption(R.id.share, menu);
                                hideOption(R.id.openmulti, menu);
                            }
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }

                    hideOption(R.id.openwith, menu);

                }
            }

            return true; // Return false if nothing is done
        }

        // called when the user selects a contextual menu item
        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
            computeScroll();
            ArrayList<LayoutElementParcelable> checkedItems = adapter.getCheckedItems();
            switch (item.getItemId()) {
            case R.id.openmulti:

                try {

                    Intent intent_result = new Intent(Intent.ACTION_SEND_MULTIPLE);
                    ArrayList<Uri> resulturis = new ArrayList<>();

                    for (LayoutElementParcelable element : checkedItems) {
                        HybridFileParcelable baseFile = element.generateBaseFile();
                        Uri resultUri = Utils.getUriForBaseFile(getActivity(), baseFile);

                        if (resultUri != null) {
                            resulturis.add(resultUri);
                        }
                    }

                    intent_result.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    getActivity().setResult(FragmentActivity.RESULT_OK, intent_result);
                    intent_result.putParcelableArrayListExtra(Intent.EXTRA_STREAM, resulturis);
                    getActivity().finish();
                    //mode.finish();
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return true;
            case R.id.about:
                LayoutElementParcelable x = checkedItems.get(0);
                GeneralDialogCreation.showPropertiesDialogWithPermissions((x).generateBaseFile(), x.permissions,
                        (ThemedActivity) getActivity(), getMainActivity().isRootExplorer(),
                        utilsProvider.getAppTheme());
                mode.finish();
                return true;
            case R.id.delete:
                GeneralDialogCreation.deleteFilesDialog(getContext(), LIST_ELEMENTS, getMainActivity(),
                        checkedItems, utilsProvider.getAppTheme());
                return true;
            case R.id.share:
                ArrayList<File> arrayList = new ArrayList<>();
                for (LayoutElementParcelable e : checkedItems) {
                    arrayList.add(new File(e.desc));
                }
                if (arrayList.size() > 100)
                    Toast.makeText(getActivity(), getResources().getString(R.string.share_limit),
                            Toast.LENGTH_SHORT).show();
                else {

                    switch (LIST_ELEMENTS.get(0).getMode()) {
                    case DROPBOX:
                    case BOX:
                    case GDRIVE:
                    case ONEDRIVE:
                        FileUtils.shareCloudFile(LIST_ELEMENTS.get(0).desc, LIST_ELEMENTS.get(0).getMode(),
                                getContext());
                        break;
                    default:
                        FileUtils.shareFiles(arrayList, getActivity(), utilsProvider.getAppTheme(), accentColor);
                        break;
                    }
                }
                return true;
            case R.id.openparent:
                loadlist(new File(checkedItems.get(0).desc).getParent(), false, OpenMode.FILE);
                return true;
            case R.id.all:
                if (adapter.areAllChecked(CURRENT_PATH)) {
                    adapter.toggleChecked(false, CURRENT_PATH);
                    item.setTitle(R.string.selectall);
                } else {
                    adapter.toggleChecked(true, CURRENT_PATH);
                    item.setTitle(R.string.deselect_all);
                }
                mode.invalidate();

                return true;
            case R.id.rename:

                final ActionMode m = mode;
                final HybridFileParcelable f;
                f = checkedItems.get(0).generateBaseFile();
                rename(f);
                mode.finish();
                return true;
            case R.id.hide:
                for (int i1 = 0; i1 < checkedItems.size(); i1++) {
                    hide(checkedItems.get(i1).desc);
                }
                updateList();
                mode.finish();
                return true;
            case R.id.ex:
                getMainActivity().mainActivityHelper.extractFile(new File(checkedItems.get(0).desc));
                mode.finish();
                return true;
            case R.id.cpy:
            case R.id.cut: {
                HybridFileParcelable[] copies = new HybridFileParcelable[checkedItems.size()];
                for (int i = 0; i < checkedItems.size(); i++) {
                    copies[i] = checkedItems.get(i).generateBaseFile();
                }
                int op = item.getItemId() == R.id.cpy ? PasteHelper.OPERATION_COPY : PasteHelper.OPERATION_CUT;

                PasteHelper pasteHelper = new PasteHelper(op, copies);
                getMainActivity().setPaste(pasteHelper);

                mode.finish();
                return true;
            }
            case R.id.compress:
                ArrayList<HybridFileParcelable> copies1 = new ArrayList<>();
                for (int i4 = 0; i4 < checkedItems.size(); i4++) {
                    copies1.add(checkedItems.get(i4).generateBaseFile());
                }
                GeneralDialogCreation.showCompressDialog((MainActivity) getActivity(), copies1, CURRENT_PATH);
                mode.finish();
                return true;
            case R.id.openwith:
                boolean useNewStack = sharedPref.getBoolean(PREFERENCE_TEXTEDITOR_NEWSTACK, false);
                FileUtils.openunknown(new File(checkedItems.get(0).desc), getActivity(), true, useNewStack);
                return true;
            case R.id.addshortcut:
                addShortcut(checkedItems.get(0));
                mode.finish();
                return true;
            default:
                return false;
            }
        }

        // called when the user exits the action mode
        public void onDestroyActionMode(ActionMode mode) {
            mActionMode = null;
            selection = false;

            // translates the drawer content up
            //if (getMainActivity().isDrawerLocked) getMainActivity().translateDrawerList(false);

            getMainActivity().floatingActionButton.getMenuButton().show();
            if (!results)
                adapter.toggleChecked(false, CURRENT_PATH);
            else
                adapter.toggleChecked(false);
            getMainActivity().setPagingEnabled(true);

            getMainActivity()
                    .updateViews(new ColorDrawable(MainActivity.currentTab == 1 ? primaryTwoColor : primaryColor));

            if (getMainActivity().getDrawer().isLocked()) {
                getMainActivity().getDrawer().unlock();
            }
        }
    };

    private BroadcastReceiver receiver2 = new BroadcastReceiver() {

        @Override
        public void onReceive(Context context, Intent intent) {
            // load the list on a load broadcast
            switch (openMode) {
            case ROOT:
            case FILE:
                // local file system don't need an explicit load, we've set an observer to
                // take actions on creation/moving/deletion/modification of file on current path

                // run media scanner
                String[] path = new String[1];
                String arg = intent.getStringExtra(MainActivity.KEY_INTENT_LOAD_LIST_FILE);

                // run media scanner for only one context
                if (arg != null && getMainActivity().getCurrentMainFragment() == MainFragment.this) {

                    if (Build.VERSION.SDK_INT >= 19) {

                        path[0] = arg;

                        MediaScannerConnection.MediaScannerConnectionClient mediaScannerConnectionClient = new MediaScannerConnection.MediaScannerConnectionClient() {
                            @Override
                            public void onMediaScannerConnected() {

                            }

                            @Override
                            public void onScanCompleted(String path, Uri uri) {

                                Log.d("SCAN completed", path);
                            }
                        };

                        if (mediaScannerConnection != null) {
                            mediaScannerConnection.disconnect();
                        }
                        mediaScannerConnection = new MediaScannerConnection(context, mediaScannerConnectionClient);
                        //FileUtils.scanFile(context, mediaScannerConnection, path);
                    } else {
                        FileUtils.scanFile(new File(arg), context);
                    }
                }
                //break;
            default:
                updateList();
                break;
            }
        }
    };

    private BroadcastReceiver decryptReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            if (isEncryptOpen && encryptBaseFile != null) {
                FileUtils.openFile(new File(encryptBaseFile.getPath()), getMainActivity(), sharedPref);
                isEncryptOpen = false;
            }
        }
    };

    public void home() {
        ma.loadlist((ma.home), false, OpenMode.FILE);
    }

    /**
     * method called when list item is clicked in the adapter
     *
     * @param isBackButton is it the back button aka '..'
     * @param position the position
     * @param e the list item
     * @param imageView the check {@link RoundedImageView} that is to be animated
     */
    public void onListItemClicked(boolean isBackButton, int position, LayoutElementParcelable e,
            ImageView imageView) {
        if (results) {
            // check to initialize search results
            // if search task is been running, cancel it
            FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
            SearchWorkerFragment fragment = (SearchWorkerFragment) fragmentManager
                    .findFragmentByTag(MainActivity.TAG_ASYNC_HELPER);
            if (fragment != null) {
                if (fragment.mSearchAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
                    fragment.mSearchAsyncTask.cancel(true);
                }
                getActivity().getSupportFragmentManager().beginTransaction().remove(fragment).commit();
            }

            mRetainSearchTask = true;
            results = false;
        } else {
            mRetainSearchTask = false;
            MainActivityHelper.SEARCH_TEXT = null;
        }

        if (selection) {
            if (isBackButton) {
                selection = false;
                if (mActionMode != null)
                    mActionMode.finish();
                mActionMode = null;
            } else {
                // the first {goback} item if back navigation is enabled
                adapter.toggleChecked(position, imageView);
            }
        } else {
            if (isBackButton) {
                goBackItemClick();
            } else {
                // hiding search view if visible
                if (getMainActivity().getAppbar().getSearchView().isEnabled()) {
                    getMainActivity().getAppbar().getSearchView().hideSearchView();
                }

                String path = !e.hasSymlink() ? e.desc : e.symlink;

                if (e.isDirectory) {
                    computeScroll();
                    loadlist(path, false, openMode);
                } else if (e.desc.endsWith(CryptUtil.CRYPT_EXTENSION)) {
                    // decrypt the file
                    isEncryptOpen = true;

                    encryptBaseFile = new HybridFileParcelable(getActivity().getExternalCacheDir().getPath() + "/"
                            + e.generateBaseFile().getName().replace(CryptUtil.CRYPT_EXTENSION, ""));
                    encryptBaseFiles.add(encryptBaseFile);

                    EncryptDecryptUtils.decryptFile(getContext(), getMainActivity(), ma, openMode,
                            e.generateBaseFile(), getActivity().getExternalCacheDir().getPath(), utilsProvider,
                            true);
                } else {
                    if (getMainActivity().mReturnIntent) {
                        // are we here to return an intent to another app
                        returnIntentResults(e.generateBaseFile());
                    } else {
                        switch (e.getMode()) {
                        case SMB:
                            launchSMB(e.generateBaseFile(), getMainActivity());
                            break;
                        case SFTP:
                            Toast.makeText(getContext(), getResources().getString(R.string.please_wait),
                                    Toast.LENGTH_LONG).show();
                            SshClientUtils.launchSftp(e.generateBaseFile(), getMainActivity());
                            break;
                        case OTG:
                            FileUtils.openFile(OTGUtil.getDocumentFile(e.desc, getContext(), false),
                                    (MainActivity) getActivity(), sharedPref);
                            break;
                        case DROPBOX:
                        case BOX:
                        case GDRIVE:
                        case ONEDRIVE:
                            Toast.makeText(getContext(), getResources().getString(R.string.please_wait),
                                    Toast.LENGTH_LONG).show();
                            CloudUtil.launchCloud(e.generateBaseFile(), openMode, getMainActivity());
                            break;
                        default:
                            FileUtils.openFile(new File(e.desc), (MainActivity) getActivity(), sharedPref);
                            break;
                        }

                        dataUtils.addHistoryFile(e.desc);
                    }
                }
            }
        }
    }

    /**
     * Queries database to find entry for the specific path
     *
     * @param path the path to match with
     * @return the entry
     */
    private static EncryptedEntry findEncryptedEntry(Context context, String path) throws Exception {

        CryptHandler handler = new CryptHandler(context);

        EncryptedEntry matchedEntry = null;
        // find closest path which matches with database entry
        for (EncryptedEntry encryptedEntry : handler.getAllEntries()) {
            if (path.contains(encryptedEntry.getPath())) {

                if (matchedEntry == null || matchedEntry.getPath().length() < encryptedEntry.getPath().length()) {
                    matchedEntry = encryptedEntry;
                }
            }
        }
        return matchedEntry;
    }

    public void updateTabWithDb(Tab tab) {
        CURRENT_PATH = tab.path;
        home = tab.home;
        loadlist(CURRENT_PATH, false, OpenMode.UNKNOWN);
    }

    /**
     * Returns the intent with uri corresponding to specific {@link HybridFileParcelable} back to external app
     */
    public void returnIntentResults(HybridFileParcelable baseFile) {

        getMainActivity().mReturnIntent = false;

        Intent intent = new Intent();
        if (getMainActivity().mRingtonePickerIntent) {

            Uri mediaStoreUri = MediaStoreHack.getUriFromFile(baseFile.getPath(), getActivity());
            Log.d(getClass().getSimpleName(), mediaStoreUri.toString() + "\t"
                    + MimeTypes.getMimeType(baseFile.getPath(), baseFile.isDirectory()));
            intent.setDataAndType(mediaStoreUri, MimeTypes.getMimeType(baseFile.getPath(), baseFile.isDirectory()));
            intent.putExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI, mediaStoreUri);
            getActivity().setResult(FragmentActivity.RESULT_OK, intent);
            getActivity().finish();
        } else {

            Log.d("pickup", "file");

            Intent intentresult = new Intent();

            Uri resultUri = Utils.getUriForBaseFile(getActivity(), baseFile);
            intentresult.setAction(Intent.ACTION_SEND);
            intentresult.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

            if (resultUri != null)
                intentresult.setDataAndType(resultUri, MimeTypes.getExtension(baseFile.getPath()));

            getActivity().setResult(FragmentActivity.RESULT_OK, intentresult);
            getActivity().finish();
            //mode.finish();
        }
    }

    LoadFilesListTask loadFilesListTask;

    /**
     * This loads a path into the MainFragment.
     * @param path the path to be loaded
     * @param back if we're coming back from any directory and want the scroll to be restored
     * @param openMode the mode in which the directory should be opened
     */
    public void loadlist(final String path, final boolean back, final OpenMode openMode) {
        if (mActionMode != null)
            mActionMode.finish();

        mSwipeRefreshLayout.setRefreshing(true);

        if (loadFilesListTask != null && loadFilesListTask.getStatus() == AsyncTask.Status.RUNNING) {
            loadFilesListTask.cancel(true);
        }

        loadFilesListTask = new LoadFilesListTask(ma.getActivity(), path, ma, openMode,
                getBoolean(PREFERENCE_SHOW_THUMB), getBoolean(PREFERENCE_SHOW_HIDDENFILES), (data) -> {
                    if (data != null && data.second != null) {
                        boolean isPathLayoutGrid = dataUtils.getListOrGridForPath(path,
                                DataUtils.LIST) == DataUtils.GRID;
                        setListElements(data.second, back, path, data.first, false, isPathLayoutGrid);
                        mSwipeRefreshLayout.setRefreshing(false);
                    }
                });
        loadFilesListTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);

    }

    void initNoFileLayout() {
        nofilesview = rootView.findViewById(R.id.nofilelayout);
        nofilesview.setColorSchemeColors(accentColor);
        nofilesview.setOnRefreshListener(() -> {
            loadlist((CURRENT_PATH), false, openMode);
            nofilesview.setRefreshing(false);
        });
        if (utilsProvider.getAppTheme().equals(AppTheme.LIGHT)) {
            ((ImageView) nofilesview.findViewById(R.id.image)).setColorFilter(Color.parseColor("#666666"));
        } else if (utilsProvider.getAppTheme().equals(AppTheme.BLACK)) {
            nofilesview.setBackgroundColor(Utils.getColor(getContext(), android.R.color.black));
            ((TextView) nofilesview.findViewById(R.id.nofiletext)).setTextColor(Color.WHITE);
        } else {
            nofilesview.setBackgroundColor(Utils.getColor(getContext(), R.color.holo_dark_background));
            ((TextView) nofilesview.findViewById(R.id.nofiletext)).setTextColor(Color.WHITE);
        }
    }

    /**
     * Loading adapter after getting a list of elements
     *
     * @param bitmap   the list of objects for the adapter
     * @param back     if we're coming back from any directory and want the scroll to be restored
     * @param path     the path for the adapter
     * @param openMode the type of file being created
     * @param results  is the list of elements a result from search
     * @param grid     whether to set grid view or list view
     */
    public void setListElements(ArrayList<LayoutElementParcelable> bitmap, boolean back, String path,
            final OpenMode openMode, boolean results, boolean grid) {
        if (bitmap != null) {
            LIST_ELEMENTS = bitmap;
            CURRENT_PATH = path;
            this.openMode = openMode;
            reloadListElements(back, results, grid);
        } else {
            // list loading cancelled
            // TODO: Add support for cancelling list loading
            loadlist(home, true, OpenMode.FILE);
        }
    }

    public void reloadListElements(boolean back, boolean results, boolean grid) {
        if (isAdded()) {
            boolean isOtg = CURRENT_PATH.equals(OTGUtil.PREFIX_OTG + "/"),
                    isOnTheCloud = CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_GOOGLE_DRIVE + "/")
                            || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_ONE_DRIVE + "/")
                            || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_BOX + "/")
                            || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_DROPBOX + "/");

            if (getBoolean(PREFERENCE_SHOW_GOBACK_BUTTON) && !CURRENT_PATH.equals("/")
                    && (openMode == OpenMode.FILE || openMode == OpenMode.ROOT) && !isOtg && !isOnTheCloud
                    && (LIST_ELEMENTS.size() == 0
                            || !LIST_ELEMENTS.get(0).size.equals(getString(R.string.goback)))) {
                LIST_ELEMENTS.add(0, getBackElement());
            }

            if (LIST_ELEMENTS.size() == 0 && !results) {
                nofilesview.setVisibility(View.VISIBLE);
                listView.setVisibility(View.GONE);
                mSwipeRefreshLayout.setEnabled(false);
            } else {
                mSwipeRefreshLayout.setEnabled(true);
                nofilesview.setVisibility(View.GONE);
                listView.setVisibility(View.VISIBLE);
            }

            if (grid && IS_LIST)
                switchToGrid();
            else if (!grid && !IS_LIST)
                switchToList();

            if (adapter == null) {
                adapter = new RecyclerAdapter(getMainActivity(), ma, utilsProvider, sharedPref, listView,
                        LIST_ELEMENTS, ma.getActivity());
            } else {
                adapter.setItems(listView, new ArrayList<>(LIST_ELEMENTS));
            }

            stopAnims = true;

            if (openMode != OpenMode.CUSTOM) {
                dataUtils.addHistoryFile(CURRENT_PATH);
            }

            listView.setAdapter(adapter);

            if (!addheader) {
                listView.removeItemDecoration(dividerItemDecoration);
                addheader = true;
            }

            if (addheader && IS_LIST) {
                dividerItemDecoration = new DividerItemDecoration(getActivity(), true,
                        getBoolean(PREFERENCE_SHOW_DIVIDERS));
                listView.addItemDecoration(dividerItemDecoration);
                addheader = false;
            }

            if (!results) {
                this.results = false;
            }

            if (back && scrolls.containsKey(CURRENT_PATH)) {
                Bundle b = scrolls.get(CURRENT_PATH);
                int index = b.getInt("index"), top = b.getInt("top");
                if (IS_LIST) {
                    mLayoutManager.scrollToPositionWithOffset(index, top);
                } else {
                    mLayoutManagerGrid.scrollToPositionWithOffset(index, top);
                }
            }

            getMainActivity().updatePaths(no);
            listView.stopScroll();
            fastScroller.setRecyclerView(listView, IS_LIST ? 1 : columns);
            mToolbarContainer.addOnOffsetChangedListener((appBarLayout, verticalOffset) -> {
                fastScroller.updateHandlePosition(verticalOffset, 112);
            });
            fastScroller.registerOnTouchListener(() -> {
                if (stopAnims && adapter != null) {
                    stopAnimation();
                    stopAnims = false;
                }
            });

            startFileObserver();
        } else {
            // list loading cancelled
            // TODO: Add support for cancelling list loading
            loadlist(home, true, OpenMode.FILE);
        }
    }

    private LayoutElementParcelable getBackElement() {
        if (back == null) {
            back = new LayoutElementParcelable("..", "", "", getString(R.string.goback), 0, false, "", true,
                    getBoolean(PREFERENCE_SHOW_THUMB), OpenMode.UNKNOWN);
        }

        return back;
    }

    private void startFileObserver() {
        switch (openMode) {
        case ROOT:
        case FILE:
            if (customFileObserver != null && !customFileObserver.wasStopped()
                    && customFileObserver.getPath().equals(getCurrentPath())) {
                return;
            }

            File file = new File(CURRENT_PATH);

            if (file.isDirectory() && file.canRead()) {
                if (customFileObserver != null) {
                    // already a watcher instantiated, first it should be stopped
                    customFileObserver.stopWatching();
                }

                customFileObserver = new CustomFileObserver(CURRENT_PATH,
                        new FileHandler(this, listView, getBoolean(PREFERENCE_SHOW_THUMB)));
                customFileObserver.startWatching();
            }
            break;
        default:
            break;
        }
    }

    /**
     * Show dialog to rename a file
     *
     * @param f the file to rename
     */
    public void rename(final HybridFileParcelable f) {
        MaterialDialog renameDialog = GeneralDialogCreation.showNameDialog(getMainActivity(), "", f.getName(),
                getResources().getString(R.string.rename), getResources().getString(R.string.save), null,
                getResources().getString(R.string.cancel), (dialog, which) -> {
                    EditText textfield = dialog.getCustomView().findViewById(R.id.singleedittext_input);
                    String name1 = textfield.getText().toString();

                    if (f.isSmb()) {
                        if (f.isDirectory() && !name1.endsWith("/"))
                            name1 = name1 + "/";
                    }
                    getMainActivity().mainActivityHelper.rename(openMode, f.getPath(), CURRENT_PATH + "/" + name1,
                            getActivity(), getMainActivity().isRootExplorer());
                }, (text) -> {
                    boolean isValidFilename = FileUtil.isValidFilename(text);

                    if (!isValidFilename) {
                        return new WarnableTextInputValidator.ReturnState(
                                WarnableTextInputValidator.ReturnState.STATE_ERROR, R.string.invalid_name);
                    } else if (text.length() < 1) {
                        return new WarnableTextInputValidator.ReturnState(
                                WarnableTextInputValidator.ReturnState.STATE_ERROR, R.string.field_empty);
                    }

                    return new WarnableTextInputValidator.ReturnState();
                });

        // place cursor at the starting of edit text by posting a runnable to edit text
        // this is done because in case android has not populated the edit text layouts yet, it'll
        // reset calls to selection if not posted in message queue
        EditText textfield = renameDialog.getCustomView().findViewById(R.id.singleedittext_input);
        textfield.post(() -> {
            if (!f.isDirectory()) {
                textfield.setSelection(f.getNameString(getContext()).length());
            }
        });
    }

    public void computeScroll() {
        View vi = listView.getChildAt(0);
        int top = (vi == null) ? 0 : vi.getTop();
        int index;
        if (IS_LIST)
            index = mLayoutManager.findFirstVisibleItemPosition();
        else
            index = mLayoutManagerGrid.findFirstVisibleItemPosition();
        Bundle b = new Bundle();
        b.putInt("index", index);
        b.putInt("top", top);
        scrolls.put(CURRENT_PATH, b);
    }

    public void goBack() {
        if (openMode == OpenMode.CUSTOM) {
            loadlist(home, false, OpenMode.FILE);
            return;
        }

        HybridFile currentFile = new HybridFile(openMode, CURRENT_PATH);
        if (!results) {
            if (!mRetainSearchTask) {
                // normal case
                if (selection) {
                    adapter.toggleChecked(false);
                } else {

                    if (openMode == OpenMode.SMB) {
                        try {
                            if (!smbPath.equals(CURRENT_PATH)) {
                                String path = (new SmbFile(CURRENT_PATH).getParent());
                                loadlist((path), true, openMode);
                            } else
                                loadlist(home, false, OpenMode.FILE);
                        } catch (MalformedURLException e) {
                            e.printStackTrace();
                        }

                    } else if (openMode == OpenMode.SFTP) {
                        if (!CURRENT_PATH.substring("ssh://".length()).contains("/"))
                            loadlist(home, false, OpenMode.FILE);
                        else
                            loadlist(currentFile.getParent(getContext()), true, openMode);
                    } else if (CURRENT_PATH.equals("/") || CURRENT_PATH.equals(home)
                            || CURRENT_PATH.equals(OTGUtil.PREFIX_OTG + "/")
                            || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_BOX + "/")
                            || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_DROPBOX + "/")
                            || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_GOOGLE_DRIVE + "/")
                            || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_ONE_DRIVE + "/"))
                        getMainActivity().exit();
                    else if (FileUtils.canGoBack(getContext(), currentFile)) {
                        loadlist(currentFile.getParent(getContext()), true, openMode);
                    } else
                        getMainActivity().exit();
                }
            } else {
                // case when we had pressed on an item from search results and wanna go back
                // leads to resuming the search task

                if (MainActivityHelper.SEARCH_TEXT != null) {

                    // starting the search query again :O
                    getMainActivity().mainFragment = (MainFragment) getMainActivity().getTabFragment()
                            .getCurrentTabFragment();
                    FragmentManager fm = getMainActivity().getSupportFragmentManager();

                    // getting parent path to resume search from there
                    String parentPath = new HybridFile(openMode, CURRENT_PATH).getParent(getActivity());
                    // don't fuckin' remove this line, we need to change
                    // the path back to parent on back press
                    CURRENT_PATH = parentPath;

                    MainActivityHelper.addSearchFragment(fm, new SearchWorkerFragment(), parentPath,
                            MainActivityHelper.SEARCH_TEXT, openMode, getMainActivity().isRootExplorer(),
                            sharedPref.getBoolean(SearchWorkerFragment.KEY_REGEX, false),
                            sharedPref.getBoolean(SearchWorkerFragment.KEY_REGEX_MATCHES, false));
                } else
                    loadlist(CURRENT_PATH, true, OpenMode.UNKNOWN);

                mRetainSearchTask = false;
            }
        } else {
            // to go back after search list have been popped
            FragmentManager fm = getActivity().getSupportFragmentManager();
            SearchWorkerFragment fragment = (SearchWorkerFragment) fm
                    .findFragmentByTag(MainActivity.TAG_ASYNC_HELPER);
            if (fragment != null) {
                if (fragment.mSearchAsyncTask.getStatus() == AsyncTask.Status.RUNNING) {
                    fragment.mSearchAsyncTask.cancel(true);
                }
            }
            loadlist(new File(CURRENT_PATH).getPath(), true, OpenMode.UNKNOWN);
            results = false;
        }
    }

    public void reauthenticateSmb() {
        if (smbPath != null) {
            try {
                getMainActivity().runOnUiThread(() -> {
                    int i;
                    if ((i = dataUtils.containsServer(smbPath)) != -1) {
                        getMainActivity().showSMBDialog(dataUtils.getServers().get(i)[0], smbPath, true);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    public void goBackItemClick() {
        if (openMode == OpenMode.CUSTOM) {
            loadlist(home, false, OpenMode.FILE);
            return;
        }
        HybridFile currentFile = new HybridFile(openMode, CURRENT_PATH);
        if (!results) {
            if (selection) {
                adapter.toggleChecked(false);
            } else {
                if (openMode == OpenMode.SMB) {
                    try {
                        if (!CURRENT_PATH.equals(smbPath)) {
                            String path = (new SmbFile(CURRENT_PATH).getParent());
                            loadlist((path), true, OpenMode.SMB);
                        } else
                            loadlist(home, false, OpenMode.FILE);
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
                } else if (CURRENT_PATH.equals("/") || CURRENT_PATH.equals(OTGUtil.PREFIX_OTG)
                        || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_BOX + "/")
                        || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_DROPBOX + "/")
                        || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_GOOGLE_DRIVE + "/")
                        || CURRENT_PATH.equals(CloudHandler.CLOUD_PREFIX_ONE_DRIVE + "/")) {
                    getMainActivity().exit();
                } else if (FileUtils.canGoBack(getContext(), currentFile)) {
                    loadlist(currentFile.getParent(getContext()), true, openMode);
                } else
                    getMainActivity().exit();
            }
        } else {
            loadlist(currentFile.getPath(), true, openMode);
        }
    }

    public void updateList() {
        computeScroll();
        loadlist((CURRENT_PATH), true, openMode);
    }

    /**
     * Assigns sort modes
     * A value from 0 to 3 defines sort mode as name/last modified/size/type in ascending order
     * Values from 4 to 7 defines sort mode as name/last modified/size/type in descending order
     * <p>
     * Final value of {@link #sortby} varies from 0 to 3
     */
    public void getSortModes() {
        int t = SortHandler.getSortType(getContext(), getCurrentPath());
        if (t <= 3) {
            sortby = t;
            asc = 1;
        } else {
            asc = -1;
            sortby = t - 4;
        }

        dsort = Integer.parseInt(sharedPref.getString(PREFERENCE_DIRECTORY_SORT_MODE, "0"));
    }

    @Override
    public void onResume() {
        super.onResume();
        (getActivity()).registerReceiver(receiver2, new IntentFilter(MainActivity.KEY_INTENT_LOAD_LIST));

        getMainActivity().getDrawer().selectCorrectDrawerItemForPath(getPath());

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {

            (getActivity()).registerReceiver(decryptReceiver,
                    new IntentFilter(EncryptDecryptUtils.DECRYPT_BROADCAST));
        }
        startFileObserver();
    }

    @Override
    public void onPause() {
        super.onPause();
        (getActivity()).unregisterReceiver(receiver2);
        if (customFileObserver != null) {
            customFileObserver.stopWatching();
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
            (getActivity()).unregisterReceiver(decryptReceiver);
        }
    }

    @Override
    public void onStop() {
        super.onStop();

        if (mediaScannerConnection != null)
            mediaScannerConnection.disconnect();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {

            if (!isEncryptOpen && encryptBaseFiles.size() != 0) {
                // we've opened the file and are ready to delete it
                new DeleteTask(getMainActivity().getContentResolver(), getActivity()).execute(encryptBaseFiles);
            }
        }
    }

    public ArrayList<LayoutElementParcelable> addToSmb(SmbFile[] mFile, String path, boolean showHiddenFiles)
            throws SmbException {
        ArrayList<LayoutElementParcelable> smbFileList = new ArrayList<>();
        if (searchHelper.size() > 500)
            searchHelper.clear();
        for (SmbFile aMFile : mFile) {
            if ((dataUtils.isFileHidden(aMFile.getPath()) || aMFile.isHidden()) && !showHiddenFiles) {
                continue;
            }
            String name = aMFile.getName();
            name = (aMFile.isDirectory() && name.endsWith("/")) ? name.substring(0, name.length() - 1) : name;
            if (path.equals(smbPath)) {
                if (name.endsWith("$"))
                    continue;
            }
            if (aMFile.isDirectory()) {
                folder_count++;

                LayoutElementParcelable layoutElement = new LayoutElementParcelable(name, aMFile.getPath(), "", "",
                        "", 0, false, aMFile.lastModified() + "", true, getBoolean(PREFERENCE_SHOW_THUMB),
                        OpenMode.SMB);

                searchHelper.add(layoutElement.generateBaseFile());
                smbFileList.add(layoutElement);

            } else {
                file_count++;
                LayoutElementParcelable layoutElement = new LayoutElementParcelable(name, aMFile.getPath(), "", "",
                        Formatter.formatFileSize(getContext(), aMFile.length()), aMFile.length(), false,
                        aMFile.lastModified() + "", false, getBoolean(PREFERENCE_SHOW_THUMB), OpenMode.SMB);
                layoutElement.setMode(OpenMode.SMB);
                searchHelper.add(layoutElement.generateBaseFile());
                smbFileList.add(layoutElement);
            }
        }
        return smbFileList;
    }

    // method to add search result entry to the LIST_ELEMENT arrayList
    private LayoutElementParcelable addTo(HybridFileParcelable mFile) {
        File f = new File(mFile.getPath());
        String size = "";
        if (!dataUtils.isFileHidden(mFile.getPath())) {
            if (mFile.isDirectory()) {
                size = "";
                LayoutElementParcelable layoutElement = new LayoutElementParcelable(f.getPath(),
                        mFile.getPermission(), mFile.getLink(), size, 0, true, mFile.getDate() + "", false,
                        getBoolean(PREFERENCE_SHOW_THUMB), mFile.getMode());

                LIST_ELEMENTS.add(layoutElement);
                folder_count++;
                return layoutElement;
            } else {
                long longSize = 0;
                try {
                    if (mFile.getSize() != -1) {
                        longSize = mFile.getSize();
                        size = Formatter.formatFileSize(getContext(), longSize);
                    } else {
                        size = "";
                        longSize = 0;
                    }
                } catch (NumberFormatException e) {
                    //e.printStackTrace();
                }
                try {
                    LayoutElementParcelable layoutElement = new LayoutElementParcelable(f.getPath(),
                            mFile.getPermission(), mFile.getLink(), size, longSize, false, mFile.getDate() + "",
                            false, getBoolean(PREFERENCE_SHOW_THUMB), mFile.getMode());
                    LIST_ELEMENTS.add(layoutElement);
                    file_count++;
                    return layoutElement;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }

        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();

        // not guaranteed to be called unless we call #finish();
        // please move code to onStop
    }

    public void hide(String path) {

        dataUtils.addHiddenFile(path);
        File file = new File(path);
        if (file.isDirectory()) {
            File f1 = new File(path + "/" + ".nomedia");
            if (!f1.exists()) {
                try {
                    getMainActivity().mainActivityHelper.mkFile(new HybridFile(OpenMode.FILE, f1.getPath()), this);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            FileUtils.scanFile(file, getActivity());
        }

    }

    public String getCurrentPath() {
        return CURRENT_PATH;
    }

    private void addShortcut(LayoutElementParcelable path) {
        //Adding shortcut for MainActivity
        //on Home screen
        final Context ctx = getContext();

        if (!ShortcutManagerCompat.isRequestPinShortcutSupported(ctx)) {
            Toast.makeText(getActivity(), getString(R.string.addshortcut_not_supported_by_launcher),
                    Toast.LENGTH_SHORT).show();
            return;
        }

        Intent shortcutIntent = new Intent(ctx, MainActivity.class);
        shortcutIntent.putExtra("path", path.desc);
        shortcutIntent.setAction(Intent.ACTION_MAIN);
        shortcutIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

        // Using file path as shortcut id.
        ShortcutInfoCompat info = new ShortcutInfoCompat.Builder(ctx, path.desc)
                .setActivity(getMainActivity().getComponentName())
                .setIcon(IconCompat.createWithResource(ctx, R.mipmap.ic_launcher)).setIntent(shortcutIntent)
                .setLongLabel(path.desc).setShortLabel(new File(path.desc).getName()).build();

        ShortcutManagerCompat.requestPinShortcut(ctx, info, null);
    }

    // This method is used to implement the modification for the pre Searching
    public void onSearchPreExecute(String query) {
        getMainActivity().getAppbar().getBottomBar().setPathText("");
        getMainActivity().getAppbar().getBottomBar().setFullPathText(getString(R.string.searching, query));
    }

    // adds search results based on result boolean. If false, the adapter is initialised with initial
    // values, if true, new values are added to the adapter.
    public void addSearchResult(HybridFileParcelable a, String query) {
        if (listView != null) {

            // initially clearing the array for new result set
            if (!results) {
                LIST_ELEMENTS.clear();
                file_count = 0;
                folder_count = 0;
            }

            // adding new value to LIST_ELEMENTS
            LayoutElementParcelable layoutElementAdded = addTo(a);
            if (!results) {
                reloadListElements(false, false, !IS_LIST);
                getMainActivity().getAppbar().getBottomBar().setPathText("");
                getMainActivity().getAppbar().getBottomBar().setFullPathText(getString(R.string.searching, query));
                results = true;
            } else {
                adapter.addItem(layoutElementAdded);
            }
            stopAnimation();
        }
    }

    public void onSearchCompleted(final String query) {
        if (!results) {
            // no results were found
            LIST_ELEMENTS.clear();
        }
        new AsyncTask<Void, Void, Void>() {
            @Override
            protected Void doInBackground(Void... params) {
                Collections.sort(LIST_ELEMENTS, new FileListSorter(dsort, sortby, asc));
                return null;
            }

            @Override
            public void onPostExecute(Void c) {
                reloadListElements(true, true, !IS_LIST);// TODO: 7/7/2017 this is really inneffient, use RecycleAdapter's createHeaders()
                getMainActivity().getAppbar().getBottomBar().setPathText("");
                getMainActivity().getAppbar().getBottomBar()
                        .setFullPathText(getString(R.string.searchresults, query));
            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    public static void launchSMB(final HybridFileParcelable baseFile, final Activity activity) {
        final Streamer s = Streamer.getInstance();
        new Thread() {
            public void run() {
                try {
                    /*
                    List<SmbFile> subtitleFiles = new ArrayList<SmbFile>();
                        
                    // finding subtitles
                    for (Layoutelements layoutelement : LIST_ELEMENTS) {
                    SmbFile smbFile = new SmbFile(layoutelement.getDesc());
                    if (smbFile.getName().contains(smbFile.getName())) subtitleFiles.add(smbFile);
                    }
                    */

                    s.setStreamSrc(new SmbFile(baseFile.getPath()), baseFile.getSize());
                    activity.runOnUiThread(() -> {
                        try {
                            Uri uri = Uri.parse(Streamer.URL + Uri
                                    .fromFile(new File(Uri.parse(baseFile.getPath()).getPath())).getEncodedPath());
                            Intent i = new Intent(Intent.ACTION_VIEW);
                            i.setDataAndType(uri,
                                    MimeTypes.getMimeType(baseFile.getPath(), baseFile.isDirectory()));
                            PackageManager packageManager = activity.getPackageManager();
                            List<ResolveInfo> resInfos = packageManager.queryIntentActivities(i, 0);
                            if (resInfos != null && resInfos.size() > 0)
                                activity.startActivity(i);
                            else
                                Toast.makeText(activity,
                                        activity.getResources().getString(R.string.smb_launch_error),
                                        Toast.LENGTH_SHORT).show();
                        } catch (ActivityNotFoundException e) {
                            e.printStackTrace();
                        }
                    });

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    @Override
    public void onDetach() {
        super.onDetach();
    }

    public MainActivity getMainActivity() {
        return (MainActivity) getActivity();
    }

    public ArrayList<LayoutElementParcelable> getElementsList() {
        return LIST_ELEMENTS;
    }

    @Override
    public void changePath(String path) {
        loadlist(path, false, openMode);
    }

    @Override
    public String getPath() {
        return getCurrentPath();
    }

    @Override
    public int getRootDrawable() {
        return R.drawable.ic_root_white_24px;
    }

    private boolean getBoolean(String key) {
        return getMainActivity().getBoolean(key);
    }

}