package de.theknut.xposedgelsettings.hooks.appdrawer.tabsandfolders;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.Color;
import android.os.AsyncTask;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import de.theknut.xposedgelsettings.hooks.Common;
import de.theknut.xposedgelsettings.hooks.ObfuscationHelper;
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.hooks.appdrawer.tabsandfolders.TabHelper.ContentType;
import de.theknut.xposedgelsettings.ui.CommonUI;
import static de.robv.android.xposed.XposedHelpers.callMethod;
import static de.robv.android.xposed.XposedHelpers.getIntField;
import static de.robv.android.xposed.XposedHelpers.getObjectField;
import static de.robv.android.xposed.XposedHelpers.getStaticObjectField;
import static de.robv.android.xposed.XposedHelpers.newInstance;
/**
* Created by Alexander Schulz on 21.08.2014.
*/
public class Tab extends AppDrawerItem {
public static int DEFAULT_COLOR = 0xFFF4F4F4;
public static int DEFAULT_TEXT_COLOR = 0xFF666666;
public static final String KEY_PREFIX= "tab";
public static final int APPS_ID = 0xABB5;
public static final int WIDGETS_ID = 0xBEEF;
private ContentType contentType = ContentType.User;
private int color = DEFAULT_COLOR;
private boolean initialized = false;
private Object GelAppFilter;
public Tab(String tabCfg) {
this(tabCfg, true);
}
public Tab(String tabCfg, boolean initData) {
String[] settings = tabCfg.split("\\|");
for (String setting : settings) {
if (setting.startsWith("idx=")) {
this.idx = Integer.parseInt(setting.split("=")[1]);
} else if (setting.startsWith("id=")) {
this.id = Long.parseLong(setting.split("=")[1]);
} else if (setting.startsWith("title=")) {
this.title = setting.split("=")[1];
} else if (setting.startsWith("contenttype=")) {
this.contentType = ContentType.valueOf(setting.split("=")[1]);
} else if (setting.startsWith("hide=")) {
this.hideFromAppsPage = Boolean.parseBoolean(setting.split("=")[1]);
} else if (setting.startsWith("sort=")) {
this.sortType = SortType.valueOf(setting.split("=")[1]);
} else if (setting.startsWith("color=")) {
this.color = Integer.parseInt(setting.split("=")[1]);
}
}
if (initData) initData();
}
public Tab(Intent intent, boolean initData) {
this.id = intent.getLongExtra("itemid", -1);
this.idx = intent.getIntExtra("index", -1);
this.title = intent.getStringExtra("name");
this.contentType = ContentType.valueOf(intent.getStringExtra("contenttype"));
this.hideFromAppsPage = intent.getBooleanExtra("hide", false);
this.color = intent.getIntExtra("color", DEFAULT_COLOR);
if (initData) initData();
}
public Tab(Intent intent, boolean initData, boolean add) {
this.id = intent.getLongExtra("itemid", -1);
this.idx = intent.getIntExtra("index", -1);
this.title = intent.getStringExtra("name");
this.contentType = ContentType.valueOf(intent.getStringExtra("contenttype"));
this.hideFromAppsPage = intent.getBooleanExtra("hide", false);
this.color = intent.getIntExtra("color", DEFAULT_COLOR);
if (initData) initData(add);
}
public void initData() {
initData(false);
}
public void initData(final boolean add) {
GelAppFilter = Common.IS_M_GNL ? newInstance(ObfuscationHelper.Classes.GelAppFilter) : null;
initialized = false;
final Tab tab = this;
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
if (isUserTab()) {
parseData();
} else if (isGoogleTab()) {
data = getGoogleApps();
} else if (isXposedTab()) {
data = getXposedModules();
} else if (isIconPacksTab()) {
data = getIconPacks();
sort(data);
} else if (isNewUpdatedTab()) {
data = getNewUpdatedApps();
setSortType(SortType.LastUpdate);
sort(data);
} else if (isNewAppsTab()) {
data = getNewApps();
setSortType(SortType.LastInstall);
sort(data);
} else if (Common.IS_M_GNL && isAppsTab()) {
data = new ArrayList(Common.ALL_APPS);
setSortType(getSortType());
sort(data);
removeAppsToHide();
}
if (data != null) {
// remove duplicates
Set<String> hs = new LinkedHashSet<>();
hs.addAll(data);
data.clear();
data.addAll(hs);
}
return null;
}
private void removeAppsToHide() {
List<String> packages = new ArrayList<String>();
if (PreferencesHelper.iconPackHide) {
packages = CommonUI.getIconPacks(Common.LAUNCHER_CONTEXT);
}
ArrayList<String> appsToHide = new ArrayList<String>(PreferencesHelper.hiddenApps);
appsToHide.addAll(TabHelper.getInstance().getAppsToHide());
appsToHide.addAll(FolderHelper.getInstance().getAppsToHide());
appsToHide.addAll(getWorkspaceIcons());
Iterator it = data.iterator();
while(it.hasNext()) {
Object appInfo = it.next();
ComponentName componentName = (ComponentName) getObjectField(appInfo, Fields.aiComponentName);
if (appsToHide.contains(componentName.flattenToString())
|| packages.contains(componentName.getPackageName())) {
// remove it from the allAppsList if it is in our list
it.remove();
}
}
}
private ArrayList<String> getWorkspaceIcons() {
ArrayList<String> appsToHide = new ArrayList<String>();
if (PreferencesHelper.autoHideHomeIcons) {
ArrayList workspaceItems = (ArrayList) getStaticObjectField(ObfuscationHelper.Classes.LauncherModel, Fields.lmWorkspaceItems);
for (Object workspaceItem : workspaceItems) {
if (workspaceItem.getClass().equals(ObfuscationHelper.Classes.ShortcutInfo)) {
Intent i = (Intent) callMethod(workspaceItem, "getIntent");
if (i != null && i.getComponent() != null) {
appsToHide.add(i.getComponent().flattenToString());
}
}
}
Iterator it = (Iterator) callMethod(getStaticObjectField(ObfuscationHelper.Classes.LauncherModel, Fields.lmFolders), "iterator");
while(it.hasNext()) {
Object item = it.next();
if (!item.getClass().equals(ObfuscationHelper.Classes.FolderInfo)) continue;
for (Object folderItem : ((ArrayList) getObjectField(item, Fields.fiContents))) {
if (folderItem.getClass().equals(ObfuscationHelper.Classes.ShortcutInfo)) {
Intent i = (Intent) callMethod(folderItem, "getIntent");
if (i != null && i.getComponent() != null) {
appsToHide.add(i.getComponent().flattenToString());
}
}
}
}
}
return appsToHide;
}
@Override
protected void onPostExecute(Void aVoid) {
if (Common.IS_M_GNL) {
if (TabHelper.getInstance().getCurrentTabData().getId() == tab.getId()) {
TabHelperM.getInstance().setCurrentTab(tab);
}
if (add) {
TabHelperM.getInstance().addTab(tab);
Intent saveIntent = TabHelper.getInstance().getBaseIntent(tab.isUserTab(), tab.getId(), tab.getTitle());
saveIntent.putExtra("contenttype", tab.getContentType().toString());
saveIntent.putExtra("new", true);
saveIntent.putExtra("index", tab.getIndex());
Common.LAUNCHER_CONTEXT.startActivity(saveIntent);
}
return;
} else {
ArrayList allApps = (ArrayList) getObjectField(Common.APP_DRAWER_INSTANCE, Fields.acpvAllApps);
callMethod(Common.APP_DRAWER_INSTANCE, Methods.acpvSetApps, allApps);
}
if (add) {
TabHelperL.getInstance().addTab(tab);
}
else if (TabHelper.getInstance().getCurrentTabData().equals(tab)) {
TabHelper.getInstance().invalidate();
}
initialized = true;
}
}.execute();
}
public ContentType getContentType() {
return contentType;
}
public int getPrimaryColor() {
if (Common.IS_PRE_GNL_4) {
return this.color;
}
return this.color == Color.WHITE ? DEFAULT_COLOR : this.color;
}
// http://stackoverflow.com/a/4928826/809277
public int getSecondaryColor() {
float[] hsv = new float[3];
Color.colorToHSV(getPrimaryColor(), hsv);
hsv[2] *= 0.9f;
return Color.HSVToColor(hsv);
}
public int getContrastColor() {
return Utils.getContrastColor(getPrimaryColor());
}
public void setColor(int color) {
this.color = color;
}
public boolean isUserTab() {
return contentType.equals(ContentType.User);
}
public boolean isWidgetsTab() {
return contentType.equals(ContentType.Widgets);
}
public boolean isXposedTab() {
return contentType.equals(ContentType.Xposed);
}
public boolean isGoogleTab() {
return contentType.equals(ContentType.Google);
}
public boolean isNewUpdatedTab() {
return contentType.equals(ContentType.NewUpdated);
}
public boolean isNewAppsTab() {
return contentType.equals(ContentType.NewApps);
}
private boolean isIconPacksTab() {
return this.contentType.equals(ContentType.IconPacks);
}
public boolean isAppsTab() {
return getId() == APPS_ID;
}
public boolean isCustomTab() {
return isUserTab() || isDynamicTab();
}
public boolean isDynamicTab() {
return isGoogleTab() || isXposedTab() || isNewUpdatedTab() || isNewAppsTab() || isIconPacksTab();
}
public boolean isInitialized() {
return this.initialized;
}
private void parseData() {
parseData(KEY_PREFIX);
}
public ArrayList getRawData() {
return getRawData(KEY_PREFIX);
}
@Override
public void setSortType(SortType type) {
super.setSortType(type);
if (isCustomTab()) sort(getData());
}
private ArrayList getXposedModules() {
final PackageManager pm = Common.LAUNCHER_CONTEXT.getPackageManager();
this.rawData = new ArrayList();
List<ApplicationInfo> apps = pm.getInstalledApplications(PackageManager.GET_META_DATA);
ArrayList modules = new ArrayList();
for (ApplicationInfo app : apps) {
if (app.metaData != null && app.metaData.getBoolean("xposedmodule", false)) {
Intent i = pm.getLaunchIntentForPackage(app.packageName);
if (i != null) {
if (!shouldShowAppInTab(i.getComponent())) continue;
Object module = Utils.createAppInfo(i.getComponent());
if (module == null) continue;
modules.add(module);
rawData.add(i.getComponent().flattenToString());
}
}
}
Intent i = pm.getLaunchIntentForPackage("de.robv.android.xposed.installer");
if (i != null && shouldShowAppInTab(i.getComponent())) {
Object module = Utils.createAppInfo(i.getComponent());
if (module != null) {
modules.add(module);
rawData.add(i.getComponent().flattenToString());
}
}
sort(modules);
return modules;
}
private ArrayList getGoogleApps() {
ArrayList<String> google = new ArrayList<String> (Arrays.asList("com.android.vending", "com.quickoffice.android", "com.android.chrome", "com.chrome.beta", "com.google.earth", "com.google.chromeremotedesktop"));
ArrayList<String> exclude = new ArrayList<String> (Arrays.asList("com.google.android.diskusage"));
ArrayList modules = new ArrayList();
this.rawData = new ArrayList();
for (ResolveInfo app : Utils.getAllApps()) {
String pkg = app.activityInfo.packageName;
if (pkg.contains("com.google.android.") || google.contains(pkg) && !exclude.contains(pkg)) {
ComponentName cmp = new ComponentName(pkg, app.activityInfo.name);
if (!shouldShowAppInTab(cmp)) continue;
Object module = Utils.createAppInfo(cmp);
if (module == null) continue;
modules.add(module);
rawData.add(cmp.flattenToString());
}
}
sort(modules);
return modules;
}
private ArrayList getNewUpdatedApps() {
ArrayList apps = new ArrayList();
this.rawData = new ArrayList();
for (ResolveInfo app : Utils.getAllApps()) {
ComponentName cmp = new ComponentName(app.activityInfo.packageName, app.activityInfo.name);
if (!shouldShowAppInTab(cmp)) continue;
Object module = Utils.createAppInfo(cmp);
if (module == null) continue;
apps.add(module);
rawData.add(cmp.flattenToString());
}
return apps;
}
private ArrayList getNewApps() {
ArrayList apps = new ArrayList();
this.rawData = new ArrayList();
for (ResolveInfo app : Utils.getAllApps()) {
ComponentName cmp = new ComponentName(app.activityInfo.packageName, app.activityInfo.name);
if (!shouldShowAppInTab(cmp)) continue;
Object module = Utils.createAppInfo(cmp);
if (module == null) continue;
apps.add(module);
rawData.add(cmp.flattenToString());
}
return apps;
}
private ArrayList getIconPacks() {
PackageManager packageManager = Common.LAUNCHER_CONTEXT.getPackageManager();
List<String> packages = new ArrayList<String>();
ArrayList apps = new ArrayList();
this.rawData = new ArrayList();
Intent i = new Intent();
String[] sIconPackCategories = new String[] {
"com.fede.launcher.THEME_ICONPACK",
"com.anddoes.launcher.THEME",
"com.teslacoilsw.launcher.THEME"
};
String[] sIconPackActions = new String[] {
"org.adw.launcher.THEMES",
"com.gau.go.launcherex.theme"
};
for (String action : sIconPackActions) {
i.setAction(action);
for (ResolveInfo r : packageManager.queryIntentActivities(i, 0)) {
if (!packages.contains(r.activityInfo.packageName))
packages.add(r.activityInfo.packageName);
}
}
i = new Intent(Intent.ACTION_MAIN);
for (String category : sIconPackCategories) {
i.addCategory(category);
for (ResolveInfo r : packageManager.queryIntentActivities(i, 0)) {
if (!packages.contains(r.activityInfo.packageName))
packages.add(r.activityInfo.packageName);
}
i.removeCategory(category);
}
for (String pkg : packages) {
Intent li = packageManager.getLaunchIntentForPackage(pkg);
if (li != null && shouldShowAppInTab(li.getComponent())) {
Object app = Utils.createAppInfo(li.getComponent());
if (app == null) continue;
apps.add(app);
rawData.add(li.getComponent().flattenToString());
}
}
return apps;
}
public int getPageCount() {
if ((isAppsTab() || isUserTab()) && FolderHelper.getInstance().hasFolder()) {
int mCellCountX = getIntField(Common.APP_DRAWER_INSTANCE, Fields.acpvCellCountX);
int mCellCountY = getIntField(Common.APP_DRAWER_INSTANCE, Fields.acpvCellCountY);
int itemCnt = FolderHelper.getInstance().getFoldersForTab(getId()).size();
itemCnt += isAppsTab() ? FolderHelper.getInstance().getAllApps().size() : getData().size();
return (int) Math.ceil((float) itemCnt / (mCellCountX * mCellCountY));
} else if (isCustomTab() && getData() != null) {
int mCellCountX = getIntField(Common.APP_DRAWER_INSTANCE, Fields.acpvCellCountX);
int mCellCountY = getIntField(Common.APP_DRAWER_INSTANCE, Fields.acpvCellCountY);
return (int) Math.ceil((float) getData().size() / (mCellCountX * mCellCountY));
} else if (isNewAppsTab() || isNewUpdatedTab()) {
return 1;
}
return 3;
}
private boolean shouldShowAppInTab(ComponentName cmp) {
return !PreferencesHelper.hiddenApps.contains(cmp.flattenToString())
|| (Boolean) callMethod(GelAppFilter, "shouldShowApp", cmp);
}
public void update() {
initData();
}
@Override
public boolean hideFromAppsPage() {
return super.hideFromAppsPage()
|| (isIconPacksTab() && PreferencesHelper.iconPackHide);
}
@Override
public String toString() {
return super.toString() + "|"
+ "contenttype=" + getContentType() + "|"
+ "color=" + getPrimaryColor();
}
}