diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bf18e1dd..cb5a1f08 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -34,12 +34,6 @@ android:name=".ui.activity.EdDownloadActivity" android:label="@string/Install" /> - - diff --git a/app/src/main/java/org/meowcat/edxposed/manager/App.java b/app/src/main/java/org/meowcat/edxposed/manager/App.java index e952e094..fb48588b 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/App.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/App.java @@ -120,8 +120,6 @@ public class App extends Application implements Application.ActivityLifecycleCal } catch (PackageManager.NameNotFoundException ignored) { } } - - //RepoLoader.getInstance().triggerFirstLoadIfNecessary(); } private void registerReceivers() { @@ -142,19 +140,6 @@ public class App extends Application implements Application.ActivityLifecycleCal mkdir("log"); } - /* - public void updateProgressIndicator(final SwipeRefreshLayout refreshLayout) { - final boolean isLoading = RepoLoader.getInstance().isLoading() || ModuleUtil.getInstance().isLoading(); - runOnUiThread(() -> { - synchronized (App.this) { - if (currentActivity != null) { - if (refreshLayout != null) - refreshLayout.setRefreshing(isLoading); - } - } - }); - } - */ @Override public synchronized void onActivityCreated(@NonNull Activity activity, Bundle savedInstanceState) { if (isUiLoaded) { @@ -182,13 +167,12 @@ public class App extends Application implements Application.ActivityLifecycleCal @Override public synchronized void onActivityResumed(@NonNull Activity activity) { - //currentActivity = (AppCompatActivity) activity; - //updateProgressIndicator(null); + } @Override public synchronized void onActivityPaused(@NonNull Activity activity) { - //currentActivity = null; + } @Override diff --git a/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppAdapter.java b/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppAdapter.java index 1c985623..f8b97612 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppAdapter.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppAdapter.java @@ -6,6 +6,7 @@ import android.content.SharedPreferences; import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.os.AsyncTask; import android.text.TextUtils; @@ -32,7 +33,6 @@ import com.bumptech.glide.request.transition.Transition; import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.util.GlideApp; -import org.meowcat.edxposed.manager.util.InstallApkUtil; import java.text.DateFormat; import java.text.SimpleDateFormat; @@ -277,7 +277,7 @@ public class AppAdapter extends RecyclerView.Adapter impl @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { ApplicationInfo info = showList.get(position); - holder.appName.setText(InstallApkUtil.getAppLabel(info, pm)); + holder.appName.setText(getAppLabel(info, pm)); try { PackageInfo packageInfo = pm.getPackageInfo(info.packageName, 0); GlideApp.with(holder.appIcon) @@ -387,7 +387,7 @@ public class AppAdapter extends RecyclerView.Adapter impl ArrayList filtered = new ArrayList<>(); String filter = constraint.toString().toLowerCase(); for (ApplicationInfo info : fullList) { - if (lowercaseContains(InstallApkUtil.getAppLabel(info, pm), filter) + if (lowercaseContains(getAppLabel(info, pm), filter) || lowercaseContains(info.packageName, filter)) { filtered.add(info); } @@ -402,4 +402,15 @@ public class AppAdapter extends RecyclerView.Adapter impl notifyDataSetChanged(); } } + + public static String getAppLabel(ApplicationInfo info, PackageManager pm) { + try { + if (info.labelRes > 0) { + Resources res = pm.getResourcesForApplication(info); + return res.getString(info.labelRes); + } + } catch (Exception ignored) { + } + return info.loadLabel(pm).toString(); + } } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/adapters/CursorRecyclerViewAdapter.java b/app/src/main/java/org/meowcat/edxposed/manager/adapters/CursorRecyclerViewAdapter.java deleted file mode 100644 index 7c6a336c..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/adapters/CursorRecyclerViewAdapter.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.meowcat.edxposed.manager.adapters; - -import android.database.Cursor; -import android.database.DataSetObserver; - -import androidx.annotation.NonNull; -import androidx.recyclerview.widget.RecyclerView; - -public abstract class CursorRecyclerViewAdapter extends RecyclerView.Adapter { - - private Cursor cursor; - - private boolean dataValid; - - private int rowIdColumn; - - private final DataSetObserver dataSetObserver; - - public CursorRecyclerViewAdapter(Cursor cursor) { - this.cursor = cursor; - dataValid = cursor != null; - rowIdColumn = dataValid ? cursor.getColumnIndex("_id") : -1; - dataSetObserver = new NotifyingDataSetObserver(); - if (this.cursor != null) { - this.cursor.registerDataSetObserver(dataSetObserver); - } - } - - protected Cursor getCursor() { - return cursor; - } - - @Override - public int getItemCount() { - if (dataValid && cursor != null) { - return cursor.getCount(); - } - return 0; - } - - @Override - public long getItemId(int position) { - if (dataValid && cursor != null && cursor.moveToPosition(position)) { - return cursor.getLong(rowIdColumn); - } - return 0; - } - - @Override - public void setHasStableIds(boolean hasStableIds) { - super.setHasStableIds(true); - } - - public abstract void onBindViewHolder(VH viewHolder, Cursor cursor); - - @Override - public void onBindViewHolder(@NonNull VH viewHolder, int position) { - if (!dataValid) { - throw new IllegalStateException("this should only be called when the cursor is valid"); - } - if (!cursor.moveToPosition(position)) { - throw new IllegalStateException("couldn't move cursor to position " + position); - } - onBindViewHolder(viewHolder, cursor); - } - - /** - * Change the underlying cursor to a new cursor. If there is an existing cursor it will be - * closed. - */ - public void changeCursor(Cursor cursor) { - Cursor old = swapCursor(cursor); - if (old != null) { - old.close(); - } - } - - /** - * Swap in a new Cursor, returning the old Cursor. Unlike - * {@link #changeCursor(Cursor)}, the returned old Cursor is not - * closed. - */ - private Cursor swapCursor(Cursor newCursor) { - if (newCursor == cursor) { - return null; - } - final Cursor oldCursor = cursor; - if (oldCursor != null && dataSetObserver != null) { - oldCursor.unregisterDataSetObserver(dataSetObserver); - } - cursor = newCursor; - if (cursor != null) { - if (dataSetObserver != null) { - cursor.registerDataSetObserver(dataSetObserver); - } - rowIdColumn = newCursor.getColumnIndexOrThrow("_id"); - dataValid = true; - } else { - rowIdColumn = -1; - dataValid = false; - //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter - } - notifyDataSetChanged(); - return oldCursor; - } - - private class NotifyingDataSetObserver extends DataSetObserver { - @Override - public void onChanged() { - super.onChanged(); - dataValid = true; - notifyDataSetChanged(); - } - - @Override - public void onInvalidated() { - super.onInvalidated(); - dataValid = false; - notifyDataSetChanged(); - //There is no notifyDataSetInvalidated() method in RecyclerView.Adapter - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/receivers/BootReceiver.java b/app/src/main/java/org/meowcat/edxposed/manager/receivers/BootReceiver.java deleted file mode 100644 index cb6d1083..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/receivers/BootReceiver.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.meowcat.edxposed.manager.receivers; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import org.json.JSONObject; -import org.meowcat.edxposed.manager.BuildConfig; -import org.meowcat.edxposed.manager.util.NotificationUtil; -import org.meowcat.edxposed.manager.util.TaskRunner; -import org.meowcat.edxposed.manager.util.json.JSONUtils; - -import java.util.concurrent.Callable; - -public class BootReceiver extends BroadcastReceiver { - - @Override - public void onReceive(final Context context, Intent intent) { - //new TaskRunner().executeAsync(new LongRunningTask()); - } - - private static class LongRunningTask implements Callable { - - @Override - public Void call() { - try { - Thread.sleep(60 * 60 * 1000); - String jsonString = JSONUtils.getFileContent(JSONUtils.JSON_LINK).replace("%XPOSED_ZIP%", ""); - - String newApkVersion = new JSONObject(jsonString).getJSONObject("apk").getString("version"); - - Integer a = BuildConfig.VERSION_CODE; - Integer b = Integer.valueOf(newApkVersion); - - if (a.compareTo(b) < 0) { - NotificationUtil.showInstallerUpdateNotification(); - } - } catch (Exception e) { - e.printStackTrace(); - } - return null; - } - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/repo/Module.java b/app/src/main/java/org/meowcat/edxposed/manager/repo/Module.java deleted file mode 100644 index 83e76989..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/repo/Module.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.meowcat.edxposed.manager.repo; - -import android.util.Pair; - -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; - -public class Module { - @SuppressWarnings("WeakerAccess") - public final Repository repository; - public final List> moreInfo = new LinkedList<>(); - public final List versions = new ArrayList<>(); - final List screenshots = new ArrayList<>(); - public String packageName; - public String name; - public String summary; - public String description; - public boolean descriptionIsHtml = false; - public String author; - public String support; - long created = -1; - long updated = -1; - - Module(Repository repository) { - this.repository = repository; - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/repo/ModuleVersion.java b/app/src/main/java/org/meowcat/edxposed/manager/repo/ModuleVersion.java deleted file mode 100644 index 299a0da0..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/repo/ModuleVersion.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.meowcat.edxposed.manager.repo; - -public class ModuleVersion { - public final Module module; - public String name; - public int code; - public String downloadLink; - public String md5sum; - public String changelog; - public boolean changelogIsHtml = false; - public ReleaseType relType = ReleaseType.STABLE; - public long uploaded = -1; - - /* package */ ModuleVersion(Module module) { - this.module = module; - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/repo/ReleaseType.java b/app/src/main/java/org/meowcat/edxposed/manager/repo/ReleaseType.java deleted file mode 100644 index 2e549a9a..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/repo/ReleaseType.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.meowcat.edxposed.manager.repo; - - -import org.meowcat.edxposed.manager.R; - -public enum ReleaseType { - STABLE(R.string.reltype_stable, R.string.reltype_stable_summary), BETA(R.string.reltype_beta, R.string.reltype_beta_summary), EXPERIMENTAL(R.string.reltype_experimental, R.string.reltype_experimental_summary); - - private static final ReleaseType[] sValuesCache = values(); - private final int mTitleId; - private final int mSummaryId; - - ReleaseType(int titleId, int summaryId) { - mTitleId = titleId; - mSummaryId = summaryId; - } - - public static ReleaseType fromString(String value) { - if (value == null || value.equals("stable")) - return STABLE; - else if (value.equals("beta")) - return BETA; - else if (value.equals("experimental")) - return EXPERIMENTAL; - else - return STABLE; - } - - public static ReleaseType fromOrdinal(int ordinal) { - return sValuesCache[ordinal]; - } - - public int getTitleId() { - return mTitleId; - } - - public int getSummaryId() { - return mSummaryId; - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoDb.java b/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoDb.java deleted file mode 100644 index 6722812c..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoDb.java +++ /dev/null @@ -1,492 +0,0 @@ -package org.meowcat.edxposed.manager.repo; - -import android.annotation.SuppressLint; -import android.content.ContentValues; -import android.content.Context; -import android.content.SharedPreferences; -import android.database.Cursor; -import android.database.sqlite.SQLiteDatabase; -import android.database.sqlite.SQLiteOpenHelper; -import android.text.TextUtils; -import android.util.Pair; - -import org.meowcat.edxposed.manager.App; -import org.meowcat.edxposed.manager.BuildConfig; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions.InstalledModulesColumns; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions.InstalledModulesUpdatesColumns; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions.ModuleVersionsColumns; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions.ModulesColumns; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions.MoreInfoColumns; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions.OverviewColumns; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions.OverviewColumnsIndexes; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions.RepositoriesColumns; -import org.meowcat.edxposed.manager.util.ModuleUtil; -import org.meowcat.edxposed.manager.util.ModuleUtil.InstalledModule; -import org.meowcat.edxposed.manager.util.RepoLoader; - -import java.io.File; -import java.util.LinkedHashMap; -import java.util.Map; - -import static android.content.Context.MODE_PRIVATE; - -public final class RepoDb extends SQLiteOpenHelper { - public static final int SORT_STATUS = 0; - public static final int SORT_UPDATED = 1; - private static final int SORT_CREATED = 2; - - @SuppressLint("StaticFieldLeak") - private static Context context; - private static final SQLiteDatabase db; - - static { - RepoDb instance = new RepoDb(App.getInstance()); - db = instance.getWritableDatabase(); - db.execSQL("PRAGMA foreign_keys=ON"); - instance.createTempTables(db); - } - - private RepoDb(Context context) { - super(context, getDbPath(context), null, RepoDbDefinitions.DATABASE_VERSION); - RepoDb.context = context; - } - - private static String getDbPath(Context context) { - return new File(context.getNoBackupFilesDir(), RepoDbDefinitions.DATABASE_NAME).getPath(); - } - - public static void beginTransation() { - db.beginTransaction(); - } - - public static void setTransactionSuccessful() { - db.setTransactionSuccessful(); - } - - public static void endTransation() { - db.endTransaction(); - } - - private static String getString(@SuppressWarnings("SameParameterValue") String table, @SuppressWarnings("SameParameterValue") String searchColumn, String searchValue, @SuppressWarnings("SameParameterValue") String resultColumn) { - String[] projection = new String[]{resultColumn}; - String where = searchColumn + " = ?"; - String[] whereArgs = new String[]{searchValue}; - Cursor c = db.query(table, projection, where, whereArgs, null, null, null, "1"); - if (c.moveToFirst()) { - String result = c.getString(c.getColumnIndexOrThrow(resultColumn)); - c.close(); - return result; - } else { - c.close(); - throw new RowNotFoundException("Could not find " + table + "." + searchColumn + " with value '" + searchValue + "'"); - } - } - - @SuppressWarnings("UnusedReturnValue") - public static long insertRepository(String url) { - ContentValues values = new ContentValues(); - values.put(RepositoriesColumns.URL, url); - return db.insertOrThrow(RepositoriesColumns.TABLE_NAME, null, values); - } - - public static void deleteRepositories() { - if (db != null) - db.delete(RepositoriesColumns.TABLE_NAME, null, null); - } - - public static Map getRepositories() { - Map result = new LinkedHashMap<>(1); - - String[] projection = new String[]{ - RepositoriesColumns._ID, - RepositoriesColumns.URL, - RepositoriesColumns.TITLE, - RepositoriesColumns.PARTIAL_URL, - RepositoriesColumns.VERSION, - }; - - Cursor c = db.query(RepositoriesColumns.TABLE_NAME, projection, null, null, null, null, RepositoriesColumns._ID); - while (c.moveToNext()) { - Repository repo = new Repository(); - long id = c.getLong(c.getColumnIndexOrThrow(RepositoriesColumns._ID)); - repo.url = c.getString(c.getColumnIndexOrThrow(RepositoriesColumns.URL)); - repo.name = c.getString(c.getColumnIndexOrThrow(RepositoriesColumns.TITLE)); - repo.partialUrl = c.getString(c.getColumnIndexOrThrow(RepositoriesColumns.PARTIAL_URL)); - repo.version = c.getString(c.getColumnIndexOrThrow(RepositoriesColumns.VERSION)); - result.put(id, repo); - } - c.close(); - - return result; - } - - public static void updateRepository(long repoId, Repository repository) { - ContentValues values = new ContentValues(); - values.put(RepositoriesColumns.TITLE, repository.name); - values.put(RepositoriesColumns.PARTIAL_URL, repository.partialUrl); - values.put(RepositoriesColumns.VERSION, repository.version); - db.update(RepositoriesColumns.TABLE_NAME, values, RepositoriesColumns._ID + " = ?", new String[]{Long.toString(repoId)}); - } - - public static void updateRepositoryVersion(long repoId, String version) { - ContentValues values = new ContentValues(); - values.put(RepositoriesColumns.VERSION, version); - db.update(RepositoriesColumns.TABLE_NAME, values, RepositoriesColumns._ID + " = ?", new String[]{Long.toString(repoId)}); - } - - @SuppressWarnings("UnusedReturnValue") - public static long insertModule(long repoId, Module mod) { - ContentValues values = new ContentValues(); - values.put(ModulesColumns.REPO_ID, repoId); - values.put(ModulesColumns.PKGNAME, mod.packageName); - values.put(ModulesColumns.TITLE, mod.name); - values.put(ModulesColumns.SUMMARY, mod.summary); - values.put(ModulesColumns.DESCRIPTION, mod.description); - values.put(ModulesColumns.DESCRIPTION_IS_HTML, mod.descriptionIsHtml); - values.put(ModulesColumns.AUTHOR, mod.author); - values.put(ModulesColumns.SUPPORT, mod.support); - values.put(ModulesColumns.CREATED, mod.created); - values.put(ModulesColumns.UPDATED, mod.updated); - - ModuleVersion latestVersion = RepoLoader.getInstance().getLatestVersion(mod); - - db.beginTransaction(); - try { - long moduleId = db.insertOrThrow(ModulesColumns.TABLE_NAME, null, values); - - long latestVersionId = -1; - for (ModuleVersion version : mod.versions) { - long versionId = insertModuleVersion(moduleId, version); - if (latestVersion == version) - latestVersionId = versionId; - } - - if (latestVersionId > -1) { - values = new ContentValues(); - values.put(ModulesColumns.LATEST_VERSION, latestVersionId); - db.update(ModulesColumns.TABLE_NAME, values, ModulesColumns._ID + " = ?", new String[]{Long.toString(moduleId)}); - } - - for (Pair moreInfoEntry : mod.moreInfo) { - insertMoreInfo(moduleId, moreInfoEntry.first, moreInfoEntry.second); - } - - // TODO Add mod.screenshots - - db.setTransactionSuccessful(); - return moduleId; - - } finally { - db.endTransaction(); - } - } - - private static long insertModuleVersion(long moduleId, ModuleVersion version) { - ContentValues values = new ContentValues(); - values.put(ModuleVersionsColumns.MODULE_ID, moduleId); - values.put(ModuleVersionsColumns.NAME, version.name); - values.put(ModuleVersionsColumns.CODE, version.code); - values.put(ModuleVersionsColumns.DOWNLOAD_LINK, version.downloadLink); - values.put(ModuleVersionsColumns.MD5SUM, version.md5sum); - values.put(ModuleVersionsColumns.CHANGELOG, version.changelog); - values.put(ModuleVersionsColumns.CHANGELOG_IS_HTML, version.changelogIsHtml); - values.put(ModuleVersionsColumns.RELTYPE, version.relType.ordinal()); - values.put(ModuleVersionsColumns.UPLOADED, version.uploaded); - return db.insertOrThrow(ModuleVersionsColumns.TABLE_NAME, null, - values); - } - - @SuppressWarnings("UnusedReturnValue") - private static long insertMoreInfo(long moduleId, String title, String value) { - ContentValues values = new ContentValues(); - values.put(MoreInfoColumns.MODULE_ID, moduleId); - values.put(MoreInfoColumns.LABEL, title); - values.put(MoreInfoColumns.VALUE, value); - return db.insertOrThrow(MoreInfoColumns.TABLE_NAME, null, values); - } - - public static void deleteAllModules(long repoId) { - db.delete(ModulesColumns.TABLE_NAME, ModulesColumns.REPO_ID + " = ?", new String[]{Long.toString(repoId)}); - } - - public static void deleteModule(long repoId, String packageName) { - db.delete(ModulesColumns.TABLE_NAME, ModulesColumns.REPO_ID + " = ? AND " + ModulesColumns.PKGNAME + " = ?", new String[]{Long.toString(repoId), packageName}); - } - - public static Module getModuleByPackageName(String packageName) { - // The module itself - String[] projection = new String[]{ - ModulesColumns._ID, - ModulesColumns.REPO_ID, - ModulesColumns.PKGNAME, - ModulesColumns.TITLE, - ModulesColumns.SUMMARY, - ModulesColumns.DESCRIPTION, - ModulesColumns.DESCRIPTION_IS_HTML, - ModulesColumns.AUTHOR, - ModulesColumns.SUPPORT, - ModulesColumns.CREATED, - ModulesColumns.UPDATED, - }; - - String where = ModulesColumns.PREFERRED + " = 1 AND " + ModulesColumns.PKGNAME + " = ?"; - String[] whereArgs = new String[]{packageName}; - - Cursor c = db.query(ModulesColumns.TABLE_NAME, projection, where, whereArgs, null, null, null, "1"); - if (!c.moveToFirst()) { - c.close(); - return null; - } - - long moduleId = c.getLong(c.getColumnIndexOrThrow(ModulesColumns._ID)); - long repoId = c.getLong(c.getColumnIndexOrThrow(ModulesColumns.REPO_ID)); - - Module mod = new Module(RepoLoader.getInstance().getRepository(repoId)); - mod.packageName = c.getString(c.getColumnIndexOrThrow(ModulesColumns.PKGNAME)); - mod.name = c.getString(c.getColumnIndexOrThrow(ModulesColumns.TITLE)); - mod.summary = c.getString(c.getColumnIndexOrThrow(ModulesColumns.SUMMARY)); - mod.description = c.getString(c.getColumnIndexOrThrow(ModulesColumns.DESCRIPTION)); - mod.descriptionIsHtml = c.getInt(c.getColumnIndexOrThrow(ModulesColumns.DESCRIPTION_IS_HTML)) > 0; - mod.author = c.getString(c.getColumnIndexOrThrow(ModulesColumns.AUTHOR)); - mod.support = c.getString(c.getColumnIndexOrThrow(ModulesColumns.SUPPORT)); - mod.created = c.getLong(c.getColumnIndexOrThrow(ModulesColumns.CREATED)); - mod.updated = c.getLong(c.getColumnIndexOrThrow(ModulesColumns.UPDATED)); - - c.close(); - - // Versions - projection = new String[]{ - ModuleVersionsColumns.NAME, - ModuleVersionsColumns.CODE, ModuleVersionsColumns.DOWNLOAD_LINK, - ModuleVersionsColumns.MD5SUM, ModuleVersionsColumns.CHANGELOG, - ModuleVersionsColumns.CHANGELOG_IS_HTML, - ModuleVersionsColumns.RELTYPE, - ModuleVersionsColumns.UPLOADED, - }; - - where = ModuleVersionsColumns.MODULE_ID + " = ?"; - whereArgs = new String[]{Long.toString(moduleId)}; - - c = db.query(ModuleVersionsColumns.TABLE_NAME, projection, where, whereArgs, null, null, null); - while (c.moveToNext()) { - ModuleVersion version = new ModuleVersion(mod); - version.name = c.getString(c.getColumnIndexOrThrow(ModuleVersionsColumns.NAME)); - version.code = c.getInt(c.getColumnIndexOrThrow(ModuleVersionsColumns.CODE)); - version.downloadLink = c.getString(c.getColumnIndexOrThrow(ModuleVersionsColumns.DOWNLOAD_LINK)); - version.md5sum = c.getString(c.getColumnIndexOrThrow(ModuleVersionsColumns.MD5SUM)); - version.changelog = c.getString(c.getColumnIndexOrThrow(ModuleVersionsColumns.CHANGELOG)); - version.changelogIsHtml = c.getInt(c.getColumnIndexOrThrow(ModuleVersionsColumns.CHANGELOG_IS_HTML)) > 0; - version.relType = ReleaseType.fromOrdinal(c.getInt(c.getColumnIndexOrThrow(ModuleVersionsColumns.RELTYPE))); - version.uploaded = c.getLong(c.getColumnIndexOrThrow(ModuleVersionsColumns.UPLOADED)); - mod.versions.add(version); - } - c.close(); - - // MoreInfo - projection = new String[]{ - MoreInfoColumns.LABEL, - MoreInfoColumns.VALUE, - }; - - where = MoreInfoColumns.MODULE_ID + " = ?"; - whereArgs = new String[]{Long.toString(moduleId)}; - - c = db.query(MoreInfoColumns.TABLE_NAME, projection, where, whereArgs, null, null, MoreInfoColumns._ID); - while (c.moveToNext()) { - String label = c.getString(c.getColumnIndexOrThrow(MoreInfoColumns.LABEL)); - String value = c.getString(c.getColumnIndexOrThrow(MoreInfoColumns.VALUE)); - mod.moreInfo.add(new Pair<>(label, value)); - } - c.close(); - - return mod; - } - - public static String getModuleSupport(String packageName) { - return getString(ModulesColumns.TABLE_NAME, ModulesColumns.PKGNAME, packageName, ModulesColumns.SUPPORT); - } - - public static void updateModuleLatestVersion(String packageName) { - int maxShownReleaseType = RepoLoader.getInstance().getMaxShownReleaseType(packageName).ordinal(); - db.execSQL("UPDATE " + ModulesColumns.TABLE_NAME - + " SET " + ModulesColumns.LATEST_VERSION - + " = (SELECT " + ModuleVersionsColumns._ID + " FROM " + ModuleVersionsColumns.TABLE_NAME + " AS v" - + " WHERE v." + ModuleVersionsColumns.MODULE_ID - + " = " + ModulesColumns.TABLE_NAME + "." + ModulesColumns._ID - + " AND reltype <= ? LIMIT 1)" - + " WHERE " + ModulesColumns.PKGNAME + " = ?", - new Object[]{maxShownReleaseType, packageName}); - } - - public static void updateAllModulesLatestVersion() { - db.beginTransaction(); - try { - String[] projection = new String[]{ModulesColumns.PKGNAME}; - Cursor c = db.query(true, ModulesColumns.TABLE_NAME, projection, null, null, null, null, null, null); - while (c.moveToNext()) { - updateModuleLatestVersion(c.getString(0)); - } - c.close(); - db.setTransactionSuccessful(); - } finally { - db.endTransaction(); - } - } - - @SuppressWarnings("UnusedReturnValue") - public static long insertInstalledModule(InstalledModule installed) { - ContentValues values = new ContentValues(); - values.put(InstalledModulesColumns.PKGNAME, installed.packageName); - values.put(InstalledModulesColumns.VERSION_CODE, installed.versionCode); - values.put(InstalledModulesColumns.VERSION_NAME, installed.versionName); - return db.insertOrThrow(InstalledModulesColumns.TABLE_NAME, null, values); - } - - public static void deleteInstalledModule(String packageName) { - db.delete(InstalledModulesColumns.TABLE_NAME, InstalledModulesColumns.PKGNAME + " = ?", new String[]{packageName}); - } - - public static void deleteAllInstalledModules() { - db.delete(InstalledModulesColumns.TABLE_NAME, null, null); - } - - public static Cursor queryModuleOverview(int sortingOrder, - CharSequence filterText) { - // Columns - String[] projection = new String[]{ - "m." + ModulesColumns._ID, - "m." + ModulesColumns.PKGNAME, - "m." + ModulesColumns.TITLE, - "m." + ModulesColumns.SUMMARY, - "m." + ModulesColumns.CREATED, - "m." + ModulesColumns.UPDATED, - - "v." + ModuleVersionsColumns.NAME + " AS " + OverviewColumns.LATEST_VERSION, - "i." + InstalledModulesColumns.VERSION_NAME + " AS " + OverviewColumns.INSTALLED_VERSION, - - "(CASE WHEN m." + ModulesColumns.PKGNAME + " = '" + ModuleUtil.getInstance().getFrameworkPackageName() - + "' THEN 1 ELSE 0 END) AS " + OverviewColumns.IS_FRAMEWORK, - - "(CASE WHEN i." + InstalledModulesColumns.VERSION_NAME + " IS NOT NULL" - + " THEN 1 ELSE 0 END) AS " + OverviewColumns.IS_INSTALLED, - - "(CASE WHEN v." + ModuleVersionsColumns.CODE + " > " + InstalledModulesColumns.VERSION_CODE - + " THEN 1 ELSE 0 END) AS " + OverviewColumns.HAS_UPDATE, - }; - - // Conditions - StringBuilder where = new StringBuilder(ModulesColumns.PREFERRED + " = 1"); - String[] whereArgs = null; - if (!TextUtils.isEmpty(filterText)) { - where.append(" AND (m." + ModulesColumns.TITLE + " LIKE ?" + " OR m." + ModulesColumns.SUMMARY + " LIKE ?" + " OR m." + ModulesColumns.DESCRIPTION + " LIKE ?" + " OR m." + ModulesColumns.AUTHOR + " LIKE ?)"); - String filterTextArg = "%" + filterText + "%"; - whereArgs = new String[]{filterTextArg, filterTextArg, filterTextArg, filterTextArg}; - } else { - SharedPreferences prefs = context.getSharedPreferences(BuildConfig.APPLICATION_ID + "_preferences", MODE_PRIVATE); - - if (prefs.getBoolean("ignore_chinese", false)) { - for (char ch : "的一是不了人我在有他这为中设微模块淘".toCharArray()) { - where.append(" AND NOT (m." + ModulesColumns.TITLE + " LIKE '%").append(ch).append("%'").append(" OR m.").append(ModulesColumns.SUMMARY).append(" LIKE '%").append(ch).append("%'").append(" OR m.").append(ModulesColumns.DESCRIPTION).append(" LIKE '%").append(ch).append("%')"); - } - } - } - - // Sorting order - StringBuilder sbOrder = new StringBuilder(); - if (sortingOrder == SORT_CREATED) { - sbOrder.append(OverviewColumns.CREATED); - sbOrder.append(" DESC,"); - } else if (sortingOrder == SORT_UPDATED) { - sbOrder.append(OverviewColumns.UPDATED); - sbOrder.append(" DESC,"); - } - sbOrder.append(OverviewColumns.IS_FRAMEWORK); - sbOrder.append(" DESC, "); - sbOrder.append(OverviewColumns.HAS_UPDATE); - sbOrder.append(" DESC, "); - sbOrder.append(OverviewColumns.IS_INSTALLED); - sbOrder.append(" DESC, "); - sbOrder.append("m."); - sbOrder.append(OverviewColumns.TITLE); - sbOrder.append(" COLLATE NOCASE, "); - sbOrder.append("m."); - sbOrder.append(OverviewColumns.PKGNAME); - - // Query - Cursor c = db.query( - ModulesColumns.TABLE_NAME + " AS m" - + " LEFT JOIN " + ModuleVersionsColumns.TABLE_NAME + " AS v" - + " ON v." + ModuleVersionsColumns._ID + " = m." + ModulesColumns.LATEST_VERSION - + " LEFT JOIN " + InstalledModulesColumns.TABLE_NAME + " AS i" - + " ON i." + InstalledModulesColumns.PKGNAME + " = m." + ModulesColumns.PKGNAME, - projection, where.toString(), whereArgs, null, null, sbOrder.toString()); - - // Cache column indexes - OverviewColumnsIndexes.fillFromCursor(c); - - return c; - } - - public static String getFrameworkUpdateVersion() { - return getFirstUpdate(true); - } - - public static boolean hasModuleUpdates() { - return getFirstUpdate(false) != null; - } - - private static String getFirstUpdate(boolean framework) { - String[] projection = new String[]{InstalledModulesUpdatesColumns.LATEST_NAME}; - String where = ModulesColumns.PKGNAME + (framework ? " = ?" : " != ?"); - String[] whereArgs = new String[]{ModuleUtil.getInstance().getFrameworkPackageName()}; - Cursor c = db.query(InstalledModulesUpdatesColumns.VIEW_NAME, projection, where, whereArgs, null, null, null, "1"); - String latestVersion = null; - if (c.moveToFirst()) - latestVersion = c.getString(c.getColumnIndexOrThrow(InstalledModulesUpdatesColumns.LATEST_NAME)); - c.close(); - return latestVersion; - } - - @Override - public void onCreate(SQLiteDatabase db) { - db.execSQL(RepoDbDefinitions.SQL_CREATE_TABLE_REPOSITORIES); - db.execSQL(RepoDbDefinitions.SQL_CREATE_TABLE_MODULES); - db.execSQL(RepoDbDefinitions.SQL_CREATE_TABLE_MODULE_VERSIONS); - db.execSQL(RepoDbDefinitions.SQL_CREATE_INDEX_MODULE_VERSIONS_MODULE_ID); - db.execSQL(RepoDbDefinitions.SQL_CREATE_TABLE_MORE_INFO); - - RepoLoader.getInstance().clear(false); - } - - private void createTempTables(SQLiteDatabase db) { - db.execSQL(RepoDbDefinitions.SQL_CREATE_TEMP_TABLE_INSTALLED_MODULES); - db.execSQL(RepoDbDefinitions.SQL_CREATE_TEMP_VIEW_INSTALLED_MODULES_UPDATES); - } - - @Override - public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - // This is only a cache, so simply drop & recreate the tables - db.execSQL("DROP TABLE IF EXISTS " + RepositoriesColumns.TABLE_NAME); - db.execSQL("DROP TABLE IF EXISTS " + ModulesColumns.TABLE_NAME); - db.execSQL("DROP TABLE IF EXISTS " + ModuleVersionsColumns.TABLE_NAME); - db.execSQL("DROP TABLE IF EXISTS " + MoreInfoColumns.TABLE_NAME); - - db.execSQL("DROP TABLE IF EXISTS " + InstalledModulesColumns.TABLE_NAME); - db.execSQL("DROP VIEW IF EXISTS " + InstalledModulesUpdatesColumns.VIEW_NAME); - - onCreate(db); - } - - @Override - public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { - onUpgrade(db, oldVersion, newVersion); - } - - public static class RowNotFoundException extends RuntimeException { - private static final long serialVersionUID = -396324186622439535L; - - RowNotFoundException(String reason) { - super(reason); - } - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoDbDefinitions.java b/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoDbDefinitions.java deleted file mode 100644 index 666b5513..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoDbDefinitions.java +++ /dev/null @@ -1,216 +0,0 @@ -package org.meowcat.edxposed.manager.repo; - -import android.database.Cursor; -import android.provider.BaseColumns; - -public class RepoDbDefinitions { - static final int DATABASE_VERSION = 4; - static final String DATABASE_NAME = "repo_cache.db"; - static final String SQL_CREATE_TABLE_REPOSITORIES = "CREATE TABLE " - + RepositoriesColumns.TABLE_NAME + " (" + RepositoriesColumns._ID - + " INTEGER PRIMARY KEY AUTOINCREMENT," + RepositoriesColumns.URL - + " TEXT NOT NULL, " + RepositoriesColumns.TITLE + " TEXT, " - + RepositoriesColumns.PARTIAL_URL + " TEXT, " - + RepositoriesColumns.VERSION + " TEXT, " + "UNIQUE (" - + RepositoriesColumns.URL + ") ON CONFLICT REPLACE)"; - static final String SQL_CREATE_TABLE_MODULES = "CREATE TABLE " - + ModulesColumns.TABLE_NAME + " (" + ModulesColumns._ID - + " INTEGER PRIMARY KEY AUTOINCREMENT," + - - ModulesColumns.REPO_ID + " INTEGER NOT NULL REFERENCES " - + RepositoriesColumns.TABLE_NAME + " ON DELETE CASCADE, " - + ModulesColumns.PKGNAME + " TEXT NOT NULL, " + ModulesColumns.TITLE - + " TEXT NOT NULL, " + ModulesColumns.SUMMARY + " TEXT, " - + ModulesColumns.DESCRIPTION + " TEXT, " - + ModulesColumns.DESCRIPTION_IS_HTML + " INTEGER DEFAULT 0, " - + ModulesColumns.AUTHOR + " TEXT, " + ModulesColumns.SUPPORT - + " TEXT, " + ModulesColumns.CREATED + " INTEGER DEFAULT -1, " - + ModulesColumns.UPDATED + " INTEGER DEFAULT -1, " - + ModulesColumns.PREFERRED + " INTEGER DEFAULT 1, " - + ModulesColumns.LATEST_VERSION + " INTEGER REFERENCES " - + ModuleVersionsColumns.TABLE_NAME + ", " + "UNIQUE (" - + ModulesColumns.PKGNAME + ", " + ModulesColumns.REPO_ID - + ") ON CONFLICT REPLACE)"; - static final String SQL_CREATE_TABLE_MODULE_VERSIONS = "CREATE TABLE " - + ModuleVersionsColumns.TABLE_NAME + " (" - + ModuleVersionsColumns._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," - + ModuleVersionsColumns.MODULE_ID + " INTEGER NOT NULL REFERENCES " - + ModulesColumns.TABLE_NAME + " ON DELETE CASCADE, " - + ModuleVersionsColumns.NAME + " TEXT NOT NULL, " - + ModuleVersionsColumns.CODE + " INTEGER NOT NULL, " - + ModuleVersionsColumns.DOWNLOAD_LINK + " TEXT, " - + ModuleVersionsColumns.MD5SUM + " TEXT, " - + ModuleVersionsColumns.CHANGELOG + " TEXT, " - + ModuleVersionsColumns.CHANGELOG_IS_HTML + " INTEGER DEFAULT 0, " - + ModuleVersionsColumns.RELTYPE + " INTEGER DEFAULT 0, " - + ModuleVersionsColumns.UPLOADED + " INTEGER DEFAULT -1)"; - static final String SQL_CREATE_INDEX_MODULE_VERSIONS_MODULE_ID = "CREATE INDEX " - + ModuleVersionsColumns.IDX_MODULE_ID + " ON " - + ModuleVersionsColumns.TABLE_NAME + " (" - + ModuleVersionsColumns.MODULE_ID + ")"; - static final String SQL_CREATE_TABLE_MORE_INFO = "CREATE TABLE " - + MoreInfoColumns.TABLE_NAME + " (" + MoreInfoColumns._ID - + " INTEGER PRIMARY KEY AUTOINCREMENT," + MoreInfoColumns.MODULE_ID - + " INTEGER NOT NULL REFERENCES " + ModulesColumns.TABLE_NAME - + " ON DELETE CASCADE, " + MoreInfoColumns.LABEL - + " TEXT NOT NULL, " + MoreInfoColumns.VALUE + " TEXT)"; - static final String SQL_CREATE_TEMP_TABLE_INSTALLED_MODULES = "CREATE TEMP TABLE " - + InstalledModulesColumns.TABLE_NAME + " (" - + InstalledModulesColumns.PKGNAME - + " TEXT PRIMARY KEY ON CONFLICT REPLACE, " - + InstalledModulesColumns.VERSION_CODE + " INTEGER NOT NULL, " - + InstalledModulesColumns.VERSION_NAME + " TEXT)"; - static final String SQL_CREATE_TEMP_VIEW_INSTALLED_MODULES_UPDATES = "CREATE TEMP VIEW " - + InstalledModulesUpdatesColumns.VIEW_NAME + " AS SELECT " + "m." - + ModulesColumns._ID + " AS " - + InstalledModulesUpdatesColumns.MODULE_ID + ", " + "i." - + InstalledModulesColumns.PKGNAME + " AS " - + InstalledModulesUpdatesColumns.PKGNAME + ", " + "i." - + InstalledModulesColumns.VERSION_CODE + " AS " - + InstalledModulesUpdatesColumns.INSTALLED_CODE + ", " + "i." - + InstalledModulesColumns.VERSION_NAME + " AS " - + InstalledModulesUpdatesColumns.INSTALLED_NAME + ", " + "v." - + ModuleVersionsColumns._ID + " AS " - + InstalledModulesUpdatesColumns.LATEST_ID + ", " + "v." - + ModuleVersionsColumns.CODE + " AS " - + InstalledModulesUpdatesColumns.LATEST_CODE + ", " + "v." - + ModuleVersionsColumns.NAME + " AS " - + InstalledModulesUpdatesColumns.LATEST_NAME + " FROM " - + InstalledModulesColumns.TABLE_NAME + " AS i" + " INNER JOIN " - + ModulesColumns.TABLE_NAME + " AS m" + " ON m." - + ModulesColumns.PKGNAME + " = i." + InstalledModulesColumns.PKGNAME - + " INNER JOIN " + ModuleVersionsColumns.TABLE_NAME + " AS v" - + " ON v." + ModuleVersionsColumns._ID + " = m." - + ModulesColumns.LATEST_VERSION + " WHERE " - + InstalledModulesUpdatesColumns.LATEST_CODE + " > " - + InstalledModulesUpdatesColumns.INSTALLED_CODE + " AND " - + ModulesColumns.PREFERRED + " = 1"; - - ////////////////////////////////////////////////////////////////////////// - public interface RepositoriesColumns extends BaseColumns { - String TABLE_NAME = "repositories"; - - String URL = "url"; - String TITLE = "title"; - String PARTIAL_URL = "partial_url"; - String VERSION = "version"; - } - - ////////////////////////////////////////////////////////////////////////// - public interface ModulesColumns extends BaseColumns { - String TABLE_NAME = "modules"; - - String REPO_ID = "repo_id"; - String PKGNAME = "pkgname"; - String TITLE = "title"; - String SUMMARY = "summary"; - String DESCRIPTION = "description"; - String DESCRIPTION_IS_HTML = "description_is_html"; - String AUTHOR = "author"; - String SUPPORT = "support"; - String CREATED = "created"; - String UPDATED = "updated"; - - String PREFERRED = "preferred"; - String LATEST_VERSION = "latest_version_id"; - } - - ////////////////////////////////////////////////////////////////////////// - public interface ModuleVersionsColumns extends BaseColumns { - String TABLE_NAME = "module_versions"; - String IDX_MODULE_ID = "module_versions_module_id_idx"; - - String MODULE_ID = "module_id"; - String NAME = "name"; - String CODE = "code"; - String DOWNLOAD_LINK = "download_link"; - String MD5SUM = "md5sum"; - String CHANGELOG = "changelog"; - String CHANGELOG_IS_HTML = "changelog_is_html"; - String RELTYPE = "reltype"; - String UPLOADED = "uploaded"; - } - - ////////////////////////////////////////////////////////////////////////// - public interface MoreInfoColumns extends BaseColumns { - String TABLE_NAME = "more_info"; - - String MODULE_ID = "module_id"; - String LABEL = "label"; - String VALUE = "value"; - } - - ////////////////////////////////////////////////////////////////////////// - public interface InstalledModulesColumns { - String TABLE_NAME = "installed_modules"; - - String PKGNAME = "pkgname"; - String VERSION_CODE = "version_code"; - String VERSION_NAME = "version_name"; - } - - ////////////////////////////////////////////////////////////////////////// - public interface InstalledModulesUpdatesColumns { - String VIEW_NAME = InstalledModulesColumns.TABLE_NAME + "_updates"; - - String MODULE_ID = "module_id"; - String PKGNAME = "pkgname"; - String INSTALLED_CODE = "installed_code"; - String INSTALLED_NAME = "installed_name"; - String LATEST_ID = "latest_id"; - String LATEST_CODE = "latest_code"; - String LATEST_NAME = "latest_name"; - } - - ////////////////////////////////////////////////////////////////////////// - public interface OverviewColumns extends BaseColumns { - String PKGNAME = ModulesColumns.PKGNAME; - String TITLE = ModulesColumns.TITLE; - String SUMMARY = ModulesColumns.SUMMARY; - String CREATED = ModulesColumns.CREATED; - String UPDATED = ModulesColumns.UPDATED; - - String INSTALLED_VERSION = "installed_version"; - String LATEST_VERSION = "latest_version"; - - String IS_FRAMEWORK = "is_framework"; - String IS_INSTALLED = "is_installed"; - String HAS_UPDATE = "has_update"; - } - - public static class OverviewColumnsIndexes { - public static int PKGNAME = -1; - public static int TITLE = -1; - public static int SUMMARY = -1; - public static int CREATED = -1; - public static int UPDATED = -1; - public static int INSTALLED_VERSION = -1; - public static int LATEST_VERSION = -1; - public static int IS_FRAMEWORK = -1; - public static int IS_INSTALLED = -1; - public static int HAS_UPDATE = -1; - private static boolean isFilled = false; - - private OverviewColumnsIndexes() { - } - - static void fillFromCursor(Cursor cursor) { - if (isFilled || cursor == null) - return; - - PKGNAME = cursor.getColumnIndexOrThrow(OverviewColumns.PKGNAME); - TITLE = cursor.getColumnIndexOrThrow(OverviewColumns.TITLE); - SUMMARY = cursor.getColumnIndexOrThrow(OverviewColumns.SUMMARY); - CREATED = cursor.getColumnIndexOrThrow(OverviewColumns.CREATED); - UPDATED = cursor.getColumnIndexOrThrow(OverviewColumns.UPDATED); - INSTALLED_VERSION = cursor.getColumnIndexOrThrow(OverviewColumns.INSTALLED_VERSION); - LATEST_VERSION = cursor.getColumnIndexOrThrow(OverviewColumns.LATEST_VERSION); - INSTALLED_VERSION = cursor.getColumnIndexOrThrow(OverviewColumns.INSTALLED_VERSION); - IS_FRAMEWORK = cursor.getColumnIndexOrThrow(OverviewColumns.IS_FRAMEWORK); - IS_INSTALLED = cursor.getColumnIndexOrThrow(OverviewColumns.IS_INSTALLED); - HAS_UPDATE = cursor.getColumnIndexOrThrow(OverviewColumns.HAS_UPDATE); - - isFilled = true; - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoParser.java b/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoParser.java deleted file mode 100644 index 2cb16b2c..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/repo/RepoParser.java +++ /dev/null @@ -1,320 +0,0 @@ -package org.meowcat.edxposed.manager.repo; - -import android.app.Activity; -import android.content.Context; -import android.graphics.Bitmap; -import android.graphics.Point; -import android.graphics.drawable.BitmapDrawable; -import android.graphics.drawable.Drawable; -import android.graphics.drawable.LevelListDrawable; -import android.text.SpannableStringBuilder; -import android.text.Spanned; -import android.util.Log; -import android.util.Pair; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.core.text.HtmlCompat; - -import com.bumptech.glide.Glide; -import com.bumptech.glide.request.target.CustomTarget; -import com.bumptech.glide.request.transition.Transition; - -import org.meowcat.edxposed.manager.App; -import org.xmlpull.v1.XmlPullParser; -import org.xmlpull.v1.XmlPullParserException; -import org.xmlpull.v1.XmlPullParserFactory; - -import java.io.IOException; -import java.io.InputStream; - -public class RepoParser { - public final static String TAG = App.TAG; - private final static String NS = null; - private final XmlPullParser parser; - private final RepoParserCallback callback; - private boolean mRepoEventTriggered = false; - - private RepoParser(InputStream is, RepoParserCallback callback) throws XmlPullParserException, IOException { - XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); - parser = factory.newPullParser(); - parser.setInput(is, null); - parser.nextTag(); - this.callback = callback; - } - - public static void parse(InputStream is, RepoParserCallback callback) throws XmlPullParserException, IOException { - new RepoParser(is, callback).readRepo(); - } - - public static Spanned parseSimpleHtml(final Context context, String source, final TextView textView) { - source = source.replaceAll("
  • ", "\t\u0095 "); - source = source.replaceAll("
  • ", "
    "); - Spanned html = HtmlCompat.fromHtml(source, HtmlCompat.FROM_HTML_MODE_LEGACY, source1 -> { - - LevelListDrawable levelListDrawable = new LevelListDrawable(); - final Drawable[] drawable = new Drawable[1]; - Glide.with(context).asBitmap().load(source1).into(new CustomTarget() { - @Override - public void onResourceReady(@NonNull Bitmap bitmap, @Nullable Transition transition) { - try { - drawable[0] = new BitmapDrawable(context.getResources(), bitmap); - Point size = new Point(); - ((Activity) context).getWindowManager().getDefaultDisplay().getSize(size); - int multiplier = size.x / bitmap.getWidth(); - if (multiplier <= 0) multiplier = 1; - levelListDrawable.addLevel(1, 1, drawable[0]); - levelListDrawable.setBounds(0, 0, bitmap.getWidth() * multiplier, bitmap.getHeight() * multiplier); - levelListDrawable.setLevel(1); - textView.setText(textView.getText()); - } catch (Exception ignored) { /* Like a null bitmap, etc. */ - } - } - - @Override - public void onLoadCleared(@Nullable Drawable placeholder) { - } - }); - return drawable[0]; - }, null); - - // trim trailing newlines - int len = html.length(); - int end = len; - for (int i = len - 1; i >= 0; i--) { - if (html.charAt(i) != '\n') - break; - end = i; - } - - if (end == len) - return html; - else - return new SpannableStringBuilder(html, 0, end); - } - - private void readRepo() throws XmlPullParserException, IOException { - parser.require(XmlPullParser.START_TAG, NS, "repository"); - Repository repository = new Repository(); - repository.isPartial = "true".equals(parser.getAttributeValue(NS, "partial")); - repository.partialUrl = parser.getAttributeValue(NS, "partial-url"); - repository.version = parser.getAttributeValue(NS, "version"); - - while (parser.nextTag() == XmlPullParser.START_TAG) { - String tagName = parser.getName(); - switch (tagName) { - case "name": - repository.name = parser.nextText(); - break; - case "module": - triggerRepoEvent(repository); - Module module = readModule(repository); - if (module != null) - callback.onNewModule(module); - break; - case "remove-module": - triggerRepoEvent(repository); - String packageName = readRemoveModule(); - if (packageName != null) - callback.onRemoveModule(packageName); - break; - default: - //skip(true); - skip(false); - break; - } - } - - callback.onCompleted(repository); - } - - private void triggerRepoEvent(Repository repository) { - if (mRepoEventTriggered) - return; - - callback.onRepositoryMetadata(repository); - mRepoEventTriggered = true; - } - - private Module readModule(Repository repository) throws XmlPullParserException, IOException { - parser.require(XmlPullParser.START_TAG, NS, "module"); - final int startDepth = parser.getDepth(); - - Module module = new Module(repository); - module.packageName = parser.getAttributeValue(NS, "package"); - if (module.packageName == null) { - logError("no package name defined"); - leave(startDepth); - return null; - } - - module.created = parseTimestamp("created"); - module.updated = parseTimestamp("updated"); - - while (parser.nextTag() == XmlPullParser.START_TAG) { - String tagName = parser.getName(); - switch (tagName) { - case "name": - module.name = parser.nextText(); - break; - case "author": - module.author = parser.nextText(); - break; - case "summary": - module.summary = parser.nextText(); - break; - case "description": - String isHtml = parser.getAttributeValue(NS, "html"); - if (isHtml != null && isHtml.equals("true")) - module.descriptionIsHtml = true; - module.description = parser.nextText(); - break; - case "screenshot": - module.screenshots.add(parser.nextText()); - break; - case "moreinfo": - String label = parser.getAttributeValue(NS, "label"); - String role = parser.getAttributeValue(NS, "role"); - String value = parser.nextText(); - module.moreInfo.add(new Pair<>(label, value)); - - if (role != null && role.contains("support")) - module.support = value; - break; - case "version": - ModuleVersion version = readModuleVersion(module); - if (version != null) - module.versions.add(version); - break; - default: - //skip(true); - skip(false); - break; - } - } - - if (module.name == null) { - logError("packages need at least a name"); - return null; - } - - return module; - } - - private long parseTimestamp(String attName) { - String value = parser.getAttributeValue(NS, attName); - if (value == null) - return -1; - try { - return Long.parseLong(value) * 1000L; - } catch (NumberFormatException ex) { - return -1; - } - } - - private ModuleVersion readModuleVersion(Module module) throws XmlPullParserException, IOException { - parser.require(XmlPullParser.START_TAG, NS, "version"); - final int startDepth = parser.getDepth(); - ModuleVersion version = new ModuleVersion(module); - - version.uploaded = parseTimestamp("uploaded"); - - while (parser.nextTag() == XmlPullParser.START_TAG) { - String tagName = parser.getName(); - switch (tagName) { - case "name": - version.name = parser.nextText(); - break; - case "code": - try { - version.code = Integer.parseInt(parser.nextText()); - } catch (NumberFormatException nfe) { - logError(nfe.getMessage()); - leave(startDepth); - return null; - } - break; - case "reltype": - version.relType = ReleaseType.fromString(parser.nextText()); - break; - case "download": - version.downloadLink = parser.nextText(); - break; - case "md5sum": - version.md5sum = parser.nextText(); - break; - case "changelog": - String isHtml = parser.getAttributeValue(NS, "html"); - if (isHtml != null && isHtml.equals("true")) - version.changelogIsHtml = true; - version.changelog = parser.nextText(); - break; - case "branch": - // obsolete -// skip(false); -// break; - default: - skip(false); - //skip(true); - break; - } - } - - return version; - } - - private String readRemoveModule() throws XmlPullParserException, IOException { - parser.require(XmlPullParser.START_TAG, NS, "remove-module"); - final int startDepth = parser.getDepth(); - - String packageName = parser.getAttributeValue(NS, "package"); - if (packageName == null) { - logError("no package name defined"); - leave(startDepth); - return null; - } - - return packageName; - } - - private void skip(@SuppressWarnings("SameParameterValue") boolean showWarning) throws XmlPullParserException, IOException { - parser.require(XmlPullParser.START_TAG, null, null); - if (showWarning) - Log.w(TAG, "skipping unknown/erronous tag: " + parser.getPositionDescription()); - int level = 1; - while (level > 0) { - int eventType = parser.next(); - if (eventType == XmlPullParser.END_TAG) { - level--; - } else if (eventType == XmlPullParser.START_TAG) { - level++; - } - } - } - - private void leave(int targetDepth) throws XmlPullParserException, IOException { - Log.w(TAG, "leaving up to level " + targetDepth + ": " + parser.getPositionDescription()); - while (parser.getDepth() > targetDepth) { - //noinspection StatementWithEmptyBody - while (parser.next() != XmlPullParser.END_TAG) { - // do nothing - } - } - } - - private void logError(String error) { - Log.e(TAG, parser.getPositionDescription() + ": " + error); - } - - public interface RepoParserCallback { - void onRepositoryMetadata(Repository repository); - - void onNewModule(Module module); - - void onRemoveModule(String packageName); - - void onCompleted(Repository repository); - } - -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/repo/Repository.java b/app/src/main/java/org/meowcat/edxposed/manager/repo/Repository.java deleted file mode 100644 index f4d851ff..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/repo/Repository.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.meowcat.edxposed.manager.repo; - -public class Repository { - public String name; - public String url; - public boolean isPartial = false; - public String partialUrl; - public String version; - - Repository() { - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/DownloadActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/DownloadActivity.java deleted file mode 100644 index af982d2a..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/DownloadActivity.java +++ /dev/null @@ -1,398 +0,0 @@ -package org.meowcat.edxposed.manager.ui.activity; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; -import android.content.SharedPreferences; -import android.content.res.Resources; -import android.database.Cursor; -import android.net.ConnectivityManager; -import android.net.Uri; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.ViewGroup; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.widget.SearchView; -import androidx.core.content.ContextCompat; -import androidx.recyclerview.widget.DividerItemDecoration; -import androidx.recyclerview.widget.RecyclerView; -import androidx.transition.TransitionManager; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter; -import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration; - -import org.meowcat.edxposed.manager.App; -import org.meowcat.edxposed.manager.R; -import org.meowcat.edxposed.manager.adapters.CursorRecyclerViewAdapter; -import org.meowcat.edxposed.manager.databinding.ActivityDownloadBinding; -import org.meowcat.edxposed.manager.databinding.ItemDownloadBinding; -import org.meowcat.edxposed.manager.repo.RepoDb; -import org.meowcat.edxposed.manager.repo.RepoDbDefinitions; -import org.meowcat.edxposed.manager.util.LinearLayoutManagerFix; -import org.meowcat.edxposed.manager.util.ModuleUtil; -import org.meowcat.edxposed.manager.util.RepoLoader; - -import java.text.DateFormat; -import java.util.Date; - -import me.zhanghai.android.fastscroll.FastScrollerBuilder; - -public class DownloadActivity extends BaseActivity implements RepoLoader.RepoListener, ModuleUtil.ModuleListener, SharedPreferences.OnSharedPreferenceChangeListener { - private DownloadsAdapter adapter; - private String filterText; - private RepoLoader repoLoader; - private ModuleUtil moduleUtil; - private int sortingOrder; - private SearchView searchView; - private SharedPreferences ignoredUpdatesPref; - private boolean changed = false; - private final BroadcastReceiver connectionListener = new BroadcastReceiver() { - @Override - public void onReceive(Context context, Intent intent) { - if (repoLoader != null) { - repoLoader.triggerReload(true); - } - } - }; - private ActivityDownloadBinding binding; - - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - binding = ActivityDownloadBinding.inflate(getLayoutInflater()); - setContentView(binding.getRoot()); - setSupportActionBar(binding.toolbar); - binding.toolbar.setNavigationOnClickListener(view -> finish()); - ActionBar bar = getSupportActionBar(); - if (bar != null) { - bar.setDisplayHomeAsUpEnabled(true); - } - - setupWindowInsets(binding.snackbar, binding.recyclerView); - repoLoader = RepoLoader.getInstance(); - moduleUtil = ModuleUtil.getInstance(); - adapter = new DownloadsAdapter(this, RepoDb.queryModuleOverview(sortingOrder, filterText)); - /*adapter.setFilterQueryProvider(new FilterQueryProvider() { - @Override - public Cursor runQuery(CharSequence constraint) { - return RepoDb.queryModuleOverview(sortingOrder, constraint); - } - });*/ - - sortingOrder = App.getPreferences().getInt("download_sorting_order", RepoDb.SORT_STATUS); - - ignoredUpdatesPref = getSharedPreferences("update_ignored", MODE_PRIVATE); - binding.recyclerView.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS); - binding.swipeRefreshLayout.setOnRefreshListener(() -> { - repoLoader.setSwipeRefreshLayout(binding.swipeRefreshLayout); - repoLoader.triggerReload(true); - }); - repoLoader.addListener(this, true); - moduleUtil.addListener(this); - binding.recyclerView.setAdapter(adapter); - - binding.recyclerView.setLayoutManager(new LinearLayoutManagerFix(this)); - StickyRecyclerHeadersDecoration headersDecor = new StickyRecyclerHeadersDecoration(adapter); - binding.recyclerView.addItemDecoration(headersDecor); - adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { - @Override - public void onChanged() { - headersDecor.invalidateHeaders(); - } - }); - FastScrollerBuilder fastScrollerBuilder = new FastScrollerBuilder(binding.recyclerView); - if (!App.getPreferences().getBoolean("md2", false)) { - DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, - DividerItemDecoration.VERTICAL); - binding.recyclerView.addItemDecoration(dividerItemDecoration); - } else { - fastScrollerBuilder.useMd2Style(); - } - fastScrollerBuilder.build(); - } - - - @Override - public void onResume() { - super.onResume(); - - ignoredUpdatesPref.registerOnSharedPreferenceChangeListener(this); - if (changed) { - reloadItems(); - changed = !changed; - } - - registerReceiver(connectionListener, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); - } - - @Override - public void onPause() { - super.onPause(); - - unregisterReceiver(connectionListener); - } - - @Override - public void onDestroy() { - super.onDestroy(); - - repoLoader.removeListener(this); - moduleUtil.removeListener(this); - ignoredUpdatesPref.unregisterOnSharedPreferenceChangeListener(this); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu_download, menu); - - // Setup search button - searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView(); - searchView.setIconifiedByDefault(true); - searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String query) { - setFilter(query); - searchView.clearFocus(); - return true; - } - - @Override - public boolean onQueryTextChange(String newText) { - setFilter(newText); - return true; - } - }); - return super.onCreateOptionsMenu(menu); - } - - private void setFilter(String filterText) { - this.filterText = filterText; - reloadItems(); - } - - private void reloadItems() { - runOnUiThread(() -> { - adapter.changeCursor(RepoDb.queryModuleOverview(sortingOrder, filterText)); - TransitionManager.beginDelayedTransition(binding.recyclerView); - adapter.notifyDataSetChanged(); - }); - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - if (item.getItemId() == R.id.menu_sort) { - new MaterialAlertDialogBuilder(this) - .setTitle(R.string.download_sorting_title) - .setSingleChoiceItems(R.array.download_sort_order, sortingOrder, (dialog, which) -> { - sortingOrder = which; - App.getPreferences().edit().putInt("download_sorting_order", sortingOrder).apply(); - reloadItems(); - dialog.dismiss(); - }) - .show(); - return true; - } - return super.onOptionsItemSelected(item); - } - - @Override - public void onRepoReloaded(final RepoLoader loader) { - reloadItems(); - } - - @Override - public void onSingleInstalledModuleReloaded(ModuleUtil moduleUtil, String packageName, ModuleUtil.InstalledModule module) { - reloadItems(); - } - - @Override - public void onInstalledModulesReloaded(ModuleUtil moduleUtil) { - reloadItems(); - } - - @Override - public void onModuleEnableChange(ModuleUtil moduleUtil) { - - } - - @Override - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - changed = true; - } - - @Override - public void onBackPressed() { - if (searchView.isIconified()) { - super.onBackPressed(); - } else { - searchView.setIconified(true); - } - } - - private class DownloadsAdapter extends CursorRecyclerViewAdapter implements StickyRecyclerHeadersAdapter { - private final Context context; - private final DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.SHORT); - private final SharedPreferences prefs; - private final String[] sectionHeaders; - - DownloadsAdapter(Context context, Cursor cursor) { - super(cursor); - this.context = context; - prefs = context.getSharedPreferences("update_ignored", MODE_PRIVATE); - - Resources res = context.getResources(); - sectionHeaders = new String[]{ - res.getString(R.string.download_section_framework), - res.getString(R.string.download_section_update_available), - res.getString(R.string.download_section_installed), - res.getString(R.string.download_section_not_installed), - res.getString(R.string.download_section_24h), - res.getString(R.string.download_section_7d), - res.getString(R.string.download_section_30d), - res.getString(R.string.download_section_older)}; - } - - @Override - public long getHeaderId(int position) { - Cursor cursor = getCursor(); - cursor.moveToPosition(position); - long created = cursor.getLong(RepoDbDefinitions.OverviewColumnsIndexes.CREATED); - long updated = cursor.getLong(RepoDbDefinitions.OverviewColumnsIndexes.UPDATED); - boolean isFramework = cursor.getInt(RepoDbDefinitions.OverviewColumnsIndexes.IS_FRAMEWORK) > 0; - boolean isInstalled = cursor.getInt(RepoDbDefinitions.OverviewColumnsIndexes.IS_INSTALLED) > 0; - boolean updateIgnored = prefs.getBoolean(cursor.getString(RepoDbDefinitions.OverviewColumnsIndexes.PKGNAME), false); - boolean updateIgnorePreference = App.getPreferences().getBoolean("ignore_updates", false); - boolean hasUpdate = cursor.getInt(RepoDbDefinitions.OverviewColumnsIndexes.HAS_UPDATE) > 0; - - if (hasUpdate && updateIgnored && updateIgnorePreference) { - hasUpdate = false; - } - - if (sortingOrder != RepoDb.SORT_STATUS) { - long timestamp = (sortingOrder == RepoDb.SORT_UPDATED) ? updated : created; - long age = System.currentTimeMillis() - timestamp; - final long mSecsPerDay = 24 * 60 * 60 * 1000L; - if (age < mSecsPerDay) - return 4; - if (age < 7 * mSecsPerDay) - return 5; - if (age < 30 * mSecsPerDay) - return 6; - return 7; - } else { - if (isFramework) - return 0; - - if (hasUpdate) - return 1; - else if (isInstalled) - return 2; - else - return 3; - } - } - - @Override - public HeaderViewHolder onCreateHeaderViewHolder(ViewGroup parent) { - View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.sticky_header_download, parent, false); - return new HeaderViewHolder(view); - } - - @Override - public void onBindHeaderViewHolder(HeaderViewHolder viewHolder, int position) { - long section = getHeaderId(position); - viewHolder.title.setText(sectionHeaders[(int) section]); - } - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - ItemDownloadBinding binding = ItemDownloadBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false); - return new ViewHolder(binding); - } - - @Override - public void onBindViewHolder(ViewHolder holder, Cursor cursor) { - String title = cursor.getString(RepoDbDefinitions.OverviewColumnsIndexes.TITLE); - String summary = cursor.getString(RepoDbDefinitions.OverviewColumnsIndexes.SUMMARY); - String installedVersion = cursor.getString(RepoDbDefinitions.OverviewColumnsIndexes.INSTALLED_VERSION); - String latestVersion = cursor.getString(RepoDbDefinitions.OverviewColumnsIndexes.LATEST_VERSION); - long created = cursor.getLong(RepoDbDefinitions.OverviewColumnsIndexes.CREATED); - long updated = cursor.getLong(RepoDbDefinitions.OverviewColumnsIndexes.UPDATED); - boolean isInstalled = cursor.getInt(RepoDbDefinitions.OverviewColumnsIndexes.IS_INSTALLED) > 0; - boolean updateIgnored = prefs.getBoolean(cursor.getString(RepoDbDefinitions.OverviewColumnsIndexes.PKGNAME), false); - boolean updateIgnorePreference = App.getPreferences().getBoolean("ignore_updates", false); - boolean hasUpdate = cursor.getInt(RepoDbDefinitions.OverviewColumnsIndexes.HAS_UPDATE) > 0; - - if (hasUpdate && updateIgnored && updateIgnorePreference) { - hasUpdate = false; - } - - TextView txtTitle = holder.appName; - txtTitle.setText(title); - - TextView txtSummary = holder.appDescription; - txtSummary.setText(summary); - - TextView txtStatus = holder.downloadStatus; - if (hasUpdate) { - txtStatus.setText(context.getString( - R.string.download_status_update_available, - installedVersion, latestVersion)); - txtStatus.setTextColor(ContextCompat.getColor(DownloadActivity.this, R.color.download_status_update_available)); - txtStatus.setVisibility(View.VISIBLE); - } else if (isInstalled) { - txtStatus.setText(context.getString( - R.string.download_status_installed, installedVersion)); - txtStatus.setTextColor(ContextCompat.getColor(DownloadActivity.this, R.color.warning)); - txtStatus.setTextColor(getThemedColor(android.R.attr.textColorHighlight)); - txtStatus.setVisibility(View.VISIBLE); - } else { - txtStatus.setVisibility(View.GONE); - } - - String creationDate = dateFormatter.format(new Date(created)); - String updateDate = dateFormatter.format(new Date(updated)); - holder.timestamps.setText(getString(R.string.download_timestamps, creationDate, updateDate)); - String packageName = cursor.getString(RepoDbDefinitions.OverviewColumnsIndexes.PKGNAME); - holder.itemView.setOnClickListener(v -> { - Intent detailsIntent = new Intent(DownloadActivity.this, DownloadDetailsActivity.class); - detailsIntent.setData(Uri.fromParts("package", packageName, null)); - startActivity(detailsIntent); - }); - } - - class ViewHolder extends RecyclerView.ViewHolder { - TextView appName; - TextView appDescription; - TextView downloadStatus; - TextView timestamps; - - ViewHolder(ItemDownloadBinding binding) { - super(binding.getRoot()); - appName = binding.title; - appDescription = binding.description; - downloadStatus = binding.downloadStatus; - timestamps = binding.timestamps; - } - } - - class HeaderViewHolder extends RecyclerView.ViewHolder { - TextView title; - - HeaderViewHolder(View view) { - super(view); - title = view.findViewById(android.R.id.title); - } - } - } -} - diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/DownloadDetailsActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/DownloadDetailsActivity.java deleted file mode 100644 index a597513a..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/DownloadDetailsActivity.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.meowcat.edxposed.manager.ui.activity; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.PackageManager; -import android.net.Uri; -import android.os.Bundle; -import android.text.TextUtils; -import android.util.Log; -import android.view.Menu; -import android.view.MenuInflater; -import android.view.MenuItem; - -import androidx.annotation.NonNull; -import androidx.appcompat.app.ActionBar; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; -import androidx.fragment.app.FragmentPagerAdapter; - -import org.meowcat.edxposed.manager.App; -import org.meowcat.edxposed.manager.R; -import org.meowcat.edxposed.manager.databinding.ActivityDownloadDetailsBinding; -import org.meowcat.edxposed.manager.databinding.ActivityDownloadDetailsNotFoundBinding; -import org.meowcat.edxposed.manager.repo.Module; -import org.meowcat.edxposed.manager.ui.fragment.DownloadDetailsFragment; -import org.meowcat.edxposed.manager.ui.fragment.DownloadDetailsSettingsFragment; -import org.meowcat.edxposed.manager.ui.fragment.DownloadDetailsVersionsFragment; -import org.meowcat.edxposed.manager.util.ModuleUtil; -import org.meowcat.edxposed.manager.util.RepoLoader; - -import java.util.List; -import java.util.Objects; - -public class DownloadDetailsActivity extends BaseActivity implements RepoLoader.RepoListener, ModuleUtil.ModuleListener { - - public static final int DOWNLOAD_DESCRIPTION = 0; - public static final int DOWNLOAD_VERSIONS = 1; - public static final int DOWNLOAD_SETTINGS = 2; - static final String XPOSED_REPO_LINK = "http://repo.xposed.info/module/%s"; - static final String PLAY_STORE_PACKAGE = "com.android.vending"; - static final String PLAY_STORE_LINK = "https://play.google.com/store/apps/details?id=%s"; - private static final String TAG = "DownloadDetailsActivity"; - private static final RepoLoader repoLoader = RepoLoader.getInstance(); - private static final ModuleUtil moduleUtil = ModuleUtil.getInstance(); - private String packageName; - private Module module; - private ModuleUtil.InstalledModule installedModule; - private ActivityDownloadDetailsBinding binding; - - @Override - public void onCreate(Bundle savedInstanceState) { - - packageName = getModulePackageName(); - try { - module = repoLoader.getModule(packageName); - } catch (Exception e) { - Log.i(App.TAG, "DownloadDetailsActivity -> " + e.getMessage()); - - module = null; - } - - installedModule = ModuleUtil.getInstance().getModule(packageName); - - super.onCreate(savedInstanceState); - repoLoader.addListener(this, false); - moduleUtil.addListener(this); - - if (module != null) { - binding = ActivityDownloadDetailsBinding.inflate(getLayoutInflater()); - setContentView(binding.getRoot()); - - setSupportActionBar(binding.toolbar); - binding.toolbar.setNavigationOnClickListener(view -> finish()); - - ActionBar ab = getSupportActionBar(); - - if (ab != null) { - ab.setDisplayHomeAsUpEnabled(true); - } - - setupTabs(); - - boolean directDownload = getIntent().getBooleanExtra("direct_download", false); - // Updates available => start on the versions page - if (installedModule != null && installedModule.isUpdate(repoLoader.getLatestVersion(module)) || directDownload) - binding.downloadPager.setCurrentItem(DOWNLOAD_VERSIONS); - - } else { - ActivityDownloadDetailsNotFoundBinding binding = ActivityDownloadDetailsNotFoundBinding.inflate(getLayoutInflater()); - setContentView(binding.getRoot()); - - binding.message.setText(getResources().getString(R.string.download_details_not_found, packageName)); - - binding.reload.setOnClickListener(v -> { - v.setEnabled(false); - repoLoader.triggerReload(true); - }); - } - setupWindowInsets(binding.snackbar, null); - } - - private void setupTabs() { - binding.downloadPager.setAdapter(new SwipeFragmentPagerAdapter(getSupportFragmentManager())); - binding.slidingTabs.setupWithViewPager(binding.downloadPager); - } - - private String getModulePackageName() { - Uri uri = getIntent().getData(); - if (uri == null) - return null; - - String scheme = uri.getScheme(); - if (TextUtils.isEmpty(scheme)) { - return null; - } else switch (Objects.requireNonNull(scheme)) { - case "xposed": - case "package": - return uri.getSchemeSpecificPart().replace("//", ""); - case "http": - List segments = uri.getPathSegments(); - if (segments.size() > 1) - return segments.get(1); - break; - } - return null; - } - - @Override - protected void onDestroy() { - super.onDestroy(); - repoLoader.removeListener(this); - moduleUtil.removeListener(this); - } - - public Module getModule() { - return module; - } - - public ModuleUtil.InstalledModule getInstalledModule() { - return installedModule; - } - - public void gotoPage(int page) { - binding.downloadPager.setCurrentItem(page); - } - - private void reload() { - runOnUiThread(this::recreate); - } - - @Override - public void onRepoReloaded(RepoLoader loader) { - reload(); - } - - @Override - public void onInstalledModulesReloaded(ModuleUtil moduleUtil) { - reload(); - } - - @Override - public void onModuleEnableChange(ModuleUtil moduleUtil) { - - } - - @Override - public void onSingleInstalledModuleReloaded(ModuleUtil moduleUtil, String packageName, ModuleUtil.InstalledModule module) { - if (this.packageName.equals(packageName)) - reload(); - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - MenuInflater inflater = getMenuInflater(); - inflater.inflate(R.menu.menu_download_details, menu); - - boolean updateIgnorePreference = App.getPreferences().getBoolean("ignore_updates", false); - if (updateIgnorePreference) { - SharedPreferences prefs = getSharedPreferences("update_ignored", MODE_PRIVATE); - - boolean ignored = prefs.getBoolean(module.packageName, false); - menu.findItem(R.id.ignoreUpdate).setChecked(ignored); - } else { - menu.removeItem(R.id.ignoreUpdate); - } - return true; - } - - @Override - public boolean onOptionsItemSelected(@NonNull MenuItem item) { - int itemId = item.getItemId(); - if (itemId == R.id.menu_refresh) { - RepoLoader.getInstance().triggerReload(true); - return true; - } else if (itemId == R.id.menu_share) { - String text = module.name + " - "; - - if (isPackageInstalled(packageName, this)) { - String s = getPackageManager().getInstallerPackageName(packageName); - boolean playStore; - - try { - playStore = PLAY_STORE_PACKAGE.equals(s); - } catch (NullPointerException e) { - playStore = false; - } - - if (playStore) { - text += String.format(PLAY_STORE_LINK, packageName); - } else { - text += String.format(XPOSED_REPO_LINK, packageName); - } - } else { - text += String.format(XPOSED_REPO_LINK, - packageName); - } - - Intent sharingIntent = new Intent(Intent.ACTION_SEND); - sharingIntent.setType("text/plain"); - sharingIntent.putExtra(Intent.EXTRA_TEXT, text); - startActivity(Intent.createChooser(sharingIntent, getString(R.string.share))); - return true; - } else if (itemId == R.id.ignoreUpdate) { - SharedPreferences prefs = getSharedPreferences("update_ignored", MODE_PRIVATE); - - boolean ignored = prefs.getBoolean(module.packageName, false); - prefs.edit().putBoolean(module.packageName, !ignored).apply(); - item.setChecked(!ignored); - } - return super.onOptionsItemSelected(item); - } - - private boolean isPackageInstalled(String packagename, Context context) { - PackageManager pm = context.getPackageManager(); - try { - pm.getPackageInfo(packagename, PackageManager.GET_ACTIVITIES); - return true; - } catch (PackageManager.NameNotFoundException e) { - return false; - } - } - - class SwipeFragmentPagerAdapter extends FragmentPagerAdapter { - final int PAGE_COUNT = 3; - private final String[] tabTitles = new String[]{getString(R.string.download_details_page_description), getString(R.string.download_details_page_versions), getString(R.string.download_details_page_settings),}; - - SwipeFragmentPagerAdapter(FragmentManager fm) { - super(fm, FragmentPagerAdapter.BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); - } - - @Override - public int getCount() { - return PAGE_COUNT; - } - - @NonNull - @Override - public Fragment getItem(int position) { - switch (position) { - case DOWNLOAD_DESCRIPTION: - return new DownloadDetailsFragment(); - case DOWNLOAD_VERSIONS: - return new DownloadDetailsVersionsFragment(); - case DOWNLOAD_SETTINGS: - return new DownloadDetailsSettingsFragment(); - default: - //noinspection ConstantConditions - return null; - } - } - - @Override - public CharSequence getPageTitle(int position) { - // Generate title based on item position - return tabTitles[position]; - } - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/MainActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/MainActivity.java index 8742e850..d53e3864 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/MainActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/MainActivity.java @@ -19,9 +19,8 @@ import org.meowcat.edxposed.manager.util.GlideHelper; import org.meowcat.edxposed.manager.util.ModuleUtil; import org.meowcat.edxposed.manager.util.light.Light; -public class MainActivity extends BaseActivity implements /*RepoLoader.RepoListener, */ModuleUtil.ModuleListener { +public class MainActivity extends BaseActivity implements ModuleUtil.ModuleListener { ActivityMainBinding binding; - //private RepoLoader repoLoader; @SuppressLint("PrivateResource") @Override @@ -33,23 +32,15 @@ public class MainActivity extends BaseActivity implements /*RepoLoader.RepoListe if (Light.setLightSourceAlpha(getWindow().getDecorView(), 0.01f, 0.029f)) { binding.status.setElevation(24); binding.modules.setElevation(12); - //binding.downloads.setElevation(12); } }); setupWindowInsets(binding.snackbar, null); - //repoLoader = RepoLoader.getInstance(); ModuleUtil.getInstance().addListener(this); - //repoLoader.addListener(this, false); binding.modules.setOnClickListener(v -> { Intent intent = new Intent(); intent.setClass(getApplicationContext(), ModulesActivity.class); startActivity(intent); }); - /*binding.downloads.setOnClickListener(v -> { - Intent intent = new Intent(); - intent.setClass(getApplicationContext(), DownloadActivity.class); - startActivity(intent); - });*/ binding.apps.setOnClickListener(v -> { Intent intent = new Intent(); intent.setClass(getApplicationContext(), BlackListActivity.class); @@ -114,28 +105,9 @@ public class MainActivity extends BaseActivity implements /*RepoLoader.RepoListe new Thread(() -> new BlackListAdapter(getApplicationContext(), AppHelper.isWhiteListMode()).generateCheckedList()); } -/* - private void notifyDataSetChanged() { - runOnUiThread(() -> { - String frameworkUpdateVersion = repoLoader.getFrameworkUpdateVersion(); - boolean moduleUpdateAvailable = repoLoader.hasModuleUpdates(); - ModuleUtil.getInstance().getEnabledModules().size(); - binding.modulesSummary.setText(String.format(getString(R.string.ModulesDetail), ModuleUtil.getInstance().getEnabledModules().size())); - if (frameworkUpdateVersion != null) { - binding.statusSummary.setText(String.format(getString(R.string.welcome_framework_update_available), frameworkUpdateVersion)); - } - if (moduleUpdateAvailable) { - binding.downloadSummary.setText(R.string.modules_updates_available); - } else { - binding.downloadSummary.setText(R.string.ModuleUptodate); - } - }); - } -*/ - @Override public void onInstalledModulesReloaded(ModuleUtil moduleUtil) { - //notifyDataSetChanged(); + } @Override @@ -145,19 +117,13 @@ public class MainActivity extends BaseActivity implements /*RepoLoader.RepoListe @Override public void onSingleInstalledModuleReloaded(ModuleUtil moduleUtil, String packageName, ModuleUtil.InstalledModule module) { - //notifyDataSetChanged(); - } - /*@Override - public void onRepoReloaded(RepoLoader loader) { - notifyDataSetChanged(); - }*/ + } @Override protected void onDestroy() { super.onDestroy(); ModuleUtil.getInstance().removeListener(this); - //repoLoader.removeListener(this); } } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/ModulesActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/ModulesActivity.java index 67d4b4dc..24cadb43 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/ModulesActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/ModulesActivity.java @@ -31,9 +31,9 @@ import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.BuildConfig; import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; +import org.meowcat.edxposed.manager.adapters.AppAdapter; import org.meowcat.edxposed.manager.databinding.ActivityModulesBinding; import org.meowcat.edxposed.manager.util.GlideApp; -import org.meowcat.edxposed.manager.util.InstallApkUtil; import org.meowcat.edxposed.manager.util.LinearLayoutManagerFix; import org.meowcat.edxposed.manager.util.ModuleUtil; @@ -82,7 +82,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi showList = new ArrayList<>(); String filter = queryStr.toLowerCase(); for (ModuleUtil.InstalledModule info : fullList) { - if (lowercaseContains(InstallApkUtil.getAppLabel(info.app, pm), filter) + if (lowercaseContains(AppAdapter.getAppLabel(info.app, pm), filter) || lowercaseContains(info.packageName, filter)) { showList.add(info); } @@ -351,52 +351,6 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi return super.onOptionsItemSelected(item); } - /* - private void importModules(Uri uri) { - RepoLoader repoLoader = RepoLoader.getInstance(); - List list = new ArrayList<>(); - - try { - InputStream inputStream = getContentResolver().openInputStream(uri); - InputStreamReader isr = new InputStreamReader(inputStream); - BufferedReader br = new BufferedReader(isr); - String line; - while ((line = br.readLine()) != null) { - Module m = repoLoader.getModule(line); - - if (m == null) { - Snackbar.make(binding.snackbar, getString(R.string.download_details_not_found, line), Snackbar.LENGTH_SHORT).show(); - } else { - list.add(m); - } - } - br.close(); - } catch (Exception e) { - e.printStackTrace(); - } - - for (final Module m : list) { - if (moduleUtil.getModule(m.packageName) != null) { - continue; - } - ModuleVersion mv = null; - for (int i = 0; i < m.versions.size(); i++) { - ModuleVersion mvTemp = m.versions.get(i); - - if (mvTemp.relType == ReleaseType.STABLE) { - mv = mvTemp; - break; - } - } - - if (mv != null) { - NavUtil.startURL(this, mv.downloadLink); - } - } - - ModuleUtil.getInstance().reloadInstalledModules(); - } - */ @Override public void onDestroy() { super.onDestroy(); diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/SettingsActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/SettingsActivity.java index 9225daaf..3d7983be 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/SettingsActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ui/activity/SettingsActivity.java @@ -111,15 +111,7 @@ public class SettingsActivity extends BaseActivity { @Override public void onCreatePreferencesFix(Bundle savedInstanceState, String rootKey) { addPreferencesFromResource(R.xml.prefs); -/* - Preference releaseType = findPreference("release_type_global"); - if (releaseType != null) { - releaseType.setOnPreferenceChangeListener((preference, newValue) -> { - RepoLoader.getInstance().setReleaseTypeGlobal((String) newValue); - return true; - }); - } -*/ + SwitchPreferenceCompat prefWhiteListMode = findPreference("white_list_switch"); if (prefWhiteListMode != null) { prefWhiteListMode.setChecked(Files.exists(whiteListModeFlag)); diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsFragment.java deleted file mode 100644 index 60331d5a..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsFragment.java +++ /dev/null @@ -1,77 +0,0 @@ -package org.meowcat.edxposed.manager.ui.fragment; - -import android.annotation.SuppressLint; -import android.net.Uri; -import android.os.Bundle; -import android.text.method.LinkMovementMethod; -import android.util.Pair; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import androidx.annotation.NonNull; -import androidx.fragment.app.Fragment; - -import org.meowcat.edxposed.manager.R; -import org.meowcat.edxposed.manager.databinding.DownloadDetailsBinding; -import org.meowcat.edxposed.manager.databinding.DownloadMoreinfoBinding; -import org.meowcat.edxposed.manager.repo.Module; -import org.meowcat.edxposed.manager.repo.RepoParser; -import org.meowcat.edxposed.manager.ui.activity.BaseActivity; -import org.meowcat.edxposed.manager.ui.activity.DownloadDetailsActivity; -import org.meowcat.edxposed.manager.util.NavUtil; -import org.meowcat.edxposed.manager.util.chrome.LinkTransformationMethod; - -public class DownloadDetailsFragment extends Fragment { - - @SuppressLint("SetTextI18n") - @Override - public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - DownloadDetailsActivity mActivity = (DownloadDetailsActivity) getActivity(); - if (mActivity == null) { - return null; - } - final Module module = mActivity.getModule(); - if (module == null) { - return null; - } - DownloadDetailsBinding binding = DownloadDetailsBinding.inflate(inflater, container, false); - binding.downloadTitle.setText(module.name); - binding.downloadTitle.setTextIsSelectable(true); - - if (module.author != null && !module.author.isEmpty()) - binding.downloadAuthor.setText(getString(R.string.download_author, module.author)); - else - binding.downloadAuthor.setText(R.string.download_unknown_author); - - if (module.description != null) { - if (module.descriptionIsHtml) { - binding.downloadDescription.setText(RepoParser.parseSimpleHtml(getActivity(), module.description, binding.downloadDescription)); - binding.downloadDescription.setTransformationMethod(new LinkTransformationMethod((BaseActivity) getActivity())); - binding.downloadDescription.setMovementMethod(LinkMovementMethod.getInstance()); - } else { - binding.downloadDescription.setText(module.description); - } - binding.downloadDescription.setTextIsSelectable(true); - } else { - binding.downloadDescription.setVisibility(View.GONE); - } - - for (Pair moreInfoEntry : module.moreInfo) { - DownloadMoreinfoBinding moreinfoBinding = DownloadMoreinfoBinding.inflate(inflater, binding.downloadMoreinfoContainer, false); - - moreinfoBinding.title.setText(moreInfoEntry.first + ":"); - moreinfoBinding.message.setText(moreInfoEntry.second); - - final Uri link = NavUtil.parseURL(moreInfoEntry.second); - if (link != null) { - moreinfoBinding.message.setTextColor(moreinfoBinding.message.getLinkTextColors()); - moreinfoBinding.getRoot().setOnClickListener(v -> NavUtil.startURL((BaseActivity) getActivity(), link)); - } - - binding.downloadMoreinfoContainer.addView(moreinfoBinding.getRoot()); - } - - return binding.getRoot(); - } -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsSettingsFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsSettingsFragment.java deleted file mode 100644 index ab8741e8..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsSettingsFragment.java +++ /dev/null @@ -1,62 +0,0 @@ -package org.meowcat.edxposed.manager.ui.fragment; - -import android.content.Context; -import android.content.SharedPreferences; -import android.os.Bundle; - -import androidx.preference.Preference; -import androidx.preference.PreferenceManager; - -import com.takisoft.preferencex.PreferenceFragmentCompat; - -import org.meowcat.edxposed.manager.R; -import org.meowcat.edxposed.manager.repo.Module; -import org.meowcat.edxposed.manager.ui.activity.DownloadDetailsActivity; -import org.meowcat.edxposed.manager.util.PrefixedSharedPreferences; -import org.meowcat.edxposed.manager.util.RepoLoader; - -import java.util.Map; - -public class DownloadDetailsSettingsFragment extends PreferenceFragmentCompat { - - @Override - public void onCreatePreferencesFix(Bundle savedInstanceState, String rootKey) { - DownloadDetailsActivity mActivity = (DownloadDetailsActivity) getActivity(); - if (mActivity == null) { - return; - } - final Module module = mActivity.getModule(); - if (module == null) { - return; - } - - final String packageName = module.packageName; - - PreferenceManager prefManager = getPreferenceManager(); - prefManager.setSharedPreferencesName("module_settings"); - PrefixedSharedPreferences.injectToPreferenceManager(prefManager, module.packageName); - addPreferencesFromResource(R.xml.module_prefs); - - SharedPreferences prefs = getActivity().getSharedPreferences("module_settings", Context.MODE_PRIVATE); - SharedPreferences.Editor editor = prefs.edit(); - - if (prefs.getBoolean("no_global", true)) { - for (Map.Entry k : prefs.getAll().entrySet()) { - if (("global").equals(prefs.getString(k.getKey(), ""))) { - editor.putString(k.getKey(), "").apply(); - } - } - - editor.putBoolean("no_global", false).apply(); - } - - Preference releaseType = findPreference("release_type"); - if (releaseType != null) { - releaseType.setOnPreferenceChangeListener((preference, newValue) -> { - RepoLoader.getInstance().setReleaseTypeLocal(packageName, (String) newValue); - return true; - }); - } - } - -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsVersionsFragment.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsVersionsFragment.java deleted file mode 100644 index 8f42223a..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/fragment/DownloadDetailsVersionsFragment.java +++ /dev/null @@ -1,188 +0,0 @@ -package org.meowcat.edxposed.manager.ui.fragment; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.content.res.Resources; -import android.os.Bundle; -import android.text.method.LinkMovementMethod; -import android.util.TypedValue; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.ArrayAdapter; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.ListFragment; - -import org.meowcat.edxposed.manager.R; -import org.meowcat.edxposed.manager.repo.Module; -import org.meowcat.edxposed.manager.repo.ModuleVersion; -import org.meowcat.edxposed.manager.repo.ReleaseType; -import org.meowcat.edxposed.manager.repo.RepoParser; -import org.meowcat.edxposed.manager.ui.activity.BaseActivity; -import org.meowcat.edxposed.manager.ui.activity.DownloadDetailsActivity; -import org.meowcat.edxposed.manager.ui.widget.DownloadView; -import org.meowcat.edxposed.manager.util.ModuleUtil.InstalledModule; -import org.meowcat.edxposed.manager.util.RepoLoader; -import org.meowcat.edxposed.manager.util.chrome.LinkTransformationMethod; - -import java.text.DateFormat; -import java.util.Date; - -public class DownloadDetailsVersionsFragment extends ListFragment { - @SuppressLint("StaticFieldLeak") - private DownloadDetailsActivity activity; - - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - activity = (DownloadDetailsActivity) getActivity(); - if (activity == null) { - return; - } - Module module = activity.getModule(); - if (module == null) - return; - - if (module.versions.isEmpty()) { - setEmptyText(getString(R.string.download_no_versions)); - setListShown(true); - } else { - RepoLoader repoLoader = RepoLoader.getInstance(); - if (!repoLoader.isVersionShown(module.versions.get(0))) { - TextView txtHeader = new TextView(getActivity()); - txtHeader.setText(R.string.download_test_version_not_shown); - txtHeader.setTextColor(ContextCompat.getColor(activity, R.color.warning)); - txtHeader.setOnClickListener(v -> activity.gotoPage(DownloadDetailsActivity.DOWNLOAD_SETTINGS)); - getListView().addHeaderView(txtHeader); - } - - VersionsAdapter sAdapter = new VersionsAdapter(activity, activity.getInstalledModule()/*, activity.findViewById(R.id.snackbar)*/); - for (ModuleVersion version : module.versions) { - if (repoLoader.isVersionShown(version)) - sAdapter.add(version); - } - setListAdapter(sAdapter); - } - } - - @Override - public void onDestroyView() { - super.onDestroyView(); - setListAdapter(null); - } - - static class ViewHolder { - TextView txtStatus; - TextView txtVersion; - TextView txtRelType; - TextView txtUploadDate; - DownloadView downloadView; - TextView txtChangesTitle; - TextView txtChanges; - } - - private class VersionsAdapter extends ArrayAdapter { - private final DateFormat dateFormatter = DateFormat - .getDateInstance(DateFormat.SHORT); - private final int colorRelTypeStable; - private final int colorRelTypeOthers; - private final int colorInstalled; - private final int colorUpdateAvailable; - private final String textInstalled; - private final String textUpdateAvailable; - private final long installedVersionCode; - - VersionsAdapter(Context context, InstalledModule installed) { - super(context, R.layout.item_version); - TypedValue typedValue = new TypedValue(); - Resources.Theme theme = context.getTheme(); - theme.resolveAttribute(android.R.attr.textColorPrimary, typedValue, true); - int color = ContextCompat.getColor(context, typedValue.resourceId); - colorRelTypeStable = color; - colorRelTypeOthers = ContextCompat.getColor(activity, R.color.warning); - colorInstalled = color; - colorUpdateAvailable = ContextCompat.getColor(activity, R.color.download_status_update_available); - textInstalled = getString(R.string.download_section_installed) + ":"; - textUpdateAvailable = getString(R.string.download_section_update_available) + ":"; - installedVersionCode = (installed != null) ? installed.versionCode : -1; - } - - @SuppressLint("InflateParams") - @Override - @NonNull - public View getView(int position, View convertView, @NonNull ViewGroup parent) { - View view = convertView; - if (view == null) { - LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); - view = inflater.inflate(R.layout.item_version, null, true); - ViewHolder viewHolder = new ViewHolder(); - viewHolder.txtStatus = view.findViewById(R.id.txtStatus); - viewHolder.txtVersion = view.findViewById(R.id.txtVersion); - viewHolder.txtRelType = view.findViewById(R.id.txtRelType); - viewHolder.txtUploadDate = view.findViewById(R.id.txtUploadDate); - viewHolder.downloadView = view.findViewById(R.id.downloadView); - viewHolder.txtChangesTitle = view.findViewById(R.id.txtChangesTitle); - viewHolder.txtChanges = view.findViewById(R.id.txtChanges); - viewHolder.downloadView.fragment = DownloadDetailsVersionsFragment.this; - view.setTag(viewHolder); - } - - ViewHolder holder = (ViewHolder) view.getTag(); - ModuleVersion item = getItem(position); - if (item == null) { - return view; - } - holder.txtVersion.setText(item.name); - holder.txtRelType.setText(item.relType.getTitleId()); - holder.txtRelType.setTextColor(item.relType == ReleaseType.STABLE - ? colorRelTypeStable : colorRelTypeOthers); - - if (item.uploaded > 0) { - holder.txtUploadDate.setText( - dateFormatter.format(new Date(item.uploaded))); - holder.txtUploadDate.setVisibility(View.VISIBLE); - } else { - holder.txtUploadDate.setVisibility(View.GONE); - } - - if (item.code <= 0 || installedVersionCode <= 0 - || item.code < installedVersionCode) { - holder.txtStatus.setVisibility(View.GONE); - } else if (item.code == installedVersionCode) { - holder.txtStatus.setText(textInstalled); - holder.txtStatus.setTextColor(colorInstalled); - holder.txtStatus.setVisibility(View.VISIBLE); - } else { // item.code > installedVersionCode - holder.txtStatus.setText(textUpdateAvailable); - holder.txtStatus.setTextColor(colorUpdateAvailable); - holder.txtStatus.setVisibility(View.VISIBLE); - } - - holder.downloadView.setUrl(item.downloadLink); - holder.downloadView.setTitle(activity.getModule().name); - - if (item.changelog != null && !item.changelog.isEmpty()) { - holder.txtChangesTitle.setVisibility(View.VISIBLE); - holder.txtChanges.setVisibility(View.VISIBLE); - - if (item.changelogIsHtml) { - holder.txtChanges.setText(RepoParser.parseSimpleHtml(getActivity(), item.changelog, holder.txtChanges)); - holder.txtChanges.setTransformationMethod(new LinkTransformationMethod((BaseActivity) getActivity())); - holder.txtChanges.setMovementMethod(LinkMovementMethod.getInstance()); - } else { - holder.txtChanges.setText(item.changelog); - holder.txtChanges.setMovementMethod(null); - } - - } else { - holder.txtChangesTitle.setVisibility(View.GONE); - holder.txtChanges.setVisibility(View.GONE); - } - - return view; - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ui/widget/DownloadView.java b/app/src/main/java/org/meowcat/edxposed/manager/ui/widget/DownloadView.java deleted file mode 100644 index 67e404d4..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/ui/widget/DownloadView.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.meowcat.edxposed.manager.ui.widget; - -import android.content.Context; -import android.util.AttributeSet; -import android.view.LayoutInflater; -import android.view.View; -import android.widget.LinearLayout; - -import androidx.fragment.app.Fragment; - -import org.meowcat.edxposed.manager.R; -import org.meowcat.edxposed.manager.databinding.DownloadViewBinding; -import org.meowcat.edxposed.manager.ui.activity.BaseActivity; -import org.meowcat.edxposed.manager.util.NavUtil; - -public class DownloadView extends LinearLayout { - public Fragment fragment; - private String mUrl = null; - private String mTitle = null; - private final DownloadViewBinding binding; - - public DownloadView(Context context, final AttributeSet attrs) { - super(context, attrs); - setFocusable(false); - setOrientation(LinearLayout.VERTICAL); - - binding = DownloadViewBinding.inflate(LayoutInflater.from(context), this); - - binding.btnDownload.setOnClickListener(v -> NavUtil.startURL((BaseActivity) context, mUrl)); - } - - public String getUrl() { - return mUrl; - } - - public void setUrl(String url) { - mUrl = url; - if (mUrl != null) { - binding.btnDownload.setVisibility(View.VISIBLE); - binding.txtInfo.setVisibility(View.GONE); - } else { - binding.btnDownload.setVisibility(View.GONE); - binding.txtInfo.setVisibility(View.VISIBLE); - binding.txtInfo.setText(R.string.download_view_no_url); - } - } - - public String getTitle() { - return mTitle; - } - - public void setTitle(String title) { - this.mTitle = title; - } -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/DownloadsUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/DownloadsUtil.java deleted file mode 100644 index 208e38e1..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/DownloadsUtil.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.meowcat.edxposed.manager.util; - -import android.content.Context; -import android.content.SharedPreferences; - -import org.meowcat.edxposed.manager.App; -import org.meowcat.edxposed.manager.R; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.net.URLConnection; - -public class DownloadsUtil { - private static final SharedPreferences pref = App.getInstance().getSharedPreferences("download_cache", Context.MODE_PRIVATE); - - static SyncDownloadInfo downloadSynchronously(String url, File target) { - final boolean useNotModifiedTags = target.exists(); - - URLConnection connection = null; - InputStream in = null; - FileOutputStream out = null; - try { - connection = new URL(url).openConnection(); - connection.setDoOutput(false); - connection.setConnectTimeout(30000); - connection.setReadTimeout(30000); - - if (connection instanceof HttpURLConnection) { - // Disable transparent gzip encoding for gzipped files - if (url.endsWith(".gz")) { - connection.addRequestProperty("Accept-Encoding", "identity"); - } - - if (useNotModifiedTags) { - String modified = pref.getString("download_" + url + "_modified", null); - String etag = pref.getString("download_" + url + "_etag", null); - - if (modified != null) { - connection.addRequestProperty("If-Modified-Since", modified); - } - if (etag != null) { - connection.addRequestProperty("If-None-Match", etag); - } - } - } - - connection.connect(); - - if (connection instanceof HttpURLConnection) { - HttpURLConnection httpConnection = (HttpURLConnection) connection; - int responseCode = httpConnection.getResponseCode(); - if (responseCode == HttpURLConnection.HTTP_NOT_MODIFIED) { - return new SyncDownloadInfo(SyncDownloadInfo.STATUS_NOT_MODIFIED, null); - } else if (responseCode < 200 || responseCode >= 300) { - return new SyncDownloadInfo(SyncDownloadInfo.STATUS_FAILED, - App.getInstance().getString(R.string.repo_download_failed_http, - url, responseCode, - httpConnection.getResponseMessage())); - } - } - - in = connection.getInputStream(); - out = new FileOutputStream(target); - byte[] buf = new byte[1024]; - int read; - while ((read = in.read(buf)) != -1) { - out.write(buf, 0, read); - } - - if (connection instanceof HttpURLConnection) { - HttpURLConnection httpConnection = (HttpURLConnection) connection; - String modified = httpConnection.getHeaderField("Last-Modified"); - String etag = httpConnection.getHeaderField("ETag"); - - pref.edit() - .putString("download_" + url + "_modified", modified) - .putString("download_" + url + "_etag", etag).apply(); - } - - return new SyncDownloadInfo(SyncDownloadInfo.STATUS_SUCCESS, null); - - } catch (Throwable t) { - return new SyncDownloadInfo(SyncDownloadInfo.STATUS_FAILED, - App.getInstance().getString(R.string.repo_download_failed, url, - t.getMessage())); - - } finally { - if (connection instanceof HttpURLConnection) - ((HttpURLConnection) connection).disconnect(); - if (in != null) - try { - in.close(); - } catch (IOException ignored) { - } - if (out != null) - try { - out.close(); - } catch (IOException ignored) { - } - } - } - - static void clearCache(String url) { - if (url != null) { - pref.edit().remove("download_" + url + "_modified") - .remove("download_" + url + "_etag").apply(); - } else { - pref.edit().clear().apply(); - } - } - - public static class SyncDownloadInfo { - static final int STATUS_SUCCESS = 0; - static final int STATUS_NOT_MODIFIED = 1; - static final int STATUS_FAILED = 2; - - public final int status; - final String errorMessage; - - private SyncDownloadInfo(int status, String errorMessage) { - this.status = status; - this.errorMessage = errorMessage; - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/HashUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/HashUtil.java deleted file mode 100644 index 0322988b..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/HashUtil.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.meowcat.edxposed.manager.util; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -public class HashUtil { - private static String hash(String input, @SuppressWarnings("SameParameterValue") String algorithm) { - try { - MessageDigest md = MessageDigest.getInstance(algorithm); - byte[] messageDigest = md.digest(input.getBytes()); - return toHexString(messageDigest); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(e); - } - } - - static String md5(String input) { - return hash(input, "MD5"); - } - -// public static String sha1(String input) { -// return hash(input, "SHA-1"); -// } - - private static String hash(File file, @SuppressWarnings("SameParameterValue") String algorithm) throws IOException { - try { - MessageDigest md = MessageDigest.getInstance(algorithm); - InputStream is = new FileInputStream(file); - byte[] buffer = new byte[8192]; - int read; - while ((read = is.read(buffer)) > 0) { - md.update(buffer, 0, read); - } - is.close(); - byte[] messageDigest = md.digest(); - return toHexString(messageDigest); - } catch (NoSuchAlgorithmException e) { - throw new IllegalArgumentException(e); - } - } - - public static String md5(File input) throws IOException { - return hash(input, "MD5"); - } - -// public static String sha1(File input) throws IOException { -// return hash(input, "SHA-1"); -// } - - private static String toHexString(byte[] bytes) { - StringBuilder sb = new StringBuilder(); - for (byte b : bytes) { - int unsignedB = b & 0xff; - if (unsignedB < 0x10) - sb.append("0"); - sb.append(Integer.toHexString(unsignedB)); - } - return sb.toString(); - } -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/InstallApkUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/InstallApkUtil.java deleted file mode 100644 index 8a05b6f2..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/InstallApkUtil.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.meowcat.edxposed.manager.util; - -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.content.res.Resources; - -public class InstallApkUtil { - - public static String getAppLabel(ApplicationInfo info, PackageManager pm) { - try { - if (info.labelRes > 0) { - Resources res = pm.getResourcesForApplication(info); - return res.getString(info.labelRes); - } - } catch (Exception ignored) { - } - return info.loadLabel(pm).toString(); - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java index 7da2ff4c..157342b4 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java @@ -18,7 +18,6 @@ import org.meowcat.edxposed.manager.App; import org.meowcat.edxposed.manager.Constants; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.databinding.ActivityModulesBinding; -import org.meowcat.edxposed.manager.repo.ModuleVersion; import java.io.IOException; import java.io.PrintWriter; @@ -33,7 +32,6 @@ public final class ModuleUtil { public static int MIN_MODULE_VERSION = 2; // reject modules with private static ModuleUtil instance = null; private final PackageManager pm; - private final String frameworkPackageName; private final List listeners = new CopyOnWriteArrayList<>(); private final SharedPreferences pref; //private InstalledModule framework = null; @@ -44,7 +42,6 @@ public final class ModuleUtil { private ModuleUtil() { pref = App.getInstance().getSharedPreferences("enabled_modules", Context.MODE_PRIVATE); pm = App.getInstance().getPackageManager(); - frameworkPackageName = App.getInstance().getPackageName(); } public static synchronized ModuleUtil getInstance() { @@ -76,32 +73,19 @@ public final class ModuleUtil { } Map modules = new HashMap<>(); - //RepoDb.beginTransation(); - try { - //RepoDb.deleteAllInstalledModules(); - for (PackageInfo pkg : pm.getInstalledPackages(PackageManager.GET_META_DATA)) { - ApplicationInfo app = pkg.applicationInfo; - if (!app.enabled) - continue; + for (PackageInfo pkg : pm.getInstalledPackages(PackageManager.GET_META_DATA)) { + ApplicationInfo app = pkg.applicationInfo; + if (!app.enabled) + continue; - InstalledModule installed = null; - if (app.metaData != null && app.metaData.containsKey("xposedmodule")) { - installed = new InstalledModule(pkg, false); - modules.put(pkg.packageName, installed); - }/* else if (isFramework(pkg.packageName)) { - framework = installed = new InstalledModule(pkg, true); - }*/ - - //if (installed != null) - // RepoDb.insertInstalledModule(installed); + if (app.metaData != null && app.metaData.containsKey("xposedmodule")) { + InstalledModule installed = new InstalledModule(pkg, false); + modules.put(pkg.packageName, installed); } - - //RepoDb.setTransactionSuccessful(); - } finally { - //RepoDb.endTransation(); } + installedModules = modules; synchronized (this) { isReloading = false; @@ -129,7 +113,6 @@ public final class ModuleUtil { ApplicationInfo app = pkg.applicationInfo; if (app.enabled && app.metaData != null && app.metaData.containsKey("xposedmodule")) { InstalledModule module = new InstalledModule(pkg, false); - //RepoDb.insertInstalledModule(module); installedModules.put(packageName, module); for (ModuleListener listener : listeners) { listener.onSingleInstalledModuleReloaded(instance, packageName, @@ -137,7 +120,6 @@ public final class ModuleUtil { } return module; } else { - //RepoDb.deleteInstalledModule(packageName); InstalledModule old = installedModules.remove(packageName); if (old != null) { for (ModuleListener listener : listeners) { @@ -148,26 +130,6 @@ public final class ModuleUtil { } } - public synchronized boolean isLoading() { - return isReloading; - } - -/* public InstalledModule getFramework() { - return framework; - }*/ - - public String getFrameworkPackageName() { - return frameworkPackageName; - } - -/* private boolean isFramework(String packageName) { - return frameworkPackageName.equals(packageName); - }*/ - -// public boolean isInstalled(String packageName) { -// return installedModules.containsKey(packageName) || isFramework(packageName); -// } - public InstalledModule getModule(String packageName) { return installedModules.get(packageName); } @@ -370,10 +332,6 @@ public final class ModuleUtil { return this.description; } - public boolean isUpdate(ModuleVersion version) { - return (version != null) && version.code > versionCode; - } - public PackageInfo getPackageInfo() { return pkg; } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/NotificationUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/NotificationUtil.java index b5874fdd..70e68794 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/NotificationUtil.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/util/NotificationUtil.java @@ -25,7 +25,6 @@ public final class NotificationUtil { public static final int NOTIFICATION_MODULE_NOT_ACTIVATED_YET = 0; private static final int NOTIFICATION_MODULES_UPDATED = 1; - private static final int NOTIFICATION_INSTALLER_UPDATE = 2; private static final int PENDING_INTENT_OPEN_MODULES = 0; private static final int PENDING_INTENT_OPEN_INSTALL = 1; private static final int PENDING_INTENT_SOFT_REBOOT = 2; @@ -36,7 +35,6 @@ public final class NotificationUtil { private static final String HEADS_UP = "heads_up"; private static final String FRAGMENT_ID = "fragment"; - private static final String NOTIFICATION_UPDATE_CHANNEL = "app_update_channel"; private static final String NOTIFICATION_MODULES_CHANNEL = "modules_channel"; @SuppressLint("StaticFieldLeak") @@ -54,9 +52,7 @@ public final class NotificationUtil { notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - NotificationChannel channelUpdate = new NotificationChannel(NOTIFICATION_UPDATE_CHANNEL, context.getString(R.string.download_section_update_available), NotificationManager.IMPORTANCE_DEFAULT); NotificationChannel channelModule = new NotificationChannel(NOTIFICATION_MODULES_CHANNEL, context.getString(R.string.nav_item_modules), NotificationManager.IMPORTANCE_DEFAULT); - notificationManager.createNotificationChannel(channelUpdate); notificationManager.createNotificationChannel(channelModule); } } @@ -137,30 +133,6 @@ public final class NotificationUtil { notificationManager.notify(null, NOTIFICATION_MODULES_UPDATED, builder.build()); } - public static void showInstallerUpdateNotification() { - Intent intent = new Intent(context, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - intent.putExtra(FRAGMENT_ID, 0); - - PendingIntent pInstallTab = PendingIntent.getActivity(context, PENDING_INTENT_OPEN_INSTALL, - intent, PendingIntent.FLAG_UPDATE_CURRENT); - - String title = context.getString(R.string.app_name); - String message = context.getString(R.string.newVersion); - NotificationCompat.Builder builder = getNotificationBuilder(title, message, NOTIFICATION_UPDATE_CHANNEL) - .setContentIntent(pInstallTab); - - if (prefs.getBoolean(HEADS_UP, true)) { - builder.setPriority(2); - } - NotificationCompat.BigTextStyle notiStyle = new NotificationCompat.BigTextStyle(); - notiStyle.setBigContentTitle(title); - notiStyle.bigText(message); - builder.setStyle(notiStyle); - - notificationManager.notify(null, NOTIFICATION_INSTALLER_UPDATE, builder.build()); - } - private static NotificationCompat.Builder getNotificationBuilder(String title, String message, String channel) { return new NotificationCompat.Builder(context, channel) .setContentTitle(title) diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/PrefixedSharedPreferences.java b/app/src/main/java/org/meowcat/edxposed/manager/util/PrefixedSharedPreferences.java deleted file mode 100644 index abe4cb21..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/PrefixedSharedPreferences.java +++ /dev/null @@ -1,161 +0,0 @@ -package org.meowcat.edxposed.manager.util; - -import android.annotation.SuppressLint; -import android.content.SharedPreferences; - -import androidx.preference.PreferenceManager; - -import java.lang.reflect.Field; -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -public class PrefixedSharedPreferences implements SharedPreferences { - private final SharedPreferences mBase; - private final String mPrefix; - - private PrefixedSharedPreferences(SharedPreferences base, String prefix) { - mBase = base; - mPrefix = prefix + "_"; - } - - public static void injectToPreferenceManager(PreferenceManager manager, String prefix) { - SharedPreferences prefixedPrefs = new PrefixedSharedPreferences(manager.getSharedPreferences(), prefix); - - try { - Field fieldSharedPref = PreferenceManager.class.getDeclaredField("mSharedPreferences"); - fieldSharedPref.setAccessible(true); - fieldSharedPref.set(manager, prefixedPrefs); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - @Override - public Map getAll() { - Map baseResult = mBase.getAll(); - Map prefixedResult = new HashMap<>(baseResult); - for (Entry entry : baseResult.entrySet()) { - prefixedResult.put(mPrefix + entry.getKey(), entry.getValue()); - } - return prefixedResult; - } - - @Override - public String getString(String key, String defValue) { - return mBase.getString(mPrefix + key, defValue); - } - - @Override - public Set getStringSet(String key, Set defValues) { - return mBase.getStringSet(mPrefix + key, defValues); - } - - @Override - public int getInt(String key, int defValue) { - return mBase.getInt(mPrefix + key, defValue); - } - - @Override - public long getLong(String key, long defValue) { - return mBase.getLong(mPrefix + key, defValue); - } - - @Override - public float getFloat(String key, float defValue) { - return mBase.getFloat(mPrefix + key, defValue); - } - - @Override - public boolean getBoolean(String key, boolean defValue) { - return mBase.getBoolean(mPrefix + key, defValue); - } - - @Override - public boolean contains(String key) { - return mBase.contains(mPrefix + key); - } - - @SuppressLint("CommitPrefEdits") - @Override - public Editor edit() { - return new EditorImpl(mBase.edit()); - } - - @Override - public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { - throw new UnsupportedOperationException("listeners are not supported in this implementation"); - } - - @Override - public void unregisterOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) { - throw new UnsupportedOperationException("listeners are not supported in this implementation"); - } - - private class EditorImpl implements Editor { - private final Editor mEditorBase; - - public EditorImpl(Editor base) { - mEditorBase = base; - } - - @Override - public Editor putString(String key, String value) { - mEditorBase.putString(mPrefix + key, value); - return this; - } - - @Override - public Editor putStringSet(String key, Set values) { - mEditorBase.putStringSet(mPrefix + key, values); - return this; - } - - @Override - public Editor putInt(String key, int value) { - mEditorBase.putInt(mPrefix + key, value); - return this; - } - - @Override - public Editor putLong(String key, long value) { - mEditorBase.putLong(mPrefix + key, value); - return this; - } - - @Override - public Editor putFloat(String key, float value) { - mEditorBase.putFloat(mPrefix + key, value); - return this; - } - - @Override - public Editor putBoolean(String key, boolean value) { - mEditorBase.putBoolean(mPrefix + key, value); - return this; - } - - @Override - public Editor remove(String key) { - mEditorBase.remove(mPrefix + key); - return this; - } - - @Override - public Editor clear() { - mEditorBase.clear(); - return this; - } - - @Override - public boolean commit() { - return mEditorBase.commit(); - } - - @Override - public void apply() { - mEditorBase.apply(); - } - } -} \ No newline at end of file diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/RepoLoader.java b/app/src/main/java/org/meowcat/edxposed/manager/util/RepoLoader.java deleted file mode 100644 index 16fe0c52..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/RepoLoader.java +++ /dev/null @@ -1,434 +0,0 @@ -package org.meowcat.edxposed.manager.util; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.database.sqlite.SQLiteException; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; -import android.text.TextUtils; -import android.util.Log; -import android.widget.Toast; - -import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; - -import com.google.android.material.dialog.MaterialAlertDialogBuilder; - -import org.meowcat.edxposed.manager.App; -import org.meowcat.edxposed.manager.R; -import org.meowcat.edxposed.manager.repo.Module; -import org.meowcat.edxposed.manager.repo.ModuleVersion; -import org.meowcat.edxposed.manager.repo.ReleaseType; -import org.meowcat.edxposed.manager.repo.RepoDb; -import org.meowcat.edxposed.manager.repo.RepoParser; -import org.meowcat.edxposed.manager.repo.RepoParser.RepoParserCallback; -import org.meowcat.edxposed.manager.repo.Repository; -import org.meowcat.edxposed.manager.ui.activity.DownloadActivity; -import org.meowcat.edxposed.manager.util.DownloadsUtil.SyncDownloadInfo; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.zip.GZIPInputStream; - -public class RepoLoader { - private static final int UPDATE_FREQUENCY = 24 * 60 * 60 * 1000; - private static String DEFAULT_REPOSITORIES; - private static RepoLoader instance = null; - private final List listeners = new CopyOnWriteArrayList<>(); - private final Map localReleaseTypesCache = new HashMap<>(); - private final App app; - private final SharedPreferences pref; - private final SharedPreferences modulePref; - private final ConnectivityManager conMgr; - private boolean isLoading = false; - private boolean reloadTriggeredOnce = false; - private Map repositories = null; - private ReleaseType globalReleaseType; - private SwipeRefreshLayout swipeRefreshLayout; - - private RepoLoader() { - instance = this; - app = App.getInstance(); - pref = app.getSharedPreferences("repo", Context.MODE_PRIVATE); - DEFAULT_REPOSITORIES = App.getPreferences().getBoolean("custom_list", false) ? "https://cdn.jsdelivr.net/gh/ElderDrivers/Repository-Website@gh-pages/assets/full.xml.gz" : "https://dl-xda.xposed.info/repo/full.xml.gz"; - modulePref = app.getSharedPreferences("module_settings", Context.MODE_PRIVATE); - conMgr = (ConnectivityManager) app.getSystemService(Context.CONNECTIVITY_SERVICE); - globalReleaseType = ReleaseType.fromString(App.getPreferences().getString("release_type_global", "stable")); - refreshRepositories(); - } - - public static synchronized RepoLoader getInstance() { - if (instance == null) - new RepoLoader(); - return instance; - } - - private boolean refreshRepositories() { - repositories = RepoDb.getRepositories(); - - // Unlikely case (usually only during initial load): DB state doesn't - // fit to configuration - boolean needReload = false; - String[] config = (pref.getString("repositories", DEFAULT_REPOSITORIES) + "").split("\\|"); - if (repositories.size() != config.length) { - needReload = true; - } else { - int i = 0; - for (Repository repo : repositories.values()) { - if (!repo.url.equals(config[i++])) { - needReload = true; - break; - } - } - } - - if (!needReload) - return false; - - clear(false); - for (String url : config) { - RepoDb.insertRepository(url); - } - repositories = RepoDb.getRepositories(); - return true; - } - - public void setReleaseTypeGlobal(String relTypeString) { - ReleaseType relType = ReleaseType.fromString(relTypeString); - if (globalReleaseType == relType) - return; - - globalReleaseType = relType; - - // Updating the latest version for all modules takes a moment - new Thread("DBUpdate") { - @Override - public void run() { - RepoDb.updateAllModulesLatestVersion(); - notifyListeners(); - } - }.start(); - } - - public void setReleaseTypeLocal(String packageName, String relTypeString) { - ReleaseType relType = (!TextUtils.isEmpty(relTypeString)) ? ReleaseType.fromString(relTypeString) : null; - - if (getReleaseTypeLocal(packageName) == relType) - return; - - synchronized (localReleaseTypesCache) { - if (relType != null) { - localReleaseTypesCache.put(packageName, relType); - } - } - - RepoDb.updateModuleLatestVersion(packageName); - notifyListeners(); - } - - private ReleaseType getReleaseTypeLocal(String packageName) { - synchronized (localReleaseTypesCache) { - if (localReleaseTypesCache.containsKey(packageName)) - return localReleaseTypesCache.get(packageName); - - String value = modulePref.getString(packageName + "_release_type", - null); - ReleaseType result = (!TextUtils.isEmpty(value)) ? ReleaseType.fromString(value) : null; - if (result != null) { - localReleaseTypesCache.put(packageName, result); - } - return result; - } - } - - public Repository getRepository(long repoId) { - return repositories.get(repoId); - } - - public Module getModule(String packageName) { - return RepoDb.getModuleByPackageName(packageName); - } - - public ModuleVersion getLatestVersion(Module module) { - if (module == null || module.versions.isEmpty()) - return null; - - for (ModuleVersion version : module.versions) { - if (version.downloadLink != null && isVersionShown(version)) - return version; - } - return null; - } - - public boolean isVersionShown(ModuleVersion version) { - return version.relType - .ordinal() <= getMaxShownReleaseType(version.module.packageName).ordinal(); - } - - public ReleaseType getMaxShownReleaseType(String packageName) { - ReleaseType localSetting = getReleaseTypeLocal(packageName); - if (localSetting != null) - return localSetting; - else - return globalReleaseType; - } - - public void triggerReload(final boolean force) { - reloadTriggeredOnce = true; - - if (force) { - resetLastUpdateCheck(); - } else { - long lastUpdateCheck = pref.getLong("last_update_check", 0); - if (System.currentTimeMillis() < lastUpdateCheck + UPDATE_FREQUENCY) - return; - } - - NetworkInfo netInfo = conMgr.getActiveNetworkInfo(); - if (netInfo == null || !netInfo.isConnected()) - return; - - synchronized (this) { - if (isLoading) - return; - isLoading = true; - } - //app.updateProgressIndicator(swipeRefreshLayout); - - new Thread("RepositoryReload") { - public void run() { - final List messages = new LinkedList<>(); - boolean hasChanged = downloadAndParseFiles(messages); - - pref.edit().putLong("last_update_check", System.currentTimeMillis()).apply(); - - if (!messages.isEmpty()) { - App.runOnUiThread(() -> { - for (String message : messages) { - Toast.makeText(app, message, Toast.LENGTH_LONG).show(); - } - }); - } - - if (hasChanged) - notifyListeners(); - - synchronized (this) { - isLoading = false; - } - //app.updateProgressIndicator(swipeRefreshLayout); - } - }.start(); - } - - public void setSwipeRefreshLayout(SwipeRefreshLayout swipeRefreshLayout) { - this.swipeRefreshLayout = swipeRefreshLayout; - } - - public void triggerFirstLoadIfNecessary() { - if (!reloadTriggeredOnce) - triggerReload(false); - } - - public void resetLastUpdateCheck() { - pref.edit().remove("last_update_check").apply(); - } - - public synchronized boolean isLoading() { - return isLoading; - } - - public void clear(boolean notify) { - synchronized (this) { - // TODO Stop reloading repository when it should be cleared - if (isLoading) - return; - - RepoDb.deleteRepositories(); - repositories = new LinkedHashMap<>(0); - DownloadsUtil.clearCache(null); - resetLastUpdateCheck(); - } - - if (notify) - notifyListeners(); - } - - public void setRepositories(String... repos) { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < repos.length; i++) { - if (i > 0) - sb.append("|"); - sb.append(repos[i]); - } - pref.edit().putString("repositories", sb.toString()).apply(); - if (refreshRepositories()) - triggerReload(true); - } - - public boolean hasModuleUpdates() { - return RepoDb.hasModuleUpdates(); - } - - public String getFrameworkUpdateVersion() { - return RepoDb.getFrameworkUpdateVersion(); - } - - private File getRepoCacheFile(String repo) { - String filename = "repo_" + HashUtil.md5(repo) + ".xml"; - if (repo.endsWith(".gz")) - filename += ".gz"; - return new File(app.getCacheDir(), filename); - } - - private boolean downloadAndParseFiles(List messages) { - // These variables don't need to be atomic, just mutable - final AtomicBoolean hasChanged = new AtomicBoolean(false); - final AtomicInteger insertCounter = new AtomicInteger(); - final AtomicInteger deleteCounter = new AtomicInteger(); - - for (Entry repoEntry : repositories.entrySet()) { - final long repoId = repoEntry.getKey(); - final Repository repo = repoEntry.getValue(); - - String url = (repo.partialUrl != null && repo.version != null) ? String.format(repo.partialUrl, repo.version) : repo.url; - - File cacheFile = getRepoCacheFile(url); - SyncDownloadInfo info = DownloadsUtil.downloadSynchronously(url, - cacheFile); - - Log.i(App.TAG, String.format( - "RepoLoader -> Downloaded %s with status %d (error: %s), size %d bytes", - url, info.status, info.errorMessage, cacheFile.length())); - - if (info.status != SyncDownloadInfo.STATUS_SUCCESS) { - if (info.errorMessage != null) - messages.add(info.errorMessage); - continue; - } - - InputStream in = null; - RepoDb.beginTransation(); - try { - in = new FileInputStream(cacheFile); - if (url.endsWith(".gz")) - in = new GZIPInputStream(in); - - RepoParser.parse(in, new RepoParserCallback() { - @Override - public void onRepositoryMetadata(Repository repository) { - if (!repository.isPartial) { - RepoDb.deleteAllModules(repoId); - hasChanged.set(true); - } - } - - @Override - public void onNewModule(Module module) { - RepoDb.insertModule(repoId, module); - hasChanged.set(true); - insertCounter.incrementAndGet(); - } - - @Override - public void onRemoveModule(String packageName) { - RepoDb.deleteModule(repoId, packageName); - hasChanged.set(true); - deleteCounter.decrementAndGet(); - } - - @Override - public void onCompleted(Repository repository) { - if (!repository.isPartial) { - RepoDb.updateRepository(repoId, repository); - repo.name = repository.name; - repo.partialUrl = repository.partialUrl; - repo.version = repository.version; - } else { - RepoDb.updateRepositoryVersion(repoId, repository.version); - repo.version = repository.version; - } - - Log.i(App.TAG, String.format( - "RepoLoader -> Updated repository %s to version %s (%d new / %d removed modules)", - repo.url, repo.version, insertCounter.get(), - deleteCounter.get())); - } - }); - - RepoDb.setTransactionSuccessful(); - } catch (SQLiteException e) { - App.runOnUiThread(() -> new MaterialAlertDialogBuilder(app) - .setTitle(R.string.restart_needed) - .setMessage(R.string.cache_cleaned) - .setPositiveButton(android.R.string.ok, (dialog, which) -> { - Intent i = new Intent(app, DownloadActivity.class); - PendingIntent pi = PendingIntent.getActivity(app, 0, i, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager mgr = (AlarmManager) app.getSystemService(Context.ALARM_SERVICE); - mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pi); - System.exit(0); - }) - .setCancelable(false) - .show()); - - DownloadsUtil.clearCache(url); - } catch (Throwable t) { - Log.e(App.TAG, "RepoLoader -> Cannot load repository from " + url, t); - messages.add(app.getString(R.string.repo_load_failed, url, t.getMessage())); - DownloadsUtil.clearCache(url); - } finally { - if (in != null) - try { - in.close(); - } catch (IOException ignored) { - } - //noinspection ResultOfMethodCallIgnored - cacheFile.delete(); - RepoDb.endTransation(); - } - } - - // TODO Set ModuleColumns.PREFERRED for modules which appear in multiple - // repositories - return hasChanged.get(); - } - - public void addListener(RepoListener listener, boolean triggerImmediately) { - if (!listeners.contains(listener)) - listeners.add(listener); - - if (triggerImmediately) - listener.onRepoReloaded(this); - } - - public void removeListener(RepoListener listener) { - listeners.remove(listener); - } - - private void notifyListeners() { - for (RepoListener listener : listeners) { - listener.onRepoReloaded(instance); - } - } - - public interface RepoListener { - /** - * Called whenever the list of modules from repositories has been - * successfully reloaded - */ - void onRepoReloaded(RepoLoader loader); - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/TaskRunner.java b/app/src/main/java/org/meowcat/edxposed/manager/util/TaskRunner.java deleted file mode 100644 index fbdbe1ac..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/TaskRunner.java +++ /dev/null @@ -1,19 +0,0 @@ -package org.meowcat.edxposed.manager.util; - -import java.util.concurrent.Callable; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; - -public class TaskRunner { - private final Executor executor = Executors.newSingleThreadExecutor(); // change according to your requirements - - public void executeAsync(Callable callable) { - executor.execute(() -> { - try { - callable.call(); - } catch (Exception e) { - e.printStackTrace(); - } - }); - } -} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_get_app.xml b/app/src/main/res/drawable/ic_get_app.xml deleted file mode 100644 index 09cd9664..00000000 --- a/app/src/main/res/drawable/ic_get_app.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml deleted file mode 100644 index 4bf68f28..00000000 --- a/app/src/main/res/drawable/ic_share.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/drawable/ic_sort.xml b/app/src/main/res/drawable/ic_sort.xml deleted file mode 100644 index 707e960d..00000000 --- a/app/src/main/res/drawable/ic_sort.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/app/src/main/res/layout/activity_download.xml b/app/src/main/res/layout/activity_download.xml deleted file mode 100644 index a459edee..00000000 --- a/app/src/main/res/layout/activity_download.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_download_details.xml b/app/src/main/res/layout/activity_download_details.xml deleted file mode 100644 index dbda5103..00000000 --- a/app/src/main/res/layout/activity_download_details.xml +++ /dev/null @@ -1,40 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_download_details_not_found.xml b/app/src/main/res/layout/activity_download_details_not_found.xml deleted file mode 100644 index 7c24a8e5..00000000 --- a/app/src/main/res/layout/activity_download_details_not_found.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - -