package de.theknut.xposedgelsettings.hooks.appdrawer.tabsandfolders; import android.app.AlertDialog; import android.content.ComponentName; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.os.Handler; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import de.theknut.xposedgelsettings.R; import de.theknut.xposedgelsettings.hooks.Common; import de.theknut.xposedgelsettings.hooks.ObfuscationHelper.Classes; import de.theknut.xposedgelsettings.hooks.ObfuscationHelper.Fields; import de.theknut.xposedgelsettings.hooks.ObfuscationHelper.Methods; import de.theknut.xposedgelsettings.hooks.PreferencesHelper; import de.theknut.xposedgelsettings.hooks.Utils; import de.theknut.xposedgelsettings.ui.AllAppsList; import de.theknut.xposedgelsettings.ui.SaveActivity; import static de.robv.android.xposed.XposedHelpers.callMethod; import static de.robv.android.xposed.XposedHelpers.getLongField; import static de.robv.android.xposed.XposedHelpers.getObjectField; /** * Created by Alexander Schulz on 26.09.2014. */ public final class FolderHelper { private static final FolderHelper INSTANCE = new FolderHelper(); private Context XGELSContext; private ArrayList<Folder> folders; private AlertDialog folderSettingsDialog; public static FolderHelper getInstance() { return INSTANCE; } public void init() { this.XGELSContext = Common.XGELS_CONTEXT; this.folders = new ArrayList<Folder>(); initFolders(); } private void initFolders() { for (String item : PreferencesHelper.appdrawerFolderData) { folders.add(Common.IS_M_GNL ? new FolderM(item) : new FolderL(item)); } Collections.sort(folders, new Comparator<Folder>() { @Override public int compare(Folder lhs, Folder rhs) { return lhs.getIndex() - rhs.getIndex(); } }); if (Common.IS_M_GNL) { for (Folder folder : folders) { folder.initData(); folder.makeFolderIcon((ViewGroup) getObjectField(Common.APP_DRAWER_INSTANCE, "mAppsRecyclerView")); } } } public boolean hasFolder() { return folders.size() != 0; } public ArrayList<Folder> getFoldersForTab(long tabId) { ArrayList<Folder> folders = new ArrayList<Folder>(); for (Folder folder : this.folders) { if (folder.getTabId() == tabId) { folders.add(folder); } } return folders; } public Folder getFolder(long id) { for (Folder folder : folders) { if (folder.getId() == id) { return folder; } } return null; } public ArrayList getAllApps() { return ((ArrayList) getObjectField(getObjectField(Common.LAUNCHER_INSTANCE, Fields.lAppsCustomizePagedView), Fields.acpvAllApps)); } public void addFolder(Folder folder) { folders.add(folder); TabHelper.getInstance().invalidate(); Toast.makeText(Common.LAUNCHER_CONTEXT, XGELSContext.getString(R.string.toast_appdrawer_folderadded_title), Toast.LENGTH_LONG).show(); Toast.makeText(Common.LAUNCHER_CONTEXT, XGELSContext.getString(R.string.toast_appdrawer_folderadded_title), Toast.LENGTH_LONG).show(); } private void syncIndexes() { int i = 0; Collections.sort(folders, new Comparator<Folder>() { @Override public int compare(Folder lhs, Folder rhs) { return lhs.getIndex() - rhs.getIndex(); } }); Iterator<Folder> it = folders.iterator(); while (it.hasNext()) { it.next().setIndex(i++); } } public void setupFolderSettings(final Folder folder) { setupFolderSettings(folder, folder.getTabId()); } public void setupFolderSettings(final Folder folder, final long tabId) { boolean newFolder = folder == null; final ViewGroup folderSettingsView = (ViewGroup) LayoutInflater.from(Common.XGELS_CONTEXT).inflate(R.layout.folder_settings_view, null); final EditText editText = (EditText) folderSettingsView.findViewById(R.id.foldername); if (newFolder) { folderSettingsView.findViewById(R.id.folder_settings_bar).setVisibility(View.GONE); folderSettingsView.findViewById(R.id.folder_settings_additional).setVisibility(View.GONE); } else { editText.setText(folder.getTitle()); } int padding = Math.round(XGELSContext.getResources().getDimension(R.dimen.folder_menu_padding)); folderSettingsDialog = new AlertDialog.Builder(Common.LAUNCHER_INSTANCE, AlertDialog.THEME_DEVICE_DEFAULT_DARK).create(); folderSettingsDialog.setView(folderSettingsView, padding, padding, padding, padding); if (!newFolder) { ImageView save = (ImageView) folderSettingsView.findViewById(R.id.folder_save_settings); Utils.setDrawableSelector(save); save.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { folderSettingsDialog.dismiss(); String title = editText.getText().toString().trim(); if (!folder.getTitle().equals(title)) { for (Folder folder1 : folders) { if (folder.getId() == folder1.getId()) { folder1.setTitle(title); ((TextView) getObjectField(folder.getFolderIcon(), Fields.fiFolderName)).setText(folder.getTitle()); ((EditText) getObjectField(getObjectField(folder.getFolderIcon(), Fields.fiFolder), Fields.fFolderEditText)).setText(folder.getTitle()); Intent intent = getBaseIntent(false, folder.getId(), folder.getTitle()); Common.LAUNCHER_CONTEXT.startActivity(intent); } } } } }); final ImageView manageApps = (ImageView) folderSettingsView.findViewById(R.id.manageapps); manageApps.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { folderSettingsDialog.dismiss(); ArrayList<String> items = new ArrayList<String>(); Object mFolder = getObjectField(folder.getFolderIcon(), Fields.fiFolder); ArrayList<View> folderItems = (ArrayList<View>) callMethod(mFolder, Methods.fGetItemsInReadingOrder); for (View item : folderItems) { items.add(((Intent) callMethod(item.getTag(), "getIntent")).getComponent().flattenToString()); } String folderName = "" + ((TextView) getObjectField(folder.getFolderIcon(), Fields.fiFolderName)).getText(); Intent intent = getBaseIntent(true, getLongField(folder.getFolderIcon().getTag(), Fields.iiID), folderName); intent.setComponent(new ComponentName(Common.PACKAGE_NAME, AllAppsList.class.getName())); intent.putExtra("mode", AllAppsList.MODE_SELECT_FOLDER_APPS); intent.putExtra("save", true); intent.putStringArrayListExtra("items", items); Common.LAUNCHER_CONTEXT.startActivity(intent); Common.CURRENT_CONTEXT_MENU_ITEM = folder.getFolderIcon(); } }); Utils.setDrawableSelector(manageApps); final ImageView deleteFolder = (ImageView) folderSettingsView.findViewById(R.id.deletefolder); deleteFolder.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Toast.makeText(Common.LAUNCHER_CONTEXT, XGELSContext.getString(R.string.toast_tab_delete), Toast.LENGTH_LONG).show(); } }); deleteFolder.setOnLongClickListener(new View.OnLongClickListener() { @Override public boolean onLongClick(View v) { folderSettingsDialog.dismiss(); long itemid = folder.getId(); removeFolder(folder); if (Common.IS_M_GNL) { TabHelper.getInstance().updateTabs(); } else { TabHelper.getInstance().invalidate(); } Intent intent = getBaseIntent(false, itemid, null); Common.LAUNCHER_CONTEXT.startActivity(intent); return true; } }); Utils.setDrawableSelector(deleteFolder); final CheckBox hideApps = (CheckBox) folderSettingsView.findViewById(R.id.folder_hide_apps); hideApps.setChecked(folder.hideFromAppsPage()); hideApps.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { folder.setHideFromAppsPage(isChecked); Intent intent = getBaseIntent(false, folder.getId(), folder.getTitle()); Common.LAUNCHER_CONTEXT.startActivity(intent); if (Common.IS_M_GNL) { TabHelper.getInstance().updateTabs(); } else { ArrayList allApps = (ArrayList) getObjectField(Common.APP_DRAWER_INSTANCE, Fields.acpvAllApps); for (String app : folder.getRawData()) { allApps.add(Utils.createAppInfo(ComponentName.unflattenFromString(app))); } callMethod(Common.APP_DRAWER_INSTANCE, Methods.acpvSetApps, allApps); TabHelper.getInstance().invalidate(); } } }); } else { folderSettingsView.findViewById(R.id.folder_save_settings).setVisibility(View.GONE); folderSettingsDialog.setButton(DialogInterface.BUTTON_POSITIVE, XGELSContext.getString(android.R.string.ok), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String newTabName = editText.getText().toString().trim(); if (newTabName.length() == 0) { folderSettingsDialog.dismiss(); return; } Intent intent = getBaseIntent(true, getNewFolderId(), newTabName); intent.putExtra("new", true); intent.putExtra("index", getFoldersForTab(tabId).size()); intent.putExtra("tabid", tabId); Common.LAUNCHER_CONTEXT.startActivity(intent); } }); folderSettingsDialog.setButton(DialogInterface.BUTTON_NEGATIVE, XGELSContext.getString(android.R.string.cancel), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { folderSettingsDialog.dismiss(); } }); } folderSettingsDialog.show(); } public void removeFolders(ArrayList<Folder> folders) { for (Folder folder : folders) { removeFolder(folder); } Common.LAUNCHER_INSTANCE.runOnUiThread(new Runnable() { @Override public void run() { new Handler().postDelayed(new Runnable() { @Override public void run() { Intent intent = getBaseIntent(false, 0, null); Common.LAUNCHER_CONTEXT.startActivity(intent); } }, 500); } }); } public void removeFolder(Folder folder) { if (folders.contains(folder)) { folders.remove(folder); if (folder.hideFromAppsPage()) { if (Common.IS_M_GNL) { TabHelper.getInstance().updateTabs(); } else { ArrayList allApps = (ArrayList) getObjectField(Common.APP_DRAWER_INSTANCE, Fields.acpvAllApps); for (String app : folder.getRawData()) { allApps.add(Utils.createAppInfo(ComponentName.unflattenFromString(app))); } callMethod(Common.APP_DRAWER_INSTANCE, Methods.acpvSetApps, allApps); } } } } public ArrayList<String> getAppsToHide() { ArrayList apps = new ArrayList(); for (Folder folder : folders) { if (folder.hideFromAppsPage()) { apps.addAll(folder.getRawData()); } } return apps; } public long getNewFolderId() { int i = 0; long[] ids = new long[folders.size()]; Iterator<Folder> it = folders.iterator(); while (it.hasNext()) { ids[i++] = it.next().getId(); } Arrays.sort(ids); long lastId = -1; for (long id : ids) { if (id > (lastId + 1)) { return ++lastId; } lastId = id; } return ++lastId; } private Intent getBaseIntent(boolean openVisible, long itemid, String foldername) { Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); intent.setComponent(new ComponentName(Common.PACKAGE_NAME, openVisible ? AllAppsList.class.getName() : SaveActivity.class.getName())); intent.putExtra("mode", AllAppsList.MODE_MANAGE_FOLDER); intent.putExtra("itemid", itemid); intent.putExtra("name", foldername); syncIndexes(); ArrayList<String> excludeApps = new ArrayList<String>(); ArrayList<String> data = new ArrayList<String>(folders.size()); for (Folder folder : folders) { data.add(folder.toString()); if (folder.getId() != itemid) { excludeApps.addAll(folder.getRawData()); } } if (openVisible) { intent.putExtra("excludeapps", excludeApps); } intent.putExtra("folderdata", data); return intent; } public Folder findOpenFolder() { for (int i = 0; i < Common.DRAG_LAYER.getChildCount(); i++) { View child = Common.DRAG_LAYER.getChildAt(i); if (child.getClass().equals(Classes.Folder)) { long id = getLongField(getObjectField(child, Fields.fFolderInfo), Fields.iiID); return FolderHelper.getInstance().getFolder(id); } } return null; } public void updateFolders(String pkg) { for (Folder folder : folders) { if (folder.contains(pkg)) { folder.invalidate(); } } } }