package com.openfarmanager.android.controllers;
import android.app.Activity;
import android.app.Dialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.openfarmanager.android.App;
import com.openfarmanager.android.FileView;
import com.openfarmanager.android.Help;
import com.openfarmanager.android.R;
import com.openfarmanager.android.SettingsActivity;
import com.openfarmanager.android.adapters.ApplicationChooserAdapter;
import com.openfarmanager.android.adapters.ExportAsAdapter;
import com.openfarmanager.android.adapters.MimeTypeChooserAdapter;
import com.openfarmanager.android.core.Settings;
import com.openfarmanager.android.core.network.NetworkConnectionManager;
import com.openfarmanager.android.dialogs.BookmarksListDialog;
import com.openfarmanager.android.dialogs.SelectEncodingDialog;
import com.openfarmanager.android.filesystem.DropboxFile;
import com.openfarmanager.android.filesystem.GoogleDriveFile;
import com.openfarmanager.android.filesystem.actions.DiffDirectoriesTask;
import com.openfarmanager.android.filesystem.actions.RootTask;
import com.openfarmanager.android.filesystem.actions.network.DropboxTask;
import com.openfarmanager.android.fragments.ArchivePanel;
import com.openfarmanager.android.fragments.BasePanel;
import com.openfarmanager.android.fragments.DirectoryDetailsView;
import com.openfarmanager.android.fragments.GenericPanel;
import com.openfarmanager.android.fragments.MainPanel;
import com.openfarmanager.android.fragments.NetworkPanel;
import com.openfarmanager.android.model.Bookmark;
import com.openfarmanager.android.model.FileActionEnum;
import com.openfarmanager.android.model.NetworkAccount;
import com.openfarmanager.android.model.NetworkEnum;
import com.openfarmanager.android.utils.SystemUtils;
import com.openfarmanager.android.view.ExpandPanelAnimation;
import com.openfarmanager.android.view.ToastNotification;
import com.openfarmanager.android.view.panels.MainToolbar;
import java.io.File;
import java.io.FileInputStream;
import java.util.LinkedHashSet;
import java.util.List;
import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import static com.openfarmanager.android.fragments.MainPanel.ARG_PANEL_LOCATION;
import static com.openfarmanager.android.fragments.MainPanel.LEFT_PANEL;
import static com.openfarmanager.android.fragments.MainPanel.RIGHT_PANEL;
public class FileSystemController {
private static enum PanelsState {
LEFT_EXPANDED, EQUALS, RIGHT_EXPANDED
}
public static final int ALT_DOWN = 0;
public static final int ALT_UP = 1;
public static final int NEW = 2;
public static final int FILTER = 3;
public static final int FILTER_RESET = 4;
public static final int SELECT = 5;
public static final int QUICKVIEW = 6;
public static final int SEARCH = 7;
public static final int MENU = 8;
public static final int DIFF = 9;
public static final int HELP = 10;
public static final int SETTINGS = 11;
public static final int EXIT = 12;
public static final int NETWORK_DROPBOX = 13;
public static final int NETWORK_SKYDRIVE = 14;
public static final int NETWORK_YANDEX = 15;
public static final int NETWORK = 16;
public static final int APPLAUNCHER = 17;
public static final int BOOKMARKS = 18;
public static final int FILE_ACTION = 100;
public static final int GAIN_FOCUS = 101;
public static final int DIRECTORY_CHANGED = 102;
public static final int FILE_OPEN = 103;
public static final int OPEN_WITH = 104;
public static final int OPEN_ARCHIVE = 105;
public static final int OPEN_COMPRESSED_ARCHIVE = 106;
public static final int EXIT_FROM_ARCHIVE = 107;
public static final int EXTRACT_ARCHIVE = 109;
public static final int CHANGE_PATH = 110;
public static final int CREATE_BOOKMARK = 111;
public static final int OPEN_NETWORK = 112;
public static final int EXIT_FROM_NETWORK_STORAGE = 113;
public static final int FTP_CONNECTED = 114;
public static final int SMB_CONNECTED = 115;
public static final int YANDEX_DISK_USERNAME_RECEIVED = 117;
public static final int EXIT_FROM_GENERIC_PANEL = 118;
public static final int SMB_SCAN_NETWORK_REQUESTED = 119;
public static final int SMB_SCAN_CANCELED = 120;
public static final int SMB_IP_SELECTED = 121;
public static final int EXPAND_PANEL = 122;
public static final int OPEN_PATH = 123;
public static final int EXPORT_AS = 124;
public static final int OPEN_WEB = 125;
public static final int OPEN_ENCODING_DIALOG = 126;
public static final int MEDIA_FIRE_CONNECTED = 127;
public static final int SFTP_CONNECTED = 128;
public static final int WEBDAV_CONNECTED = 129;
public static final int YANDEX_DISK_CONNECTED = 130;
public static final int ADD_STAR = 131;
public static final int REMOVE_STAR = 132;
public static final int SHARE = 133;
public static final int GOTO_HOME = 134;
public static final int OPEN_DIRECTORY = 135;
public static final int INVALIDATE = 136;
public static final int ARG_FORCE_OPEN_FILE_IN_EDITOR = 1000;
public static final int ARG_EXPAND_LEFT_PANEL = 1001;
public static final int ARG_EXPAND_RIGHT_PANEL = 1002;
protected MainPanel mLeftPanel;
protected MainPanel mRightPanel;
protected MainToolbar mToolbar;
protected ArchivePanel mLeftArchivePanel;
protected ArchivePanel mRightArchivePanel;
protected NetworkPanel mLeftNetworkPanel;
protected NetworkPanel mRightNetworkPanel;
protected GenericPanel mLeftGenericPanel;
protected GenericPanel mRightGenericPanel;
protected DirectoryDetailsView mDirectoryDetailsView;
protected BasePanel mHiddenPanel;
protected BasePanel mLeftVisibleFragment;
protected BasePanel mRightVisibleFragment;
protected View mLeftFragmentContainer;
protected View mRightFragmentContainer;
private Dialog mProgressDialog;
private PanelsState mPanelsState = PanelsState.EQUALS;
protected View mMainView;
protected FileSystemController() {
}
public FileSystemController(FragmentManager manager, View view) {
Context appContext = App.sInstance.getApplicationContext();
mMainView = view;
mLeftPanel = (MainPanel) Fragment.instantiate(appContext, MainPanel.class.getName());
mRightPanel = (MainPanel) Fragment.instantiate(appContext, MainPanel.class.getName());
mLeftArchivePanel = (ArchivePanel) Fragment.instantiate(appContext, ArchivePanel.class.getName());
mRightArchivePanel = (ArchivePanel) Fragment.instantiate(appContext, ArchivePanel.class.getName());
mLeftNetworkPanel = (NetworkPanel) Fragment.instantiate(appContext, NetworkPanel.class.getName());
mRightNetworkPanel = (NetworkPanel) Fragment.instantiate(appContext, NetworkPanel.class.getName());
mLeftGenericPanel = (GenericPanel) Fragment.instantiate(appContext, GenericPanel.class.getName());
mRightGenericPanel = (GenericPanel) Fragment.instantiate(appContext, GenericPanel.class.getName());
mToolbar = (MainToolbar) mMainView.findViewById(R.id.toolbar);
mLeftFragmentContainer = view.findViewById(R.id.panel_left);
mRightFragmentContainer = view.findViewById(R.id.panel_right);
mDirectoryDetailsView = (DirectoryDetailsView) Fragment.instantiate(appContext, DirectoryDetailsView.class.getName());
mLeftVisibleFragment = mLeftPanel;
mRightVisibleFragment = mRightPanel;
initPanels();
manager.beginTransaction().add(R.id.panel_left, mLeftPanel).
add(R.id.panel_right, mRightPanel).
commit();
}
public void invalidateToolbar() {
mToolbar.invalidate();
}
public void hideMainToolbar() {
mToolbar.setVisibility(View.GONE);
}
public void showMainToolbar() {
mToolbar.setVisibility(View.VISIBLE);
}
protected void initPanels() {
mToolbar.setHandler(mToolbarHandler);
mLeftPanel.setHandler(mPanelHandler);
mRightPanel.setHandler(mPanelHandler);
mLeftArchivePanel.setHandler(mPanelHandler);
mRightArchivePanel.setHandler(mPanelHandler);
mLeftNetworkPanel.setHandler(mPanelHandler);
mRightNetworkPanel.setHandler(mPanelHandler);
mLeftGenericPanel.setHandler(mPanelHandler);
mRightGenericPanel.setHandler(mPanelHandler);
Bundle argsLeft = new Bundle();
argsLeft.putInt(ARG_PANEL_LOCATION, LEFT_PANEL);
Bundle argsRight = new Bundle();
argsRight.putInt(ARG_PANEL_LOCATION, RIGHT_PANEL);
mLeftPanel.setArguments(argsLeft);
mLeftArchivePanel.setArguments(argsLeft);
mLeftNetworkPanel.setArguments(argsLeft);
mLeftGenericPanel.setArguments(argsLeft);
mRightPanel.setArguments(argsRight);
mRightArchivePanel.setArguments(argsRight);
mRightNetworkPanel.setArguments(argsRight);
mRightGenericPanel.setArguments(argsRight);
}
public void invalidate() {
MainPanel leftPanel = getLeftVisiblePanel();
MainPanel rightPanel = getRightVisiblePanel();
if (leftPanel != null) {
leftPanel.getSelectedFiles().clear();
leftPanel.invalidate();
}
if (rightPanel != null) {
rightPanel.getSelectedFiles().clear();
rightPanel.invalidate();
}
}
public Handler getToolbarHandler() {
return mToolbarHandler;
}
private Handler mToolbarHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
final MainPanel activePanel = getActivePanel();
final MainPanel inactivePanel = getInactivePanel();
// something really bad :( but we want to avoid crash, so let's try to make soft restart.
if (activePanel == null) {
restorePanelState();
}
Activity activity = null;
if (activePanel != null) {
activity = activePanel.getActivity();
}
if (activity == null || inactivePanel != null) {
activity = inactivePanel.getActivity();
}
switch (msg.what) {
case ALT_DOWN:
if (SystemUtils.isHoneycombOrNever() && !App.sInstance.getSettings().isHoldAltOnTouch()) {
if (getLeftVisiblePanel() != null) {
getLeftVisiblePanel().setIsMultiSelectMode(true);
}
if (getRightVisiblePanel() != null) {
//getRightVisiblePanel().showAltTip(true);
getRightVisiblePanel().setIsMultiSelectMode(true);
}
} else {
if (getLeftVisiblePanel() != null) {
getLeftVisiblePanel().switchMultiSelectMode();
}
if (getRightVisiblePanel() != null) {
getRightVisiblePanel().switchMultiSelectMode();
//getRightVisiblePanel().showAltTip(getRightVisiblePanel().switchMultiSelectMode());
}
}
break;
case ALT_UP:
if (getLeftVisiblePanel() != null) {
getLeftVisiblePanel().setIsMultiSelectMode(false);
}
if (getRightVisiblePanel() != null) {
//getRightVisiblePanel().showAltTip(false);
getRightVisiblePanel().setIsMultiSelectMode(false);
}
break;
case NEW:
if (activePanel != null) {
activePanel.createFile(inactivePanel);
}
break;
case QUICKVIEW:
openQuickPanel(activePanel, inactivePanel);
break;
case EXIT:
if (activity != null && !activity.isFinishing()) {
activity.finish();
}
break;
case FILTER:
filter((String) msg.obj);
break;
case SELECT:
if (activePanel == null) {
return;
}
activePanel.showSelectDialog();
break;
case SEARCH:
if (activePanel == null) {
return;
}
activePanel.showSearchDialog();
break;
case MENU:
if (activePanel == null) {
return;
}
activePanel.openFileActionMenu();
break;
case DIFF:
diffDirectories();
break;
case HELP:
if (activity != null) {
activity.startActivity(new Intent(App.sInstance.getApplicationContext(), Help.class));
}
break;
case SETTINGS:
if (activity != null) {
activity.startActivityForResult(new Intent(App.sInstance.getApplicationContext(), SettingsActivity.class), 0);
}
break;
case NETWORK:
App.sInstance.getNetworkConnectionManager().openAvailableCloudsList();
break;
case APPLAUNCHER:
openAppLaucnher();
break;
case BOOKMARKS:
if (activePanel != null) {
openBookmarkList(activity);
}
break;
}
}
};
private void openQuickPanel(MainPanel activePanel, MainPanel inactivePanel) {
if (!isDetailsPanelVisible()) {
boolean panelShowed = showDetailsView(activePanel, inactivePanel);
if (activePanel == null) {
return;
}
if (panelShowed) {
mDirectoryDetailsView.selectFile(activePanel.getCurrentDir());
}
} else {
hideDetailsView(activePanel, inactivePanel);
}
}
public Handler getPanelHandler() {
return mPanelHandler;
}
private Handler mPanelHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
boolean initPanels = msg.what != GAIN_FOCUS;
MainPanel activePanel = null;
MainPanel inactivePanel = null;
if (initPanels) {
activePanel = getActivePanel();
inactivePanel = getInactivePanel();
if (activePanel != null) {
boolean isLeftPanelActive = activePanel.getPanelLocation() == LEFT_PANEL;
inactivePanel = isLeftPanelActive ? getRightVisiblePanel() : getLeftVisiblePanel();
if (inactivePanel == null) {
inactivePanel = getInactivePanel();
}
}
}
switch (msg.what) {
case FILE_ACTION:
if (activePanel != null) {
activePanel.executeAction((FileActionEnum) msg.obj, inactivePanel);
}
break;
case GAIN_FOCUS:
BasePanel panel = msg.arg1 == LEFT_PANEL ? mLeftVisibleFragment : mRightVisibleFragment;
if (panel instanceof MainPanel) {
MainPanel mainPanel = (MainPanel) panel;
if (!mainPanel.isActive()) {
setActivePanel(mainPanel);
}
}
break;
case DIRECTORY_CHANGED:
if (isDetailsPanelVisible()) {
showDetails(activePanel);
}
break;
case FILE_OPEN:
try {
boolean forceOpenEditor = msg.arg1 == ARG_FORCE_OPEN_FILE_IN_EDITOR;
openFile((File) msg.obj, forceOpenEditor);
} catch (Exception e) {
handleUnexpectedException(mLeftVisibleFragment.getActivity());
}
break;
case OPEN_WITH:
openWith((File) msg.obj);
break;
case OPEN_ARCHIVE:
if (activePanel != null) {
openArchive(activePanel, (File) msg.obj);
}
break;
case OPEN_COMPRESSED_ARCHIVE:
if (activePanel != null) {
openCompressedArchive(activePanel, (File) msg.obj);
}
break;
case EXIT_FROM_ARCHIVE:
try {
exitFromArchive(getWorkingArchivePanel());
} catch (Exception e) {
handleUnexpectedException(mLeftVisibleFragment.getActivity());
}
break;
case EXTRACT_ARCHIVE:
try {
getWorkingArchivePanel().extractArchive(inactivePanel);
} catch (Exception e) {
handleUnexpectedException(mLeftVisibleFragment.getActivity());
}
break;
case CHANGE_PATH:
changePath((Integer) msg.obj);
break;
case CREATE_BOOKMARK:
if (activePanel != null) {
activePanel.createBookmark(inactivePanel);
}
break;
case OPEN_NETWORK:
Bookmark bookmark = (Bookmark) msg.obj;
NetworkConnectionManager manager = App.sInstance.getNetworkConnectionManager();
if (bookmark != null) {
manager.openNetworkBookmark(bookmark);
} else {
manager.openAvailableCloudsList();
}
break;
case EXIT_FROM_NETWORK_STORAGE:
exitFromNetworkStorage((Integer) msg.obj == MainPanel.LEFT_PANEL ? mLeftNetworkPanel : mRightNetworkPanel);
break;
case EXIT_FROM_GENERIC_PANEL:
exitFromGenericPanel((Integer) msg.obj == MainPanel.LEFT_PANEL ? mLeftGenericPanel : mRightGenericPanel);
break;
case EXPAND_PANEL:
try {
expandPanel(msg.arg1 == ARG_EXPAND_LEFT_PANEL);
} catch (Exception ignore) {
// avoid very unexpected crash
}
break;
case OPEN_PATH:
if (activePanel != null) {
activePanel.openDirectory(new File((String) msg.obj));
}
break;
case EXPORT_AS:
try {
openExportAsDialog((GoogleDriveFile) msg.obj);
} catch (Exception e) {
e.printStackTrace();
}
break;
case OPEN_WEB:
GoogleDriveFile file = (GoogleDriveFile) msg.obj;
try {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(file.getOpenWithLink()));
activePanel.getActivity().startActivity(browserIntent);
} catch (ActivityNotFoundException e) {
ToastNotification.makeText(activePanel.getActivity(), App.sInstance.getString(R.string.error_no_browser), Toast.LENGTH_LONG).show();
e.printStackTrace();
}
break;
case OPEN_ENCODING_DIALOG:
showSelectEncodingDialog((NetworkEnum) msg.obj);
break;
case EditViewController.MSG_SELECT_ENCODING:
SelectEncodingDialog.SelectedEncodingInfo info = (SelectEncodingDialog.SelectedEncodingInfo) msg.obj;
if (info.networkType == NetworkEnum.SFTP) {
App.sInstance.getSftpApi().setCharset(info.charset);
} else {
App.sInstance.getFtpApi().setCharset(info.charset);
}
activePanel.invalidatePanels(inactivePanel);
break;
case ADD_STAR:
GoogleDriveFile googleDriveFile = (GoogleDriveFile) msg.obj;
inactivePanel.updateGoogleDriveData(activePanel, googleDriveFile.getId(), getStarredData(true));
break;
case REMOVE_STAR:
googleDriveFile = (GoogleDriveFile) msg.obj;
inactivePanel.updateGoogleDriveData(activePanel, googleDriveFile.getId(), getStarredData(false));
break;
case SHARE:
inactivePanel.doDropboxTask((DropboxFile) msg.obj, DropboxTask.TASK_SHARE);
break;
case GOTO_HOME:
activePanel.openHomeFolder();
break;
case OPEN_DIRECTORY:
activePanel.openDirectory((String) msg.obj);
break;
case INVALIDATE:
invalidate();
break;
}
}
private String getStarredData(boolean star) {
return String.format("{\"labels\":{\"starred\":%s}}", star);
}
};
public void expandPanel(boolean expandLeftPanel) {
ExpandPanelAnimation animation = null;
switch (mPanelsState) {
case LEFT_EXPANDED:
if (!expandLeftPanel) {
animation = new ExpandPanelAnimation(mLeftFragmentContainer, mRightFragmentContainer, 1f, 1f);
mPanelsState = PanelsState.EQUALS;
}
break;
case EQUALS:
animation = new ExpandPanelAnimation(mLeftFragmentContainer, mRightFragmentContainer,
expandLeftPanel ? 0.8f : 0.2f, expandLeftPanel ? 0.2f : 0.8f);
mPanelsState = expandLeftPanel ? PanelsState.LEFT_EXPANDED : PanelsState.RIGHT_EXPANDED;
break;
case RIGHT_EXPANDED:
if (expandLeftPanel) {
animation = new ExpandPanelAnimation(mLeftFragmentContainer, mRightFragmentContainer, 1f, 1f);
mPanelsState = PanelsState.EQUALS;
}
}
if (animation == null) {
return;
}
animation.setDuration(500);
animation.setFillAfter(true);
mLeftFragmentContainer.startAnimation(animation);
}
private void handleUnexpectedException(Activity activity) {
// something really unexpected happened. at least avoid crash
if (activity != null) {
ToastNotification.makeText(activity, activity.getString(R.string.error_unknown_unexpected_error), Toast.LENGTH_SHORT).show();
}
}
private void changePath(int panel) {
MainPanel srcPanel = panel == LEFT_PANEL ? mLeftPanel : mRightPanel;
MainPanel dstPanel = panel == LEFT_PANEL ? mRightPanel : mLeftPanel;
File path = srcPanel.getCurrentDir();
if (!dstPanel.isAdded()) {
int location = dstPanel.getPanelLocation();
BasePanel activeDstPanel = location == LEFT_PANEL ? mLeftVisibleFragment : mRightVisibleFragment;
if (activeDstPanel instanceof DirectoryDetailsView) {
mToolbarHandler.sendEmptyMessage(QUICKVIEW);
} else if (activeDstPanel instanceof ArchivePanel) {
((ArchivePanel) activeDstPanel).exitFromArchive();
} else if (activeDstPanel instanceof NetworkPanel) {
((NetworkPanel) activeDstPanel).exitFromNetwork();
}
}
dstPanel.openDirectory(path);
dstPanel.gainFocus();
}
public void setInitActivePanel() {
setActivePanel(mLeftPanel);
}
protected void setActivePanel(MainPanel activePanel) {
// remove focus from all panels
mLeftPanel.setIsActivePanel(false);
mRightPanel.setIsActivePanel(false);
mLeftArchivePanel.setIsActivePanel(false);
mRightArchivePanel.setIsActivePanel(false);
mLeftNetworkPanel.setIsActivePanel(false);
mRightNetworkPanel.setIsActivePanel(false);
mLeftGenericPanel.setIsActivePanel(false);
mRightGenericPanel.setIsActivePanel(false);
activePanel.setIsActivePanel(true);
}
protected boolean showDetailsView(MainPanel panel, MainPanel inactivePanel) {
if (panel == null || !mLeftVisibleFragment.isFileSystemPanel() || !mRightVisibleFragment.isFileSystemPanel()) {
return false;
}
boolean isLeftPanel = panel.getPanelLocation() == LEFT_PANEL;
if (isLeftPanel) {
mHiddenPanel = mRightVisibleFragment;
mRightVisibleFragment = mDirectoryDetailsView;
} else {
mHiddenPanel = mLeftVisibleFragment;
mLeftVisibleFragment = mDirectoryDetailsView;
}
mHiddenPanel.getFragmentManager().beginTransaction().remove(mHiddenPanel).
add(getContainerId(!isLeftPanel), mDirectoryDetailsView).commit();
return true;
}
protected void hideDetailsView(MainPanel panel, MainPanel inactivePanel) {
BasePanel panelToShow = mHiddenPanel;
boolean isLeftPanel = panel != null ?
panel.getPanelLocation() == LEFT_PANEL :
inactivePanel.getPanelLocation() == LEFT_PANEL;
if (panelToShow == null) {
panelToShow = isLeftPanel ? mRightVisibleFragment : mLeftVisibleFragment;
}
if (isLeftPanel) {
mRightVisibleFragment = panelToShow;
} else {
mLeftVisibleFragment = panelToShow;
}
mDirectoryDetailsView.getFragmentManager().beginTransaction().remove(mDirectoryDetailsView).add(getContainerId(!isLeftPanel), panelToShow).commit();
}
protected void showDetails(MainPanel panel) {
if (panel == null || !mDirectoryDetailsView.isAdded()) {
return;
}
mDirectoryDetailsView.selectFile(panel.getCurrentDir());
}
protected void openArchive(MainPanel activePanel, File file) {
ArchivePanel activeArchivePanel = switchToArchivePanel(activePanel);
activeArchivePanel.openArchive(file);
}
protected void openCompressedArchive(MainPanel activePanel, File file) {
ArchivePanel activeArchivePanel = switchToArchivePanel(activePanel);
activeArchivePanel.openCompressedArchive(file);
}
private ArchivePanel switchToArchivePanel(MainPanel activePanel) {
boolean isLeftPanel = activePanel.getPanelLocation() == MainPanel.LEFT_PANEL;
ArchivePanel activeArchivePanel;
FragmentManager fragmentManager;
if (isLeftPanel) {
activeArchivePanel = mLeftArchivePanel;
mLeftVisibleFragment = mLeftArchivePanel;
fragmentManager = mRightVisibleFragment.getFragmentManager();
} else {
activeArchivePanel = mRightArchivePanel;
mRightVisibleFragment = mRightArchivePanel;
fragmentManager = mLeftVisibleFragment.getFragmentManager();
}
activeArchivePanel.gainFocus();
fragmentManager.beginTransaction().remove(activePanel).add(getContainerId(isLeftPanel), activeArchivePanel).commit();
return activeArchivePanel;
}
public void openNetworkPanel(NetworkEnum networkType) {
openNetworkPanel(networkType, null);
}
public void openNetworkPanel(NetworkEnum networkType, String path) {
MainPanel activePanel = getActivePanel();
boolean isLeftPanel = activePanel.getPanelLocation() == MainPanel.LEFT_PANEL;
NetworkPanel networkPanel;
FragmentManager fragmentManager;
forceExitFromNetwork(networkType, activePanel);
if (isLeftPanel) {
networkPanel = mLeftNetworkPanel;
mLeftVisibleFragment = networkPanel;
fragmentManager = mRightVisibleFragment.getFragmentManager();
} else {
networkPanel = mRightNetworkPanel;
mRightVisibleFragment = networkPanel;
fragmentManager = mLeftVisibleFragment.getFragmentManager();
}
networkPanel.setNetworkType(networkType);
networkPanel.gainFocus();
fragmentManager.beginTransaction().remove(activePanel).add(getContainerId(isLeftPanel), networkPanel).commit();
networkPanel.openBookmark(path);
}
protected void forceExitFromNetwork(NetworkEnum networkType, MainPanel activePanel) {
MainPanel inactivePanel = getInactivePanel();
if (inactivePanel instanceof NetworkPanel) {
final NetworkPanel inactiveNetworkPanel = (NetworkPanel) inactivePanel;
NetworkAccount newAccount = App.sInstance.getNetworkApi(networkType).getCurrentNetworkAccount();
NetworkAccount account = inactiveNetworkPanel.getCurrentNetworkAccount();
if (account != null && newAccount.getId() == account.getId()) {
return;
}
if (inactiveNetworkPanel.getNetworkType() == networkType) {
activePanel.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
ToastNotification.makeText(App.sInstance.getApplicationContext(),
App.sInstance.getString(R.string.one_network_instance), Toast.LENGTH_LONG).show();
inactiveNetworkPanel.exitFromNetwork();
}
});
}
}
}
protected void exitFromArchive(ArchivePanel archivePanel) {
boolean isLeftPanel = archivePanel.getPanelLocation() == MainPanel.LEFT_PANEL;
MainPanel activePanel = isLeftPanel ? mLeftPanel : mRightPanel;
FragmentManager fragmentManager;
if (isLeftPanel) {
mLeftVisibleFragment = activePanel;
fragmentManager = mRightVisibleFragment.getFragmentManager();
} else {
mRightVisibleFragment = activePanel;
fragmentManager = mLeftVisibleFragment.getFragmentManager();
}
activePanel.gainFocus();
fragmentManager.beginTransaction().remove(archivePanel).add(getContainerId(isLeftPanel), activePanel).commit();
}
protected void exitFromGenericPanel(MainPanel genericPanel) {
boolean isLeftPanel = genericPanel.getPanelLocation() == MainPanel.LEFT_PANEL;
MainPanel activePanel = isLeftPanel ? mLeftPanel : mRightPanel;
FragmentManager fragmentManager;
if (isLeftPanel) {
mLeftVisibleFragment = activePanel;
fragmentManager = mRightVisibleFragment.getFragmentManager();
} else {
mRightVisibleFragment = activePanel;
fragmentManager = mLeftVisibleFragment.getFragmentManager();
}
activePanel.gainFocus();
fragmentManager.beginTransaction().remove(genericPanel).add(getContainerId(isLeftPanel), activePanel).commit();
}
protected void exitFromNetworkStorage(NetworkPanel networkPanel) {
boolean isLeftPanel = networkPanel.getPanelLocation() == MainPanel.LEFT_PANEL;
MainPanel activePanel = isLeftPanel ? mLeftPanel : mRightPanel;
FragmentManager fragmentManager;
if (isLeftPanel) {
mLeftVisibleFragment = activePanel;
fragmentManager = mRightVisibleFragment.getFragmentManager();
} else {
mRightVisibleFragment = activePanel;
fragmentManager = mLeftVisibleFragment.getFragmentManager();
}
activePanel.gainFocus();
fragmentManager.beginTransaction().remove(networkPanel).add(getContainerId(isLeftPanel), activePanel).commit();
}
private int getContainerId(boolean isLeftPanel) {
return isLeftPanel ? R.id.panel_left : R.id.panel_right;
}
private void filter(String obj) {
if (getActivePanel() != null) {
getActivePanel().filter(obj);
}
}
private void diffDirectories() {
final MainPanel activePanel = getActivePanel();
final MainPanel inactivePanel = getInactivePanel();
if (activePanel == null || inactivePanel == null) {
return;
}
if (!activePanel.isFileSystemPanel() || !inactivePanel.isFileSystemPanel()) {
Activity activity = activePanel.getActivity();
ToastNotification.makeText(activity, activity.getString(R.string.error_diff_not_supported), Toast.LENGTH_SHORT).show();
return;
}
final File activePanelCurrentDir = activePanel.getCurrentDir();
final File inactivePanelCurrentDir = inactivePanel.getCurrentDir();
final DiffDirectoriesTask task = new DiffDirectoriesTask(new DiffDirectoriesTask.OnActionListener() {
@Override
public void onActionFinish(LinkedHashSet<File> activePanelDiffFiles, LinkedHashSet<File> inactivePanelDiffFiles) {
if (!activePanelCurrentDir.equals(activePanel.getCurrentDir()) ||
!inactivePanelCurrentDir.equals(inactivePanel.getCurrentDir())) {
return;
}
activePanel.addSelectedFiles(activePanelDiffFiles);
inactivePanel.addSelectedFiles(inactivePanelDiffFiles);
runOnUiThread(new Runnable() {
@Override
public void run() {
activePanel.showQuickActionPanel();
inactivePanel.showQuickActionPanel();
}
});
}
}, getActivePanel().getAllFiles(), getInactivePanel().getAllFiles());
task.execute();
}
public void savePanelState() {
App.sInstance.getSettings().savePanelsState(mLeftPanel.getCurrentDir().getAbsolutePath(),
mRightPanel.getCurrentDir().getAbsolutePath(), getActivePanel() == mLeftPanel);
}
public void restorePanelState() {
Settings settings = App.sInstance.getSettings();
mLeftPanel.restoreState(settings.getLeftPanelPath(), settings.isLeftPanelActive());
mRightPanel.restoreState(settings.getRightPanelPath(), !settings.isLeftPanelActive());
}
private MainPanel getVisibleActivePanel() {
MainPanel panel = getActivePanel();
return panel != null && panel.isAdded() ? panel : getWorkingArchivePanel();
}
public MainPanel getActivePanel() {
MainPanel leftVisiblePanel = getLeftVisiblePanel();
MainPanel rightVisiblePanel = getRightVisiblePanel();
if (leftVisiblePanel != null && leftVisiblePanel.isActive()) {
return leftVisiblePanel;
} else if (rightVisiblePanel != null && rightVisiblePanel.isActive()) {
return rightVisiblePanel;
} else {
// hack: avoid NPE: request focus for non null panel.
if (leftVisiblePanel != null) {
leftVisiblePanel.gainFocus();
return leftVisiblePanel;
} else if (rightVisiblePanel != null) {
rightVisiblePanel.gainFocus();
return rightVisiblePanel;
}
return null;
}
}
protected ArchivePanel getWorkingArchivePanel() {
if (mLeftArchivePanel.isActive()) {
return mLeftArchivePanel;
} else if (mRightArchivePanel.isActive()) {
return mRightArchivePanel;
} else {
if (mLeftVisibleFragment instanceof ArchivePanel) {
return (ArchivePanel) mLeftVisibleFragment;
} else if (mRightVisibleFragment instanceof ArchivePanel) {
return (ArchivePanel) mRightVisibleFragment;
}
return null;
}
}
public MainPanel getInactivePanel() {
MainPanel leftVisiblePanel = getLeftVisiblePanel();
MainPanel rightVisiblePanel = getRightVisiblePanel();
if (leftVisiblePanel != null && !leftVisiblePanel.isActive()) {
return leftVisiblePanel;
} else if (rightVisiblePanel != null && !rightVisiblePanel.isActive()) {
return rightVisiblePanel;
} else {
return null;
}
}
protected MainPanel getLeftVisiblePanel() {
return mLeftVisibleFragment instanceof MainPanel ? (MainPanel) mLeftVisibleFragment : null;
}
protected MainPanel getRightVisiblePanel() {
return mRightVisibleFragment instanceof MainPanel ? (MainPanel) mRightVisibleFragment : null;
}
protected boolean isDetailsPanelVisible() {
return mDirectoryDetailsView.isAdded();
}
public boolean navigateBack() {
MainPanel panel = getVisibleActivePanel();
if (panel != null) {
if (panel.isRootDirectory()) {
if (panel instanceof ArchivePanel) {
((ArchivePanel) panel).exitFromArchive();
return true;
} else if (panel instanceof NetworkPanel) {
panel.navigateParent();
return true;
} else if (panel instanceof GenericPanel) {
panel.navigateParent();
return true;
}
return false;
} else {
panel.unselectAll();
panel.navigateParent();
return true;
}
}
return false;
}
private void openFile(File item, boolean forceOpenEditor) {
MainPanel panel = getActivePanel();
if (panel == null) {
panel = getInactivePanel();
}
// unexpected error, it's better to just exit from method.
if (panel == null || item == null) {
return;
}
Activity activity = panel.getActivity();
// unexpected error, it's better to just exit from method.
if (activity == null) {
return;
}
if (!item.canRead() && !RootTask.canReadFile(item)) {
ToastNotification.makeText(activity, activity.getString(R.string.error_cannot_open_file), Toast.LENGTH_SHORT).show();
return;
}
if (!forceOpenEditor && openExternal(item)) {
return;
}
Intent intent;
//Can't find application, user internal viewer
//try to detect zip archive
if (!forceOpenEditor) {
try {
FileInputStream is = new FileInputStream(item);
byte[] buff = new byte[2];
is.read(buff);
if (buff[0] == 0x50 && buff[1] == 0x4b) {
//ToastNotification.makeText(activity,"Zip archive",Toast.LENGTH_SHORT).show();
openArchive(getActivePanel(), item);
return;
}
is.close();
} catch (Exception e) {
e.printStackTrace();
}
}
//Can't find application, user internal viewer
intent = new Intent(App.sInstance, FileView.class).setData(Uri.fromFile(item));
activity.startActivity(intent);
}
/**
* Try to open file by external application.
*
* @param item file to open
* @return <code>true</code> application to handle this file was found, <code>false</code> otherwise.
*/
private boolean openExternal(File item) {
Intent intent = App.sInstance.getAppManager().getFilteredIntent(item);
String mime = intent.getType();
//try to find external viewer
try {
if (mime != null && !mime.startsWith("text")) {
if (intent.resolveActivity(App.sInstance.getPackageManager()) != null) {
getActivePanel().getActivity().startActivity(intent);
return true;
}
}
} catch (Exception ignore) { /*sometimes unexpected NPE occurs */}
return false;
}
/**
* Perform 'Open width' operation - chow chooser dialog with applications to handle selected file.
*
* @param item to handle.
*/
private void openWith(File item) {
final Intent intent = App.sInstance.getAppManager().getFilteredIntent(item);
List<ResolveInfo> infoList = App.sInstance.getAppManager().getIntentActivities(intent);
List<ResolveInfo> allInfoList = App.sInstance.getAppManager().getAllCallableActivities(item);
showChooserDialog(intent, item, infoList, allInfoList);
}
public void openBookmarkList(Activity activity) {
final Dialog dialog = new BookmarksListDialog(activity, mPanelHandler);
dialog.show();
adjustDialogSize(dialog);
}
/**
* Show customized chooser dialog with available applications for current <code>intent</code>.
*
* @param intent intent to be handled. Created from previously selected file.
* @param itemToHandle file item to be opened.
* @param applications available apps which can handle requested intent.
* @param allApplications all applications which can handle any content.
*/
private void showChooserDialog(final Intent intent, final File itemToHandle, List<ResolveInfo> applications, List<ResolveInfo> allApplications) {
final Dialog dialog = new Dialog(getActivePanel().getActivity(), R.style.Action_Dialog_Invert);
View dialogView = View.inflate(App.sInstance.getApplicationContext(), R.layout.application_chooser, null);
final ListView appList = (ListView) dialogView.findViewById(R.id.applications_list);
final ApplicationChooserAdapter adapter = new ApplicationChooserAdapter(applications, allApplications);
appList.setAdapter(adapter);
appList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
boolean isDelimiter = (Boolean) view.getTag(R.string.is_delimiter);
if (isDelimiter) {
adapter.delimiterClicked();
return;
}
ResolveInfo info = (ResolveInfo) appList.getAdapter().getItem(position);
//Intent intent = new Intent(Intent.ACTION_SEND);
intent.setClassName(info.activityInfo.packageName, info.activityInfo.name);
if (dialog.isShowing()) {
dialog.dismiss();
}
Activity activity = getActivePanel().getActivity();
try {
activity.startActivity(intent);
} catch (SecurityException e) {
ToastNotification.makeText(activity, activity.getString(R.string.error_cant_open_intent), Toast.LENGTH_LONG).show();
} catch (Exception e) {
e.printStackTrace();
}
}
});
dialogView.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
dialogView.findViewById(R.id.open_as).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (dialog.isShowing()) {
dialog.dismiss();
}
showOpenAsDialog(itemToHandle);
}
});
dialog.setContentView(dialogView);
dialog.show();
adjustDialogSize(dialog);
}
/**
* Show mime type chooser dialog.
*
* @param itemToHandle file item to be opened.
*/
private void showOpenAsDialog(final File itemToHandle) {
final Dialog dialog = new Dialog(getActivePanel().getActivity(), R.style.Action_Dialog_Invert);
View dialogView = View.inflate(App.sInstance.getApplicationContext(), R.layout.mime_type_chooser, null);
final ListView mimeTypes = (ListView) dialogView.findViewById(R.id.mime_types);
final MimeTypeChooserAdapter adapter = new MimeTypeChooserAdapter();
mimeTypes.setAdapter(adapter);
dialogView.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
mimeTypes.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String mime = (String) view.getTag();
final Intent intent = App.sInstance.getAppManager().getFilteredIntent(itemToHandle);
List<ResolveInfo> infoList = App.sInstance.getAppManager().getCallableActivities(itemToHandle, mime);
List<ResolveInfo> allInfoList = App.sInstance.getAppManager().getAllCallableActivities(itemToHandle);
showChooserDialog(intent, itemToHandle, infoList, allInfoList);
if (dialog.isShowing()) {
dialog.dismiss();
}
}
});
dialog.setContentView(dialogView);
dialog.show();
adjustDialogSize(dialog);
}
public void showSelectEncodingDialog(NetworkEnum network) {
Dialog mCharsetSelectDialog = new SelectEncodingDialog(getActivePanel().getActivity(), mPanelHandler, network, false);
mCharsetSelectDialog.setCancelable(true);
mCharsetSelectDialog.show();
adjustDialogSize(mCharsetSelectDialog, 0.6f);
}
private void openExportAsDialog(final GoogleDriveFile file) {
final Dialog dialog = new Dialog(getActivePanel().getActivity(), R.style.Action_Dialog_Invert);
View dialogView = View.inflate(App.sInstance.getApplicationContext(), R.layout.mime_type_chooser, null);
final ListView exportTypes = (ListView) dialogView.findViewById(R.id.mime_types);
final ExportAsAdapter adapter = new ExportAsAdapter(file.getExportLinks());
exportTypes.setAdapter(adapter);
dialogView.findViewById(R.id.cancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
dialog.dismiss();
}
});
((TextView) dialogView.findViewById(R.id.title)).setText(App.sInstance.getString(R.string.export_as));
exportTypes.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final String downloadLink = (String) view.getTag();
final MainPanel inactivePanel = getInactivePanel();
if (inactivePanel == null || inactivePanel.getActivity().isFinishing()) {
return;
}
final String fileName = file.getName();
inactivePanel.export(getActivePanel(), downloadLink,
inactivePanel.getCurrentPath() + File.separator + fileName + "." +
downloadLink.substring(downloadLink.lastIndexOf('=') + 1));
if (dialog.isShowing()) {
dialog.dismiss();
}
}
});
dialog.setContentView(dialogView);
dialog.show();
adjustDialogSize(dialog);
}
private void adjustDialogSize(Dialog dialog) {
adjustDialogSize(dialog, 0.8f);
}
/**
* Adjust dialog size. Actuall for old android version only (due to absence of Holo themes).
*
* @param dialog dialog whose size should be adjusted.
*/
private void adjustDialogSize(Dialog dialog, float scaleFactor) {
if (!SystemUtils.isHoneycombOrNever()) {
DisplayMetrics metrics = new DisplayMetrics();
getActivePanel().getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
params.copyFrom(dialog.getWindow().getAttributes());
params.width = (int) (metrics.widthPixels * scaleFactor);
params.height = (int) (metrics.heightPixels * scaleFactor);
dialog.getWindow().setAttributes(params);
}
}
public void openAppLaucnher() {
MainPanel activePanel = getActivePanel();
if (activePanel == null) {
return;
}
if (activePanel instanceof GenericPanel) {
exitFromGenericPanel(activePanel);
return;
}
boolean isLeftPanel = activePanel.getPanelLocation() == MainPanel.LEFT_PANEL;
GenericPanel panel;
FragmentManager fragmentManager;
if (isLeftPanel) {
panel = mLeftGenericPanel;
mLeftVisibleFragment = panel;
fragmentManager = mRightVisibleFragment.getFragmentManager();
} else {
panel = mRightGenericPanel;
mRightVisibleFragment = panel;
fragmentManager = mLeftVisibleFragment.getFragmentManager();
}
panel.gainFocus();
fragmentManager.beginTransaction().remove(activePanel).add(getContainerId(isLeftPanel), panel).commit();
}
public void showProgressDialog(int messageId) {
try {
getActivePanel().getActivity().runOnUiThread(mShowProgressRunnable);
((TextView) mProgressDialog.findViewById(R.id.progress_bar_text)).setText(messageId);
} catch (Exception e) {
e.printStackTrace();
}
}
public void dismissProgressDialog() {
runOnUiThread(mDismissProgressRunnable);
}
private void runOnUiThread(Runnable runnable) {
try {
getActivePanel().getActivity().runOnUiThread(runnable);
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
MainPanel panel = getActivePanel();
MainPanel inactivePanel = getInactivePanel();
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
return navigateBack();
//Hardware keybord events
case KeyEvent.KEYCODE_TAB:
MainPanel active = getActivePanel();
getLeftVisiblePanel().setIsActivePanel(getLeftVisiblePanel() != active);
getRightVisiblePanel().setIsActivePanel(getRightVisiblePanel() != active);
return true;
case KeyEvent.KEYCODE_DEL:
navigateBack();
return true;
case KeyEvent.KEYCODE_F1:
if (event.isAltPressed()) {
App.sInstance.getNetworkConnectionManager().openAvailableCloudsList();
}
return true;
case KeyEvent.KEYCODE_F2:
if (event.isAltPressed()) {
if (panel != null) {
openQuickPanel(panel, inactivePanel);
}
} else {
getActivePanel().openFileActionMenu();
}
return true;
case KeyEvent.KEYCODE_F3:
if (event.isAltPressed()) {
if (panel != null) {
panel.showSearchDialog();
}
} else {
openAppLaucnher();
}
return true;
case KeyEvent.KEYCODE_F4:
if (event.isAltPressed()) {
if (panel != null) {
Activity activity = panel.getActivity();
if (activity != null) {
openBookmarkList(activity);
}
}
} else {
if (panel != null) {
panel.showSelectDialog();
}
}
return true;
case KeyEvent.KEYCODE_F5:
getActivePanel().copy(getInactivePanel());
return true;
case KeyEvent.KEYCODE_F6:
getActivePanel().move(getInactivePanel(), false);
return true;
case KeyEvent.KEYCODE_F7:
getActivePanel().createFile(getInactivePanel());
return true;
case KeyEvent.KEYCODE_F8:
getActivePanel().delete(getInactivePanel());
return true;
case KeyEvent.KEYCODE_F9:
getActivePanel().showSearchDialog();
return true;
case KeyEvent.KEYCODE_F10:
if (panel != null) {
Activity activity = panel.getActivity();
if (activity != null) {
activity.startActivity(new Intent(App.sInstance.getApplicationContext(), Help.class));
}
}
return true;
case KeyEvent.KEYCODE_F11:
if (panel != null) {
Activity activity = panel.getActivity();
if (activity != null) {
activity.startActivity(new Intent(App.sInstance.getApplicationContext(), SettingsActivity.class));
}
}
return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
case KeyEvent.KEYCODE_DPAD_RIGHT:
return true;
case KeyEvent.KEYCODE_DPAD_DOWN:
if (event.isShiftPressed()) {
getActivePanel().selectCurrentFile(1);
}
return true;
case KeyEvent.KEYCODE_DPAD_UP:
if (event.isShiftPressed()) {
getActivePanel().selectCurrentFile(-1);
}
return true;
}
return false;
}
private Runnable mDismissProgressRunnable = new Runnable() {
@Override
public void run() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
mProgressDialog = null;
}
}
};
private Runnable mShowProgressRunnable = new Runnable() {
@Override
public void run() {
if (mProgressDialog != null && mProgressDialog.isShowing()) {
dismissProgressDialog();
}
mProgressDialog = new Dialog(getActivePanel().getActivity(), android.R.style.Theme_Translucent);
mProgressDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
mProgressDialog.setCancelable(false);
mProgressDialog.setContentView(R.layout.dialog_progress);
mProgressDialog.show();
}
};
}